From 9fe87fe10d692c5b9142e0c8f00f4118c07fc49e Mon Sep 17 00:00:00 2001 From: Harald Kuhr Date: Fri, 22 Apr 2022 14:41:57 +0200 Subject: [PATCH] #672: WebPImageReader now supports unknown stream lengths --- .../imageio/plugins/webp/WebPImageReader.java | 52 +++++++++++-------- .../plugins/webp/WebPImageReaderTest.java | 41 ++++++++++++--- 2 files changed, 64 insertions(+), 29 deletions(-) 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 0b5a32fa..64d2bc6d 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 @@ -31,6 +31,28 @@ package com.twelvemonkeys.imageio.plugins.webp; +import java.awt.*; +import java.awt.color.ICC_ColorSpace; +import java.awt.color.ICC_Profile; +import java.awt.image.BufferedImage; +import java.awt.image.ColorConvertOp; +import java.awt.image.ColorModel; +import java.awt.image.DataBuffer; +import java.awt.image.WritableRaster; +import java.io.IOException; +import java.nio.ByteOrder; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.imageio.IIOException; +import javax.imageio.ImageReadParam; +import javax.imageio.ImageReader; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.spi.ImageReaderSpi; + import com.twelvemonkeys.imageio.ImageReaderBase; import com.twelvemonkeys.imageio.color.ColorProfiles; import com.twelvemonkeys.imageio.color.ColorSpaces; @@ -45,23 +67,6 @@ import com.twelvemonkeys.imageio.util.ImageTypeSpecifiers; import com.twelvemonkeys.imageio.util.ProgressListenerBase; import com.twelvemonkeys.imageio.util.RasterUtils; -import javax.imageio.IIOException; -import javax.imageio.ImageReadParam; -import javax.imageio.ImageReader; -import javax.imageio.ImageTypeSpecifier; -import javax.imageio.metadata.IIOMetadata; -import javax.imageio.spi.ImageReaderSpi; -import java.awt.*; -import java.awt.color.ICC_ColorSpace; -import java.awt.color.ICC_Profile; -import java.awt.image.*; -import java.io.IOException; -import java.nio.ByteOrder; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - /** * WebPImageReader */ @@ -72,6 +77,7 @@ final class WebPImageReader extends ImageReaderBase { private LSBBitReader lsbBitReader; // Either VP8_, VP8L or VP8X chunk + private long fileSize; private VP8xChunk header; private ICC_Profile iccProfile; private final List frames = new ArrayList<>(); @@ -82,6 +88,7 @@ final class WebPImageReader extends ImageReaderBase { @Override protected void resetMembers() { + fileSize = -1; header = null; iccProfile = null; lsbBitReader = null; @@ -119,7 +126,7 @@ final class WebPImageReader extends ImageReaderBase { RIFFChunk frame = frames.isEmpty() ? header : frames.get(frames.size() - 1); imageInput.seek(frame.offset + frame.length); - while (imageInput.getStreamPosition() < imageInput.length()) { + while (imageInput.getStreamPosition() < fileSize) { int nextChunk = imageInput.readInt(); long chunkLength = imageInput.readUnsignedInt(); long chunkStart = imageInput.getStreamPosition(); @@ -184,7 +191,7 @@ final class WebPImageReader extends ImageReaderBase { throw new IIOException(String.format("Not a WebP file, invalid 'RIFF' magic: '%s'", fourCC(riff))); } - imageInput.readUnsignedInt(); // Skip file size NOTE: LITTLE endian! + fileSize = 8 + imageInput.readUnsignedInt(); // 8 + RIFF container length (LITTLE endian) == file size int webp = imageInput.readInt(); if (webp != WebP.WEBP_MAGIC) { @@ -282,7 +289,7 @@ final class WebPImageReader extends ImageReaderBase { if (header.containsICCP) { // ICCP chunk must be first chunk, if present - while (iccProfile == null && imageInput.getStreamPosition() < imageInput.length()) { + while (iccProfile == null && imageInput.getStreamPosition() < fileSize) { int nextChunk = imageInput.readInt(); long chunkLength = imageInput.readUnsignedInt(); long chunkStart = imageInput.getStreamPosition(); @@ -305,6 +312,7 @@ final class WebPImageReader extends ImageReaderBase { } if (DEBUG) { + System.out.println("file size: " + fileSize + " (stream length: " + imageInput.length() + ")"); System.out.println("header: " + header); } } @@ -422,7 +430,7 @@ final class WebPImageReader extends ImageReaderBase { } else { imageInput.seek(header.offset + header.length); - readVP8Extended(destination, param, imageInput.length()); + readVP8Extended(destination, param, fileSize); } break; @@ -591,7 +599,7 @@ final class WebPImageReader extends ImageReaderBase { // TODO: WebP spec says possible EXIF and XMP chunks are always AFTER image data imageInput.seek(header.offset + header.length); - while (imageInput.getStreamPosition() < imageInput.length()) { + while (imageInput.getStreamPosition() < fileSize) { int nextChunk = imageInput.readInt(); long chunkLength = imageInput.readUnsignedInt(); long chunkStart = imageInput.getStreamPosition(); 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 d4277562..8d3b6dc6 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 @@ -1,20 +1,22 @@ package com.twelvemonkeys.imageio.plugins.webp; -import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest; +import static java.util.Arrays.asList; -import org.junit.Test; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.List; import javax.imageio.ImageIO; import javax.imageio.ImageReadParam; import javax.imageio.ImageTypeSpecifier; import javax.imageio.spi.ImageReaderSpi; import javax.imageio.stream.ImageInputStream; -import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.util.List; +import javax.imageio.stream.MemoryCacheImageInputStream; -import static java.util.Arrays.asList; +import org.junit.Test; + +import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest; /** * WebPImageReaderTest @@ -102,4 +104,29 @@ public class WebPImageReaderTest extends ImageReaderAbstractTest