Author: damjan
Date: Sat Dec 10 10:14:26 2011
New Revision: 1212757
URL: http://svn.apache.org/viewvc?rev=1212757&view=rev
Log:
Add support for TIFF files with compression=2,
(CCITT Group 3 1-Dimensional Modified Huffman
run length encoding), and a sample image
that tests this. CCITT is now the ITU,
so the naming reflects this.
Jira issue key: SANSELAN-48
Added:
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/BitArrayOutputStream.java
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/itu_t4/
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/itu_t4/HuffmanTree.java
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/itu_t4/HuffmanTreeException.java
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/itu_t4/T4Compression.java
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/itu_t4/T4_T6_Tables.java
commons/proper/sanselan/trunk/src/test/data/images/tiff/3/
commons/proper/sanselan/trunk/src/test/data/images/tiff/3/1pagefax.tif
(with props)
commons/proper/sanselan/trunk/src/test/data/images/tiff/3/info.txt
Modified:
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/BitInputStreamFlexible.java
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReader.java
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReaderStrips.java
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReaderTiled.java
Added:
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/BitArrayOutputStream.java
URL:
http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/BitArrayOutputStream.java?rev=1212757&view=auto
==============================================================================
---
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/BitArrayOutputStream.java
(added)
+++
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/BitArrayOutputStream.java
Sat Dec 10 10:14:26 2011
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sanselan.common;
+
+public class BitArrayOutputStream {
+ private byte[] buffer;
+ private int bytesWritten = 0;
+ private int cache = 0;
+ private int cacheMask = 0x80;
+
+ public BitArrayOutputStream() {
+ buffer = new byte[16];
+ }
+
+ public BitArrayOutputStream(int size) {
+ buffer = new byte[size];
+ }
+
+ public int size() {
+ return bytesWritten;
+ }
+
+ public byte[] toByteArray() {
+ flush();
+ if (bytesWritten == buffer.length) {
+ return buffer;
+ }
+ byte[] out = new byte[bytesWritten];
+ System.arraycopy(buffer, 0, out, 0, bytesWritten);
+ return out;
+ }
+
+ public void close() {
+ flush();
+ }
+
+ public void flush() {
+ if (cacheMask != 0x80) {
+ writeByte(cache);
+ cache = 0;
+ cacheMask = 0x80;
+ }
+ }
+
+ public void write(int b) {
+ flush();
+ writeByte(b);
+ }
+
+ public void writeBit(int bit) {
+ if (bit != 0) {
+ cache |= cacheMask;
+ }
+ cacheMask >>>= 1;
+ if (cacheMask == 0) {
+ flush();
+ }
+ }
+
+ private void writeByte(int b) {
+ if (bytesWritten >= buffer.length) {
+ byte[] bigger = new byte[buffer.length * 2];
+ System.arraycopy(buffer, 0, bigger, 0, bytesWritten);
+ buffer = bigger;
+ }
+ buffer[bytesWritten++] = (byte)b;
+ }
+}
Modified:
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/BitInputStreamFlexible.java
URL:
http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/BitInputStreamFlexible.java?rev=1212757&r1=1212756&r2=1212757&view=diff
==============================================================================
---
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/BitInputStreamFlexible.java
(original)
+++
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/BitInputStreamFlexible.java
Sat Dec 10 10:14:26 2011
@@ -73,9 +73,9 @@ public class BitInputStreamFlexible exte
cache = is.read();
if (cache < 0)
throw new IOException("couldn't read bits");
- System.out.println("cache 1: " + cache + " ("
- + Integer.toHexString(cache) + ", "
- + Integer.toBinaryString(cache) + ")");
+// System.out.println("cache 1: " + cache + " ("
+// + Integer.toHexString(cache) + ", "
+// + Integer.toBinaryString(cache) + ")");
bytesRead++;
result = (result << 8) | (0xff & cache);
count -= 8;
@@ -85,9 +85,9 @@ public class BitInputStreamFlexible exte
cache = is.read();
if (cache < 0)
throw new IOException("couldn't read bits");
- System.out.println("cache 2: " + cache + " ("
- + Integer.toHexString(cache) + ", "
- + Integer.toBinaryString(cache) + ")");
+// System.out.println("cache 2: " + cache + " ("
+// + Integer.toHexString(cache) + ", "
+// + Integer.toBinaryString(cache) + ")");
bytesRead++;
cacheBitsRemaining = 8 - count;
result = (result << count)
Added:
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/itu_t4/HuffmanTree.java
URL:
http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/itu_t4/HuffmanTree.java?rev=1212757&view=auto
==============================================================================
---
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/itu_t4/HuffmanTree.java
(added)
+++
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/itu_t4/HuffmanTree.java
Sat Dec 10 10:14:26 2011
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sanselan.common.itu_t4;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import org.apache.sanselan.common.BitInputStreamFlexible;
+
+/**
+ * A Huffman tree implemented as 1 array for high locality of reference.
+ */
+public class HuffmanTree {
+ private static class Node {
+ boolean isEmpty = true;
+ Object value = null;
+ }
+ private ArrayList nodes = new ArrayList();
+
+ public final void insert(String pattern, Object value) throws
HuffmanTreeException {
+ int position = 0;
+ Node node = growAndGetNode(position);
+ if (node.value != null) {
+ throw new HuffmanTreeException("Can't add child to a leaf");
+ }
+ for(int patternPosition = 0; patternPosition < pattern.length();
patternPosition++) {
+ char nextChar = pattern.charAt(patternPosition);
+ if (nextChar == '0') {
+ position = (position << 1) + 1;
+ } else {
+ position = (position + 1) << 1;
+ }
+ node = growAndGetNode(position);
+ if (node.value != null) {
+ throw new HuffmanTreeException("Can't add child to a leaf");
+ }
+ }
+ node.value = value;
+ }
+
+ private Node growAndGetNode(int position) {
+ while (position >= nodes.size()) {
+ nodes.add(new Node());
+ }
+ Node node = (Node) nodes.get(position);
+ node.isEmpty = false;
+ return node;
+ }
+
+ public final Object decode(BitInputStreamFlexible bitStream) throws
HuffmanTreeException {
+ int position = 0;
+ Node node = (Node) nodes.get(0);
+ while (node.value == null) {
+ int nextBit;
+ try {
+ nextBit = bitStream.readBits(1);
+ } catch (IOException ioEx) {
+ throw new HuffmanTreeException("Error reading stream for
huffman tree", ioEx);
+ }
+ if (nextBit == 0) {
+ position = (position << 1) + 1;
+ } else {
+ position = (position + 1) << 1;
+ }
+ if (position >= nodes.size()) {
+ throw new HuffmanTreeException("Invalid bit pattern");
+ }
+ node = (Node) nodes.get(position);
+ if (node.isEmpty) {
+ throw new HuffmanTreeException("Invalid bit pattern");
+ }
+ }
+ return node.value;
+ }
+}
Added:
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/itu_t4/HuffmanTreeException.java
URL:
http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/itu_t4/HuffmanTreeException.java?rev=1212757&view=auto
==============================================================================
---
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/itu_t4/HuffmanTreeException.java
(added)
+++
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/itu_t4/HuffmanTreeException.java
Sat Dec 10 10:14:26 2011
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sanselan.common.itu_t4;
+
+public class HuffmanTreeException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ public HuffmanTreeException(String message) {
+ super(message);
+ }
+
+ public HuffmanTreeException(String message, Throwable throwable) {
+ super(message, throwable);
+ }
+}
Added:
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/itu_t4/T4Compression.java
URL:
http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/itu_t4/T4Compression.java?rev=1212757&view=auto
==============================================================================
---
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/itu_t4/T4Compression.java
(added)
+++
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/itu_t4/T4Compression.java
Sat Dec 10 10:14:26 2011
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sanselan.common.itu_t4;
+
+import java.io.ByteArrayInputStream;
+
+import org.apache.sanselan.ImageReadException;
+import org.apache.sanselan.common.BitArrayOutputStream;
+import org.apache.sanselan.common.BitInputStreamFlexible;
+
+
+public class T4Compression {
+ private static final HuffmanTree whiteRunLengths = new HuffmanTree();
+ private static final HuffmanTree blackRunLengths = new HuffmanTree();
+
+ static {
+ try {
+ for (int i = 0; i < T4_T6_Tables.whiteTerminatingCodes.length;
i++) {
+ T4_T6_Tables.Entry entry =
T4_T6_Tables.whiteTerminatingCodes[i];
+ whiteRunLengths.insert(entry.bitString, entry.value);
+ }
+ for (int i = 0; i < T4_T6_Tables.whiteMakeUpCodes.length; i++) {
+ T4_T6_Tables.Entry entry = T4_T6_Tables.whiteMakeUpCodes[i];
+ whiteRunLengths.insert(entry.bitString, entry.value);
+ }
+ for (int i = 0; i < T4_T6_Tables.blackTerminatingCodes.length;
i++) {
+ T4_T6_Tables.Entry entry =
T4_T6_Tables.blackTerminatingCodes[i];
+ blackRunLengths.insert(entry.bitString, entry.value);
+ }
+ for (int i = 0; i < T4_T6_Tables.blackMakeUpCodes.length; i++) {
+ T4_T6_Tables.Entry entry = T4_T6_Tables.blackMakeUpCodes[i];
+ blackRunLengths.insert(entry.bitString, entry.value);
+ }
+ for (int i = 0; i < T4_T6_Tables.additionalMakeUpCodes.length;
i++) {
+ T4_T6_Tables.Entry entry =
T4_T6_Tables.additionalMakeUpCodes[i];
+ whiteRunLengths.insert(entry.bitString, entry.value);
+ blackRunLengths.insert(entry.bitString, entry.value);
+ }
+ } catch (HuffmanTreeException cannotHappen) {
+ }
+ }
+
+ public static byte[] decompress1D(byte[] compressed, int width, int
height) throws ImageReadException {
+ BitInputStreamFlexible inputStream = new BitInputStreamFlexible(
+ new ByteArrayInputStream(compressed));
+ BitArrayOutputStream outputStream = new BitArrayOutputStream();
+ for (int y = 0; y < height; y++) {
+ int totalRunLength = 0;
+ boolean isWhite = true;
+ boolean isTerminated = false;
+ int rowLength;
+ for (rowLength = 0; rowLength < width || !isTerminated;) {
+ Integer runLength;
+ int color;
+ try {
+ if (isWhite) {
+ runLength =
(Integer)whiteRunLengths.decode(inputStream);
+ color = 0x00;
+ } else {
+ runLength =
(Integer)blackRunLengths.decode(inputStream);
+ color = 0x01;
+ }
+ } catch (HuffmanTreeException huffmanException) {
+ throw new ImageReadException("Decompression error",
huffmanException);
+ }
+
+ totalRunLength += runLength.intValue();
+ rowLength += runLength.intValue();
+ if (runLength.intValue() <= 63) {
+ for (int i = 0; i < totalRunLength; i++) {
+ outputStream.writeBit(color);
+ }
+ totalRunLength = 0;
+ isWhite = !isWhite;
+ isTerminated = true;
+ } else {
+ isTerminated = false;
+ }
+ }
+
+ if (rowLength == width) {
+ inputStream.flushCache();
+ outputStream.flush();
+ } else if (rowLength > width) {
+ throw new ImageReadException("Unrecoverable row length error
in image row " + y);
+ }
+ }
+ return outputStream.toByteArray();
+ }
+}
Added:
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/itu_t4/T4_T6_Tables.java
URL:
http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/itu_t4/T4_T6_Tables.java?rev=1212757&view=auto
==============================================================================
---
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/itu_t4/T4_T6_Tables.java
(added)
+++
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/common/itu_t4/T4_T6_Tables.java
Sat Dec 10 10:14:26 2011
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sanselan.common.itu_t4;
+
+public class T4_T6_Tables {
+ public static class Entry {
+ String bitString;
+ Integer value;
+
+ public Entry(String bitString, Integer value) {
+ this.bitString = bitString;
+ this.value = value;
+ }
+ }
+
+ public static final Entry[] whiteTerminatingCodes = {
+ new Entry("00110101", Integer.valueOf(0)),
+ new Entry("000111", Integer.valueOf(1)),
+ new Entry("0111", Integer.valueOf(2)),
+ new Entry("1000", Integer.valueOf(3)),
+ new Entry("1011", Integer.valueOf(4)),
+ new Entry("1100", Integer.valueOf(5)),
+ new Entry("1110", Integer.valueOf(6)),
+ new Entry("1111", Integer.valueOf(7)),
+ new Entry("10011", Integer.valueOf(8)),
+ new Entry("10100", Integer.valueOf(9)),
+ new Entry("00111", Integer.valueOf(10)),
+ new Entry("01000", Integer.valueOf(11)),
+ new Entry("001000", Integer.valueOf(12)),
+ new Entry("000011", Integer.valueOf(13)),
+ new Entry("110100", Integer.valueOf(14)),
+ new Entry("110101", Integer.valueOf(15)),
+ new Entry("101010", Integer.valueOf(16)),
+ new Entry("101011", Integer.valueOf(17)),
+ new Entry("0100111", Integer.valueOf(18)),
+ new Entry("0001100", Integer.valueOf(19)),
+ new Entry("0001000", Integer.valueOf(20)),
+ new Entry("0010111", Integer.valueOf(21)),
+ new Entry("0000011", Integer.valueOf(22)),
+ new Entry("0000100", Integer.valueOf(23)),
+ new Entry("0101000", Integer.valueOf(24)),
+ new Entry("0101011", Integer.valueOf(25)),
+ new Entry("0010011", Integer.valueOf(26)),
+ new Entry("0100100", Integer.valueOf(27)),
+ new Entry("0011000", Integer.valueOf(28)),
+ new Entry("00000010", Integer.valueOf(29)),
+ new Entry("00000011", Integer.valueOf(30)),
+ new Entry("00011010", Integer.valueOf(31)),
+ new Entry("00011011", Integer.valueOf(32)),
+ new Entry("00010010", Integer.valueOf(33)),
+ new Entry("00010011", Integer.valueOf(34)),
+ new Entry("00010100", Integer.valueOf(35)),
+ new Entry("00010101", Integer.valueOf(36)),
+ new Entry("00010110", Integer.valueOf(37)),
+ new Entry("00010111", Integer.valueOf(38)),
+ new Entry("00101000", Integer.valueOf(39)),
+ new Entry("00101001", Integer.valueOf(40)),
+ new Entry("00101010", Integer.valueOf(41)),
+ new Entry("00101011", Integer.valueOf(42)),
+ new Entry("00101100", Integer.valueOf(43)),
+ new Entry("00101101", Integer.valueOf(44)),
+ new Entry("00000100", Integer.valueOf(45)),
+ new Entry("00000101", Integer.valueOf(46)),
+ new Entry("00001010", Integer.valueOf(47)),
+ new Entry("00001011", Integer.valueOf(48)),
+ new Entry("01010010", Integer.valueOf(49)),
+ new Entry("01010011", Integer.valueOf(50)),
+ new Entry("01010100", Integer.valueOf(51)),
+ new Entry("01010101", Integer.valueOf(52)),
+ new Entry("00100100", Integer.valueOf(53)),
+ new Entry("00100101", Integer.valueOf(54)),
+ new Entry("01011000", Integer.valueOf(55)),
+ new Entry("01011001", Integer.valueOf(56)),
+ new Entry("01011010", Integer.valueOf(57)),
+ new Entry("01011011", Integer.valueOf(58)),
+ new Entry("01001010", Integer.valueOf(59)),
+ new Entry("01001011", Integer.valueOf(60)),
+ new Entry("00110010", Integer.valueOf(61)),
+ new Entry("00110011", Integer.valueOf(62)),
+ new Entry("00110100", Integer.valueOf(63)),
+ };
+
+ public static final Entry[] blackTerminatingCodes = {
+ new Entry("0000110111", Integer.valueOf(0)),
+ new Entry("010", Integer.valueOf(1)),
+ new Entry("11", Integer.valueOf(2)),
+ new Entry("10", Integer.valueOf(3)),
+ new Entry("011", Integer.valueOf(4)),
+ new Entry("0011", Integer.valueOf(5)),
+ new Entry("0010", Integer.valueOf(6)),
+ new Entry("00011", Integer.valueOf(7)),
+ new Entry("000101", Integer.valueOf(8)),
+ new Entry("000100", Integer.valueOf(9)),
+ new Entry("0000100", Integer.valueOf(10)),
+ new Entry("0000101", Integer.valueOf(11)),
+ new Entry("0000111", Integer.valueOf(12)),
+ new Entry("00000100", Integer.valueOf(13)),
+ new Entry("00000111", Integer.valueOf(14)),
+ new Entry("000011000", Integer.valueOf(15)),
+ new Entry("0000010111", Integer.valueOf(16)),
+ new Entry("0000011000", Integer.valueOf(17)),
+ new Entry("0000001000", Integer.valueOf(18)),
+ new Entry("00001100111", Integer.valueOf(19)),
+ new Entry("00001101000", Integer.valueOf(20)),
+ new Entry("00001101100", Integer.valueOf(21)),
+ new Entry("00000110111", Integer.valueOf(22)),
+ new Entry("00000101000", Integer.valueOf(23)),
+ new Entry("00000010111", Integer.valueOf(24)),
+ new Entry("00000011000", Integer.valueOf(25)),
+ new Entry("000011001010", Integer.valueOf(26)),
+ new Entry("000011001011", Integer.valueOf(27)),
+ new Entry("000011001100", Integer.valueOf(28)),
+ new Entry("000011001101", Integer.valueOf(29)),
+ new Entry("000001101000", Integer.valueOf(30)),
+ new Entry("000001101001", Integer.valueOf(31)),
+ new Entry("000001101010", Integer.valueOf(32)),
+ new Entry("000001101011", Integer.valueOf(33)),
+ new Entry("000011010010", Integer.valueOf(34)),
+ new Entry("000011010011", Integer.valueOf(35)),
+ new Entry("000011010100", Integer.valueOf(36)),
+ new Entry("000011010101", Integer.valueOf(37)),
+ new Entry("000011010110", Integer.valueOf(38)),
+ new Entry("000011010111", Integer.valueOf(39)),
+ new Entry("000001101100", Integer.valueOf(40)),
+ new Entry("000001101101", Integer.valueOf(41)),
+ new Entry("000011011010", Integer.valueOf(42)),
+ new Entry("000011011011", Integer.valueOf(43)),
+ new Entry("000001010100", Integer.valueOf(44)),
+ new Entry("000001010101", Integer.valueOf(45)),
+ new Entry("000001010110", Integer.valueOf(46)),
+ new Entry("000001010111", Integer.valueOf(47)),
+ new Entry("000001100100", Integer.valueOf(48)),
+ new Entry("000001100101", Integer.valueOf(49)),
+ new Entry("000001010010", Integer.valueOf(50)),
+ new Entry("000001010011", Integer.valueOf(51)),
+ new Entry("000000100100", Integer.valueOf(52)),
+ new Entry("000000110111", Integer.valueOf(53)),
+ new Entry("000000111000", Integer.valueOf(54)),
+ new Entry("000000100111", Integer.valueOf(55)),
+ new Entry("000000101000", Integer.valueOf(56)),
+ new Entry("000001011000", Integer.valueOf(57)),
+ new Entry("000001011001", Integer.valueOf(58)),
+ new Entry("000000101011", Integer.valueOf(59)),
+ new Entry("000000101100", Integer.valueOf(60)),
+ new Entry("000001011010", Integer.valueOf(61)),
+ new Entry("000001100110", Integer.valueOf(62)),
+ new Entry("000001100111", Integer.valueOf(63)),
+ };
+
+ public static final Entry[] whiteMakeUpCodes = {
+ new Entry("11011", Integer.valueOf(64)),
+ new Entry("10010", Integer.valueOf(128)),
+ new Entry("010111", Integer.valueOf(192)),
+ new Entry("0110111", Integer.valueOf(256)),
+ new Entry("00110110", Integer.valueOf(320)),
+ new Entry("00110111", Integer.valueOf(384)),
+ new Entry("01100100", Integer.valueOf(448)),
+ new Entry("01100101", Integer.valueOf(512)),
+ new Entry("01101000", Integer.valueOf(576)),
+ new Entry("01100111", Integer.valueOf(640)),
+ new Entry("011001100", Integer.valueOf(704)),
+ new Entry("011001101", Integer.valueOf(768)),
+ new Entry("011010010", Integer.valueOf(832)),
+ new Entry("011010011", Integer.valueOf(896)),
+ new Entry("011010100", Integer.valueOf(960)),
+ new Entry("011010101", Integer.valueOf(1024)),
+ new Entry("011010110", Integer.valueOf(1088)),
+ new Entry("011010111", Integer.valueOf(1152)),
+ new Entry("011011000", Integer.valueOf(1216)),
+ new Entry("011011001", Integer.valueOf(1280)),
+ new Entry("011011010", Integer.valueOf(1344)),
+ new Entry("011011011", Integer.valueOf(1408)),
+ new Entry("010011000", Integer.valueOf(1472)),
+ new Entry("010011001", Integer.valueOf(1536)),
+ new Entry("010011010", Integer.valueOf(1600)),
+ new Entry("011000", Integer.valueOf(1664)),
+ new Entry("010011011", Integer.valueOf(1728)),
+ new Entry("000000000001", Integer.valueOf(0)) // EOL
+ };
+
+ public static final Entry[] blackMakeUpCodes = {
+ new Entry("0000001111", Integer.valueOf(64)),
+ new Entry("000011001000", Integer.valueOf(128)),
+ new Entry("000011001001", Integer.valueOf(192)),
+ new Entry("000001011011", Integer.valueOf(256)),
+ new Entry("000000110011", Integer.valueOf(320)),
+ new Entry("000000110100", Integer.valueOf(384)),
+ new Entry("000000110101", Integer.valueOf(448)),
+ new Entry("0000001101100", Integer.valueOf(512)),
+ new Entry("0000001101101", Integer.valueOf(576)),
+ new Entry("0000001001010", Integer.valueOf(640)),
+ new Entry("0000001001011", Integer.valueOf(704)),
+ new Entry("0000001001100", Integer.valueOf(768)),
+ new Entry("0000001001101", Integer.valueOf(832)),
+ new Entry("0000001110010", Integer.valueOf(896)),
+ new Entry("0000001110011", Integer.valueOf(960)),
+ new Entry("0000001110100", Integer.valueOf(1024)),
+ new Entry("0000001110101", Integer.valueOf(1088)),
+ new Entry("0000001110110", Integer.valueOf(1152)),
+ new Entry("0000001110111", Integer.valueOf(1216)),
+ new Entry("0000001010010", Integer.valueOf(1280)),
+ new Entry("0000001010011", Integer.valueOf(1344)),
+ new Entry("0000001010100", Integer.valueOf(1408)),
+ new Entry("0000001010101", Integer.valueOf(1472)),
+ new Entry("0000001011010", Integer.valueOf(1536)),
+ new Entry("0000001011011", Integer.valueOf(1600)),
+ new Entry("0000001100100", Integer.valueOf(1664)),
+ new Entry("0000001100101", Integer.valueOf(1728)),
+ new Entry("00000000000", Integer.valueOf(0)) // EOL
+ };
+
+ public static final Entry[] additionalMakeUpCodes = {
+ new Entry("00000001000", Integer.valueOf(1792)),
+ new Entry("00000001100", Integer.valueOf(1856)),
+ new Entry("00000001101", Integer.valueOf(1920)),
+ new Entry("000000010010", Integer.valueOf(1984)),
+ new Entry("000000010011", Integer.valueOf(2048)),
+ new Entry("000000010100", Integer.valueOf(2112)),
+ new Entry("000000010101", Integer.valueOf(2176)),
+ new Entry("000000010110", Integer.valueOf(2240)),
+ new Entry("000000010111", Integer.valueOf(2304)),
+ new Entry("000000011100", Integer.valueOf(2368)),
+ new Entry("000000011101", Integer.valueOf(2432)),
+ new Entry("000000011110", Integer.valueOf(2496)),
+ new Entry("000000011111", Integer.valueOf(2560)),
+ };
+}
Modified:
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReader.java
URL:
http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReader.java?rev=1212757&r1=1212756&r2=1212757&view=diff
==============================================================================
---
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReader.java
(original)
+++
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReader.java
Sat Dec 10 10:14:26 2011
@@ -25,6 +25,7 @@ import org.apache.sanselan.ImageReadExce
import org.apache.sanselan.common.BinaryConstants;
import org.apache.sanselan.common.BitInputStream;
import org.apache.sanselan.common.PackBits;
+import org.apache.sanselan.common.itu_t4.T4Compression;
import org.apache.sanselan.common.mylzw.MyLZWDecompressor;
import org.apache.sanselan.formats.tiff.constants.TiffConstants;
import
org.apache.sanselan.formats.tiff.photometricinterpreters.PhotometricInterpreter;
@@ -37,14 +38,18 @@ public abstract class DataReader impleme
protected final int predictor;
protected final int samplesPerPixel;
+ protected final int width, height;
public DataReader(PhotometricInterpreter photometricInterpreter,
- int bitsPerSample[], int predictor, int samplesPerPixel)
+ int bitsPerSample[], int predictor, int samplesPerPixel,
+ int width, int height)
{
this.photometricInterpreter = photometricInterpreter;
this.bitsPerSample = bitsPerSample;
this.samplesPerPixel = samplesPerPixel;
this.predictor = predictor;
+ this.width = width;
+ this.height = height;
last = new int[samplesPerPixel];
}
@@ -101,11 +106,10 @@ public abstract class DataReader impleme
{
switch (compression)
{
- case 1 : // None;
+ case TIFF_COMPRESSION_UNCOMPRESSED : // None;
return compressed;
- case 2 : // CCITT Group 3 1-Dimensional Modified Huffman
run-length encoding.
- throw new ImageReadException("Tiff: unknown compression: "
- + compression);
+ case TIFF_COMPRESSION_CCITT_1D : // CCITT Group 3 1-Dimensional
Modified Huffman run-length encoding.
+ return T4Compression.decompress1D(compressed, width, height);
case TIFF_COMPRESSION_LZW : // LZW
{
InputStream is = new ByteArrayInputStream(compressed);
@@ -132,7 +136,7 @@ public abstract class DataReader impleme
}
default :
- throw new ImageReadException("Tiff: unknown compression: "
+ throw new ImageReadException("Tiff: unknown/unsupported
compression: "
+ compression);
}
}
Modified:
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReaderStrips.java
URL:
http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReaderStrips.java?rev=1212757&r1=1212756&r2=1212757&view=diff
==============================================================================
---
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReaderStrips.java
(original)
+++
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReaderStrips.java
Sat Dec 10 10:14:26 2011
@@ -29,7 +29,6 @@ public final class DataReaderStrips exte
{
private final int bitsPerPixel;
- private final int width, height;
private final int compression;
private final int rowsPerStrip;
@@ -40,11 +39,9 @@ public final class DataReaderStrips exte
int samplesPerPixel, int width, int height, int compression,
int rowsPerStrip, TiffImageData.Strips imageData)
{
- super(photometricInterpreter, bitsPerSample, predictor,
samplesPerPixel);
+ super(photometricInterpreter, bitsPerSample, predictor,
samplesPerPixel, width, height);
this.bitsPerPixel = bitsPerPixel;
- this.width = width;
- this.height = height;
this.compression = compression;
this.rowsPerStrip = rowsPerStrip;
this.imageData = imageData;
Modified:
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReaderTiled.java
URL:
http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReaderTiled.java?rev=1212757&r1=1212756&r2=1212757&view=diff
==============================================================================
---
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReaderTiled.java
(original)
+++
commons/proper/sanselan/trunk/src/main/java/org/apache/sanselan/formats/tiff/datareaders/DataReaderTiled.java
Sat Dec 10 10:14:26 2011
@@ -33,8 +33,6 @@ public final class DataReaderTiled exten
private final int bitsPerPixel;
- private final int width, height;
-
private final int compression;
private final TiffImageData.Tiles imageData;
@@ -44,14 +42,12 @@ public final class DataReaderTiled exten
int bitsPerSample[], int predictor, int samplesPerPixel, int width,
int height, int compression, TiffImageData.Tiles imageData)
{
- super(photometricInterpreter, bitsPerSample, predictor,
samplesPerPixel);
+ super(photometricInterpreter, bitsPerSample, predictor,
samplesPerPixel, width, height);
this.tileWidth = tileWidth;
this.tileLength = tileLength;
this.bitsPerPixel = bitsPerPixel;
- this.width = width;
- this.height = height;
this.compression = compression;
this.imageData = imageData;
Added: commons/proper/sanselan/trunk/src/test/data/images/tiff/3/1pagefax.tif
URL:
http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/test/data/images/tiff/3/1pagefax.tif?rev=1212757&view=auto
==============================================================================
Binary file - no diff available.
Propchange:
commons/proper/sanselan/trunk/src/test/data/images/tiff/3/1pagefax.tif
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: commons/proper/sanselan/trunk/src/test/data/images/tiff/3/info.txt
URL:
http://svn.apache.org/viewvc/commons/proper/sanselan/trunk/src/test/data/images/tiff/3/info.txt?rev=1212757&view=auto
==============================================================================
--- commons/proper/sanselan/trunk/src/test/data/images/tiff/3/info.txt (added)
+++ commons/proper/sanselan/trunk/src/test/data/images/tiff/3/info.txt Sat Dec
10 10:14:26 2011
@@ -0,0 +1,9 @@
+1pagefax.tiff
+-------------
+Contributed to the project by Damjan Jovanovic
+
+This is a completely blank standard resolution fax,
+in compression=2 format.
+
+It was generated from a similarly blank PDF using Ghostscript:
+gs -q -sDEVICE=tiffcrle -r204x98 -dBATCH -dPDFFitPage -dNOPAUSE
-sOutputFile=1pagefax.tif 1pagefax.pdf