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