exif
stableRead and inspect EXIF metadata embedded in JPEG and TIFF image files. Extract camera info, GPS coordinates, orientation, timestamps, and arbitrary tag values.
use plugin exif::{read_file, get_tag, has_gps, …} Functions (10)
- read_file Read all EXIF tags from an image file
- get_tag Find a tag value by name in a tag table
- has_gps Check if a tag table contains GPS data
- image_dimensions Read pixel width and height from file
- camera_info Extract make and model from a tag table
- list_tags List all tag names from a tag table
- tag_count Count the number of tags in a table
- orientation Get the Orientation tag value
- gps_coords Extract latitude and longitude strings
- date_time Get the DateTimeOriginal or DateTime value
Overview
exif reads the EXIF metadata block embedded in JPEG and TIFF photos and exposes
it to Zolo as plain tables of {tag, value_str} entries. The whole API is
stateless: read_file (or image_dimensions) opens a file once and hands back an
ordinary table, and every other function is a pure query over that table — there
are no handles to close and no mutable state to track. Pixel dimensions, camera
make/model, GPS coordinates, orientation, and capture timestamps are all just tags
in the same block, so the convenience helpers simply locate the right entries for
you.
The mental model is a two-step pipeline: call read_file(path) once to get the
entries table, then pass that table into the helpers (get_tag, camera_info,
gps_coords, orientation, date_time, list_tags, tag_count, has_gps).
The lone exception is image_dimensions, which takes a file path directly rather
than an entries table. Use this plugin whenever you need to inspect what a camera
recorded about a photo without decoding the image pixels themselves.
Common patterns
Read a photo once, then summarize the camera and capture details:
use plugin exif::{read_file, camera_info, date_time, orientation}
let tags = read_file("photo.jpg")
let cam = camera_info(tags)
print("camera: {cam["make"]} {cam["model"]}")
print("taken: {date_time(tags)}")
print("orient: {orientation(tags)}")
Guard GPS access with has_gps before pulling coordinates:
use plugin exif::{read_file, has_gps, gps_coords}
let tags = read_file("photo.jpg")
if has_gps(tags) {
let coords = gps_coords(tags)
print("{coords["latitude"]} {coords["latitude_ref"]}")
print("{coords["longitude"]} {coords["longitude_ref"]}")
} else {
print("no location embedded")
}
Combine the file-path and entries-table APIs into one report:
use plugin exif::{read_file, image_dimensions, tag_count, get_tag}
let path = "photo.jpg"
let tags = read_file(path)
let dims = image_dimensions(path)
print("{dims["width"]}x{dims["height"]} with {tag_count(tags)} tags")
print("exposure: {get_tag(tags, "ExposureTime")}")
Read all EXIF tags from an image file
Opens an image file and reads all primary EXIF tags. Returns a table of {tag, value_str} entries. This table is the input for most other functions in this plugin.
use plugin exif::{read_file, list_tags}
let tags = read_file("photo.jpg")
let names = list_tags(tags)
print(names)
Because the result is an ordinary table, you can feed it straight into the other helpers without re-reading the file:
use plugin exif::{read_file, tag_count, camera_info}
let tags = read_file("photo.jpg")
print("read {tag_count(tags)} tags")
print(camera_info(tags)["model"])
Find a tag value by name in a tag table
Searches the tag table returned by read_file for an entry whose tag field matches tag_name. Returns the string value, or nil if not found.
use plugin exif::{read_file, get_tag}
let tags = read_file("photo.jpg")
let iso = get_tag(tags, "ISOSpeedRatings")
let focal = get_tag(tags, "FocalLength")
print("ISO: {iso}, focal: {focal}")
Since a missing tag comes back as nil, you can branch on the result to handle photos that lack a particular field:
use plugin exif::{read_file, get_tag}
let tags = read_file("photo.jpg")
let lens = get_tag(tags, "LensModel")
if lens != nil {
print("shot with {lens}")
} else {
print("lens not recorded")
}
Check if a tag table contains GPS data
Returns true if the tag table contains any GPS-related tags (GPSLatitude, GPSLongitude, etc.).
use plugin exif::{read_file, has_gps}
let tags = read_file("photo.jpg")
if has_gps(tags) {
print("image has location data")
}
Read pixel width and height from file
Reads PixelXDimension and PixelYDimension directly from the file. Returns {width, height} as integers (0 if the tags are absent).
use plugin exif::{image_dimensions}
let dims = image_dimensions("photo.jpg")
print("size: {dims["width"]}x{dims["height"]}")
The width and height are integers, so you can compute derived values like the aspect ratio or megapixel count directly:
use plugin exif::{image_dimensions}
let dims = image_dimensions("photo.jpg")
let mp = (dims["width"] * dims["height"]) / 1000000
print("{mp} megapixels")
Extract make and model from a tag table
Extracts the Make and Model tag values from a tag table. Returns {make, model} as strings (empty if not present).
use plugin exif::{read_file, camera_info}
let tags = read_file("photo.jpg")
let cam = camera_info(tags)
print("{cam["make"]} {cam["model"]}")
Count the number of tags in a table
Returns the number of EXIF tags in the table.
use plugin exif::{read_file, tag_count}
let tags = read_file("photo.jpg")
print(tag_count(tags))
Get the Orientation tag value
Returns the value of the Orientation tag (e.g., "top-left", "right-top"). Returns nil if the tag is absent.
use plugin exif::{read_file, orientation}
let tags = read_file("photo.jpg")
let o = orientation(tags)
if o != nil {
print("orientation: {o}")
}
Extract latitude and longitude strings
Extracts GPSLatitude, GPSLongitude, GPSLatitudeRef, and GPSLongitudeRef tag values. Returns a table with those four keys, or nil if GPS data is absent.
use plugin exif::{read_file, gps_coords}
let tags = read_file("photo.jpg")
let coords = gps_coords(tags)
if coords != nil {
print("{coords["latitude"]} {coords["latitude_ref"]}")
print("{coords["longitude"]} {coords["longitude_ref"]}")
}
Pair it with has_gps so you only build the coordinate string when location data
is actually present:
use plugin exif::{read_file, has_gps, gps_coords}
let tags = read_file("photo.jpg")
if has_gps(tags) {
let c = gps_coords(tags)
print("located at {c["latitude"]}{c["latitude_ref"]}, {c["longitude"]}{c["longitude_ref"]}")
}
Get the DateTimeOriginal or DateTime value
Returns the value of DateTimeOriginal (preferred) or DateTime, or nil if neither is present. The format is typically "YYYY:MM:DD HH:MM:SS".
use plugin exif::{read_file, date_time}
let tags = read_file("photo.jpg")
let dt = date_time(tags)
print("taken: {dt}")