/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.pdfbox.jbig2.segments;

import java.io.IOException;

import org.apache.pdfbox.jbig2.Bitmap;
import org.apache.pdfbox.jbig2.Region;
import org.apache.pdfbox.jbig2.SegmentHeader;
import org.apache.pdfbox.jbig2.decoder.arithmetic.ArithmeticDecoder;
import org.apache.pdfbox.jbig2.decoder.arithmetic.CX;
import org.apache.pdfbox.jbig2.decoder.mmr.MMRDecompressor;
import org.apache.pdfbox.jbig2.err.InvalidHeaderValueException;
import org.apache.pdfbox.jbig2.io.SubInputStream;

/**
 * This class represents a generic region segment.<br>
 * Parsing is done as described in 7.4.5.<br>
 * Decoding procedure is done as described in 6.2.5.7 and 7.4.6.4.
 */
public class GenericRegion implements Region
{
    private SubInputStream subInputStream;
    private long dataHeaderOffset;
    private long dataHeaderLength;
    private long dataOffset;
    private long dataLength;

    /** Region segment information field, 7.4.1 */
    private RegionSegmentInformation regionInfo;

    /** Generic region segment flags, 7.4.6.2 */
    private boolean useExtTemplates;
    private boolean isTPGDon;
    private byte gbTemplate;
    private boolean isMMREncoded;

    /** Generic region segment AT flags, 7.4.6.3 */
    private short[] gbAtX;
    private short[] gbAtY;
    private boolean[] gbAtOverride;

    /**
     * If true, AT pixels are not on their nominal location and have to be overridden
     */
    private boolean override;

    /** Decoded data as pixel values (use row stride/width to wrap line) */
    private Bitmap regionBitmap;

    private ArithmeticDecoder arithDecoder;
    private CX cx;

    private MMRDecompressor mmrDecompressor;

    public GenericRegion()
    {
    }

    public GenericRegion(final SubInputStream subInputStream)
    {
        this.subInputStream = subInputStream;
        this.regionInfo = new RegionSegmentInformation(subInputStream);
    }

    private void parseHeader() throws IOException, InvalidHeaderValueException
    {
        regionInfo.parseHeader();

        /* Bit 5-7 */
        subInputStream.readBits(3); // Dirty read...

        /* Bit 4 */
        if (subInputStream.readBit() == 1)
        {
            useExtTemplates = true;
        }

        /* Bit 3 */
        if (subInputStream.readBit() == 1)
        {
            isTPGDon = true;
        }

        /* Bit 1-2 */
        gbTemplate = (byte) (subInputStream.readBits(2) & 0xf);

        /* Bit 0 */
        if (subInputStream.readBit() == 1)
        {
            isMMREncoded = true;
        }

        if (!isMMREncoded)
        {
            final int amountOfGbAt;
            if (gbTemplate == 0)
            {
                if (useExtTemplates)
                {
                    amountOfGbAt = 12;
                }
                else
                {
                    amountOfGbAt = 4;
                }
            }
            else
            {
                amountOfGbAt = 1;
            }

            readGbAtPixels(amountOfGbAt);
        }

        /* Segment data structure */
        computeSegmentDataStructure();
    }

    private void readGbAtPixels(final int amountOfGbAt) throws IOException
    {
        gbAtX = new short[amountOfGbAt];
        gbAtY = new short[amountOfGbAt];

        for (int i = 0; i < amountOfGbAt; i++)
        {
            gbAtX[i] = subInputStream.readByte();
            gbAtY[i] = subInputStream.readByte();
        }
    }

    private void computeSegmentDataStructure() throws IOException
    {
        dataOffset = subInputStream.getStreamPosition();
        dataHeaderLength = dataOffset - dataHeaderOffset;
        dataLength = subInputStream.length() - dataHeaderLength;
    }

    /**
     * The procedure is described in 6.2.5.7, page 17.
     * 
     * @return The decoded {@link Bitmap} of this region.
     */
    public Bitmap getRegionBitmap() throws IOException
    {
        if (null == regionBitmap)
        {

            if (isMMREncoded)
            {

                /*
                 * MMR DECODER CALL
                 */
                if (null == mmrDecompressor)
                {
                    mmrDecompressor = new MMRDecompressor(regionInfo.getBitmapWidth(),
                            regionInfo.getBitmapHeight(),
                            new SubInputStream(subInputStream, dataOffset, dataLength));
                }

                /* 6.2.6 */
                regionBitmap = mmrDecompressor.uncompress();

            }
            else
            {

                /*
                 * ARITHMETIC DECODER PROCEDURE for generic region segments
                 */

                updateOverrideFlags();

                /* 6.2.5.7 - 1) */
                int ltp = 0;

                if (arithDecoder == null)
                {
                    arithDecoder = new ArithmeticDecoder(subInputStream);
                }
                if (cx == null)
                {
                    cx = new CX(65536, 1);
                }

                /* 6.2.5.7 - 2) */
                regionBitmap = new Bitmap(regionInfo.getBitmapWidth(),
                        regionInfo.getBitmapHeight());

                final int paddedWidth = (regionBitmap.getWidth() + 7) & -8;

                /* 6.2.5.7 - 3 */
                for (int line = 0; line < regionBitmap.getHeight(); line++)
                {

                    /* 6.2.5.7 - 3 b) */
                    if (isTPGDon)
                    {
                        ltp ^= decodeSLTP();
                    }

                    /* 6.2.5.7 - 3 c) */
                    if (ltp == 1)
                    {
                        if (line > 0)
                        {
                            copyLineAbove(line);
                        }
                    }
                    else
                    {
                        /* 3 d) */
                        // NOT USED ATM - If corresponding pixel of SKIP bitmap is 0, set
                        // current pixel to 0. Something like that:
                        // if (useSkip) {
                        // for (int i = 1; i < rowstride; i++) {
                        // if (skip[pixel] == 1) {
                        // gbReg[pixel] = 0;
                        // }
                        // pixel++;
                        // }
                        // } else {
                        decodeLine(line, regionBitmap.getWidth(), regionBitmap.getRowStride(),
                                paddedWidth);
                        // }
                    }
                }
            }
        }

        // if (JBIG2ImageReader.DEBUG)
        // if (header != null && header.getSegmentNr() == 3)
        // new Testbild(gbReg.getByteArray(), (int) gbReg.getWidth(), (int) gbReg.getHeight(),
        // gbReg.getRowStride());

        /* 4 */
        return regionBitmap;
    }

    private int decodeSLTP() throws IOException
    {
        switch (gbTemplate)
        {
        case 0:
            cx.setIndex(0x9b25);
            break;
        case 1:
            cx.setIndex(0x795);
            break;
        case 2:
            cx.setIndex(0xe5);
            break;
        case 3:
            cx.setIndex(0x195);
            break;
        }
        return arithDecoder.decode(cx);
    }

    private void decodeLine(final int lineNumber, final int width, final int rowStride,
            final int paddedWidth) throws IOException
    {
        final int byteIndex = regionBitmap.getByteIndex(0, lineNumber);
        final int idx = byteIndex - rowStride;

        switch (gbTemplate)
        {
        case 0:
            if (!useExtTemplates)
            {
                decodeTemplate0a(lineNumber, width, rowStride, paddedWidth, byteIndex, idx);
            }
            else
            {
                decodeTemplate0b(lineNumber, width, rowStride, paddedWidth, byteIndex, idx);
            }
            break;
        case 1:
            decodeTemplate1(lineNumber, width, rowStride, paddedWidth, byteIndex, idx);
            break;
        case 2:
            decodeTemplate2(lineNumber, width, rowStride, paddedWidth, byteIndex, idx);
            break;
        case 3:
            decodeTemplate3(lineNumber, width, rowStride, paddedWidth, byteIndex, idx);
            break;
        }
    }

    /**
     * Each pixel gets the value from the corresponding pixel of the row above. Line 0 cannot get copied values (source
     * will be -1, doesn't exist).
     * 
     * @param lineNumber - Coordinate of the row that should be set.
     */
    private void copyLineAbove(final int lineNumber)
    {
        int targetByteIndex = lineNumber * regionBitmap.getRowStride();
        int sourceByteIndex = targetByteIndex - regionBitmap.getRowStride();

        for (int i = 0; i < regionBitmap.getRowStride(); i++)
        {
            // Get the byte that should be copied and put it into Bitmap
            regionBitmap.setByte(targetByteIndex++, regionBitmap.getByte(sourceByteIndex++));
        }
    }

    private void decodeTemplate0a(final int lineNumber, final int width, final int rowStride,
            final int paddedWidth, int byteIndex, int idx) throws IOException
    {
        int context;
        int overriddenContext = 0;

        int line1 = 0;
        int line2 = 0;

        if (lineNumber >= 1)
        {
            line1 = regionBitmap.getByteAsInteger(idx);
        }

        if (lineNumber >= 2)
        {
            line2 = regionBitmap.getByteAsInteger(idx - rowStride) << 6;
        }

        context = (line1 & 0xf0) | (line2 & 0x3800);

        int nextByte;
        for (int x = 0; x < paddedWidth; x = nextByte)
        {
            /* 6.2.5.7 3d */
            byte result = 0;
            nextByte = x + 8;
            final int minorWidth = width - x > 8 ? 8 : width - x;

            if (lineNumber > 0)
            {
                line1 = (line1 << 8)
                        | (nextByte < width ? regionBitmap.getByteAsInteger(idx + 1) : 0);
            }

            if (lineNumber > 1)
            {
                line2 = (line2 << 8) | (nextByte < width
                        ? regionBitmap.getByteAsInteger(idx - rowStride + 1) << 6 : 0);
            }

            for (int minorX = 0; minorX < minorWidth; minorX++)
            {
                final int toShift = 7 - minorX;
                if (override)
                {
                    overriddenContext = overrideAtTemplate0a(context, (x + minorX), lineNumber,
                            result, minorX, toShift);
                    cx.setIndex(overriddenContext);
                }
                else
                {
                    cx.setIndex(context);
                }

                int bit = arithDecoder.decode(cx);

                result |= bit << toShift;

                context = ((context & 0x7bf7) << 1) | bit | ((line1 >> toShift) & 0x10)
                        | ((line2 >> toShift) & 0x800);
            }

            regionBitmap.setByte(byteIndex++, result);
            idx++;
        }
    }

    private void decodeTemplate0b(final int lineNumber, final int width, final int rowStride,
            final int paddedWidth, int byteIndex, int idx) throws IOException
    {
        int context;
        int overriddenContext = 0;

        int line1 = 0;
        int line2 = 0;

        if (lineNumber >= 1)
        {
            line1 = regionBitmap.getByteAsInteger(idx);
        }

        if (lineNumber >= 2)
        {
            line2 = regionBitmap.getByteAsInteger(idx - rowStride) << 6;
        }

        context = (line1 & 0xf0) | (line2 & 0x3800);

        int nextByte;
        for (int x = 0; x < paddedWidth; x = nextByte)
        {
            /* 6.2.5.7 3d */
            byte result = 0;
            nextByte = x + 8;
            final int minorWidth = width - x > 8 ? 8 : width - x;

            if (lineNumber > 0)
            {
                line1 = (line1 << 8)
                        | (nextByte < width ? regionBitmap.getByteAsInteger(idx + 1) : 0);
            }

            if (lineNumber > 1)
            {
                line2 = (line2 << 8) | (nextByte < width
                        ? regionBitmap.getByteAsInteger(idx - rowStride + 1) << 6 : 0);
            }

            for (int minorX = 0; minorX < minorWidth; minorX++)
            {
                final int toShift = 7 - minorX;
                if (override)
                {
                    overriddenContext = overrideAtTemplate0b(context, (x + minorX), lineNumber,
                            result, minorX, toShift);
                    cx.setIndex(overriddenContext);
                }
                else
                {
                    cx.setIndex(context);
                }

                final int bit = arithDecoder.decode(cx);

                result |= bit << toShift;

                context = ((context & 0x7bf7) << 1) | bit | ((line1 >> toShift) & 0x10)
                        | ((line2 >> toShift) & 0x800);
            }

            regionBitmap.setByte(byteIndex++, result);
            idx++;
        }
    }

    private void decodeTemplate1(final int lineNumber, int width, final int rowStride,
            final int paddedWidth, int byteIndex, int idx) throws IOException
    {
        int context;
        int overriddenContext;

        int line1 = 0;
        int line2 = 0;

        if (lineNumber >= 1)
        {
            line1 = regionBitmap.getByteAsInteger(idx);
        }

        if (lineNumber >= 2)
        {
            line2 = regionBitmap.getByteAsInteger(idx - rowStride) << 5;
        }

        context = ((line1 >> 1) & 0x1f8) | ((line2 >> 1) & 0x1e00);

        int nextByte;
        for (int x = 0; x < paddedWidth; x = nextByte)
        {
            /* 6.2.5.7 3d */
            byte result = 0;
            nextByte = x + 8;
            final int minorWidth = width - x > 8 ? 8 : width - x;

            if (lineNumber >= 1)
            {
                line1 = (line1 << 8)
                        | (nextByte < width ? regionBitmap.getByteAsInteger(idx + 1) : 0);
            }

            if (lineNumber >= 2)
            {
                line2 = (line2 << 8) | (nextByte < width
                        ? regionBitmap.getByteAsInteger(idx - rowStride + 1) << 5 : 0);
            }

            for (int minorX = 0; minorX < minorWidth; minorX++)
            {
                if (override)
                {
                    overriddenContext = overrideAtTemplate1(context, x + minorX, lineNumber, result,
                            minorX);
                    cx.setIndex(overriddenContext);
                }
                else
                {
                    cx.setIndex(context);
                }

                final int bit = arithDecoder.decode(cx);

                result |= bit << 7 - minorX;

                final int toShift = 8 - minorX;
                context = ((context & 0xefb) << 1) | bit | ((line1 >> toShift) & 0x8)
                        | ((line2 >> toShift) & 0x200);
            }

            regionBitmap.setByte(byteIndex++, result);
            idx++;
        }
    }

    private void decodeTemplate2(final int lineNumber, final int width, final int rowStride,
            final int paddedWidth, int byteIndex, int idx) throws IOException
    {
        int context;
        int overriddenContext;

        int line1 = 0;
        int line2 = 0;

        if (lineNumber >= 1)
        {
            line1 = regionBitmap.getByteAsInteger(idx);
        }

        if (lineNumber >= 2)
        {
            line2 = regionBitmap.getByteAsInteger(idx - rowStride) << 4;
        }

        context = ((line1 >> 3) & 0x7c) | ((line2 >> 3) & 0x380);

        int nextByte;
        for (int x = 0; x < paddedWidth; x = nextByte)
        {
            /* 6.2.5.7 3d */
            byte result = 0;
            nextByte = x + 8;
            final int minorWidth = width - x > 8 ? 8 : width - x;

            if (lineNumber >= 1)
            {
                line1 = (line1 << 8)
                        | (nextByte < width ? regionBitmap.getByteAsInteger(idx + 1) : 0);
            }

            if (lineNumber >= 2)
            {
                line2 = (line2 << 8) | (nextByte < width
                        ? regionBitmap.getByteAsInteger(idx - rowStride + 1) << 4 : 0);
            }

            for (int minorX = 0; minorX < minorWidth; minorX++)
            {

                if (override)
                {
                    overriddenContext = overrideAtTemplate2(context, x + minorX, lineNumber, result,
                            minorX);
                    cx.setIndex(overriddenContext);
                }
                else
                {
                    cx.setIndex(context);
                }

                final int bit = arithDecoder.decode(cx);

                result |= bit << (7 - minorX);

                final int toShift = 10 - minorX;
                context = ((context & 0x1bd) << 1) | bit | ((line1 >> toShift) & 0x4)
                        | ((line2 >> toShift) & 0x80);
            }

            regionBitmap.setByte(byteIndex++, result);
            idx++;
        }
    }

    private void decodeTemplate3(final int lineNumber, final int width, final int rowStride,
            final int paddedWidth, int byteIndex, int idx) throws IOException
    {
        int context;
        int overriddenContext;

        int line1 = 0;

        if (lineNumber >= 1)
        {
            line1 = regionBitmap.getByteAsInteger(idx);
        }

        context = (line1 >> 1) & 0x70;

        int nextByte;
        for (int x = 0; x < paddedWidth; x = nextByte)
        {
            /* 6.2.5.7 3d */
            byte result = 0;
            nextByte = x + 8;
            final int minorWidth = width - x > 8 ? 8 : width - x;

            if (lineNumber >= 1)
            {
                line1 = (line1 << 8)
                        | (nextByte < width ? regionBitmap.getByteAsInteger(idx + 1) : 0);
            }

            for (int minorX = 0; minorX < minorWidth; minorX++)
            {

                if (override)
                {
                    overriddenContext = overrideAtTemplate3(context, x + minorX, lineNumber, result,
                            minorX);
                    cx.setIndex(overriddenContext);
                }
                else
                {
                    cx.setIndex(context);
                }

                final int bit = arithDecoder.decode(cx);

                result |= bit << (7 - minorX);
                context = ((context & 0x1f7) << 1) | bit | ((line1 >> (8 - minorX)) & 0x010);
            }

            regionBitmap.setByte(byteIndex++, result);
            idx++;
        }
    }

    private void updateOverrideFlags()
    {
        if (gbAtX == null || gbAtY == null)
        {
            return;
        }

        if (gbAtX.length != gbAtY.length)
        {
            return;
        }

        gbAtOverride = new boolean[gbAtX.length];

        switch (gbTemplate)
        {
        case 0:
            if (!useExtTemplates)
            {
                if (gbAtX[0] != 3 || gbAtY[0] != -1)
                    setOverrideFlag(0);

                if (gbAtX[1] != -3 || gbAtY[1] != -1)
                    setOverrideFlag(1);

                if (gbAtX[2] != 2 || gbAtY[2] != -2)
                    setOverrideFlag(2);

                if (gbAtX[3] != -2 || gbAtY[3] != -2)
                    setOverrideFlag(3);

            }
            else
            {
                if (gbAtX[0] != -2 || gbAtY[0] != 0)
                    setOverrideFlag(0);

                if (gbAtX[1] != 0 || gbAtY[1] != -2)
                    setOverrideFlag(1);

                if (gbAtX[2] != -2 || gbAtY[2] != -1)
                    setOverrideFlag(2);

                if (gbAtX[3] != -1 || gbAtY[3] != -2)
                    setOverrideFlag(3);

                if (gbAtX[4] != 1 || gbAtY[4] != -2)
                    setOverrideFlag(4);

                if (gbAtX[5] != 2 || gbAtY[5] != -1)
                    setOverrideFlag(5);

                if (gbAtX[6] != -3 || gbAtY[6] != 0)
                    setOverrideFlag(6);

                if (gbAtX[7] != -4 || gbAtY[7] != 0)
                    setOverrideFlag(7);

                if (gbAtX[8] != 2 || gbAtY[8] != -2)
                    setOverrideFlag(8);

                if (gbAtX[9] != 3 || gbAtY[9] != -1)
                    setOverrideFlag(9);

                if (gbAtX[10] != -2 || gbAtY[10] != -2)
                    setOverrideFlag(10);

                if (gbAtX[11] != -3 || gbAtY[11] != -1)
                    setOverrideFlag(11);
            }
            break;
        case 1:
            if (gbAtX[0] != 3 || gbAtY[0] != -1)
                setOverrideFlag(0);
            break;
        case 2:
            if (gbAtX[0] != 2 || gbAtY[0] != -1)
                setOverrideFlag(0);
            break;
        case 3:
            if (gbAtX[0] != 2 || gbAtY[0] != -1)
                setOverrideFlag(0);
            break;
        }

    }

    private void setOverrideFlag(final int index)
    {
        gbAtOverride[index] = true;
        override = true;
    }

    private int overrideAtTemplate0a(int context, final int x, final int y, final int result,
            final int minorX, final int toShift) throws IOException
    {
        if (gbAtOverride[0])
        {
            context &= 0xffef;
            if (gbAtY[0] == 0 && gbAtX[0] >= -minorX)
                context |= (result >> (toShift - gbAtX[0]) & 0x1) << 4;
            else
                context |= getPixel(x + gbAtX[0], y + gbAtY[0]) << 4;
        }

        if (gbAtOverride[1])
        {
            context &= 0xfbff;
            if (gbAtY[1] == 0 && gbAtX[1] >= -minorX)
                context |= (result >> (toShift - gbAtX[1]) & 0x1) << 10;
            else
                context |= getPixel(x + gbAtX[1], y + gbAtY[1]) << 10;
        }

        if (gbAtOverride[2])
        {
            context &= 0xf7ff;
            if (gbAtY[2] == 0 && gbAtX[2] >= -minorX)
                context |= (result >> (toShift - gbAtX[2]) & 0x1) << 11;
            else
                context |= getPixel(x + gbAtX[2], y + gbAtY[2]) << 11;
        }

        if (gbAtOverride[3])
        {
            context &= 0x7fff;
            if (gbAtY[3] == 0 && gbAtX[3] >= -minorX)
                context |= (result >> (toShift - gbAtX[3]) & 0x1) << 15;
            else
                context |= getPixel(x + gbAtX[3], y + gbAtY[3]) << 15;
        }
        return context;
    }

    private int overrideAtTemplate0b(int context, final int x, final int y, final int result,
            final int minorX, final int toShift) throws IOException
    {
        if (gbAtOverride[0])
        {
            context &= 0xfffd;
            if (gbAtY[0] == 0 && gbAtX[0] >= -minorX)
                context |= (result >> (toShift - gbAtX[0]) & 0x1) << 1;
            else
                context |= getPixel(x + gbAtX[0], y + gbAtY[0]) << 1;
        }

        if (gbAtOverride[1])
        {
            context &= 0xdfff;
            if (gbAtY[1] == 0 && gbAtX[1] >= -minorX)
                context |= (result >> (toShift - gbAtX[1]) & 0x1) << 13;
            else
                context |= getPixel(x + gbAtX[1], y + gbAtY[1]) << 13;
        }
        if (gbAtOverride[2])
        {
            context &= 0xfdff;
            if (gbAtY[2] == 0 && gbAtX[2] >= -minorX)
                context |= (result >> (toShift - gbAtX[2]) & 0x1) << 9;
            else
                context |= getPixel(x + gbAtX[2], y + gbAtY[2]) << 9;
        }
        if (gbAtOverride[3])
        {
            context &= 0xbfff;
            if (gbAtY[3] == 0 && gbAtX[3] >= -minorX)
                context |= (result >> (toShift - gbAtX[3]) & 0x1) << 14;
            else
                context |= getPixel(x + gbAtX[3], y + gbAtY[3]) << 14;
        }
        if (gbAtOverride[4])
        {
            context &= 0xefff;
            if (gbAtY[4] == 0 && gbAtX[4] >= -minorX)
                context |= (result >> (toShift - gbAtX[4]) & 0x1) << 12;
            else
                context |= getPixel(x + gbAtX[4], y + gbAtY[4]) << 12;
        }
        if (gbAtOverride[5])
        {
            context &= 0xffdf;
            if (gbAtY[5] == 0 && gbAtX[5] >= -minorX)
                context |= (result >> (toShift - gbAtX[5]) & 0x1) << 5;
            else
                context |= getPixel(x + gbAtX[5], y + gbAtY[5]) << 5;
        }
        if (gbAtOverride[6])
        {
            context &= 0xfffb;
            if (gbAtY[6] == 0 && gbAtX[6] >= -minorX)
                context |= (result >> (toShift - gbAtX[6]) & 0x1) << 2;
            else
                context |= getPixel(x + gbAtX[6], y + gbAtY[6]) << 2;
        }
        if (gbAtOverride[7])
        {
            context &= 0xfff7;
            if (gbAtY[7] == 0 && gbAtX[7] >= -minorX)
                context |= (result >> (toShift - gbAtX[7]) & 0x1) << 3;
            else
                context |= getPixel(x + gbAtX[7], y + gbAtY[7]) << 3;
        }
        if (gbAtOverride[8])
        {
            context &= 0xf7ff;
            if (gbAtY[8] == 0 && gbAtX[8] >= -minorX)
                context |= (result >> (toShift - gbAtX[8]) & 0x1) << 11;
            else
                context |= getPixel(x + gbAtX[8], y + gbAtY[8]) << 11;
        }
        if (gbAtOverride[9])
        {
            context &= 0xffef;
            if (gbAtY[9] == 0 && gbAtX[9] >= -minorX)
                context |= (result >> (toShift - gbAtX[9]) & 0x1) << 4;
            else
                context |= getPixel(x + gbAtX[9], y + gbAtY[9]) << 4;
        }
        if (gbAtOverride[10])
        {
            context &= 0x7fff;
            if (gbAtY[10] == 0 && gbAtX[10] >= -minorX)
                context |= (result >> (toShift - gbAtX[10]) & 0x1) << 15;
            else
                context |= getPixel(x + gbAtX[10], y + gbAtY[10]) << 15;
        }
        if (gbAtOverride[11])
        {
            context &= 0xfdff;
            if (gbAtY[11] == 0 && gbAtX[11] >= -minorX)
                context |= (result >> (toShift - gbAtX[11]) & 0x1) << 10;
            else
                context |= getPixel(x + gbAtX[11], y + gbAtY[11]) << 10;
        }

        return context;
    }

    private int overrideAtTemplate1(int context, final int x, final int y, final int result,
            final int minorX) throws IOException
    {
        context &= 0x1ff7;
        if (gbAtY[0] == 0 && gbAtX[0] >= -minorX)
            return (context | (result >> (7 - (minorX + gbAtX[0])) & 0x1) << 3);
        else
            return (context | getPixel(x + gbAtX[0], y + gbAtY[0]) << 3);
    }

    private int overrideAtTemplate2(int context, final int x, final int y, final int result,
            final int minorX) throws IOException
    {
        context &= 0x3fb;
        if (gbAtY[0] == 0 && gbAtX[0] >= -minorX)
            return (context | (result >> (7 - (minorX + gbAtX[0])) & 0x1) << 2);
        else
            return (context | getPixel(x + gbAtX[0], y + gbAtY[0]) << 2);
    }

    private int overrideAtTemplate3(int context, final int x, final int y, final int result,
            final int minorX) throws IOException
    {
        context &= 0x3ef;
        if (gbAtY[0] == 0 && gbAtX[0] >= -minorX)
            return (context | (result >> (7 - (minorX + gbAtX[0])) & 0x1) << 4);
        else
            return (context | getPixel(x + gbAtX[0], y + gbAtY[0]) << 4);
    }

    private byte getPixel(final int x, final int y) throws IOException
    {
        if (x < 0 || x >= regionBitmap.getWidth())
            return 0;

        if (y < 0 || y >= regionBitmap.getHeight())
            return 0;

        return regionBitmap.getPixel(x, y);
    }

    /**
     * Used by {@link SymbolDictionary}.
     * 
     * @param isMMREncoded the data is MMR encoded
     * @param dataOffset the offset
     * @param dataLength the length of the data
     * @param gbh bitmap height
     * @param gbw bitmap width
     */
    protected void setParameters(final boolean isMMREncoded, final long dataOffset,
            final long dataLength, final int gbh, final int gbw)
    {
        this.isMMREncoded = isMMREncoded;
        this.dataOffset = dataOffset;
        this.dataLength = dataLength;
        this.regionInfo.setBitmapHeight(gbh);
        this.regionInfo.setBitmapWidth(gbw);

        this.mmrDecompressor = null;
        resetBitmap();
    }

    /**
     * @param isMMREncoded the data is MMR encoded
     * @param sdTemplate sd template
     * @param isTPGDon is TPGDon
     * @param useSkip use skip
     * @param sdATX x values gbA pixels
     * @param sdATY y values gbA pixels
     * @param symWidth bitmap width
     * @param hcHeight bitmap height
     * @param cx context for the arithmetic decoder
     * @param arithmeticDecoder the arithmetic decode to be used
     * 
     * Used by {@link SymbolDictionary}.
     */
    protected void setParameters(final boolean isMMREncoded, final byte sdTemplate,
            final boolean isTPGDon, final boolean useSkip, final short[] sdATX, final short[] sdATY,
            final int symWidth, final int hcHeight, final CX cx,
            final ArithmeticDecoder arithmeticDecoder)
    {
        this.isMMREncoded = isMMREncoded;
        this.gbTemplate = sdTemplate;
        this.isTPGDon = isTPGDon;
        this.gbAtX = sdATX;
        this.gbAtY = sdATY;
        this.regionInfo.setBitmapWidth(symWidth);
        this.regionInfo.setBitmapHeight(hcHeight);
        if (null != cx)
            this.cx = cx;
        if (null != arithmeticDecoder)
            this.arithDecoder = arithmeticDecoder;

        this.mmrDecompressor = null;
        resetBitmap();
    }

    /**
     * Used by {@link PatternDictionary} and {@link HalftoneRegion}.
     * 
     * @param isMMREncoded the data is MMR encoded
     * @param dataOffset the offset
     * @param dataLength the length of the data
     * @param gbh bitmap height
     * @param gbw bitmap width
     * @param gbTemplate gb template
     * @param isTPGDon is TPGDon
     * @param useSkip use skip
     * @param gbAtX x values of gbA pixels
     * @param gbAtY y values of gbA pixels
     * 
     */
    protected void setParameters(final boolean isMMREncoded, final long dataOffset,
            final long dataLength, final int gbh, final int gbw, final byte gbTemplate,
            final boolean isTPGDon, final boolean useSkip, final short[] gbAtX, final short[] gbAtY)
    {
        this.dataOffset = dataOffset;
        this.dataLength = dataLength;

        this.regionInfo = new RegionSegmentInformation();
        this.regionInfo.setBitmapHeight(gbh);
        this.regionInfo.setBitmapWidth(gbw);
        this.gbTemplate = gbTemplate;

        this.isMMREncoded = isMMREncoded;
        this.isTPGDon = isTPGDon;
        this.gbAtX = gbAtX;
        this.gbAtY = gbAtY;
    }

    /**
     * Simply sets the memory-critical bitmap of this region to {@code null}.
     */
    protected void resetBitmap()
    {
        this.regionBitmap = null;
    }

    public void init(final SegmentHeader header, final SubInputStream sis)
            throws InvalidHeaderValueException, IOException
    {
        this.subInputStream = sis;
        this.regionInfo = new RegionSegmentInformation(subInputStream);
        parseHeader();
    }

    public RegionSegmentInformation getRegionInfo()
    {
        return regionInfo;
    }

    protected boolean useExtTemplates()
    {
        return useExtTemplates;
    }

    protected boolean isTPGDon()
    {
        return isTPGDon;
    }

    protected byte getGbTemplate()
    {
        return gbTemplate;
    }

    protected boolean isMMREncoded()
    {
        return isMMREncoded;
    }

    protected short[] getGbAtX()
    {
        return gbAtX;
    }

    protected short[] getGbAtY()
    {
        return gbAtY;
    }
}
