fix(exif): FileSource reaches its PrintConv instead of the blob renderer - #405
Merged
Conversation
`ExifIFD:FileSource` printed `(Binary data 1 bytes, use -b option to
extract)` in 2,874 of the 4,238 sample-corpus files -- in every output
mode, `-j`, `-e -j` and human alike -- where ExifTool prints a label.
The decoder was never missing. `exiftool_compat`'s 0xa300 arm has always
been correct; it simply never ran. Exif.pm declares the tag
`Writable => 'undef'`, so the TIFF reader hands the value over as
`TagValue::Binary([3])` and the arm's `value.as_integer()` is `None` for
a blob. Three further transcriptions of the same table existed elsewhere
in the tree, none of them on this path.
ExifTool resolves the same mismatch one layer earlier: `ProcessExif`
rewrites the format of any one-element UNDEFINED value to `int8u`
(Exif.pm:6682, "treat single unknown byte as int8u"), which is the only
reason a PrintConv hash keyed `1, 2, 3` can match a stored `"\x03"` at
all -- `exiftool -FileSource#` returns the string "3", not the byte 0x03.
The binary arm reproduces that lookup for this tag rather than changing
how every UNDEFINED value in the tree is read.
Four copies of Exif.pm 0xa300's PrintConv are now one,
`core::formatters::exif_enums::file_source_label{,_bytes}`, dumped from
the loaded Perl symbol table rather than read off the source. They had
already drifted: only the RAW copy carried the hash's one non-integer
key, `"\3\0\0\0" => 'Sigma Digital Camera'`, and
`binary_decoders::decode_file_source` read `data[0]` and answered
`Digital Camera` for it -- with a test asserting exactly that, under the
comment "Extra bytes should be ignored".
Measured per file, keyed `Group1:Name`, against ExifTool 13.59 over the
4,238-file corpus (oxidex reads 4,104 of them):
matched set +2,874 / -0
files 2,874 improved, 0 regressed
keys changed ExifIFD:FileSource, and nothing else
Composite:* 0 values changed
All five label classes ExifTool emits for this corpus now agree:
`Digital Camera` (2,848), `Reflection Print Scanner` (33),
`Unknown (0)` (4, e.g. GPS.jpg), `Film Scanner` (CanonCanoScan8800F.jpg)
and `Sigma Digital Camera` (Sigma.jpg, `undef[4]` = `03 00 00 00`).
The two files still short of ExifTool -- LeicaM.jpg and LeicaS2.jpg --
do not emit the tag at all; that is a separate MISSING-class gap in the
Leica path, not a value divergence.
Mutation-tested: restoring the integer-only arm fails
`file_source_reaches_the_print_conv_from_the_binary_form` with
`Binary([1])` unconverted, and restoring the `data[0]` lookup fails
`test_file_source_sigma_four_byte_form` with `Digital Camera`. The three
pre-existing FileSource tests pass against both.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
swackhamer
enabled auto-merge (squash)
August 2, 2026 03:47
# Conflicts: # src/core/exiftool_compat.rs # src/core/formatters/mod.rs # src/parsers/pdf/mod.rs # src/parsers/raw/metadata.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ExifIFD:FileSourceprinted(Binary data 1 bytes, use -b option to extract)in 2,874 of the 4,238 sample-corpus files -- in every output mode,-j,-e -jand human alike -- where ExifTool prints a label.Root cause
The decoder was never missing.
exiftool_compat's 0xa300 arm has always been correct; it simply never ran. Exif.pm declares the tagWritable => 'undef', so the TIFF reader hands the value over asTagValue::Binary([3])and the arm'svalue.as_integer()isNonefor a blob. Three further transcriptions of the same table existed elsewhere in the tree, none of them on this path.ExifTool resolves the same mismatch one layer earlier.
ProcessExifrewrites the format of any one-element UNDEFINED value toint8u:That single line is the only reason a PrintConv hash keyed
1, 2, 3can match a stored"\x03"at all --exiftool -FileSource#returns the string3, not the byte0x03. The binary arm reproduces that lookup for this tag rather than changing how every UNDEFINED value in the tree is read.Consolidation
Four copies of Exif.pm 0xa300's PrintConv are now one,
core::formatters::exif_enums::file_source_label{,_bytes}-- dumped from the loaded Perl symbol table rather than read off the source. They had already drifted: only the RAW copy carried the hash's one non-integer key,and
binary_decoders::decode_file_sourcereaddata[0], answeringDigital Camerafor it -- with a test asserting exactly that, under the comment "Extra bytes should be ignored".Measurement
Per file, keyed
Group1:Name, against ExifTool 13.59 over the 4,238-file corpus (oxidex reads 4,104 of them). JSON parsed withparse_float=str; files keyed on full relative path.ExifIFD:FileSource, and nothing elseComposite:*All five label classes ExifTool emits for this corpus now agree:
Digital Camera(2,848),Reflection Print Scanner(33),Unknown (0)(4, e.g.GPS.jpg),Film Scanner(CanonCanoScan8800F.jpg) andSigma Digital Camera(Sigma.jpg,undef[4]=03 00 00 00).The two files still short of ExifTool --
LeicaM.jpgandLeicaS2.jpg-- do not emit the tag at all. That is a separate MISSING-class gap in the Leica path, not a value divergence.Mutation test
Restoring the integer-only arm fails
file_source_reaches_the_print_conv_from_the_binary_formwithBinary([1])unconverted. Restoring thedata[0]lookup failstest_file_source_sigma_four_byte_formwithDigital Camerawhere ExifTool saysSigma Digital Camera. The three pre-existing FileSource tests pass against both old and new behaviour, which is why they never caught this.🤖 Generated with Claude Code