Skip to content

fix gps metadata being stripped from exports (#1165)#1207

Open
Waynting wants to merge 1 commit into
CyberTimon:mainfrom
Waynting:fix/1165-gps-export-preserved
Open

fix gps metadata being stripped from exports (#1165)#1207
Waynting wants to merge 1 commit into
CyberTimon:mainfrom
Waynting:fix/1165-gps-export-preserved

Conversation

@Waynting
Copy link
Copy Markdown

Summary

Fixes #1165. GPS EXIF (location data) was always being stripped on export, even with Remove location data turned off.

Root cause

write_image_with_metadata has three branches for sourcing the original image's metadata: the .rrdata sidecar, kamadak-exif (JPEG/PNG), and rawler (RAW). Only the kamadak and rawler branches had GPS-reading code.

Opening any image in the app triggers persist_exif_if_missing (image_loader.rs:81), which writes the .rrdata sidecar. From then on the sidecar branch fires on every export — silently bypassing both GPS code paths. So in practice strip_gps=false did nothing for any image you'd opened in the editor.

Affects JPEG (as reported) and RAW (same mechanism, just less likely to be noticed).

Fix

GPS reading is orthogonal to the rest of the metadata sourcing. Lifted GPS reading out of the per-branch logic into two helpers and added a single tail call that runs unconditionally when !strip_gps:

if !strip_gps {
    if is_raw_file(original_path_str) {
        apply_gps_from_rawler(&mut metadata, original_path_str);
    } else {
        apply_gps_from_kamadak(&mut metadata, original_path);
    }
}

The sidecar / kamadak / rawler branches now handle only the non-GPS metadata they always did. GPS is re-read from the source file rather than parsed back from the sidecar's display strings (lossy — "40 deg 26' 12.345\"" can't round-trip cleanly into the rationals little_exif needs).

Behavior table

Before After
JPEG + sidecar + strip_gps=false ❌ stripped ✅ preserved
JPEG + sidecar + strip_gps=true ✅ stripped ✅ stripped
RAW + sidecar + strip_gps=false ❌ stripped ✅ preserved
RAW + sidecar + strip_gps=true ✅ stripped ✅ stripped
TIFF output / keep_metadata=false (early return) (early return — unchanged)

Tests

Added two regression tests in exif_processing::tests. No new dependencies — tempfile, image, little_exif, kamadak-exif are all already in the project.

  • issue_1165_gps_preserved_when_sidecar_exists_and_strip_gps_false — reproduces the exact bug trigger (real GPS tags + .rrdata sidecar via persist_exif_if_missing), asserts GPS lat/lon/alt are preserved in the exported bytes.
  • issue_1165_gps_stripped_when_strip_gps_true — asserts the toggle still works.

Both pass:

test exif_processing::tests::issue_1165_gps_stripped_when_strip_gps_true ... ok
test exif_processing::tests::issue_1165_gps_preserved_when_sidecar_exists_and_strip_gps_false ... ok

Also verified:

  • cargo fmt --check clean on the file
  • cargo clippy --lib --tests --no-deps — no new warnings introduced

Notes

  • Bonus: the kamadak helper now also writes GPSAltitudeRef (above/below sea-level reference). The rawler branch already wrote it; added for symmetry. Harmless if downstream readers don't expect it.
  • Follow-up not done here: get_string_val closure is now defined in two places (the helper + the inline kamadak branch). Kept this PR narrow; happy to lift it to a module-level helper in a follow-up if you'd like.

Test plan

  • cargo test --lib exif_processing::tests
  • cargo fmt -- --check src/exif_processing.rs
  • cargo clippy --lib --tests --no-deps
  • Manual: open a GPS-tagged JPEG, export with "Remove location data" off → exiftool -GPS:all exported.jpg shows coords
  • Manual: same with the toggle on → no GPS tags in output

write_image_with_metadata has three branches for sourcing the original
image's metadata: the .rrdata sidecar, kamadak-exif, and rawler. Only the
kamadak and rawler branches had GPS-reading code. Opening any image
triggers persist_exif_if_missing, which writes a sidecar -- from then on
the sidecar branch fires on every export, silently bypassing both GPS
code paths. Affects JPEG (as reported) and any RAW the user has opened.

Lift GPS reading into two helpers (apply_gps_from_kamadak,
apply_gps_from_rawler) and run them at the tail of the function,
unconditionally when !strip_gps. The sidecar/kamadak/rawler branches now
handle only the non-GPS metadata they always did. Re-read GPS from the
source file rather than parsing the lossy display strings stored in the
sidecar.

Add two regression tests using only existing project deps (tempfile,
image, little_exif, kamadak-exif). The first reproduces the bug trigger
(real GPS + .rrdata sidecar) and asserts GPS is preserved; the second
asserts the strip toggle still works.

Bonus: kamadak helper now also writes GPSAltitudeRef -- the rawler
branch already did this, added for symmetry.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Waynting Waynting requested a review from CyberTimon as a code owner May 24, 2026 14:42
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.

BUG: Location data stripped from exported JPEG

1 participant