Fixed DCX off-by one issue + minor optimization.

This commit is contained in:
Harald Kuhr 2018-01-09 20:33:35 +01:00
parent 6113ae1c9c
commit 2a40bdb14b
4 changed files with 74 additions and 31 deletions

View File

@ -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) +
'}';
']';
}
}

View File

@ -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<ImageTypeSpecifier> getImageTypes(final int imageIndex) throws IOException {
@Override
public Iterator<ImageTypeSpecifier> 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,10 +146,12 @@ public final class DCXImageReader extends ImageReaderBase {
private void initIndex(final int imageIndex) throws IOException {
checkBounds(imageIndex);
if (index != imageIndex) {
imageInput.seek(header.getOffset(imageIndex));
progressDelegator.index = imageIndex;
index = imageIndex;
readerDelegate.setInput(new SubImageInputStream(imageInput, Long.MAX_VALUE));
}
}
private void readHeader() throws IOException {
assertInput();
@ -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,8 +171,6 @@ public final class DCXImageReader extends ImageReaderBase {
}
private class ProgressDelegator extends ProgressListenerBase implements IIOReadWarningListener {
private int index;
@Override
public void imageComplete(ImageReader source) {
processImageComplete();
@ -190,7 +206,6 @@ public final class DCXImageReader extends ImageReaderBase {
}
}
public static void main(String[] args) throws IOException {
DCXImageReader reader = new DCXImageReader(null);

View File

@ -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;
}
@ -69,10 +70,13 @@ public final class DCXImageReaderSpi extends ImageReaderSpiBase {
}
}
@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";
}}
}
}

View File

@ -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<DCXImageReader>
"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);
}
}
}