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=2for 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 rewritesmoovand skips deletions,
while a HEIF keeps its EXIF and XMP as items of themetabox: every edit
was dropped andwrite_infostill reported each request as written. The
new writer edits the primary image's Exif and XMP items the way ExifTool's
WriteItemInfodoes. 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
iniloc(field sizes 0, 4 and 8, base offsets, several extents, versions
0 to 2, data inmdatoridat) 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:XMPToolkitnames 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 thecolr,pixiandclapitem properties
(ColorProfiles, ColorPrimaries, ..., ImagePixelDepth, CleanAperture); a
file whose major brand isheicis typed HEIC (image/heic), as
ExifTool types it. XMP GPS coordinates print as ExifTool prints them
(51 deg 30' 2.52" N, not51,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_inforeturns 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:allandXMP:alldelete 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:alldeletes 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 withXMP:all), and each tag
goes to the namespace ExifTool picks, from a table generated from its
sources (XMP:Descriptionwent toxmpinstead ofdc). 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, asSetNewValuedoes. - 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,
andstco/co64chunk offsets are relocated. ID3 frames are edited in
place (v2.2 to 2.4, ID3v1 kept in sync, AIFFID3chunk); 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_infoand 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
returningOkwith 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 --dumpemits the write results after the read TSV, and
--dump-writeemits 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_editedits 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_editedits an XMP packet in place.formats::heif_itemsparses the HEIF item tables (iinf,iloc,iref,
ipma,idat).- A
write_heiffuzz target.
Full Changelog: v0.9.0...v0.10.0