libexif clib

EXIF metadata reader and writer for PascalAI. Read GPS coordinates, camera settings, orientation, timestamps, and lens data from JPEG photos. Edit or strip metadata for privacy. The standard library used by photo management and geotagging tools.

Version1.0.0
Typeclib
System reqlibexif-dev
CategoryMultimedia
ppm install libexif
CLib package — system library required

Ubuntu/Debian: sudo apt install libexif-dev  •  Fedora: sudo dnf install libexif-devel  •  macOS: brew install libexif

Quick Start

uses libexif;

var exif := LoadFromFile('/photos/IMG_1234.jpg');
var gps := GetGPS(exif);
if gps.HasGPS then
  WriteLn('Location: ' + FloatToStr(gps.Latitude) + ', ' +
          FloatToStr(gps.Longitude));

var cam := GetCameraInfo(exif);
WriteLn('Camera: ' + cam.Make + ' ' + cam.Model);
WriteLn('ISO: ' + IntToStr(cam.ISO) + '  f/' + FloatToStr(cam.Aperture));
WriteLn('Shutter: 1/' + IntToStr(Round(1/cam.ShutterSpeed)));
FreeData(exif);
uses libexif;

{ Strip EXIF for privacy before publishing }
StripEXIF('/private/photo.jpg', '/public/photo.jpg');

{ Fix orientation (rotate pixel data based on EXIF tag) }
FixOrientation('/input/photo.jpg', '/output/photo.jpg');

{ Export all metadata as JSON }
var exif := LoadFromFile('/photos/photo.jpg');
var json := ToJSON(exif);
WriteLn(json);
FreeData(exif);

Load / Save API

All operations work on an opaque TExifData handle. Always call FreeData when done to release memory.

FunctionDescription
LoadFromFile(path)Load EXIF data from a JPEG file. Returns TExifData handle.
LoadFromBytes(data)Load EXIF from an in-memory byte array (JPEG data).
SaveToFile(exif, srcPath, dstPath)Write modified EXIF back into a new JPEG file.
SaveInPlace(exif, path)Overwrite the EXIF segment of an existing JPEG file.
FreeData(exif)Release memory for a TExifData handle.
HasEXIF(path)Returns True if the JPEG file contains an EXIF segment.

Reading Entries API

Low-level access to individual EXIF tags by numeric ID or name. Use the Structured Access API below for common fields.

FunctionDescription
GetEntryString(exif, tagId)Read tag value as a formatted string. Returns empty string if not present.
GetEntryInt(exif, tagId)Read tag value as integer. Raises exception if tag absent.
GetEntryFloat(exif, tagId)Read rational tag (e.g. exposure time) as floating-point.
GetEntryBytes(exif, tagId)Read tag raw bytes.
HasEntry(exif, tagId)Returns True if tag exists in any IFD.
ListTags(exif)Returns array of all tag IDs present.
TagName(tagId)Human-readable tag name for a numeric ID. E.g. 0x010F → 'Make'.
uses libexif;

var exif := LoadFromFile('photo.jpg');

{ Low-level tag reads }
var make := GetEntryString(exif, $010F);   { Make }
var iso  := GetEntryInt(exif, $8827);       { ISOSpeedRatings }
var exp  := GetEntryFloat(exif, $829A);    { ExposureTime }

WriteLn('Make: '     + make);
WriteLn('ISO: '      + IntToStr(iso));
WriteLn('Exposure: ' + FloatToStr(exp) + 's');

{ List all tags }
var tags := ListTags(exif);
for var tid in tags do
  WriteLn(TagName(tid) + ': ' + GetEntryString(exif, tid));

FreeData(exif);

Structured Access API

High-level functions that parse common EXIF groups into typed records.

FunctionDescription
GetGPS(exif)Returns TExifGPS with latitude, longitude, altitude, heading, and speed.
GetCameraInfo(exif)Returns TExifCameraInfo with make, model, ISO, aperture, shutter, focal length.
GetDateTime(exif)Returns TDateTime parsed from the DateTimeOriginal tag.
GetDateTimeStr(exif)Returns DateTimeOriginal as a string in 'YYYY:MM:DD HH:MM:SS' format.
GetOrientation(exif)Returns orientation value 1–8 (EXIF rotation/flip code).
GetThumbnail(exif)Returns embedded JPEG thumbnail as byte array, or empty if absent.
GetSoftware(exif)Software tag value (editing app name, e.g. 'Lightroom').
GetFlash(exif)Returns True if flash fired.
GetWhiteBalance(exif)Returns 'Auto' or 'Manual'.

Writing Entries API

FunctionDescription
SetEntryString(exif, tagId, value)Write or update a string tag.
SetEntryInt(exif, tagId, value)Write or update an integer tag.
SetEntryRational(exif, tagId, num, den)Write a rational tag as numerator/denominator.
SetGPS(exif, lat, lon, alt)Write GPS IFD tags (latitude, longitude, altitude).
SetDateTime(exif, dt)Write DateTimeOriginal from a TDateTime value.
SetOrientation(exif, value)Set orientation tag (1–8).
RemoveEntry(exif, tagId)Delete a specific tag.
RemoveGPS(exif)Delete all GPS IFD tags.
uses libexif;

var exif := LoadFromFile('photo.jpg');

{ Update GPS coordinates }
SetGPS(exif, 40.41650, -3.70379, 667.0);  { Madrid, 667m }

{ Update timestamp }
SetDateTime(exif, Now());

{ Remove identifying tags }
RemoveEntry(exif, $013B);   { Artist }
RemoveEntry(exif, $8298);   { Copyright }

SaveToFile(exif, 'photo.jpg', 'photo_updated.jpg');
FreeData(exif);

Convenience API

FunctionDescription
StripEXIF(srcPath, dstPath)Copy JPEG removing all metadata. Output is clean for publishing.
FixOrientation(srcPath, dstPath)Rotate/flip pixel data to match orientation tag, then clear tag.
ToJSON(exif)Serialize all EXIF tags to a JSON string.
FromJSON(json)Create a TExifData handle populated from a JSON string.
CopyEXIF(srcPath, dstPath)Copy EXIF segment from srcPath into dstPath (must both be JPEG).
EXIFVersion()Returns libexif library version string.

TExifGPS Record

FieldTypeDescription
HasGPSBooleanFalse if no GPS IFD present in file.
LatitudeDoubleDecimal degrees. Negative = South.
LongitudeDoubleDecimal degrees. Negative = West.
AltitudeDoubleMeters above sea level. Negative if below.
HeadingDoubleTrue north heading in degrees (0–360), or -1 if absent.
SpeedDoubleSpeed in km/h at capture time, or -1 if absent.
TimestampStringGPS timestamp string 'HH:MM:SS'.
DatestampStringGPS datestamp string 'YYYY:MM:DD'.

TExifCameraInfo Record

FieldTypeDescription
MakeStringCamera manufacturer (e.g. 'Apple', 'Canon', 'Sony').
ModelStringCamera model string (e.g. 'iPhone 15 Pro', 'EOS R5').
LensMakeStringLens manufacturer, if present.
LensModelStringLens model string, if present.
ISOIntegerISO speed (e.g. 100, 800, 3200).
ApertureDoubleF-number (e.g. 1.8, 4.0, 11.0).
ShutterSpeedDoubleExposure time in seconds (e.g. 0.001 = 1/1000s).
FocalLengthDoubleFocal length in mm.
FocalLength35mmInteger35mm-equivalent focal length, or 0 if absent.
ExposureModeString'Auto', 'Manual', or 'Auto bracket'.
ExposureProgramString'Normal', 'Aperture priority', 'Shutter priority', etc.
MeteringModeString'Matrix', 'Center-weighted', 'Spot', etc.

Common EXIF Tag IDs

Tag IDNameDescription
0x010FMakeCamera manufacturer string.
0x0110ModelCamera model string.
0x0112Orientation1–8 rotation/flip code.
0x011AXResolutionHorizontal resolution (DPI).
0x011BYResolutionVertical resolution (DPI).
0x0132DateTimeFile modification date/time.
0x013BArtistPhotographer name.
0x8298CopyrightCopyright string.
0x829AExposureTimeShutter speed as rational (e.g. 1/1000).
0x829DFNumberF-number (aperture) as rational.
0x8827ISOSpeedRatingsISO sensitivity value.
0x9003DateTimeOriginalOriginal capture date/time.
0x9004DateTimeDigitizedDate/time image was digitized.
0x920AFocalLengthFocal length in mm.
0xA405FocalLengthIn35mmFilm35mm-equivalent focal length.
0xA432LensSpecificationMin/max focal length and aperture.
0xA434LensModelLens model string.
0x8825GPSInfoOffset to GPS sub-IFD.
Memory management

Every LoadFromFile or LoadFromBytes call allocates a handle. Always call FreeData(exif) when finished. Handles are not garbage-collected automatically.