private final int uncompress2D()

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;
    }