Skip to content

fix(exif): FileSource reaches its PrintConv instead of the blob renderer - #405

Merged
swackhamer merged 2 commits into
mainfrom
fix/exif-filesource-print-conv
Aug 2, 2026
Merged

fix(exif): FileSource reaches its PrintConv instead of the blob renderer#405
swackhamer merged 2 commits into
mainfrom
fix/exif-filesource-print-conv

Conversation

@swackhamer

Copy link
Copy Markdown
Collaborator

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.

Root cause

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:

# treat single unknown byte as int8u
$formatStr = 'int8u' if $format == 7 and $count == 1;   # Exif.pm:6682

That single line 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.

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,

# handle the case where Sigma incorrectly gives this tag a count of 4
"\3\0\0\0" => 'Sigma Digital Camera',

and binary_decoders::decode_file_source read data[0], answering Digital Camera for 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 with parse_float=str; files keyed on full relative path.

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 test

Restoring the integer-only arm fails file_source_reaches_the_print_conv_from_the_binary_form with Binary([1]) unconverted. Restoring the data[0] lookup fails test_file_source_sigma_four_byte_form with Digital Camera where ExifTool says Sigma 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

`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
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
@swackhamer
swackhamer merged commit 7993375 into main Aug 2, 2026
6 of 7 checks passed
@swackhamer
swackhamer deleted the fix/exif-filesource-print-conv branch August 2, 2026 08:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant