From 2a40bdb14b59bede13f668fb08e4e85a95ec1879 Mon Sep 17 00:00:00 2001 From: Harald Kuhr Date: Tue, 9 Jan 2018 20:33:35 +0100 Subject: [PATCH] Fixed DCX off-by one issue + minor optimization. --- .../imageio/plugins/dcx/DCXHeader.java | 10 ++-- .../imageio/plugins/dcx/DCXImageReader.java | 57 ++++++++++++------- .../plugins/dcx/DCXImageReaderSpi.java | 14 +++-- .../plugins/dcx/DCXImageReaderTest.java | 24 ++++++++ 4 files changed, 74 insertions(+), 31 deletions(-) diff --git a/imageio/imageio-pcx/src/main/java/com/twelvemonkeys/imageio/plugins/dcx/DCXHeader.java b/imageio/imageio-pcx/src/main/java/com/twelvemonkeys/imageio/plugins/dcx/DCXHeader.java index bc6dd672..6b7c839d 100755 --- a/imageio/imageio-pcx/src/main/java/com/twelvemonkeys/imageio/plugins/dcx/DCXHeader.java +++ b/imageio/imageio-pcx/src/main/java/com/twelvemonkeys/imageio/plugins/dcx/DCXHeader.java @@ -65,16 +65,16 @@ final class DCXHeader { int count = 0; do { offsets[count] = imageInput.readInt(); - count++; } - while (offsets[count - 1] != 0 && count < offsets.length); + while (offsets[count] != 0 && count++ < offsets.length); return new DCXHeader(count == offsets.length ? offsets : Arrays.copyOf(offsets, count)); } - @Override public String toString() { - return "DCXHeader{" + + @Override + public String toString() { + return "DCXHeader[" + "offsetTable=" + Arrays.toString(offsetTable) + - '}'; + ']'; } } diff --git a/imageio/imageio-pcx/src/main/java/com/twelvemonkeys/imageio/plugins/dcx/DCXImageReader.java b/imageio/imageio-pcx/src/main/java/com/twelvemonkeys/imageio/plugins/dcx/DCXImageReader.java index a7984a60..e2a41409 100755 --- a/imageio/imageio-pcx/src/main/java/com/twelvemonkeys/imageio/plugins/dcx/DCXImageReader.java +++ b/imageio/imageio-pcx/src/main/java/com/twelvemonkeys/imageio/plugins/dcx/DCXImageReader.java @@ -42,7 +42,6 @@ import javax.imageio.event.IIOReadWarningListener; import javax.imageio.metadata.IIOMetadata; import javax.imageio.metadata.IIOMetadataFormatImpl; import javax.imageio.spi.ImageReaderSpi; -import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; @@ -50,14 +49,16 @@ import java.nio.ByteOrder; import java.util.Iterator; public final class DCXImageReader extends ImageReaderBase { - // TODO: Delegate listeners with correct index! + + final static boolean DEBUG = "true".equalsIgnoreCase(System.getProperty("com.twelvemonkeys.imageio.plugins.dcx.debug")); private DCXHeader header; + private int index = -1; private PCXImageReader readerDelegate; private ProgressDelegator progressDelegator; - public DCXImageReader(final ImageReaderSpi provider) { + DCXImageReader(final ImageReaderSpi provider) { super(provider); readerDelegate = new PCXImageReader(provider); @@ -70,62 +71,73 @@ public final class DCXImageReader extends ImageReaderBase { readerDelegate.addIIOReadWarningListener(progressDelegator); } - @Override protected void resetMembers() { + @Override + protected void resetMembers() { header = null; + index = -1; readerDelegate.reset(); installListeners(); } - @Override public void dispose() { + @Override + public void dispose() { super.dispose(); readerDelegate.dispose(); readerDelegate = null; } - @Override public int getWidth(final int imageIndex) throws IOException { + @Override + public int getWidth(final int imageIndex) throws IOException { initIndex(imageIndex); return readerDelegate.getWidth(0); } - @Override public int getHeight(final int imageIndex) throws IOException { + @Override + public int getHeight(final int imageIndex) throws IOException { initIndex(imageIndex); return readerDelegate.getHeight(0); } - @Override public ImageTypeSpecifier getRawImageType(final int imageIndex) throws IOException { + @Override + public ImageTypeSpecifier getRawImageType(final int imageIndex) throws IOException { initIndex(imageIndex); return readerDelegate.getRawImageType(0); } - @Override public Iterator getImageTypes(final int imageIndex) throws IOException { + @Override + public Iterator getImageTypes(final int imageIndex) throws IOException { initIndex(imageIndex); return readerDelegate.getImageTypes(0); } - @Override public BufferedImage read(final int imageIndex, final ImageReadParam param) throws IOException { + @Override + public BufferedImage read(final int imageIndex, final ImageReadParam param) throws IOException { initIndex(imageIndex); return readerDelegate.read(imageIndex, param); } - @Override public IIOMetadata getImageMetadata(final int imageIndex) throws IOException { + @Override + public IIOMetadata getImageMetadata(final int imageIndex) throws IOException { initIndex(imageIndex); return readerDelegate.getImageMetadata(0); } - @Override public synchronized void abort() { + @Override + public synchronized void abort() { super.abort(); readerDelegate.abort(); } - @Override public int getNumImages(final boolean allowSearch) throws IOException { + @Override + public int getNumImages(final boolean allowSearch) throws IOException { readHeader(); return header.getCount(); @@ -134,9 +146,11 @@ public final class DCXImageReader extends ImageReaderBase { private void initIndex(final int imageIndex) throws IOException { checkBounds(imageIndex); - imageInput.seek(header.getOffset(imageIndex)); - progressDelegator.index = imageIndex; - readerDelegate.setInput(new SubImageInputStream(imageInput, Long.MAX_VALUE)); + if (index != imageIndex) { + imageInput.seek(header.getOffset(imageIndex)); + index = imageIndex; + readerDelegate.setInput(new SubImageInputStream(imageInput, Long.MAX_VALUE)); + } } private void readHeader() throws IOException { @@ -145,7 +159,11 @@ public final class DCXImageReader extends ImageReaderBase { if (header == null) { imageInput.setByteOrder(ByteOrder.LITTLE_ENDIAN); header = DCXHeader.read(imageInput); -// System.err.println("header: " + header); + + if (DEBUG) { + System.err.println("header: " + header); + } + imageInput.flushBefore(imageInput.getStreamPosition()); } @@ -153,11 +171,9 @@ public final class DCXImageReader extends ImageReaderBase { } private class ProgressDelegator extends ProgressListenerBase implements IIOReadWarningListener { - private int index; - @Override public void imageComplete(ImageReader source) { - processImageComplete(); + processImageComplete(); } @Override @@ -190,7 +206,6 @@ public final class DCXImageReader extends ImageReaderBase { } } - public static void main(String[] args) throws IOException { DCXImageReader reader = new DCXImageReader(null); diff --git a/imageio/imageio-pcx/src/main/java/com/twelvemonkeys/imageio/plugins/dcx/DCXImageReaderSpi.java b/imageio/imageio-pcx/src/main/java/com/twelvemonkeys/imageio/plugins/dcx/DCXImageReaderSpi.java index b5749027..d14b92fc 100755 --- a/imageio/imageio-pcx/src/main/java/com/twelvemonkeys/imageio/plugins/dcx/DCXImageReaderSpi.java +++ b/imageio/imageio-pcx/src/main/java/com/twelvemonkeys/imageio/plugins/dcx/DCXImageReaderSpi.java @@ -45,7 +45,8 @@ public final class DCXImageReaderSpi extends ImageReaderSpiBase { super(new DCXProviderInfo()); } - @Override public boolean canDecodeInput(final Object source) throws IOException { + @Override + public boolean canDecodeInput(final Object source) throws IOException { if (!(source instanceof ImageInputStream)) { return false; } @@ -64,15 +65,18 @@ public final class DCXImageReaderSpi extends ImageReaderSpiBase { stream.setByteOrder(originalByteOrder); } } - finally{ + finally { stream.reset(); } } - @Override public ImageReader createReaderInstance(final Object extension) throws IOException { + @Override + public ImageReader createReaderInstance(final Object extension) throws IOException { return new DCXImageReader(this); } - @Override public String getDescription(final Locale locale) { + @Override + public String getDescription(final Locale locale) { return "Multi-page PCX fax document (DCX) image reader"; - }} + } +} diff --git a/imageio/imageio-pcx/src/test/java/com/twelvemonkeys/imageio/plugins/dcx/DCXImageReaderTest.java b/imageio/imageio-pcx/src/test/java/com/twelvemonkeys/imageio/plugins/dcx/DCXImageReaderTest.java index 51ef59f3..cdc4f0d4 100755 --- a/imageio/imageio-pcx/src/test/java/com/twelvemonkeys/imageio/plugins/dcx/DCXImageReaderTest.java +++ b/imageio/imageio-pcx/src/test/java/com/twelvemonkeys/imageio/plugins/dcx/DCXImageReaderTest.java @@ -29,13 +29,21 @@ package com.twelvemonkeys.imageio.plugins.dcx; import com.twelvemonkeys.imageio.util.ImageReaderAbstractTest; +import org.junit.Test; +import javax.imageio.ImageIO; 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.Arrays; import java.util.Collections; import java.util.List; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + /** * DCXImageReaderTest * @@ -82,4 +90,20 @@ public class DCXImageReaderTest extends ImageReaderAbstractTest "image/dcx", "image/x-dcx" ); } + + @Test + public void testCount() throws IOException { + try (ImageInputStream input = ImageIO.createImageInputStream(getClassLoaderResource("/dcx/input.dcx"))) { + DCXImageReader reader = createReader(); + reader.setInput(input); + + assertEquals(1, reader.getNumImages(true)); + assertEquals(70, reader.getWidth(0)); + assertEquals(46, reader.getHeight(0)); + + BufferedImage image = reader.read(0); + + assertNotNull(image); + } + } }