Skip to content

Round-trip transform, crs, and tag metadata through to_geotiff/open_geotiff#1494

Merged
brendancol merged 1 commit intomainfrom
issue-1484
May 5, 2026
Merged

Round-trip transform, crs, and tag metadata through to_geotiff/open_geotiff#1494
brendancol merged 1 commit intomainfrom
issue-1484

Conversation

@brendancol
Copy link
Copy Markdown
Contributor

Closes #1484. Findings M-1 through M-4 from the geotiff metadata audit, mirroring the polish from #1462 (reproject) and #1472 (resample).

Summary

  • attrs['transform'] (rasterio 6-tuple (pixel_width, 0, origin_x, 0, pixel_height, origin_y)) is now stored on every read path. to_geotiff prefers it over _coords_to_transform, which can drift on fractional pixel sizes because x[1] - x[0] is recomputed from already-rounded coord arrays. Coord-derived transform stays as the fallback when the attr is absent.
  • The int-EPSG convention for attrs['crs'] is now documented in open_geotiff and read_vrt. WKT strings are still tolerated on the write side for backward compatibility.
  • ColorMap (tag 320) drops out of _MANAGED_TAGS so it rides extra_tags and round-trips without dedicated writer plumbing. The raw uint16 value lands on attrs['colormap'].
  • ImageDescription (tag 270) and ExtraSamples (tag 338) get friendly attrs['image_description'] / attrs['extra_samples'] entries. to_geotiff folds user-edited values back into extra_tags before write, with any verbatim entries winning so byte-stable round-trips stay byte-stable.
  • The integer-with-nodata to float64 promotion is now documented in the open_geotiff docstring along with the dtype=... override.

Test plan

  • pytest xrspatial/geotiff/tests/test_metadata_round_trip_1484.py (10 new tests, all pass)
  • pytest xrspatial/geotiff/tests/ (483 passed, 4 skipped, 3 deselected; the 3 deselected TestPalette::test_xrs_plot_* tests were already failing on main with a matplotlib deepcopy recursion unrelated to this PR)
  • pytest xrspatial/tests/test_resample.py xrspatial/tests/test_reproject.py (362 passed) -- confirms the new attrs['transform'] does not break callers that compare result attrs

Notes

  • ExtraSamples is sometimes auto-emitted by the writer for multi-band photometric layouts; the existing existing_ids guard in the writer's extra_tags loop already deduplicates so the friendly attr round-trip stays consistent.
  • ColorMap on the write side now goes through the generic extra_tags pass-through. Adding a writer-managed ColorMap path with full validation would be a heavier lift; that's out of scope here.

…eotiff (#1484)

Findings M-1 through M-4 from the geotiff metadata audit.

- attrs['transform'] (rasterio 6-tuple) now lands on every read path so
  to_geotiff can rebuild the source GeoTransform without going through
  _coords_to_transform. That route can drift on fractional pixel sizes
  because x[1] - x[0] is recomputed in float64 from already-rounded
  coords. Coord-derived transform stays as the fallback when the attr
  is absent.
- Document the int-EPSG convention for attrs['crs'] in open_geotiff and
  read_vrt; keep tolerating WKT strings on the write side.
- Drop ColorMap (320) from _MANAGED_TAGS so the tag rides extra_tags
  and round-trips without a dedicated writer path. Surface the raw
  uint16 ColorMap value as attrs['colormap'].
- Surface ImageDescription (270) as attrs['image_description'] and
  ExtraSamples (338) as attrs['extra_samples']. to_geotiff folds
  user-edited values back into extra_tags before write, with verbatim
  entries winning to keep round-trips byte-stable.
- Document the int-with-nodata -> float64 promotion in open_geotiff's
  docstring along with the dtype= override.

Tests added in test_metadata_round_trip_1484.py cover transform double
round-trip on a fractional transform, ColorMap on a uint8 indexed
raster, ImageDescription read and write, ExtraSamples surface, and the
uint16 nodata promotion plus the dtype='uint16' ValueError.

Mirrors the polish from #1462 (reproject) and #1472 (resample).

Closes #1484
@github-actions github-actions Bot added the performance PR touches performance-sensitive code label May 5, 2026
@brendancol brendancol merged commit 69b873a into main May 5, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

performance PR touches performance-sensitive code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Round-trip transform, crs, and tag metadata through to_geotiff/open_geotiff

1 participant