Library

TinyEXIF 1.2.0

Version1.2.0
Stars★ 148
Released2026-10-01

Tiny ISO-compliant C++ EXIF and XMP parsing library for JPEG.

Release notes

### Added
- `MaxApertureValue` (EXIF 0x9205), the widest aperture of the lens, as an
  f-number like `ApertureValue`, with `FIELD_ID_MaxApertureValue`.
- DJI XMP flight speed (`drone-dji:FlightXSpeed`/`YSpeed`/`ZSpeed`) now fills
  `GeoLocation.SpeedX/Y/Z` when the DJI MakerNote has not, as on cameras that
  write no MakerNote speed (e.g. the Osmo 360). The MakerNote, being binary,
  still takes precedence.
- Multi-Picture Format (MPF, CIPA DC-007) index: `MPImages` lists the images a
  JPEG stores after its own, such as the preview of a panorama, the second view
  of a stereo (`.MPO`) image or an HDR gain map, with the type, flags, offset
  and length of each (`FIELD_ID_MPImages`). They are only located, never read;
  the README shows how to read one safely and parse it in turn. To reach the
  index, the scan no longer stops as soon as it has EXIF and XMP: it goes on to
  the image data, skipping any further EXIF or XMP segment as before.
- The README now documents every feature. That covers the input sources and
  return codes, and a reference of every field with the EXIF tag or XMP
  property it comes from. It also covers the presence API, MPF, the guarantees
  for untrusted files, building with CMake or vcpkg, and testing. The header
  comments of `ShutterSpeedValue`, an exposure time in seconds, and of
  `LensInfo.FStopMin`/`FStopMax`, the widest aperture at each end of the zoom
  range, described other values.

### Fixed
- Shared-library ABI identity now changes with the new `EXIFInfo` layout: ABI
  version 2 on Linux/macOS, and `TinyEXIF-2.dll` on Windows. Consumers must
  rebuild with the 1.2.0 header; old binaries must not load the new library.
- XMP flight speed fills each missing component individually, preserving a
  finite DJI MakerNote speed even when another component is absent or invalid.
- MPF entry byte counts must describe complete 16-byte entries; a truncated
  count is rejected rather than rounded down to an apparently valid index.
- The release workflow now runs the sample corpus for the tagged build before
  publishing the release.
- `BUILD_FUZZER=ON` now links the coverage runtime for the demo and shared
  library too, so the documented build works with the demo enabled.
- **A GPS receiver without a fix no longer yields a position.** Cameras write
  the position tags even then, usually all zeros, which placed the image at
  0°N 0°E. With `GPSStatus` `V` (measurement void) latitude, longitude and
  altitude are now left absent, as is the DJI XMP `AbsoluteAltitude` when
  `drone-dji:GpsStatus` is `Invalid`.
- A latitude, longitude or altitude of 0 with a south, west or below-sea-level
  reference read back as IEEE 754 `-0`, which prints as "-0".
- A DJI MakerNote was skipped entirely, speeds and camera angles included, in
  files whose EXIF was rewritten in Motorola byte order: DJI writes the
  MakerNote little-endian and editors copy it unchanged, so its byte order is
  now detected rather than taken from the TIFF header.
- **Big-endian CPUs could not parse EXIF at all.** The "Big-endian CPU
  support" of 1.0.3 (#14) combined the TIFF byte-order marker with the host's
  byte order, but `parse16()`/`parse32()` assemble values byte by byte and were
  already host-independent, so on a big-endian host both `II` and `MM` were
  inverted: `II` files failed with `PARSE_CORRUPT_DATA` and `MM` files decoded
  corrupted values. The marker now selects the file's byte order alone.
  Little-endian hosts are unaffected. A new CI job runs the full corpus on
  s390x under QEMU. Reported by @cinema-ONE. (#29)
- gcc 16 `-Wmaybe-uninitialized` warnings on the six fetch-into-temporary
  sites. Rather than initializing each temporary, they are gone: the new
  `EntryParser::FetchAs<T>()` fetches a value stored as one type into a member
  of another, and also replaces `FetchFloat()`. Builds with
  `TINYEXIF_NO_XMP_SUPPORT` no longer warn about the XMP-only string helpers.
  A new CI job compiles with gcc 16 `-Wall -Wextra -We…

Share this resource


Discovered 2026-10-02 Source GitHub Archive 2026-10 →