public void DecodeT4()
{
int height = h;
int a0, a1, b1, b2;
int[] b = new int[2];
int entry, code, bits;
bool isWhite;
int currIndex = 0;
int[] temp;
if (data.Length < 2) {
throw new Exception("Insufficient data to read initial EOL.");
}
// The data should start with an EOL code
int next12 = NextNBits(12);
if (next12 != 1) {
++fails;
}
UpdatePointer(12);
// Find the first one-dimensionally encoded line.
int modeFlag = 0;
int lines = -1; // indicates imaginary line before first actual line.
while (modeFlag != 1) {
try {
modeFlag = FindNextLine();
lines++; // Normally 'lines' will be 0 on exiting loop.
} catch {
throw new Exception("No reference line present.");
}
}
int bitOffset;
// Then the 1D encoded scanline data will occur, changing elements
// array gets set.
DecodeNextScanline();
lines++;
lineBitNum += bitsPerScanline;
while (lines < height) {
// Every line must begin with an EOL followed by a bit which
// indicates whether the following scanline is 1D or 2D encoded.
try {
modeFlag = FindNextLine();
} catch {
++fails;
break;
}
if (modeFlag == 0) {
// 2D encoded scanline follows
// Initialize previous scanlines changing elements, and
// initialize current scanline's changing elements array
temp = prevChangingElems;
prevChangingElems = currChangingElems;
currChangingElems = temp;
currIndex = 0;
// a0 has to be set just before the start of this scanline.
a0 = -1;
isWhite = true;
bitOffset = 0;
lastChangingElement = 0;
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 = (int) (twoDCodes[entry] & 0xff);
// Get the code and the number of bits used up
code = (entry & 0x78) >> 3;
bits = entry & 0x07;
if (code == 0) {
if (!isWhite) {
SetToBlack(bitOffset, b2 - bitOffset);
}
bitOffset = a0 = b2;
// Set pointer to consume the correct number of bits.
UpdatePointer(7 - bits);
} else if (code == 1) {
// Horizontal
UpdatePointer(7 - bits);
// identify the next 2 codes.
int number;
if (isWhite) {
number = DecodeWhiteCodeWord();
bitOffset += number;
currChangingElems[currIndex++] = bitOffset;
number = DecodeBlackCodeWord();
SetToBlack(bitOffset, number);
bitOffset += number;
currChangingElems[currIndex++] = bitOffset;
} else {
number = DecodeBlackCodeWord();
SetToBlack(bitOffset, number);
bitOffset += number;
currChangingElems[currIndex++] = bitOffset;
number = DecodeWhiteCodeWord();
bitOffset += number;
currChangingElems[currIndex++] = bitOffset;
}
a0 = bitOffset;
} else if (code <= 8) {
// Vertical
a1 = b1 + (code - 5);
currChangingElems[currIndex++] = a1;
// We write the current color till a1 - 1 pos,
// since a1 is where the next color starts
if (!isWhite) {
SetToBlack(bitOffset, a1 - bitOffset);
}
bitOffset = a0 = a1;
isWhite = !isWhite;
UpdatePointer(7 - bits);
} else {
++fails;
// Find the next one-dimensionally encoded line.
int numLinesTested = 0;
while (modeFlag != 1) {
try {
modeFlag = FindNextLine();
numLinesTested++;
} catch {
return;
}
}
lines += numLinesTested - 1;
UpdatePointer(13);
break;
}
}
// Add the changing element beyond the current scanline for the
// other color too
currChangingElems[currIndex++] = bitOffset;
changingElemSize = currIndex;
} else { // modeFlag == 1
// 1D encoded scanline follows
DecodeNextScanline();
}
lineBitNum += bitsPerScanline;
lines++;
} // while (lines < height)
}