in src/main/java/org/apache/pdfbox/jbig2/decoder/mmr/MMRDecompressor.java [288:496]
private final int uncompress2D(RunData runData, int[] referenceOffsets, int refRunLength,
int[] runOffsets, int width)
{
int referenceBufferOffset = 0;
int currentBufferOffset = 0;
int currentLineBitPosition = 0;
boolean whiteRun = true; // Always start with a white run
Code code = null; // Storage var for current code being processed
referenceOffsets[refRunLength] = referenceOffsets[refRunLength + 1] = width;
referenceOffsets[refRunLength + 2] = referenceOffsets[refRunLength + 3] = width + 1;
try
{
decodeLoop: while (currentLineBitPosition < width)
{
// Get the mode code
code = runData.uncompressGetCode(modeTable);
if (code == null)
{
runData.offset++;
break decodeLoop;
}
// Add the code length to the bit offset
runData.offset += code.bitLength;
switch (code.runLength)
{
case MMRConstants.CODE_V0:
currentLineBitPosition = referenceOffsets[referenceBufferOffset];
break;
case MMRConstants.CODE_VR1:
currentLineBitPosition = referenceOffsets[referenceBufferOffset] + 1;
break;
case MMRConstants.CODE_VL1:
currentLineBitPosition = referenceOffsets[referenceBufferOffset] - 1;
break;
case MMRConstants.CODE_H:
for (int ever = 1; ever > 0;)
{
code = runData
.uncompressGetCode(whiteRun == true ? whiteTable : blackTable);
if (code == null)
break decodeLoop;
runData.offset += code.bitLength;
if (code.runLength < 64)
{
if (code.runLength < 0)
{
runOffsets[currentBufferOffset++] = currentLineBitPosition;
code = null;
break decodeLoop;
}
currentLineBitPosition += code.runLength;
runOffsets[currentBufferOffset++] = currentLineBitPosition;
break;
}
currentLineBitPosition += code.runLength;
}
final int firstHalfBitPos = currentLineBitPosition;
for (int ever1 = 1; ever1 > 0;)
{
code = runData
.uncompressGetCode(whiteRun != true ? whiteTable : blackTable);
if (code == null)
break decodeLoop;
runData.offset += code.bitLength;
if (code.runLength < 64)
{
if (code.runLength < 0)
{
runOffsets[currentBufferOffset++] = currentLineBitPosition;
break decodeLoop;
}
currentLineBitPosition += code.runLength;
// don't generate 0-length run at EOL for cases where the line ends in an H-run.
if (currentLineBitPosition < width
|| currentLineBitPosition != firstHalfBitPos)
runOffsets[currentBufferOffset++] = currentLineBitPosition;
break;
}
currentLineBitPosition += code.runLength;
}
while (currentLineBitPosition < width
&& referenceOffsets[referenceBufferOffset] <= currentLineBitPosition)
{
referenceBufferOffset += 2;
}
continue decodeLoop;
case MMRConstants.CODE_P:
referenceBufferOffset++;
currentLineBitPosition = referenceOffsets[referenceBufferOffset++];
continue decodeLoop;
case MMRConstants.CODE_VR2:
currentLineBitPosition = referenceOffsets[referenceBufferOffset] + 2;
break;
case MMRConstants.CODE_VL2:
currentLineBitPosition = referenceOffsets[referenceBufferOffset] - 2;
break;
case MMRConstants.CODE_VR3:
currentLineBitPosition = referenceOffsets[referenceBufferOffset] + 3;
break;
case MMRConstants.CODE_VL3:
currentLineBitPosition = referenceOffsets[referenceBufferOffset] - 3;
break;
case MMRConstants.EOL:
default:
System.err.println("Should not happen!");
// Possibly MMR Decoded
if (runData.offset == 12 && code.runLength == MMRConstants.EOL)
{
runData.offset = 0;
uncompress1D(runData, referenceOffsets, width);
runData.offset++;
uncompress1D(runData, runOffsets, width);
int retCode = uncompress1D(runData, referenceOffsets, width);
runData.offset++;
return retCode;
}
currentLineBitPosition = width;
continue decodeLoop;
}
// Only vertical modes get this far
if (currentLineBitPosition <= width)
{
whiteRun = !whiteRun;
runOffsets[currentBufferOffset++] = currentLineBitPosition;
if (referenceBufferOffset > 0)
{
referenceBufferOffset--;
}
else
{
referenceBufferOffset++;
}
while (currentLineBitPosition < width
&& referenceOffsets[referenceBufferOffset] <= currentLineBitPosition)
{
referenceBufferOffset += 2;
}
}
}
}
catch (Throwable t)
{
StringBuffer strBuf = new StringBuffer();
strBuf.append("whiteRun = ");
strBuf.append(whiteRun);
strBuf.append("\n");
strBuf.append("code = ");
strBuf.append(code);
strBuf.append("\n");
strBuf.append("refOffset = ");
strBuf.append(referenceBufferOffset);
strBuf.append("\n");
strBuf.append("curOffset = ");
strBuf.append(currentBufferOffset);
strBuf.append("\n");
strBuf.append("bitPos = ");
strBuf.append(currentLineBitPosition);
strBuf.append("\n");
strBuf.append("runData.offset = ");
strBuf.append(runData.offset);
strBuf.append(" ( byte:");
strBuf.append(runData.offset / 8);
strBuf.append(", bit:");
strBuf.append(runData.offset & 0x07);
strBuf.append(" )");
System.out.println(strBuf.toString());
return MMRConstants.EOF;
}
if (runOffsets[currentBufferOffset] != width)
{
runOffsets[currentBufferOffset] = width;
}
if (code == null)
{
return MMRConstants.EOL;
}
return currentBufferOffset;
}