Skip to content

Reject compression='jpeg' in to_geotiff (no JPEGTables)#1514

Open
brendancol wants to merge 1 commit intoxarray-contrib:mainfrom
brendancol:fix-jpeg-tiff-disable
Open

Reject compression='jpeg' in to_geotiff (no JPEGTables)#1514
brendancol wants to merge 1 commit intoxarray-contrib:mainfrom
brendancol:fix-jpeg-tiff-disable

Conversation

@brendancol
Copy link
Copy Markdown
Contributor

Summary

Pass-8 accuracy sweep finding. The JPEG-in-TIFF write path tags compression=7 (new-style JPEG) but writes a self-contained JFIF stream per tile/strip and never emits the JPEGTables tag (347) that the TIFF spec requires for that codec. libtiff, GDAL, and rasterio all reject the file with TIFFReadEncodedStrip() failed. Our reader round-trips because Pillow decodes the standalone JFIF bytes directly, which masks the break. The user thinks they wrote a TIFF; nothing else can read it.

Repro:
```python
import numpy as np, xarray as xr, rasterio
from xrspatial.geotiff import to_geotiff
arr = np.zeros((32, 32, 3), dtype=np.uint8); arr[..., 0] = 200
da = xr.DataArray(
arr, dims=['y','x','band'],
coords={'y': np.arange(32), 'x': np.arange(32), 'band': [0,1,2]},
attrs={'crs': 4326},
)
to_geotiff(da, '/tmp/x.tif', compression='jpeg', tiled=False)
rasterio.open('/tmp/x.tif').read() # CPLE_AppDefinedError: TIFFReadEncodedStrip() failed
```

Fix: reject compression='jpeg' at the to_geotiff entry point with a clear ValueError pointing at deflate/zstd/lzw. The lower-level _writer.write is untouched so the existing self-decoding tests still cover the codec until someone wires up a JPEGTables-aware encoder.

Test plan

  • new test_to_geotiff_jpeg_rejected covers the user-facing error
  • existing _writer.write JPEG round-trip tests pass unchanged
  • full geotiff suite: 671 passed, 4 skipped (3 unrelated matplotlib deepcopy failures predate this change)

The JPEG-in-TIFF write path tags compression=7 (new-style JPEG) but
writes a self-contained JFIF stream per tile/strip and never emits the
JPEGTables tag (347) that the TIFF spec requires for that codec.
libtiff, GDAL, and rasterio all reject the file with
"TIFFReadEncodedStrip() failed". The internal reader round-trips because
Pillow decodes the standalone JFIF bytes directly, which hides the break
from xrspatial's own tests.

Fix: reject compression='jpeg' at the to_geotiff entry point with a
ValueError that points at deflate/zstd/lzw. The lower-level _writer.write
is untouched so the existing self-decoding tests still demonstrate the
codec works internally; re-enabling the public path needs a
JPEGTables-aware encoder.
@github-actions github-actions Bot added the performance PR touches performance-sensitive code label May 7, 2026
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.

1 participant