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