CITT Group 3/4 Support - some cleanup, group 3 /T.4 should work now

This commit is contained in:
Schmidor 2015-07-02 23:35:19 +02:00
parent a2042e75bf
commit 2b22b02523
3 changed files with 745 additions and 735 deletions

View File

@ -92,8 +92,8 @@ interface TIFFExtension {
int ORIENTATION_RIGHTBOT = 7; int ORIENTATION_RIGHTBOT = 7;
int ORIENTATION_LEFTBOT = 8; int ORIENTATION_LEFTBOT = 8;
int GROUP3OPT_2DENCODING = 1; int GROUP3OPT_2DENCODING = 1;
int GROUP3OPT_UNCOMPRESSED = 2; int GROUP3OPT_UNCOMPRESSED = 2;
int GROUP3OPT_FILLBITS = 4; int GROUP3OPT_FILLBITS = 4;
int GROUP4OPT_UNCOMPRESSED = 2; int GROUP4OPT_UNCOMPRESSED = 2;
} }

View File

@ -50,154 +50,143 @@ import static org.junit.Assert.*;
*/ */
public class CCITTFaxDecoderStreamTest { public class CCITTFaxDecoderStreamTest {
static final byte[] DATA_G3_1D = { 0x00, 0x18, // 000000000001|1000| EOL|3W| // group3_1d.tif: EOL|3W|1B|2W|EOL|3W|1B|2W|EOL|3W|1B|2W|EOL|2W|2B|2W|5*F
0x4E, 0x00, // 010|0111|000000000 1B|2W|EOL static final byte[] DATA_G3_1D = { 0x00, 0x18, 0x4E, 0x00, 0x30, (byte) 0x9C, 0x00, 0x61, 0x38, 0x00, (byte) 0xBE,
0x30, (byte) 0x9C, // 001|1000|010|0111|00 |3W|1B|2W|EOL (byte) 0xE0 };
0x00, 0x61, // 0000000001|1000|01 |3W|1B
0x38, 0x00, // 0|0111|00000000000 |2W|EOL
(byte) 0xBE, (byte) 0xE0 }; // 1|0111|11|0111|00000 |2W|2B|2W|5F
static final byte[] DATA_G3_1D_FILL = { 0x00, 0x01, (byte) 0x84, (byte) 0xE0, 0x01, (byte) 0x84, (byte) 0xE0, 0x01, // group3_1d_fill.tif
(byte) 0x84, (byte) 0xE0, 0x1, 0x7D, (byte) 0xC0 }; static final byte[] DATA_G3_1D_FILL = { 0x00, 0x01, (byte) 0x84, (byte) 0xE0, 0x01, (byte) 0x84, (byte) 0xE0, 0x01,
(byte) 0x84, (byte) 0xE0, 0x1, 0x7D, (byte) 0xC0 };
static final byte[] DATA_G3_2D = { // group3_2d.tif: EOL|k=1|3W|1B|2W|EOL|k=0|V|V|V|EOL|k=1|3W|1B|2W|EOL|k=0|V-1|V|V|6*F
0x00, 0x1C, // 000000000001|1|100 EOL|1|3W static final byte[] DATA_G3_2D = { 0x00, 0x1C, 0x27, 0x00, 0x17, 0x00, 0x1C, 0x27, 0x00, 0x12, (byte) 0xC0 };
0x27, 0x00, // 0|010|0111|00000000 |1B|2W|EOL
0x17, 0x00, // 0001|0|1|1|1|00000000 |0|V|V|V|EOL
0x1C, 0x27, // 0001|1|1000|010|0111| |1|3W|1B|2W|
0x00, 0x12, // 000000000001|0|010| EOL|0|V-1|
(byte) 0xC0 }; // 1|1|000000 V|V|6F
static final byte[] DATA_G3_2D_FILL = { 0x00, 0x01, (byte) 0xC2, 0x70, 0x01, 0x70, 0x01, (byte) 0xC2, 0x70, 0x01, // group3_2d_fill.tif
0x2C }; static final byte[] DATA_G3_2D_FILL = { 0x00, 0x01, (byte) 0xC2, 0x70, 0x01, 0x70, 0x01, (byte) 0xC2, 0x70, 0x01,
0x2C };
// EOF exception, not sure static final byte[] DATA_G3_2D_lsb2msb = { 0x00, 0x38, (byte) 0xE4, 0x00, (byte) 0xE8, 0x00, 0x38, (byte) 0xE4,
static final byte[] DATA_G3_2D_lsb2msb = { 0x00, 0x38, (byte) 0xE4, 0x00, (byte) 0xE8, 0x00, 0x38, (byte) 0xE4, 0x00, 0x48, 0x03 };
0x00, 0x48, 0x03 };
static final byte[] DATA_G4 = { // group4.tif:
0x04, 0x17, // 0000 0100 0001 01|11 // Line 1: V-3, V-2, V0
(byte) 0xF5, (byte) 0x80, // 1|111| 0101 1000 0000 // Line 2: V0 V0 V0
0x08, 0x00, // 0000 1000 0000 0000 // Line 3: V0 V0 V0
(byte) 0x80 }; // 1000 0000 // Line 4: V-1, V0, V0 EOL EOL
// Line 1: V-3, V-2, V0 static final byte[] DATA_G4 = { 0x04, 0x17, (byte) 0xF5, (byte) 0x80, 0x08, 0x00, (byte) 0x80 };
// Line 2: V0 V0 V0
// Line 3: V0 V0 V0
// Line 4: V-1, V0, V0 EOL EOL
// TODO: Better tests (full A4 width scan lines?) // TODO: Better tests (full A4 width scan lines?)
// From http://www.mikekohn.net/file_formats/tiff.php // From http://www.mikekohn.net/file_formats/tiff.php
static final byte[] DATA_TYPE_2 = { (byte) 0x84, (byte) 0xe0, // 10000100 static final byte[] DATA_TYPE_2 = { (byte) 0x84, (byte) 0xe0, // 10000100
// 11100000 // 11100000
(byte) 0x84, (byte) 0xe0, // 10000100 11100000 (byte) 0x84, (byte) 0xe0, // 10000100 11100000
(byte) 0x84, (byte) 0xe0, // 10000100 11100000 (byte) 0x84, (byte) 0xe0, // 10000100 11100000
(byte) 0x7d, (byte) 0xc0, // 01111101 11000000 (byte) 0x7d, (byte) 0xc0, // 01111101 11000000
}; };
static final byte[] DATA_TYPE_3 = { 0x00, 0x01, (byte) 0xc2, 0x70, // 00000000 static final byte[] DATA_TYPE_3 = { 0x00, 0x01, (byte) 0xc2, 0x70, // 00000000
// 00000001 // 00000001
// 11000010 // 11000010
// 01110000 // 01110000
0x00, 0x01, 0x78, // 00000000 00000001 01111000 0x00, 0x01, 0x78, // 00000000 00000001 01111000
0x00, 0x01, 0x78, // 00000000 00000001 01110000 0x00, 0x01, 0x78, // 00000000 00000001 01110000
0x00, 0x01, 0x56, // 00000000 00000001 01010110 0x00, 0x01, 0x56, // 00000000 00000001 01010110
// 0x01, // 00000001 // 0x01, // 00000001
}; };
// 001 00110101 10 000010 1 1 1 1 1 1 1 1 1 1 010 11 (000000 padding) // 001 00110101 10 000010 1 1 1 1 1 1 1 1 1 1 010 11 (000000 padding)
static final byte[] DATA_TYPE_4 = { 0x26, // 001 00110 static final byte[] DATA_TYPE_4 = { 0x26, // 001 00110
(byte) 0xb0, // 101 10 000 (byte) 0xb0, // 101 10 000
0x5f, // 010 1 1 1 1 1 0x5f, // 010 1 1 1 1 1
(byte) 0xfa, // 1 1 1 1 1 010 (byte) 0xfa, // 1 1 1 1 1 010
(byte) 0xc0 // 11 (000000 padding) (byte) 0xc0 // 11 (000000 padding)
}; };
// Image should be (6 x 4): // Image should be (6 x 4):
// 1 1 1 0 1 1 x x // 1 1 1 0 1 1 x x
// 1 1 1 0 1 1 x x // 1 1 1 0 1 1 x x
// 1 1 1 0 1 1 x x // 1 1 1 0 1 1 x x
// 1 1 0 0 1 1 x x // 1 1 0 0 1 1 x x
BufferedImage image; BufferedImage image;
@Before @Before
public void init() { public void init() {
image = new BufferedImage(6, 4, BufferedImage.TYPE_BYTE_BINARY); image = new BufferedImage(6, 4, BufferedImage.TYPE_BYTE_BINARY);
for (int y = 0; y < 4; y++) { for (int y = 0; y < 4; y++) {
for (int x = 0; x < 6; x++) { for (int x = 0; x < 6; x++) {
image.setRGB(x, y, x == 3 ? 0xff000000 : 0xffffffff); image.setRGB(x, y, x == 3 ? 0xff000000 : 0xffffffff);
} }
} }
image.setRGB(2, 3, 0xff000000); image.setRGB(2, 3, 0xff000000);
} }
@Test @Test
public void testDecodeType2() throws IOException { public void testDecodeType2() throws IOException {
InputStream stream = new CCITTFaxDecoderStream(new ByteArrayInputStream(DATA_TYPE_2), 6, InputStream stream = new CCITTFaxDecoderStream(new ByteArrayInputStream(DATA_TYPE_2), 6,
TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE, 1, 0L); TIFFBaseline.COMPRESSION_CCITT_MODIFIED_HUFFMAN_RLE, 1, 0L);
byte[] imageData = ((DataBufferByte) image.getData().getDataBuffer()).getData(); byte[] imageData = ((DataBufferByte) image.getData().getDataBuffer()).getData();
byte[] bytes = new byte[imageData.length]; byte[] bytes = new byte[imageData.length];
new DataInputStream(stream).readFully(bytes); new DataInputStream(stream).readFully(bytes);
assertArrayEquals(imageData, bytes); assertArrayEquals(imageData, bytes);
} }
@Test @Test
public void testDecodeType3_1D() throws IOException { public void testDecodeType3_1D() throws IOException {
InputStream stream = new CCITTFaxDecoderStream(new ByteArrayInputStream(DATA_G3_1D), 6, InputStream stream = new CCITTFaxDecoderStream(new ByteArrayInputStream(DATA_G3_1D), 6,
TIFFExtension.COMPRESSION_CCITT_T4, 1, 0L); TIFFExtension.COMPRESSION_CCITT_T4, 1, 0L);
byte[] imageData = ((DataBufferByte) image.getData().getDataBuffer()).getData(); byte[] imageData = ((DataBufferByte) image.getData().getDataBuffer()).getData();
byte[] bytes = new byte[imageData.length]; byte[] bytes = new byte[imageData.length];
new DataInputStream(stream).readFully(bytes); new DataInputStream(stream).readFully(bytes);
assertArrayEquals(imageData, bytes); assertArrayEquals(imageData, bytes);
} }
@Test @Test
public void testDecodeType3_1D_FILL() throws IOException { public void testDecodeType3_1D_FILL() throws IOException {
InputStream stream = new CCITTFaxDecoderStream(new ByteArrayInputStream(DATA_G3_1D_FILL), 6, InputStream stream = new CCITTFaxDecoderStream(new ByteArrayInputStream(DATA_G3_1D_FILL), 6,
TIFFExtension.COMPRESSION_CCITT_T4, 1, TIFFExtension.GROUP3OPT_FILLBITS); TIFFExtension.COMPRESSION_CCITT_T4, 1, TIFFExtension.GROUP3OPT_FILLBITS);
byte[] imageData = ((DataBufferByte) image.getData().getDataBuffer()).getData(); byte[] imageData = ((DataBufferByte) image.getData().getDataBuffer()).getData();
byte[] bytes = new byte[imageData.length]; byte[] bytes = new byte[imageData.length];
new DataInputStream(stream).readFully(bytes); new DataInputStream(stream).readFully(bytes);
assertArrayEquals(imageData, bytes); assertArrayEquals(imageData, bytes);
} }
@Test @Test
public void testDecodeType3_2D() throws IOException { public void testDecodeType3_2D() throws IOException {
InputStream stream = new CCITTFaxDecoderStream(new ByteArrayInputStream(DATA_G3_2D), 6, InputStream stream = new CCITTFaxDecoderStream(new ByteArrayInputStream(DATA_G3_2D), 6,
TIFFExtension.COMPRESSION_CCITT_T4, 1, TIFFExtension.GROUP3OPT_2DENCODING); TIFFExtension.COMPRESSION_CCITT_T4, 1, TIFFExtension.GROUP3OPT_2DENCODING);
byte[] imageData = ((DataBufferByte) image.getData().getDataBuffer()).getData(); byte[] imageData = ((DataBufferByte) image.getData().getDataBuffer()).getData();
byte[] bytes = new byte[imageData.length]; byte[] bytes = new byte[imageData.length];
new DataInputStream(stream).readFully(bytes); new DataInputStream(stream).readFully(bytes);
assertArrayEquals(imageData, bytes); assertArrayEquals(imageData, bytes);
} }
@Test @Test
public void testDecodeType3_2D_FILL() throws IOException { public void testDecodeType3_2D_FILL() throws IOException {
InputStream stream = new CCITTFaxDecoderStream(new ByteArrayInputStream(DATA_G3_2D_FILL), 6, InputStream stream = new CCITTFaxDecoderStream(new ByteArrayInputStream(DATA_G3_2D_FILL), 6,
TIFFExtension.COMPRESSION_CCITT_T4, 1, TIFFExtension.COMPRESSION_CCITT_T4, 1,
TIFFExtension.GROUP3OPT_2DENCODING | TIFFExtension.GROUP3OPT_FILLBITS); TIFFExtension.GROUP3OPT_2DENCODING | TIFFExtension.GROUP3OPT_FILLBITS);
byte[] imageData = ((DataBufferByte) image.getData().getDataBuffer()).getData(); byte[] imageData = ((DataBufferByte) image.getData().getDataBuffer()).getData();
byte[] bytes = new byte[imageData.length]; byte[] bytes = new byte[imageData.length];
new DataInputStream(stream).readFully(bytes); new DataInputStream(stream).readFully(bytes);
assertArrayEquals(imageData, bytes); assertArrayEquals(imageData, bytes);
} }
@Test @Test
public void testDecodeType4() throws IOException { public void testDecodeType4() throws IOException {
InputStream stream = new CCITTFaxDecoderStream(new ByteArrayInputStream(DATA_G4), 6, InputStream stream = new CCITTFaxDecoderStream(new ByteArrayInputStream(DATA_G4), 6,
TIFFExtension.COMPRESSION_CCITT_T6, 1, TIFFExtension.COMPRESSION_CCITT_T6, 1, 0L);
0L);
byte[] imageData = ((DataBufferByte) image.getData().getDataBuffer()).getData(); byte[] imageData = ((DataBufferByte) image.getData().getDataBuffer()).getData();
byte[] bytes = new byte[imageData.length]; byte[] bytes = new byte[imageData.length];
new DataInputStream(stream).readFully(bytes); new DataInputStream(stream).readFully(bytes);
assertArrayEquals(imageData, bytes); assertArrayEquals(imageData, bytes);
} }
} }