RasterFormatException thrown when drawing a tiled image made of non-writable rasters

Philip Race philip.race at oracle.com
Fri Oct 15 16:28:51 UTC 2021


Hi Martin,

You  do show up on the list of folks who have signed the OCA so the 
process is to submit a bug
and then a PR referencing it at https://github.com/openjdk/jdk following 
the process at https://openjdk.java.net/guide/
I don't see that you have a JBS (https://bugs.openjdk.java.net/) account 
so I can submit the bug for you
if needed or (better for me) you can submit it yourself at 
https://bugreport.java.com/bugreport/ and
let me know the ID and I can convert it into a JBS bug.

-phil

On 10/15/21 8:10 AM, Martin Desruisseaux wrote:
> Hello all
>
> Call to Graphics2D.drawRenderedImage(RenderedImage, AffineTransform) 
> fails if the image contains more than one tile (or a single tile not 
> located at 0,0) and the tiles are not instances of WritableRaster 
> (i.e. are instances of the read-only Raster parent class). A test case 
> [1] reproduces this issue. The bug is demonstrated by drawing the same 
> image twice: once with WritableRaster tiles (which succeed), then the 
> same operation where the only change is the use of Raster tiles. The 
> exception is:
>
> Exception in thread "main" java.awt.image.RasterFormatException: 
> (parentX + width) is outside raster
>     at 
> java.desktop/java.awt.image.WritableRaster.createWritableChild(WritableRaster.java:228)
>     at 
> java.desktop/sun.java2d.SunGraphics2D.drawTranslatedRenderedImage(SunGraphics2D.java:2852)
>     at 
> java.desktop/sun.java2d.SunGraphics2D.drawRenderedImage(SunGraphics2D.java:2711)
>
> The cause is in the following code in SunGraphics2D:
>
> // Create a WritableRaster containing the tile
> WritableRaster wRaster = null;
> if (raster instanceof WritableRaster) {
>     wRaster = (WritableRaster)raster;
> } else {
>     // Create a WritableRaster in the same coordinate system
>     // as the original raster.
>     wRaster =
>         Raster.createWritableRaster(raster.getSampleModel(),
>                                     raster.getDataBuffer(),
>                                     null);
> }
> // Translate wRaster to start at (0, 0) and to contain
> // only the relevent portion of the tile
> wRaster = wRaster.createWritableChild(tileRect.x, tileRect.y,
>                                       tileRect.width,
>                                       tileRect.height,
>                                       0, 0,
>                                       null);
>
> If the tile is not an instance of WritableRaster, then the code wraps 
> the tile DataBuffer in a new WritableRaster*but with a location set to 
> (0,0)*, because the location argument in createWritableRaster(…) call 
> is null. Then the call to createWritableChild(…) applies a translation 
> for bringing the tile location to (0,0). But in the case where the 
> raster has been converted from Raster to WritableRaster, that 
> translation has already been applied, and the effect of current code 
> is to apply the translation twice.
>
> I think that this bug has been largely unnoticed because most users 
> use BufferedImage, which has a single tile always located at (0,0), 
> and the minority of developers using their own RenderedImage 
> implementation uses WritableRaster instances, because Raster.create(…) 
> methods provide optimizations for common cases which result in 
> WritableRaster instances created even when the user asked only for a 
> Raster. To make this bug apparent, it is necessary to invoke 
> Raster.createRaster(…) with a sample model for which no optimization 
> is provided.
>
> The commit at [1] provides a test case and a suggested fix. From that 
> point, I'm not sure how to proceed (I'm sure there is many steps, that 
> the proposed commit needs to be modified, etc.). Can anyone can give 
> me some hints?
>
>     Regards,
>
>         Martin
>
> [1]https://github.com/Geomatys/jdk/commit/94242a05ff8b9c1af603a11133af7c6016c9e833 
>




More information about the client-libs-dev mailing list