diff --git a/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/WebPImageReader.java b/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/WebPImageReader.java index bd09e610..938185a5 100644 --- a/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/WebPImageReader.java +++ b/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/WebPImageReader.java @@ -61,6 +61,8 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import static com.twelvemonkeys.imageio.plugins.webp.lossless.VP8LDecoder.copyIntoRasterWithParams; + import static java.lang.Math.max; import static java.lang.Math.min; @@ -536,21 +538,26 @@ final class WebPImageReader extends ImageReaderBase { // Simulate header imageInput.seek(imageInput.getStreamPosition() - 5); - WritableRaster tempRaster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, destination.getWidth(), destination.getHeight(), 4, null); - readVP8Lossless(tempRaster, param, width, height); + // Temp alpha raster must have same dimensions as the source, because of filtering. + WritableRaster tempRaster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, height, 4, null); + readVP8Lossless(tempRaster, null, width, height); // Copy from green (band 1) in temp to alpha in destination - alphaRaster.setRect(tempRaster.createChild(0, 0, tempRaster.getWidth(), tempRaster.getHeight(), 0, 0, new int[] {1})); + WritableRaster alphaChannel = tempRaster.createWritableChild(0, 0, tempRaster.getWidth(), tempRaster.getHeight(), 0, 0, new int[]{1}); + alphaFilter(alphaChannel, filtering); + copyIntoRasterWithParams(alphaChannel, alphaRaster, param); break; default: processWarningOccurred("Unknown WebP alpha compression: " + compression); opaqueAlpha(alphaRaster); break; } + } + private void alphaFilter(WritableRaster alphaRaster, int filtering) { if (filtering != AlphaFiltering.NONE) { - for (int y = 0; y < destination.getHeight(); y++) { - for (int x = 0; x < destination.getWidth(); x++) { + for (int y = 0; y < alphaRaster.getHeight(); y++) { + for (int x = 0; x < alphaRaster.getWidth(); x++) { int predictorAlpha = getPredictorAlpha(alphaRaster, filtering, y, x); alphaRaster.setSample(x, y, 0, alphaRaster.getSample(x, y, 0) + predictorAlpha % 256); } diff --git a/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/VP8LDecoder.java b/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/VP8LDecoder.java index 49c52017..21f46a49 100644 --- a/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/VP8LDecoder.java +++ b/imageio/imageio-webp/src/main/java/com/twelvemonkeys/imageio/plugins/webp/lossless/VP8LDecoder.java @@ -135,33 +135,36 @@ public final class VP8LDecoder { } if (fullSizeRaster != raster && param != null) { - // Copy into destination raster with settings applied - Rectangle sourceRegion = param.getSourceRegion(); - int sourceXSubsampling = param.getSourceXSubsampling(); - int sourceYSubsampling = param.getSourceYSubsampling(); - int subsamplingXOffset = param.getSubsamplingXOffset(); - int subsamplingYOffset = param.getSubsamplingYOffset(); - Point destinationOffset = param.getDestinationOffset(); + copyIntoRasterWithParams(fullSizeRaster, raster, param); + } + } + + /** + * Copy a source raster into a destination raster with settings applied. + */ + public static void copyIntoRasterWithParams(final Raster srcRaster, final WritableRaster dstRaster, + final ImageReadParam param) { + Rectangle sourceRegion = param != null && param.getSourceRegion() != null ? param.getSourceRegion() : dstRaster.getBounds(); + int sourceXSubsampling = param != null ? param.getSourceXSubsampling() : 1; + int sourceYSubsampling = param != null ? param.getSourceYSubsampling() : 1; + int subsamplingXOffset = param != null ? param.getSubsamplingXOffset() : 0; + int subsamplingYOffset = param != null ? param.getSubsamplingYOffset() : 0; + Point destinationOffset = param != null ? param.getDestinationOffset() : new Point(0, 0) ; - if (sourceRegion == null) { - sourceRegion = raster.getBounds(); - } + if (sourceXSubsampling == 1 && sourceYSubsampling == 1) { + // Only apply offset (and limit to requested region) + dstRaster.setRect(destinationOffset.x, destinationOffset.y, srcRaster); + } + else { + // Manual copy, more efficient way might exist + byte[] rgba = new byte[4]; + int xEnd = dstRaster.getWidth() + dstRaster.getMinX(); + int yEnd = dstRaster.getHeight() + dstRaster.getMinY(); - if (sourceXSubsampling == 1 && sourceYSubsampling == 1) { - // Only apply offset (and limit to requested region) - raster.setRect(destinationOffset.x, destinationOffset.y, fullSizeRaster); - } - else { - // Manual copy, more efficient way might exist - byte[] rgba = new byte[4]; - int xEnd = raster.getWidth() + raster.getMinX(); - int yEnd = raster.getHeight() + raster.getMinY(); - - for (int xDst = destinationOffset.x, xSrc = sourceRegion.x + subsamplingXOffset; xDst < xEnd; xDst++, xSrc += sourceXSubsampling) { - for (int yDst = destinationOffset.y, ySrc = sourceRegion.y + subsamplingYOffset; yDst < yEnd; yDst++, ySrc += sourceYSubsampling) { - fullSizeRaster.getDataElements(xSrc, ySrc, rgba); - raster.setDataElements(xDst, yDst, rgba); - } + for (int xDst = destinationOffset.x, xSrc = sourceRegion.x + subsamplingXOffset; xDst < xEnd; xDst++, xSrc += sourceXSubsampling) { + for (int yDst = destinationOffset.y, ySrc = sourceRegion.y + subsamplingYOffset; yDst < yEnd; yDst++, ySrc += sourceYSubsampling) { + srcRaster.getDataElements(xSrc, ySrc, rgba); + dstRaster.setDataElements(xDst, yDst, rgba); } } } diff --git a/imageio/imageio-webp/src/test/java/com/twelvemonkeys/imageio/plugins/webp/WebPImageReaderTest.java b/imageio/imageio-webp/src/test/java/com/twelvemonkeys/imageio/plugins/webp/WebPImageReaderTest.java index 66959421..6f1665f5 100644 --- a/imageio/imageio-webp/src/test/java/com/twelvemonkeys/imageio/plugins/webp/WebPImageReaderTest.java +++ b/imageio/imageio-webp/src/test/java/com/twelvemonkeys/imageio/plugins/webp/WebPImageReaderTest.java @@ -58,7 +58,9 @@ public class WebPImageReaderTest extends ImageReaderAbstractTest