blob: 3cc77874c6479501c5740f8f1b4f49025a02e1ad [file] [log] [blame]
/*
* 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.commons.sanselan.common.itu_t4;
import java.io.ByteArrayInputStream;
import org.apache.commons.sanselan.ImageReadException;
import org.apache.commons.sanselan.common.BitArrayOutputStream;
import org.apache.commons.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();
}
}