Skip to content

[GH-3245] Fix RS_AsCOG ArrayIndexOutOfBoundsException for byte-band rasters - #3259

Open
jiayuasu wants to merge 1 commit into
apache:masterfrom
jiayuasu:fix/cog-byte-band-deflate-overrun
Open

[GH-3245] Fix RS_AsCOG ArrayIndexOutOfBoundsException for byte-band rasters#3259
jiayuasu wants to merge 1 commit into
apache:masterfrom
jiayuasu:fix/cog-byte-band-deflate-overrun

Conversation

@jiayuasu

Copy link
Copy Markdown
Member

Did you read the Contributor Guide?

Is this PR related to a ticket?

What changes were proposed in this PR?

RS_AsCOG threw ArrayIndexOutOfBoundsException at Deflater.setInput for 1024x1024 byte-band rasters. The root cause is in imageio-ext's TIFFDeflater: it passes (offset, height * scanlineStride) verbatim to Deflater.setInput(). The COG pipeline's overview images are JAI PlanarImages tiled wider than the 256px output tile (a 1024 input produces a single-tile 512x512 overview); TIFFImageWriter's 8-bit optimized path hands the compressor the overview's backing array with a tile offset and the full scanline stride, and for the last row of output tiles the computed range overruns the array. Only byte bands take that direct-buffer path, which is why int/double rasters were unaffected. The bug is still present in imageio-ext 2.1.0.

Two related consequences of the same code path are also covered:

  • When it did not crash, it compressed the inter-row slack between tile width and scanline stride, silently corrupting overview pixels for non-empty data.
  • The full-resolution write crashes the same way for any byte raster whose image is tiled wider than the output tile size (e.g. loaded from a 512-tiled GeoTIFF).

The fix retiles byte-band coverages to the output tile grid in CogWriter before handing them to GeoTiffWriter, so every raster the writer reads starts at offset 0 of a tile-sized buffer. The copy happens lazily one tile at a time via javax.media.jai.TiledImage; pixel data, geo-referencing, sample dimensions, and metadata are unchanged, and non-byte bands are untouched.

How was this patch tested?

New regression tests in CogWriterTest:

  • testWriteByteBandRasterAsCog: byte rasters at 512/768/1024/1536 write successfully and full-resolution pixel values round-trip exactly (the 1024 and 1536 cases crashed before this fix).
  • testByteBandOverviewPixelsSurviveCogEncoding: reads the overview IFD back and verifies overview pixel content, catching the silent stride corruption.
  • testWriteTiledByteSourceAsCog: a byte coverage whose own image is 512-tiled writes correctly with overviewCount=0, covering the full-resolution-path variant.

Full common module suite passes (1288 tests).

Did this PR include necessary documentation updates?

  • No, this PR does not affect any public API so no need to change the documentation.

…band rasters

imageio-ext's TIFFDeflater passes (offset, height * scanlineStride) verbatim
to Deflater.setInput(). When TIFFImageWriter's 8-bit optimized path hands it
a raster sharing a source tile wider than the output tile (e.g. a JAI
overview image with a single 512x512 tile written as 256x256 tiles), the
range overruns the backing array on the last row of tiles. The same path
also compressed the inter-row slack of wide source tiles, corrupting
overview pixels. The bug is still present in imageio-ext 2.1.0.

Work around it in CogWriter by retiling byte-band coverages to the output
tile grid before handing them to GeoTiffWriter, so every raster the writer
reads starts at offset 0 of a tile-sized buffer. The copy happens lazily
one tile at a time via javax.media.jai.TiledImage; pixel data and the
written TIFF are unchanged.
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.

RS_AsCOG throws ArrayIndexOutOfBoundsException for 1024x1024 byte-band rasters

1 participant