Skip to content

fix(panasonic): correct 7 MakerNote value conversions (Format/ValueConv/PrintConv) - #428

Merged
swackhamer merged 1 commit into
mainfrom
claude/relaxed-goldwasser-94e1a2
Aug 2, 2026
Merged

fix(panasonic): correct 7 MakerNote value conversions (Format/ValueConv/PrintConv)#428
swackhamer merged 1 commit into
mainfrom
claude/relaxed-goldwasser-94e1a2

Conversation

@swackhamer

Copy link
Copy Markdown
Collaborator

Summary

Seven Panasonic:* MakerNote tags disagreed with ExifTool on every corpus file that carries them, all under real ExifTool tag names — the "plausible-but-wrong value under a real tag name" failure mode AGENTS.md calls out.

  • AccelerometerX/Y (0x8d/0x8e): int16u on the wire, but Panasonic.pm declares Format => 'int16s'. A plain unsigned decode turned a negative reading like -3 into 65533.
  • RollAngle/PitchAngle (0x90/0x91): the special case meant to apply their ValueConv ($val/10 and -$val/10) was keyed to 0x8d/0x8e instead — the accelerometer axes — so Roll/Pitch fell through to the plain-integer path (no /10, no sign) while the accelerometers got a bogus "N.N°" degree suffix that isn't in ExifTool's output at all.
  • CameraOrientation (0x8f): registered with no decoder, so it printed the raw byte instead of Panasonic.pm's PrintConv (0 => "Normal", ...).
  • AFPointPosition (0x4d): a rational64u[2] handled as a scalar. Now reads both rationals and applies the exact PrintConv from Panasonic.pm:924-929, including the 'none'/'n/a' sentinels.
  • ClearRetouchValue (0xa3): a plain rational64u with no PrintConv, previously decoded as if it were an integer. GetRational64u's 0/0 => "undef" case (ExifTool.pm:6114-6120) is now reproduced exactly.

Note: the originally-reported 11 tags also included BurstSpeed, InternalNDFilter (already fixed in #400), and PhotoStyle, LongExposureNoiseReduction (already fixed in #413) — this PR covers the remaining 7 not addressed by those two open PRs.

Verification

Measured per-file, keyed Group1:Name, against ExifTool 13.59 over every Panasonic/Leica JPEG in the combined corpus that emits these tags:

tag                              both  match   diff
AFPointPosition                   239    239      0
AccelerometerX                     83     83      0
AccelerometerY                     83     83      0
AccelerometerZ                     83     83      0
CameraOrientation                  76     76      0
RollAngle                          76     76      0
PitchAngle                         76     76      0
ClearRetouchValue                  88     88      0

(0 mismatches, previously 100% mismatch on every file that carries each tag. Some files show 0 "both" counts due to unrelated pre-existing gaps — big-endian MakerNote byte order for a handful of bodies, "LEICA CAMERA AG" Make routing — tracked separately by #416 and #399.)

Ground truth, combined-samples/Leica/LeicaD-Lux7.jpg (exiftool -G1 -s):

AFPointPosition    : 0.5 0.5
AccelerometerX     : -3
AccelerometerY     : -178
AccelerometerZ     : 183
CameraOrientation  : Normal
RollAngle          : -1
PitchAngle         : 44.1
ClearRetouchValue  : undef

oxidex now matches all eight exactly (AccelerometerZ already matched on main).

Test plan

  • cargo test --release --lib panasonic:: — 66 passed, 0 failed
  • New ground-truth tests: test_sprintf_g, test_format_rational64u, test_decode_af_point_position, test_matches_exiftool_on_leica_d_lux7_bytes (exact MakerNote bytes), test_matches_exiftool_on_panasonic_fz80_zero_values
  • cargo fmt --all
  • cargo clippy --release --lib -- -D warnings — clean
  • Corpus-wide comparison against ExifTool 13.59 (see above) — zero regressions on the matched set

🤖 Generated with Claude Code

…nv/PrintConv)

Seven Panasonic MakerNote tags disagreed with ExifTool on every file
that carries them, all under real ExifTool tag names:

- AccelerometerX/Y (0x8d/0x8e): int16u on the wire, but Panasonic.pm
  declares Format => 'int16s'. A plain unsigned decode turned a
  negative reading like -3 into 65533.
- RollAngle/PitchAngle (0x90/0x91): the special case that was supposed
  to apply their ValueConv ('$val/10' and '-$val/10') was keyed to
  0x8d/0x8e instead -- the accelerometer axes -- so Roll/Pitch fell
  through to the plain-integer path (no /10, no sign) while the
  accelerometers got a bogus "N.N°" degree suffix that isn't in
  ExifTool's output at all.
- CameraOrientation (0x8f): registered with no decoder, so it printed
  the raw byte instead of Panasonic.pm's PrintConv (0 => "Normal", ...).
- AFPointPosition (0x4d): a rational64u[2] handled as a scalar. Now
  reads both rationals and applies the exact PrintConv from
  Panasonic.pm:924-929, including the 'none'/'n/a' sentinels.
- ClearRetouchValue (0xa3): a plain rational64u with no PrintConv,
  previously decoded as if it were an integer. GetRational64u's
  0/0 => "undef" case (ExifTool.pm:6114-6120) is now reproduced exactly.

Verified per-file, keyed Group1:Name, against ExifTool 13.59 over
every Panasonic/Leica JPEG in the combined corpus that already emits
these tags: 0 mismatches (previously 100% mismatch on every one).
Ground truth, combined-samples/Leica/LeicaD-Lux7.jpg
(`exiftool -G1 -s`):

  AFPointPosition    : 0.5 0.5
  AccelerometerX      : -3
  AccelerometerY      : -178
  AccelerometerZ      : 183
  CameraOrientation   : Normal
  RollAngle           : -1
  PitchAngle          : 44.1
  ClearRetouchValue   : undef

oxidex now matches all eight exactly (AccelerometerZ already matched).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@swackhamer
swackhamer force-pushed the claude/relaxed-goldwasser-94e1a2 branch from 56036fb to 4b9c6c4 Compare August 2, 2026 09:38
@swackhamer
swackhamer merged commit fd0a8cb into main Aug 2, 2026
6 of 7 checks passed
@swackhamer
swackhamer deleted the claude/relaxed-goldwasser-94e1a2 branch August 2, 2026 09:39
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