github Le-Syl21/exiftool-rs v0.10.0

4 hours ago

Every write now really lands. The parity report gained a write section that edits every corpus file with exiftool-rs and with ExifTool 13.59, then re-reads both outputs: 418 of 460 cases are identical to ExifTool (29 before), with no silent no-op, refused write or broken file left. Reads are unchanged: 199/199 files identical. This started with issue #17 (HEIF/HEIC/AVIF writes silently doing nothing). Minor bump: some writer signatures changed.

Report: https://le-syl21.github.io/exiftool-rs/#write

Changed

  • Breaking: the format writers in writer (TIFF, PNG, GIF, PDF, PSD, WebP,
    JP2/JXL and others) take new arguments, and a raw value such as
    ColorSpace=2 for a conversion with no fallback is now rejected, as
    ExifTool rejects it.
  • Dependencies updated; the GUI uses egui and eframe 0.37.

Fixed

  • HEIF, HEIC and AVIF files can now really be written (#17). The writer used
    to hand them to the MP4 writer, which rewrites moov and skips deletions,
    while a HEIF keeps its EXIF and XMP as items of the meta box: every edit
    was dropped and write_info still reported each request as written. The
    new writer edits the primary image's Exif and XMP items the way ExifTool's
    WriteItemInfo does. It sets, adds and deletes single tags, deletes whole
    groups (EXIF:all, XMP:all, GPS:all, ExifIFD:all, XMP-dc:all,
    all), creates a missing Exif or XMP item, and relocates every other item
    in iloc (field sizes 0, 4 and 8, base offsets, several extents, versions
    0 to 2, data in mdat or idat) along with the chunk offsets of any
    track. The coded image and its properties are copied byte for byte.
    Against ExifTool 13.59, the reporter's 16 deletions, -EXIF:all= -XMP:all=, -GPS:all=, edits of Make, Artist and the GPS position, and
    adding EXIF, GPS or XMP to a file without them give the same tags and
    values on the reporter's file and on AVIF samples; libheif decodes every
    output to the same pixels.
    Differences from ExifTool: an item whose metadata is all deleted is
    removed (ExifTool keeps it, empty), and deleted bytes are zeroed;
    XMP-x:XMPToolkit names exiftool-rs; ExifTool's 2 KB of XMP padding is
    not added.
  • Reading HEIF/AVIF now extracts the Exif and XMP items (it extracted
    neither) and the colr, pixi and clap item properties
    (ColorProfiles, ColorPrimaries, ..., ImagePixelDepth, CleanAperture); a
    file whose major brand is heic is typed HEIC (image/heic), as
    ExifTool types it. XMP GPS coordinates print as ExifTool prints them
    (51 deg 30' 2.52" N, not 51,30.042N), and the XMP Composite
    GPSLatitudeRef/GPSLongitudeRef are built. The reporter's file and the two
    new AVIF samples now read identically to ExifTool 13.59.
  • write_info returns the number of requests that took effect, checked by
    reading the output back: a written tag must be there with its value, a
    deleted tag or group must be gone. It used to return the number of queued
    requests whatever happened. When none of them can be applied to the file
    type, it now fails and writes nothing.
  • EXIF:all and XMP:all delete the group in JPEG and WebP too; only the
    EXIF:* spelling did.
  • Writing an XMP sidecar edits the packet in place instead of replacing it
    with the written properties alone, so the rest of the file survives.
  • Every write now really lands, checked end to end by the parity audit's
    write matrix: 418 of 460 cases are identical to ExifTool 13.59, up from
    29, with no silent no-op, refused write or broken file left (114 silent
    no-ops and 64 broken files before). The other 37 cases have no Perl
    reference (ExifTool does not write ID3, Vorbis comments or Matroska, and
    refuses the truncated NEF/ARW samples) and are checked by re-reading
    alone. 5 known mismatches remain, all on files damaged at the source:
    GE.jpg, whose bogus maker-note offsets ExifTool repairs by rebuilding the
    maker note while we keep it as it is, and a Ricoh.jpg value that points at
    layout-dependent bytes.
  • JPEG: EXIF is edited in place instead of rebuilt, keeping the byte order,
    IFD1 and its thumbnail, the Interop IFD and valid maker-note offsets
    (Perl used to warn "Invalid PrintIM header" or "Bad ExifIFD directory" on
    our output). GPS tags are written, GPS:all deletes the GPS IFD, an
    unqualified delete only reaches the tag's write group, and a new EXIF
    block takes its resolution from JFIF, as ExifTool does. AFCP and MPF
    offsets follow any change in size.
  • IPTC: the encoder is a port of ExifTool's DoWriteIPTC, so the record
    bytes and the digest match ExifTool's. Only the IPTC resource of the
    Photoshop block is edited; the other resources and IPTCDigest were lost.
    Times without a zone use the local zone and "Latin" text is cp1252, as in
    ExifTool. IPTC in AFCP, FotoStation, PhotoMechanic and MIE trailers is
    edited along the whole trailer chain.
  • XMP: packets are edited in place everywhere (including UTF-16 packets and
    extended XMP, which is merged and removed with XMP:all), and each tag
    goes to the namespace ExifTool picks, from a table generated from its
    sources (XMP:Description went to xmp instead of dc). The inverse
    conversions of the XMP tables are ported, so the 54 tags we refused are
    written. An ungrouped tag is created in its preferred family and replaced
    wherever another family already holds it, as SetNewValue does.
  • TIFF and TIFF-based RAW (DNG, CR2, NEF, ARW) can add and delete tags, not
    only replace existing ones; image data stays at its offsets.
  • PNG text chunks are replaced instead of duplicated and can be deleted;
    EXIF and XMP go to their own chunks. GIF comments are found by walking
    the block structure. PDF edits are written as an incremental update, as
    ExifTool does, instead of splicing bytes and breaking the xref table.
    PSD, WebP, JP2 and JXL edit their existing EXIF, IPTC and XMP instead of
    rebuilding them from the new values alone.
  • QuickTime (MOV, MP4, M4A): deletions are applied, other ItemList tags
    are kept, UserData and Keys are edited, XMP goes where ExifTool reads it,
    and stco/co64 chunk offsets are relocated. ID3 frames are edited in
    place (v2.2 to 2.4, ID3v1 kept in sync, AIFF ID3 chunk); FLAC and
    Ogg (Vorbis, Opus, FLAC) comments are edited, re-paged and re-checksummed;
    Matroska writes its title and tags and keeps its index consistent.
  • Reading: maker-note tables are chosen as ExifTool chooses them once Make,
    Model or Software are changed or deleted (they come from IFD0 only, and a
    missing value reads as empty), with Canon, Nikon, Pentax, Ricoh and Sony
    model conditions ported. MIE trailer directories are decoded, PDF
    reading uses the last revision, and empty ID3v1 fields read as ExifTool
    reads them.

Added

  • The parity audit now checks writes end to end, and the
    parity report has a Write
    section. Every corpus file whose type exiftool-rs writes gets a small,
    deterministic set of edits (set, add and delete a tag, delete a whole
    EXIF, GPS, XMP or IPTC group, and a mixed edit), applied both with
    write_info and with Perl ExifTool. Both outputs are re-read by Perl
    ExifTool and by exiftool-rs, and each case checks the requested state,
    equality with Perl's output, agreement between the two readers, and that
    the file still reads without a new error or warning. write_info
    returning Ok with nothing changed, the pattern of issue #17, is
    reported as a silent no-op. Known failures are recorded in
    tests/parity_write_baseline.txt, and the release gate fails on a new
    one. parity --dump emits the write results after the read TSV, and
    --dump-write emits them alone. The four IPTC write cases the audit
    had before are part of the matrix, now compared on every tag rather than
    on the IPTC block alone.
  • writer::exif_edit edits an EXIF block in place, keeping what it is not
    asked to change (IFD1, Interop IFD, maker notes and their offsets), and
    follows ExifTool's mandatory-tag rules: a directory left with only its
    mandatory tags after a deletion is dropped, and a new one gets them.
  • writer::xmp_edit edits an XMP packet in place.
  • formats::heif_items parses the HEIF item tables (iinf, iloc, iref,
    ipma, idat).
  • A write_heif fuzz target.

Full Changelog: v0.9.0...v0.10.0

Don't miss a new exiftool-rs release

NewReleases is sending notifications on new releases.