public void DecodeNextScanline(byte[] buffer,
int lineOffset, int bitOffset) {
int bits = 0, code = 0, isT = 0;
int current, entry, twoBits;
bool isWhite = true;
// Initialize starting of the changing elements array
changingElemSize = 0;
// While scanline not complete
while (bitOffset < w) {
while (isWhite) {
// White run
current = NextNBits(10);
entry = white[current];
// Get the 3 fields from the entry
isT = entry & 0x0001;
bits = (entry >> 1) & 0x0f;
if (bits == 12) { // Additional Make up code
// Get the next 2 bits
twoBits = NextLesserThan8Bits(2);
// Consolidate the 2 new bits and last 2 bits into 4 bits
current = ((current << 2) & 0x000c) | twoBits;
entry = additionalMakeup[current];
bits = (entry >> 1) & 0x07; // 3 bits 0000 0111
code = (entry >> 4) & 0x0fff; // 12 bits
bitOffset += code; // Skip white run
UpdatePointer(4 - bits);
} else if (bits == 0) { // ERROR
throw new Exception("Invalid code encountered.");
} else if (bits == 15) { // EOL
throw new Exception("EOL code word encountered in White run.");
} else {
// 11 bits - 0000 0111 1111 1111 = 0x07ff
code = (entry >> 5) & 0x07ff;
bitOffset += code;
UpdatePointer(10 - bits);
if (isT == 0) {
isWhite = false;
currChangingElems[changingElemSize++] = bitOffset;
}
}
}
// Check whether this run completed one width, if so
// advance to next byte boundary for compression = 2.
if (bitOffset == w) {
if (compression == 2) {
AdvancePointer();
}
break;
}
while (isWhite == false) {
// Black run
current = NextLesserThan8Bits(4);
entry = initBlack[current];
// Get the 3 fields from the entry
isT = entry & 0x0001;
bits = (entry >> 1) & 0x000f;
code = (entry >> 5) & 0x07ff;
if (code == 100) {
current = NextNBits(9);
entry = black[current];
// Get the 3 fields from the entry
isT = entry & 0x0001;
bits = (entry >> 1) & 0x000f;
code = (entry >> 5) & 0x07ff;
if (bits == 12) {
// Additional makeup codes
UpdatePointer(5);
current = NextLesserThan8Bits(4);
entry = additionalMakeup[current];
bits = (entry >> 1) & 0x07; // 3 bits 0000 0111
code = (entry >> 4) & 0x0fff; // 12 bits
SetToBlack(buffer, lineOffset, bitOffset, code);
bitOffset += code;
UpdatePointer(4 - bits);
} else if (bits == 15) {
// EOL code
throw new Exception("EOL code word encountered in Black run.");
} else {
SetToBlack(buffer, lineOffset, bitOffset, code);
bitOffset += code;
UpdatePointer(9 - bits);
if (isT == 0) {
isWhite = true;
currChangingElems[changingElemSize++] = bitOffset;
}
}
} else if (code == 200) {
// Is a Terminating code
current = NextLesserThan8Bits(2);
entry = twoBitBlack[current];
code = (entry >> 5) & 0x07ff;
bits = (entry >> 1) & 0x0f;
SetToBlack(buffer, lineOffset, bitOffset, code);
bitOffset += code;
UpdatePointer(2 - bits);
isWhite = true;
currChangingElems[changingElemSize++] = bitOffset;
} else {
// Is a Terminating code
SetToBlack(buffer, lineOffset, bitOffset, code);
bitOffset += code;
UpdatePointer(4 - bits);
isWhite = true;
currChangingElems[changingElemSize++] = bitOffset;
}
}
// Check whether this run completed one width
if (bitOffset == w) {
if (compression == 2) {
AdvancePointer();
}
break;
}
}
currChangingElems[changingElemSize++] = bitOffset;
}