#232: Cleanup after merge of #225

This commit is contained in:
Harald Kuhr 2016-04-21 14:05:45 +02:00
parent 2cec177c6d
commit 047884e3d9
4 changed files with 107 additions and 80 deletions

View File

@ -281,7 +281,6 @@ final class CCITTFaxDecoderStream extends FilterInputStream {
int index = 0;
boolean white = true;
for (int i = 0; i <= changesCurrentRowCount; i++) {
int nextChange = columns;
@ -404,14 +403,14 @@ final class CCITTFaxDecoderStream extends FilterInputStream {
@Override
public int read() throws IOException {
if (decodedLength < 0) {
return 0xFF;
return 0x0;
}
if (decodedPos >= decodedLength) {
fetch();
if (decodedLength < 0) {
return 0xFF;
return 0x0;
}
}
@ -421,7 +420,7 @@ final class CCITTFaxDecoderStream extends FilterInputStream {
@Override
public int read(byte[] b, int off, int len) throws IOException {
if (decodedLength < 0) {
Arrays.fill(b, off, len, (byte)0xFF);
Arrays.fill(b, off, off + len, (byte) 0x0);
return len;
}
@ -429,7 +428,7 @@ final class CCITTFaxDecoderStream extends FilterInputStream {
fetch();
if (decodedLength < 0) {
Arrays.fill(b, off, len, (byte)0xFF);
Arrays.fill(b, off, off + len, (byte) 0x0);
return len;
}
}
@ -570,146 +569,146 @@ final class CCITTFaxDecoderStream extends FilterInputStream {
static final short[][] BLACK_CODES = {
{ // 2 bits
0x2, 0x3,
},
},
{ // 3 bits
0x2, 0x3,
},
},
{ // 4 bits
0x2, 0x3,
},
},
{ // 5 bits
0x3,
},
},
{ // 6 bits
0x4, 0x5,
},
},
{ // 7 bits
0x4, 0x5, 0x7,
},
},
{ // 8 bits
0x4, 0x7,
},
},
{ // 9 bits
0x18,
},
},
{ // 10 bits
0x17, 0x18, 0x37, 0x8, 0xf,
},
},
{ // 11 bits
0x17, 0x18, 0x28, 0x37, 0x67, 0x68, 0x6c, 0x8, 0xc, 0xd,
},
},
{ // 12 bits
0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x1c, 0x1d, 0x1e, 0x1f, 0x24, 0x27, 0x28, 0x2b, 0x2c, 0x33,
0x34, 0x35, 0x37, 0x38, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x64, 0x65,
0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xd2, 0xd3,
0xd4, 0xd5, 0xd6, 0xd7, 0xda, 0xdb,
},
},
{ // 13 bits
0x4a, 0x4b, 0x4c, 0x4d, 0x52, 0x53, 0x54, 0x55, 0x5a, 0x5b, 0x64, 0x65, 0x6c, 0x6d, 0x72, 0x73,
0x74, 0x75, 0x76, 0x77,
}
}
};
static final short[][] BLACK_RUN_LENGTHS = {
{ // 2 bits
3, 2,
},
},
{ // 3 bits
1, 4,
},
},
{ // 4 bits
6, 5,
},
},
{ // 5 bits
7,
},
},
{ // 6 bits
9, 8,
},
},
{ // 7 bits
10, 11, 12,
},
},
{ // 8 bits
13, 14,
},
},
{ // 9 bits
15,
},
},
{ // 10 bits
16, 17, 0, 18, 64,
},
},
{ // 11 bits
24, 25, 23, 22, 19, 20, 21, 1792, 1856, 1920,
},
},
{ // 12 bits
1984, 2048, 2112, 2176, 2240, 2304, 2368, 2432, 2496, 2560, 52, 55, 56, 59, 60, 320, 384, 448, 53,
54, 50, 51, 44, 45, 46, 47, 57, 58, 61, 256, 48, 49, 62, 63, 30, 31, 32, 33, 40, 41, 128, 192, 26,
27, 28, 29, 34, 35, 36, 37, 38, 39, 42, 43,
},
},
{ // 13 bits
640, 704, 768, 832, 1280, 1344, 1408, 1472, 1536, 1600, 1664, 1728, 512, 576, 896, 960, 1024, 1088,
1152, 1216,
}
}
};
public static final short[][] WHITE_CODES = {
{ // 4 bits
0x7, 0x8, 0xb, 0xc, 0xe, 0xf,
},
},
{ // 5 bits
0x12, 0x13, 0x14, 0x1b, 0x7, 0x8,
},
},
{ // 6 bits
0x17, 0x18, 0x2a, 0x2b, 0x3, 0x34, 0x35, 0x7, 0x8,
},
},
{ // 7 bits
0x13, 0x17, 0x18, 0x24, 0x27, 0x28, 0x2b, 0x3, 0x37, 0x4, 0x8, 0xc,
},
},
{ // 8 bits
0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x1a, 0x1b, 0x2, 0x24, 0x25, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
0x3, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x4, 0x4a, 0x4b, 0x5, 0x52, 0x53, 0x54, 0x55, 0x58, 0x59,
0x5a, 0x5b, 0x64, 0x65, 0x67, 0x68, 0xa, 0xb,
},
},
{ // 9 bits
0x98, 0x99, 0x9a, 0x9b, 0xcc, 0xcd, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb,
},
},
{ // 10 bits
},
{ // 11 bits
0x8, 0xc, 0xd,
},
},
{ // 12 bits
0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x1c, 0x1d, 0x1e, 0x1f,
}
}
};
public static final short[][] WHITE_RUN_LENGTHS = {
{ // 4 bits
2, 3, 4, 5, 6, 7,
},
},
{ // 5 bits
128, 8, 9, 64, 10, 11,
},
},
{ // 6 bits
192, 1664, 16, 17, 13, 14, 15, 1, 12,
},
},
{ // 7 bits
26, 21, 28, 27, 18, 24, 25, 22, 256, 23, 20, 19,
},
},
{ // 8 bits
33, 34, 35, 36, 37, 38, 31, 32, 29, 53, 54, 39, 40, 41, 42, 43, 44, 30, 61, 62, 63, 0, 320, 384, 45,
59, 60, 46, 49, 50, 51, 52, 55, 56, 57, 58, 448, 512, 640, 576, 47, 48,
},
},
{ // 9 bits
1472, 1536, 1600, 1728, 704, 768, 832, 896, 960, 1024, 1088, 1152, 1216, 1280, 1344, 1408,
},
},
{ // 10 bits
},
{ // 11 bits
1792, 1856, 1920,
},
},
{ // 12 bits
1984, 2048, 2112, 2176, 2240, 2304, 2368, 2432, 2496, 2560,
}
}
};
final static Node EOL;

View File

@ -40,7 +40,7 @@ import java.io.OutputStream;
* @author last modified by $Author$
* @version $Id$
*/
public class CCITTFaxEncoderStream extends OutputStream {
final class CCITTFaxEncoderStream extends OutputStream {
private int currentBufferLength = 0;
private final byte[] inputBuffer;

View File

@ -37,8 +37,9 @@ import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import static org.junit.Assert.*;
import static org.junit.Assert.assertArrayEquals;
/**
* CCITTFaxDecoderStreamTest
@ -109,11 +110,11 @@ public class CCITTFaxDecoderStreamTest {
// 1 1 1 0 1 1 x x
// 1 1 1 0 1 1 x x
// 1 1 0 0 1 1 x x
BufferedImage image;
final BufferedImage image = new BufferedImage(6, 4, BufferedImage.TYPE_BYTE_BINARY);;
@Before
public void init() {
image = new BufferedImage(6, 4, BufferedImage.TYPE_BYTE_BINARY);
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 6; x++) {
image.setRGB(x, y, x != 3 ? 0xff000000 : 0xffffffff);
@ -200,4 +201,32 @@ public class CCITTFaxDecoderStreamTest {
new DataInputStream(stream).readFully(bytes);
assertArrayEquals(imageData, bytes);
}
@Test
public void testDecodeMissingRows() throws IOException {
// See https://github.com/haraldk/TwelveMonkeys/pull/225 and https://github.com/haraldk/TwelveMonkeys/issues/232
InputStream inputStream = getClass().getResourceAsStream("/tiff/ccitt_tolessrows.tif");
// Skip until StripOffsets: 8
for (int i = 0; i < 8; i++) {
inputStream.read();
}
// Read until StripByteCounts: 7
byte[] data = new byte[7];
new DataInputStream(inputStream).readFully(data);
InputStream stream = new CCITTFaxDecoderStream(new ByteArrayInputStream(data),
6, TIFFExtension.COMPRESSION_CCITT_T6, 1, 0L);
byte[] bytes = new byte[6]; // 6 x 6 pixel, 1 bpp => 6 bytes
new DataInputStream(stream).readFully(bytes);
// Pad image data with 0s
byte[] imageData = Arrays.copyOf(((DataBufferByte) image.getData().getDataBuffer()).getData(), 6);
assertArrayEquals(imageData, bytes);
// Ideally, we should have no more data now, but the stream don't know that...
// assertEquals("Should contain no more data", -1, stream.read());
}
}

View File

@ -29,7 +29,6 @@
package com.twelvemonkeys.imageio.plugins.tiff;
import com.twelvemonkeys.imageio.plugins.tiff.CCITTFaxEncoderStream.Code;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@ -122,16 +121,34 @@ public class CCITTFaxEncoderStreamTest {
@Test
public void testReencodeImages() throws IOException {
testImage(getClassLoaderResource("/tiff/fivepages-scan-causingerrors.tif"));
try (ImageInputStream iis = ImageIO.createImageInputStream(getClassLoaderResource("/tiff/fivepages-scan-causingerrors.tif").openStream())) {
ImageReader reader = ImageIO.getImageReaders(iis).next();
reader.setInput(iis, true);
ByteArrayOutputStream outputBuffer = new ByteArrayOutputStream();
ImageWriter writer = ImageIO.getImageWritersByFormatName("TIFF").next();
BufferedImage originalImage;
try (ImageOutputStream output = ImageIO.createImageOutputStream(outputBuffer)) {
writer.setOutput(output);
originalImage = reader.read(0);
IIOImage outputImage = new IIOImage(originalImage, null, reader.getImageMetadata(0));
writer.write(outputImage);
}
byte[] originalData = ((DataBufferByte) originalImage.getData().getDataBuffer()).getData();
BufferedImage reencodedImage = ImageIO.read(new ByteArrayInputStream(outputBuffer.toByteArray()));
byte[] reencodedData = ((DataBufferByte) reencodedImage.getData().getDataBuffer()).getData();
assertArrayEquals(originalData, reencodedData);
}
}
/**
* Test for "Fixed an issue with long runlengths in CCITTFax writing #188"
*
* @throws IOException
*/
@Test
public void testRunlengthIssue() throws IOException {
// Test for "Fixed an issue with long runlengths in CCITTFax writing #188"
byte[] data = new byte[400];
Arrays.fill(data, (byte) 0xFF);
data[0] = 0;
@ -158,37 +175,19 @@ public class CCITTFaxEncoderStreamTest {
private void testStreamEncodeDecode(int type, int fillOrder, long options) throws IOException {
byte[] imageData = ((DataBufferByte) image.getData().getDataBuffer()).getData();
byte[] redecodedData = new byte[imageData.length];
ByteArrayOutputStream imageOutput = new ByteArrayOutputStream();
OutputStream outputSteam = new CCITTFaxEncoderStream(imageOutput, 6, 4, type, fillOrder, options);
outputSteam.write(imageData);
outputSteam.close();
byte[] encodedData = imageOutput.toByteArray();
CCITTFaxDecoderStream inputStream = new CCITTFaxDecoderStream(new ByteArrayInputStream(encodedData), 6, type,
fillOrder, options);
new DataInputStream(inputStream).readFully(redecodedData);
inputStream.close();
try (CCITTFaxDecoderStream inputStream =
new CCITTFaxDecoderStream(new ByteArrayInputStream(encodedData), 6, type, fillOrder, options)) {
new DataInputStream(inputStream).readFully(redecodedData);
}
assertArrayEquals(imageData, redecodedData);
}
private void testImage(URL imageUrl) throws IOException {
ImageInputStream iis = ImageIO.createImageInputStream(imageUrl.openStream());
ImageReader reader = ImageIO.getImageReadersByFormatName("TIFF").next();
reader.setInput(iis, true);
ByteArrayOutputStream outputBuffer = new ByteArrayOutputStream();
ImageWriter writer = ImageIO.getImageWritersByFormatName("TIFF").next();
ImageOutputStream output = ImageIO.createImageOutputStream(outputBuffer);
writer.setOutput(output);
BufferedImage originalImage = reader.read(0);
IIOImage outputImage = new IIOImage(originalImage, null, reader.getImageMetadata(0));
writer.write(outputImage);
BufferedImage reencodedImage = ImageIO.read(new ByteArrayInputStream(outputBuffer.toByteArray()));
byte[] reencodedData = ((DataBufferByte) reencodedImage.getData().getDataBuffer()).getData();
Assert.assertArrayEquals(((DataBufferByte) originalImage.getData().getDataBuffer()).getData(), reencodedData);
}
}