in src/main/java/org/apache/xmlgraphics/image/codec/tiff/TIFFFaxDecoder.java [892:1106]
public synchronized void decodeT6(byte[] buffer,
byte[] compData,
int startX,
int height,
long tiffT6Options) {
this.data = compData;
compression = 4;
bitPointer = 0;
bytePointer = 0;
int scanlineStride = (w + 7) / 8;
int a0;
int a1;
int b1;
int b2;
int entry;
int code;
int bits;
boolean isWhite;
int currIndex;
int[] temp;
// Return values from getNextChangingElement
int[] b = new int[2];
// uncompressedMode - have written some code for this, but this
// has not been tested due to lack of test images using this optional
// uncompressedMode = (int)((tiffT6Options & 0x02) >> 1);
// Local cached reference
int[] cce = currChangingElems;
// Assume invisible preceding row of all white pixels and insert
// both black and white changing elements beyond the end of this
// imaginary scanline.
changingElemSize = 0;
cce[changingElemSize++] = w;
cce[changingElemSize++] = w;
int lineOffset = 0;
int bitOffset;
for (int lines = 0; lines < height; lines++) {
// a0 has to be set just before the start of the scanline.
a0 = -1;
isWhite = true;
// Assign the changing elements of the previous scanline to
// prevChangingElems and start putting this new scanline's
// changing elements into the currChangingElems.
temp = prevChangingElems;
prevChangingElems = currChangingElems;
cce = currChangingElems = temp;
currIndex = 0;
// Start decoding the scanline at startX in the raster
bitOffset = startX;
// Reset search start position for getNextChangingElement
lastChangingElement = 0;
// Till one whole scanline is decoded
while (bitOffset < w) {
// Get the next changing element
getNextChangingElement(a0, isWhite, b);
b1 = b[0];
b2 = b[1];
// Get the next seven bits
entry = nextLesserThan8Bits(7);
// Run these through the 2DCodes table
entry = twoDCodes[entry] & 0xff;
// Get the code and the number of bits used up
code = (entry & 0x78) >>> 3;
bits = entry & 0x07;
if (code == 0) { // Pass
// We always assume WhiteIsZero format for fax.
if (!isWhite) {
setToBlack(buffer, lineOffset, bitOffset,
b2 - bitOffset);
}
bitOffset = a0 = b2;
// Set pointer to only consume the correct number of bits.
updatePointer(7 - bits);
} else if (code == 1) { // Horizontal
// Set pointer to only consume the correct number of bits.
updatePointer(7 - bits);
// identify the next 2 alternating color codes.
int number;
if (isWhite) {
// Following are white and black runs
number = decodeWhiteCodeWord();
bitOffset += number;
cce[currIndex++] = bitOffset;
number = decodeBlackCodeWord();
setToBlack(buffer, lineOffset, bitOffset, number);
bitOffset += number;
cce[currIndex++] = bitOffset;
} else {
// First a black run and then a white run follows
number = decodeBlackCodeWord();
setToBlack(buffer, lineOffset, bitOffset, number);
bitOffset += number;
cce[currIndex++] = bitOffset;
number = decodeWhiteCodeWord();
bitOffset += number;
cce[currIndex++] = bitOffset;
}
a0 = bitOffset;
} else if (code <= 8) { // Vertical
a1 = b1 + (code - 5);
cce[currIndex++] = a1;
// We write the current color till a1 - 1 pos,
// since a1 is where the next color starts
if (!isWhite) {
setToBlack(buffer, lineOffset, bitOffset,
a1 - bitOffset);
}
bitOffset = a0 = a1;
isWhite = !isWhite;
updatePointer(7 - bits);
} else if (code == 11) {
if (nextLesserThan8Bits(3) != 7) {
throw new RuntimeException(PropertyUtil.getString("TIFFFaxDecoder5"));
}
int zeros = 0;
boolean exit = false;
while (!exit) {
while (nextLesserThan8Bits(1) != 1) {
zeros++;
}
if (zeros > 5) {
// Exit code
// Zeros before exit code
zeros = zeros - 6;
if (!isWhite && (zeros > 0)) {
cce[currIndex++] = bitOffset;
}
// Zeros before the exit code
bitOffset += zeros;
if (zeros > 0) {
// Some zeros have been written
isWhite = true;
}
// Read in the bit which specifies the color of
// the following run
if (nextLesserThan8Bits(1) == 0) {
if (!isWhite) {
cce[currIndex++] = bitOffset;
}
isWhite = true;
} else {
if (isWhite) {
cce[currIndex++] = bitOffset;
}
isWhite = false;
}
exit = true;
}
if (zeros == 5) {
if (!isWhite) {
cce[currIndex++] = bitOffset;
}
bitOffset += zeros;
// Last thing written was white
isWhite = true;
} else {
bitOffset += zeros;
cce[currIndex++] = bitOffset;
setToBlack(buffer, lineOffset, bitOffset, 1);
++bitOffset;
// Last thing written was black
isWhite = false;
}
}
} else {
throw new RuntimeException(PropertyUtil.getString("TIFFFaxDecoder5"));
}
}
// Add the changing element beyond the current scanline for the
// other color too
cce[currIndex++] = bitOffset;
// Number of changing elements in this scanline.
changingElemSize = currIndex;
lineOffset += scanlineStride;
}
}