Skip to content

geotiff: route write_vrt dtype through central resolver#1919

Merged
brendancol merged 1 commit into
mainfrom
fix-vrt-12bit-dtype-2026-05-15
May 15, 2026
Merged

geotiff: route write_vrt dtype through central resolver#1919
brendancol merged 1 commit into
mainfrom
fix-vrt-12bit-dtype-2026-05-15

Conversation

@brendancol
Copy link
Copy Markdown
Contributor

Summary

Fixes #1914. write_vrt built the VRT dataType attribute from a local if/elif/else ladder keyed on sample_format and bps. For bps=12, sf=1 it fell through to 'Byte', even though the reader path in _dtypes.py promotes the same sample to uint16. A VRT over a valid 12-bit unsigned source advertised a narrower type than the actual data, which can cause downstream GDAL/VRT readers to truncate values above 255.

The ladder also defaulted to 'Byte' / 'Int32' for any other unknown bps, silently mis-typing future bit widths.

Changes

  • Add _vrt_dtype_name_for(bps, sample_format) to xrspatial/geotiff/_vrt.py. It calls tiff_dtype_to_numpy (the central TIFF-to-numpy resolver) and looks up the GDAL name in the existing _NP_TO_VRT_DTYPE table. A numpy dtype with no GDAL mapping raises ValueError instead of falling back to Byte.
  • Replace the if/elif/else ladder in write_vrt with a single call to the helper.
  • Add xrspatial/geotiff/tests/test_vrt_dtype_12bit_1914.py covering every supported (bps, sample_format) pair (sub-byte, 12-bit, 8/16/32/64-bit integer, 32/64-bit float), the regression case explicitly, and an end-to-end run via write_vrt on uint16 and int16 source TIFFs.

Test plan

  • python -m pytest xrspatial/geotiff/tests/test_vrt_dtype_12bit_1914.py -x -q (20 passed)
  • python -m pytest xrspatial/geotiff/tests/ -q -k "vrt or VRT" (all VRT tests pass; pre-existing GPU and tile-size failures on main are unrelated)
  • No files touched outside xrspatial/geotiff/

write_vrt built the VRT dataType attribute from a local if/elif/else
ladder keyed on sample_format and bps. The ladder had no entry for
bps=12, so unsigned 12-bit TIFF sources were tagged as Byte in the
VRT header. The reader path promotes those samples to uint16, so
downstream GDAL/VRT consumers could truncate values above 255.

Replace the ladder with _vrt_dtype_name_for, which calls
tiff_dtype_to_numpy and then looks up the GDAL name in the existing
_NP_TO_VRT_DTYPE table. A numpy dtype with no GDAL mapping now
raises ValueError instead of falling back to Byte. The helper is
exposed at module scope so the dtype path can be unit-tested without
writing a 12-bit TIFF to disk.
Copilot AI review requested due to automatic review settings May 15, 2026 13:29
@github-actions github-actions Bot added the performance PR touches performance-sensitive code label May 15, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Replaces a local dtype ladder in write_vrt with a helper that funnels TIFF bps/sample_format through the central tiff_dtype_to_numpy resolver, fixing the case where 12-bit unsigned sources were incorrectly tagged as Byte in the VRT.

Changes:

  • Add _vrt_dtype_name_for(bps, sample_format) helper in _vrt.py that resolves via tiff_dtype_to_numpy and maps through _NP_TO_VRT_DTYPE, raising ValueError on unsupported types.
  • Replace the if/elif/else dtype ladder in write_vrt with a single helper call.
  • Add regression tests covering all supported (bps, sample_format) pairs and end-to-end write_vrt runs on uint16/int16 sources.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
xrspatial/geotiff/_vrt.py Introduces _vrt_dtype_name_for helper and routes write_vrt dtype resolution through it.
xrspatial/geotiff/tests/test_vrt_dtype_12bit_1914.py Adds regression and end-to-end tests for VRT dtype mapping including the 12-bit case.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@brendancol brendancol merged commit 333dbb0 into main May 15, 2026
15 of 16 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.

geotiff: write_vrt misrepresents 12-bit unsigned TIFF as Byte

2 participants