http://git-wip-us.apache.org/repos/asf/pdfbox-jbig2/blob/30839c32/src/main/java/org/apache/pdfbox/jbig2/segments/GenericRegion.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/pdfbox/jbig2/segments/GenericRegion.java 
b/src/main/java/org/apache/pdfbox/jbig2/segments/GenericRegion.java
index a799f73..9e22ee9 100644
--- a/src/main/java/org/apache/pdfbox/jbig2/segments/GenericRegion.java
+++ b/src/main/java/org/apache/pdfbox/jbig2/segments/GenericRegion.java
@@ -35,901 +35,1057 @@ import org.apache.pdfbox.jbig2.util.log.LoggerFactory;
  * 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 {
+public class GenericRegion implements Region
+{
 
-  private final Logger log = LoggerFactory.getLogger(GenericRegion.class);
+    private final Logger log = LoggerFactory.getLogger(GenericRegion.class);
 
-  private SubInputStream subInputStream;
-  private long dataHeaderOffset;
-  private long dataHeaderLength;
-  private long dataOffset;
-  private long dataLength;
+    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;
+    /** 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 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;
+    /** 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;
+    /**
+     * 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;
+    /** Decoded data as pixel values (use row stride/width to wrap line) */
+    private Bitmap regionBitmap;
 
-  private ArithmeticDecoder arithDecoder;
-  private CX cx;
+    private ArithmeticDecoder arithDecoder;
+    private CX cx;
 
-  private MMRDecompressor mmrDecompressor;
+    private MMRDecompressor mmrDecompressor;
 
-  public GenericRegion() {
-  }
+    public GenericRegion()
+    {
+    }
 
-  public GenericRegion(final SubInputStream subInputStream) {
-    this.subInputStream = subInputStream;
-    this.regionInfo = new RegionSegmentInformation(subInputStream);
-  }
+    public GenericRegion(final SubInputStream subInputStream)
+    {
+        this.subInputStream = subInputStream;
+        this.regionInfo = new RegionSegmentInformation(subInputStream);
+    }
 
-  private void parseHeader() throws IOException, InvalidHeaderValueException {
-    regionInfo.parseHeader();
+    private void parseHeader() throws IOException, InvalidHeaderValueException
+    {
+        regionInfo.parseHeader();
 
-    /* Bit 5-7 */
-    subInputStream.readBits(3); // Dirty read...
+        /* Bit 5-7 */
+        subInputStream.readBits(3); // Dirty read...
 
-    /* Bit 4 */
-    if (subInputStream.readBit() == 1) {
-      useExtTemplates = true;
-    }
+        /* Bit 4 */
+        if (subInputStream.readBit() == 1)
+        {
+            useExtTemplates = true;
+        }
 
-    /* Bit 3 */
-    if (subInputStream.readBit() == 1) {
-      isTPGDon = true;
-    }
+        /* Bit 3 */
+        if (subInputStream.readBit() == 1)
+        {
+            isTPGDon = true;
+        }
 
-    /* Bit 1-2 */
-    gbTemplate = (byte) (subInputStream.readBits(2) & 0xf);
+        /* Bit 1-2 */
+        gbTemplate = (byte) (subInputStream.readBits(2) & 0xf);
+
+        /* Bit 0 */
+        if (subInputStream.readBit() == 1)
+        {
+            isMMREncoded = true;
+        }
 
-    /* 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();
+
+        this.checkInput();
     }
 
-    if (!isMMREncoded) {
-      final int amountOfGbAt;
-      if (gbTemplate == 0) {
-        if (useExtTemplates) {
-          amountOfGbAt = 12;
-        } else {
-          amountOfGbAt = 4;
+    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();
         }
-      } else {
-        amountOfGbAt = 1;
-      }
+    }
 
-      readGbAtPixels(amountOfGbAt);
+    private void computeSegmentDataStructure() throws IOException
+    {
+        dataOffset = subInputStream.getStreamPosition();
+        dataHeaderLength = dataOffset - dataHeaderOffset;
+        dataLength = subInputStream.length() - dataHeaderLength;
     }
 
-    /* Segment data structure */
-    computeSegmentDataStructure();
+    private void checkInput() throws InvalidHeaderValueException
+    {
+        if (isMMREncoded)
+        {
+            if (gbTemplate != 0)
+            {
+                log.info("gbTemplate should contain the value 0");
+            }
+        }
+    }
 
-    this.checkInput();
-  }
+    /**
+     * 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);
+                        // }
+                    }
+                }
+            }
+        }
 
-  private void readGbAtPixels(final int amountOfGbAt) throws IOException {
-    gbAtX = new short[amountOfGbAt];
-    gbAtY = new short[amountOfGbAt];
+        // if (JBIG2ImageReader.DEBUG)
+        // if (header != null && header.getSegmentNr() == 3)
+        // new Testbild(gbReg.getByteArray(), (int) gbReg.getWidth(), (int) 
gbReg.getHeight(),
+        // gbReg.getRowStride());
 
-    for (int i = 0; i < amountOfGbAt; i++) {
-      gbAtX[i] = subInputStream.readByte();
-      gbAtY[i] = subInputStream.readByte();
+        /* 4 */
+        return regionBitmap;
     }
-  }
 
-  private void computeSegmentDataStructure() throws IOException {
-    dataOffset = subInputStream.getStreamPosition();
-    dataHeaderLength = dataOffset - dataHeaderOffset;
-    dataLength = subInputStream.length() - dataHeaderLength;
-  }
+    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 checkInput() throws InvalidHeaderValueException {
-    if (isMMREncoded) {
-      if (gbTemplate != 0) {
-        log.info("gbTemplate should contain the value 0");
-      }
+    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;
+        }
     }
-  }
 
-  /**
-   * 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) {
+    /**
+     * 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;
 
-      if (isMMREncoded) {
+        int line1 = 0;
+        int line2 = 0;
 
-        /*
-         * MMR DECODER CALL
-         */
-        if (null == mmrDecompressor) {
-          mmrDecompressor = new MMRDecompressor(regionInfo.getBitmapWidth(), 
regionInfo.getBitmapHeight(),
-              new SubInputStream(subInputStream, dataOffset, dataLength));
+        if (lineNumber >= 1)
+        {
+            line1 = regionBitmap.getByteAsInteger(idx);
         }
 
-        /* 6.2.6 */
-        regionBitmap = mmrDecompressor.uncompress();
+        if (lineNumber >= 2)
+        {
+            line2 = regionBitmap.getByteAsInteger(idx - rowStride) << 6;
+        }
 
-      } else {
+        context = (line1 & 0xf0) | (line2 & 0x3800);
 
-        /*
-         * ARITHMETIC DECODER PROCEDURE for generic region segments
-         */
+        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;
 
-        updateOverrideFlags();
+            if (lineNumber > 0)
+            {
+                line1 = (line1 << 8)
+                        | (nextByte < width ? 
regionBitmap.getByteAsInteger(idx + 1) : 0);
+            }
 
-        /* 6.2.5.7 - 1) */
-        int ltp = 0;
+            if (lineNumber > 1)
+            {
+                line2 = (line2 << 8) | (nextByte < width
+                        ? regionBitmap.getByteAsInteger(idx - rowStride + 1) 
<< 6 : 0);
+            }
 
-        if (arithDecoder == null) {
-          arithDecoder = new ArithmeticDecoder(subInputStream);
-        }
-        if (cx == null) {
-          cx = new CX(65536, 1);
+            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++;
         }
+    }
 
-        /* 6.2.5.7 - 2) */
-        regionBitmap = new Bitmap(regionInfo.getBitmapWidth(), 
regionInfo.getBitmapHeight());
+    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;
 
-        final int paddedWidth = (regionBitmap.getWidth() + 7) & -8;
+        int line1 = 0;
+        int line2 = 0;
 
-        /* 6.2.5.7 - 3 */
-        for (int line = 0; line < regionBitmap.getHeight(); line++) {
+        if (lineNumber >= 1)
+        {
+            line1 = regionBitmap.getByteAsInteger(idx);
+        }
 
-          /* 6.2.5.7 - 3 b) */
-          if (isTPGDon) {
-            ltp ^= decodeSLTP();
-          }
+        if (lineNumber >= 2)
+        {
+            line2 = regionBitmap.getByteAsInteger(idx - rowStride) << 6;
+        }
 
-          /* 6.2.5.7 - 3 c) */
-          if (ltp == 1) {
-            if (line > 0) {
-              copyLineAbove(line);
+        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);
             }
-          } 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;
-    }
+            if (lineNumber > 1)
+            {
+                line2 = (line2 << 8) | (nextByte < width
+                        ? regionBitmap.getByteAsInteger(idx - rowStride + 1) 
<< 6 : 0);
+            }
 
-    context = (line1 & 0xf0) | (line2 & 0x3800);
+            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);
+            }
 
-    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;
+            regionBitmap.setByte(byteIndex++, result);
+            idx++;
+        }
+    }
 
-      if (lineNumber > 0) {
-        line1 = (line1 << 8) | (nextByte < width ? 
regionBitmap.getByteAsInteger(idx + 1) : 0);
-      }
+    private void decodeTemplate1(final int lineNumber, int width, final int 
rowStride,
+            final int paddedWidth, int byteIndex, int idx) throws IOException
+    {
+        int context;
+        int overriddenContext;
 
-      if (lineNumber > 1) {
-        line2 = (line2 << 8) | (nextByte < width ? 
regionBitmap.getByteAsInteger(idx - rowStride + 1) << 6 : 0);
-      }
+        int line1 = 0;
+        int line2 = 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);
+        if (lineNumber >= 1)
+        {
+            line1 = regionBitmap.getByteAsInteger(idx);
         }
 
-        int bit = arithDecoder.decode(cx);
+        if (lineNumber >= 2)
+        {
+            line2 = regionBitmap.getByteAsInteger(idx - rowStride) << 5;
+        }
 
-        result |= bit << toShift;
+        context = ((line1 >> 1) & 0x1f8) | ((line2 >> 1) & 0x1e00);
 
-        context = ((context & 0x7bf7) << 1) | bit | ((line1 >> toShift) & 
0x10) | ((line2 >> toShift) & 0x800);
-      }
+        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;
 
-      regionBitmap.setByte(byteIndex++, result);
-      idx++;
-    }
-  }
+            if (lineNumber >= 1)
+            {
+                line1 = (line1 << 8)
+                        | (nextByte < width ? 
regionBitmap.getByteAsInteger(idx + 1) : 0);
+            }
 
-  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;
+            if (lineNumber >= 2)
+            {
+                line2 = (line2 << 8) | (nextByte < width
+                        ? regionBitmap.getByteAsInteger(idx - rowStride + 1) 
<< 5 : 0);
+            }
 
-    int line1 = 0;
-    int line2 = 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);
+            }
 
-    if (lineNumber >= 1) {
-      line1 = regionBitmap.getByteAsInteger(idx);
+            regionBitmap.setByte(byteIndex++, result);
+            idx++;
+        }
     }
 
-    if (lineNumber >= 2) {
-      line2 = regionBitmap.getByteAsInteger(idx - rowStride) << 6;
-    }
+    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;
 
-    context = (line1 & 0xf0) | (line2 & 0x3800);
+        int line1 = 0;
+        int line2 = 0;
 
-    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 = regionBitmap.getByteAsInteger(idx);
+        }
 
-      if (lineNumber > 0) {
-        line1 = (line1 << 8) | (nextByte < width ? 
regionBitmap.getByteAsInteger(idx + 1) : 0);
-      }
+        if (lineNumber >= 2)
+        {
+            line2 = regionBitmap.getByteAsInteger(idx - rowStride) << 4;
+        }
 
-      if (lineNumber > 1) {
-        line2 = (line2 << 8) | (nextByte < width ? 
regionBitmap.getByteAsInteger(idx - rowStride + 1) << 6 : 0);
-      }
+        context = ((line1 >> 3) & 0x7c) | ((line2 >> 3) & 0x380);
 
-      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);
-        }
+        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);
+            }
 
-        final int bit = arithDecoder.decode(cx);
+            if (lineNumber >= 2)
+            {
+                line2 = (line2 << 8) | (nextByte < width
+                        ? regionBitmap.getByteAsInteger(idx - rowStride + 1) 
<< 4 : 0);
+            }
 
-        result |= bit << toShift;
+            for (int minorX = 0; minorX < minorWidth; minorX++)
+            {
 
-        context = ((context & 0x7bf7) << 1) | bit | ((line1 >> toShift) & 
0x10) | ((line2 >> toShift) & 0x800);
-      }
+                if (override)
+                {
+                    overriddenContext = overrideAtTemplate2(context, x + 
minorX, lineNumber, result,
+                            minorX);
+                    cx.setIndex(overriddenContext);
+                }
+                else
+                {
+                    cx.setIndex(context);
+                }
 
-      regionBitmap.setByte(byteIndex++, result);
-      idx++;
-    }
-  }
+                final int bit = arithDecoder.decode(cx);
 
-  private void decodeTemplate1(final int lineNumber, int width, final int 
rowStride, final int paddedWidth,
-      int byteIndex, int idx) throws IOException {
-    int context;
-    int overriddenContext;
+                result |= bit << (7 - minorX);
 
-    int line1 = 0;
-    int line2 = 0;
+                final int toShift = 10 - minorX;
+                context = ((context & 0x1bd) << 1) | bit | ((line1 >> toShift) 
& 0x4)
+                        | ((line2 >> toShift) & 0x80);
+            }
 
-    if (lineNumber >= 1) {
-      line1 = regionBitmap.getByteAsInteger(idx);
+            regionBitmap.setByte(byteIndex++, result);
+            idx++;
+        }
     }
 
-    if (lineNumber >= 2) {
-      line2 = regionBitmap.getByteAsInteger(idx - rowStride) << 5;
-    }
+    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;
 
-    context = ((line1 >> 1) & 0x1f8) | ((line2 >> 1) & 0x1e00);
+        int line1 = 0;
 
-    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 = regionBitmap.getByteAsInteger(idx);
+        }
 
-      if (lineNumber >= 1) {
-        line1 = (line1 << 8) | (nextByte < width ? 
regionBitmap.getByteAsInteger(idx + 1) : 0);
-      }
+        context = (line1 >> 1) & 0x70;
 
-      if (lineNumber >= 2) {
-        line2 = (line2 << 8) | (nextByte < width ? 
regionBitmap.getByteAsInteger(idx - rowStride + 1) << 5 : 0);
-      }
+        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;
 
-      for (int minorX = 0; minorX < minorWidth; minorX++) {
-        if (override) {
-          overriddenContext = overrideAtTemplate1(context, x + minorX, 
lineNumber, result, minorX);
-          cx.setIndex(overriddenContext);
-        } else {
-          cx.setIndex(context);
-        }
+            if (lineNumber >= 1)
+            {
+                line1 = (line1 << 8)
+                        | (nextByte < width ? 
regionBitmap.getByteAsInteger(idx + 1) : 0);
+            }
+
+            for (int minorX = 0; minorX < minorWidth; minorX++)
+            {
 
-        final int bit = arithDecoder.decode(cx);
+                if (override)
+                {
+                    overriddenContext = overrideAtTemplate3(context, x + 
minorX, lineNumber, result,
+                            minorX);
+                    cx.setIndex(overriddenContext);
+                }
+                else
+                {
+                    cx.setIndex(context);
+                }
 
-        result |= bit << 7 - minorX;
+                final int bit = arithDecoder.decode(cx);
 
-        final int toShift = 8 - minorX;
-        context = ((context & 0xefb) << 1) | bit | ((line1 >> toShift) & 0x8) 
| ((line2 >> toShift) & 0x200);
-      }
+                result |= bit << (7 - minorX);
+                context = ((context & 0x1f7) << 1) | bit | ((line1 >> (8 - 
minorX)) & 0x010);
+            }
 
-      regionBitmap.setByte(byteIndex++, result);
-      idx++;
+            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;
+    private void updateOverrideFlags()
+    {
+        if (gbAtX == null || gbAtY == null)
+        {
+            log.info("AT pixels not set");
+            return;
+        }
 
-    int line1 = 0;
-    int line2 = 0;
+        if (gbAtX.length != gbAtY.length)
+        {
+            log.info("AT pixel inconsistent, amount of x pixels: " + 
gbAtX.length
+                    + ", amount of y pixels:" + gbAtY.length);
+            return;
+        }
 
-    if (lineNumber >= 1) {
-      line1 = regionBitmap.getByteAsInteger(idx);
-    }
+        gbAtOverride = new boolean[gbAtX.length];
 
-    if (lineNumber >= 2) {
-      line2 = regionBitmap.getByteAsInteger(idx - rowStride) << 4;
-    }
+        switch (gbTemplate)
+        {
+        case 0:
+            if (!useExtTemplates)
+            {
+                if (gbAtX[0] != 3 || gbAtY[0] != -1)
+                    setOverrideFlag(0);
 
-    context = ((line1 >> 3) & 0x7c) | ((line2 >> 3) & 0x380);
+                if (gbAtX[1] != -3 || gbAtY[1] != -1)
+                    setOverrideFlag(1);
 
-    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 (gbAtX[2] != 2 || gbAtY[2] != -2)
+                    setOverrideFlag(2);
 
-      if (lineNumber >= 1) {
-        line1 = (line1 << 8) | (nextByte < width ? 
regionBitmap.getByteAsInteger(idx + 1) : 0);
-      }
+                if (gbAtX[3] != -2 || gbAtY[3] != -2)
+                    setOverrideFlag(3);
 
-      if (lineNumber >= 2) {
-        line2 = (line2 << 8) | (nextByte < width ? 
regionBitmap.getByteAsInteger(idx - rowStride + 1) << 4 : 0);
-      }
+            }
+            else
+            {
+                if (gbAtX[0] != -2 || gbAtY[0] != 0)
+                    setOverrideFlag(0);
 
-      for (int minorX = 0; minorX < minorWidth; minorX++) {
+                if (gbAtX[1] != 0 || gbAtY[1] != -2)
+                    setOverrideFlag(1);
 
-        if (override) {
-          overriddenContext = overrideAtTemplate2(context, x + minorX, 
lineNumber, result, minorX);
-          cx.setIndex(overriddenContext);
-        } else {
-          cx.setIndex(context);
-        }
+                if (gbAtX[2] != -2 || gbAtY[2] != -1)
+                    setOverrideFlag(2);
 
-        final int bit = arithDecoder.decode(cx);
+                if (gbAtX[3] != -1 || gbAtY[3] != -2)
+                    setOverrideFlag(3);
 
-        result |= bit << (7 - minorX);
+                if (gbAtX[4] != 1 || gbAtY[4] != -2)
+                    setOverrideFlag(4);
 
-        final int toShift = 10 - minorX;
-        context = ((context & 0x1bd) << 1) | bit | ((line1 >> toShift) & 0x4) 
| ((line2 >> toShift) & 0x80);
-      }
+                if (gbAtX[5] != 2 || gbAtY[5] != -1)
+                    setOverrideFlag(5);
 
-      regionBitmap.setByte(byteIndex++, result);
-      idx++;
-    }
-  }
+                if (gbAtX[6] != -3 || gbAtY[6] != 0)
+                    setOverrideFlag(6);
 
-  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;
+                if (gbAtX[7] != -4 || gbAtY[7] != 0)
+                    setOverrideFlag(7);
 
-    int line1 = 0;
+                if (gbAtX[8] != 2 || gbAtY[8] != -2)
+                    setOverrideFlag(8);
 
-    if (lineNumber >= 1) {
-      line1 = regionBitmap.getByteAsInteger(idx);
-    }
+                if (gbAtX[9] != 3 || gbAtY[9] != -1)
+                    setOverrideFlag(9);
 
-    context = (line1 >> 1) & 0x70;
+                if (gbAtX[10] != -2 || gbAtY[10] != -2)
+                    setOverrideFlag(10);
 
-    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 (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;
+        }
 
-      if (lineNumber >= 1) {
-        line1 = (line1 << 8) | (nextByte < width ? 
regionBitmap.getByteAsInteger(idx + 1) : 0);
-      }
+    }
 
-      for (int minorX = 0; minorX < minorWidth; minorX++) {
+    private void setOverrideFlag(final int index)
+    {
+        gbAtOverride[index] = true;
+        override = true;
+    }
 
-        if (override) {
-          overriddenContext = overrideAtTemplate3(context, x + minorX, 
lineNumber, result, minorX);
-          cx.setIndex(overriddenContext);
-        } else {
-          cx.setIndex(context);
+    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;
         }
 
-        final int bit = arithDecoder.decode(cx);
+        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;
+        }
 
-        result |= bit << (7 - minorX);
-        context = ((context & 0x1f7) << 1) | bit | ((line1 >> (8 - minorX)) & 
0x010);
-      }
+        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;
+        }
 
-      regionBitmap.setByte(byteIndex++, result);
-      idx++;
+        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 void updateOverrideFlags() {
-    if (gbAtX == null || gbAtY == null) {
-      log.info("AT pixels not set");
-      return;
+    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;
     }
 
-    if (gbAtX.length != gbAtY.length) {
-      log.info("AT pixel inconsistent, amount of x pixels: " + gbAtX.length + 
", amount of y pixels:" + gbAtY.length);
-      return;
+    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);
     }
 
-    gbAtOverride = new boolean[gbAtX.length];
+    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);
+    }
 
-    switch (gbTemplate){
-      case 0 :
-        if (!useExtTemplates) {
-          if (gbAtX[0] != 3 || gbAtY[0] != -1)
-            setOverrideFlag(0);
+    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);
+    }
 
-          if (gbAtX[1] != -3 || gbAtY[1] != -1)
-            setOverrideFlag(1);
+    private byte getPixel(final int x, final int y) throws IOException
+    {
+        if (x < 0 || x >= regionBitmap.getWidth())
+            return 0;
 
-          if (gbAtX[2] != 2 || gbAtY[2] != -2)
-            setOverrideFlag(2);
+        if (y < 0 || y >= regionBitmap.getHeight())
+            return 0;
 
-          if (gbAtX[3] != -2 || gbAtY[3] != -2)
-            setOverrideFlag(3);
+        return regionBitmap.getPixel(x, y);
+    }
 
-        } else {
-          if (gbAtX[0] != -2 || gbAtY[0] != 0)
-            setOverrideFlag(0);
+    /**
+     * 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();
+    }
 
-          if (gbAtX[1] != 0 || gbAtY[1] != -2)
-            setOverrideFlag(1);
+    /**
+     * @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();
+    }
 
-          if (gbAtX[2] != -2 || gbAtY[2] != -1)
-            setOverrideFlag(2);
+    /**
+     * 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;
+    }
 
-          if (gbAtX[3] != -1 || gbAtY[3] != -2)
-            setOverrideFlag(3);
+    /**
+     * Simply sets the memory-critical bitmap of this region to {@code null}.
+     */
+    protected void resetBitmap()
+    {
+        this.regionBitmap = null;
+    }
 
-          if (gbAtX[4] != 1 || gbAtY[4] != -2)
-            setOverrideFlag(4);
+    public void init(final SegmentHeader header, final SubInputStream sis)
+            throws InvalidHeaderValueException, IOException
+    {
+        this.subInputStream = sis;
+        this.regionInfo = new RegionSegmentInformation(subInputStream);
+        parseHeader();
+    }
 
-          if (gbAtX[5] != 2 || gbAtY[5] != -1)
-            setOverrideFlag(5);
+    public RegionSegmentInformation getRegionInfo()
+    {
+        return regionInfo;
+    }
 
-          if (gbAtX[6] != -3 || gbAtY[6] != 0)
-            setOverrideFlag(6);
+    protected boolean useExtTemplates()
+    {
+        return useExtTemplates;
+    }
 
-          if (gbAtX[7] != -4 || gbAtY[7] != 0)
-            setOverrideFlag(7);
+    protected boolean isTPGDon()
+    {
+        return isTPGDon;
+    }
 
-          if (gbAtX[8] != 2 || gbAtY[8] != -2)
-            setOverrideFlag(8);
+    protected byte getGbTemplate()
+    {
+        return gbTemplate;
+    }
 
-          if (gbAtX[9] != 3 || gbAtY[9] != -1)
-            setOverrideFlag(9);
+    protected boolean isMMREncoded()
+    {
+        return isMMREncoded;
+    }
 
-          if (gbAtX[10] != -2 || gbAtY[10] != -2)
-            setOverrideFlag(10);
+    protected short[] getGbAtX()
+    {
+        return gbAtX;
+    }
 
-          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;
-  }
+    protected short[] getGbAtY()
+    {
+        return gbAtY;
+    }
 }

http://git-wip-us.apache.org/repos/asf/pdfbox-jbig2/blob/30839c32/src/main/java/org/apache/pdfbox/jbig2/segments/HalftoneRegion.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/pdfbox/jbig2/segments/HalftoneRegion.java 
b/src/main/java/org/apache/pdfbox/jbig2/segments/HalftoneRegion.java
index 4121d58..651f4b7 100644
--- a/src/main/java/org/apache/pdfbox/jbig2/segments/HalftoneRegion.java
+++ b/src/main/java/org/apache/pdfbox/jbig2/segments/HalftoneRegion.java
@@ -32,378 +32,431 @@ import org.apache.pdfbox.jbig2.util.log.Logger;
 import org.apache.pdfbox.jbig2.util.log.LoggerFactory;
 
 /**
- * This class represents the data of segment type "Halftone region". Parsing 
is described in 7.4.5,
- * page 67. Decoding procedure in 6.6.5 and 7.4.5.2.
+ * This class represents the data of segment type "Halftone region". Parsing 
is described in 7.4.5, page 67. Decoding
+ * procedure in 6.6.5 and 7.4.5.2.
  */
-public class HalftoneRegion implements Region {
-
-  private final Logger log = LoggerFactory.getLogger(HalftoneRegion.class);
-
-  private SubInputStream subInputStream;
-  private SegmentHeader segmentHeader;
-  private long dataHeaderOffset;
-  private long dataHeaderLength;
-  private long dataOffset;
-  private long dataLength;
-
-  /** Region segment information field, 7.4.1 */
-  private RegionSegmentInformation regionInfo;
-
-  /** Halftone segment information field, 7.4.5.1.1 */
-  private byte hDefaultPixel;
-  private CombinationOperator hCombinationOperator;
-  private boolean hSkipEnabled;
-  private byte hTemplate;
-  private boolean isMMREncoded;
-
-  /** Halftone grid position and size, 7.4.5.1.2 */
-  /** Width of the gray-scale image, 7.4.5.1.2.1 */
-  private int hGridWidth;
-  /** Height of the gray-scale image, 7.4.5.1.2.2 */
-  private int hGridHeight;
-  /** Horizontal offset of the grid, 7.4.5.1.2.3 */
-  private int hGridX;
-  /** Vertical offset of the grid, 7.4.5.1.2.4 */
-  private int hGridY;
-
-  /** Halftone grid vector, 7.4.5.1.3 */
-  /** Horizontal coordinate of the halftone grid vector, 7.4.5.1.3.1 */
-  private int hRegionX;
-  /** Vertical coordinate of the halftone grod vector, 7.4.5.1.3.2 */
-  private int hRegionY;
-
-  /** Decoded data */
-  private Bitmap halftoneRegionBitmap;
-
-  /**
-   * Previously decoded data from other regions or dictionaries, stored to use 
as patterns in this
-   * region.
-   */
-  private ArrayList<Bitmap> patterns;
-
-  public HalftoneRegion() {
-  }
-
-  public HalftoneRegion(final SubInputStream subInputStream) {
-    this.subInputStream = subInputStream;
-    this.regionInfo = new RegionSegmentInformation(subInputStream);
-  }
-
-  public HalftoneRegion(final SubInputStream subInputStream, final 
SegmentHeader segmentHeader) {
-    this.subInputStream = subInputStream;
-    this.segmentHeader = segmentHeader;
-    this.regionInfo = new RegionSegmentInformation(subInputStream);
-  }
-
-  private void parseHeader() throws IOException, InvalidHeaderValueException {
-    regionInfo.parseHeader();
-
-    /* Bit 7 */
-    hDefaultPixel = (byte) subInputStream.readBit();
-
-    /* Bit 4-6 */
-    hCombinationOperator = 
CombinationOperator.translateOperatorCodeToEnum((short) 
(subInputStream.readBits(3) & 0xf));
-
-    /* Bit 3 */
-    if (subInputStream.readBit() == 1) {
-      hSkipEnabled = true;
+public class HalftoneRegion implements Region
+{
+
+    private final Logger log = LoggerFactory.getLogger(HalftoneRegion.class);
+
+    private SubInputStream subInputStream;
+    private SegmentHeader segmentHeader;
+    private long dataHeaderOffset;
+    private long dataHeaderLength;
+    private long dataOffset;
+    private long dataLength;
+
+    /** Region segment information field, 7.4.1 */
+    private RegionSegmentInformation regionInfo;
+
+    /** Halftone segment information field, 7.4.5.1.1 */
+    private byte hDefaultPixel;
+    private CombinationOperator hCombinationOperator;
+    private boolean hSkipEnabled;
+    private byte hTemplate;
+    private boolean isMMREncoded;
+
+    /** Halftone grid position and size, 7.4.5.1.2 */
+    /** Width of the gray-scale image, 7.4.5.1.2.1 */
+    private int hGridWidth;
+    /** Height of the gray-scale image, 7.4.5.1.2.2 */
+    private int hGridHeight;
+    /** Horizontal offset of the grid, 7.4.5.1.2.3 */
+    private int hGridX;
+    /** Vertical offset of the grid, 7.4.5.1.2.4 */
+    private int hGridY;
+
+    /** Halftone grid vector, 7.4.5.1.3 */
+    /** Horizontal coordinate of the halftone grid vector, 7.4.5.1.3.1 */
+    private int hRegionX;
+    /** Vertical coordinate of the halftone grod vector, 7.4.5.1.3.2 */
+    private int hRegionY;
+
+    /** Decoded data */
+    private Bitmap halftoneRegionBitmap;
+
+    /**
+     * Previously decoded data from other regions or dictionaries, stored to 
use as patterns in this region.
+     */
+    private ArrayList<Bitmap> patterns;
+
+    public HalftoneRegion()
+    {
     }
 
-    /* Bit 1-2 */
-    hTemplate = (byte) (subInputStream.readBits(2) & 0xf);
+    public HalftoneRegion(final SubInputStream subInputStream)
+    {
+        this.subInputStream = subInputStream;
+        this.regionInfo = new RegionSegmentInformation(subInputStream);
+    }
 
-    /* Bit 0 */
-    if (subInputStream.readBit() == 1) {
-      isMMREncoded = true;
+    public HalftoneRegion(final SubInputStream subInputStream, final 
SegmentHeader segmentHeader)
+    {
+        this.subInputStream = subInputStream;
+        this.segmentHeader = segmentHeader;
+        this.regionInfo = new RegionSegmentInformation(subInputStream);
     }
 
-    hGridWidth = (int) (subInputStream.readBits(32) & 0xffffffff);
-    hGridHeight = (int) (subInputStream.readBits(32) & 0xffffffff);
+    private void parseHeader() throws IOException, InvalidHeaderValueException
+    {
+        regionInfo.parseHeader();
+
+        /* Bit 7 */
+        hDefaultPixel = (byte) subInputStream.readBit();
+
+        /* Bit 4-6 */
+        hCombinationOperator = CombinationOperator
+                .translateOperatorCodeToEnum((short) 
(subInputStream.readBits(3) & 0xf));
+
+        /* Bit 3 */
+        if (subInputStream.readBit() == 1)
+        {
+            hSkipEnabled = true;
+        }
 
-    hGridX = (int) subInputStream.readBits(32);
-    hGridY = (int) subInputStream.readBits(32);
+        /* Bit 1-2 */
+        hTemplate = (byte) (subInputStream.readBits(2) & 0xf);
 
-    hRegionX = (int) subInputStream.readBits(16) & 0xffff;
-    hRegionY = (int) subInputStream.readBits(16) & 0xffff;
+        /* Bit 0 */
+        if (subInputStream.readBit() == 1)
+        {
+            isMMREncoded = true;
+        }
 
-    /* Segment data structure */
-    computeSegmentDataStructure();
+        hGridWidth = (int) (subInputStream.readBits(32) & 0xffffffff);
+        hGridHeight = (int) (subInputStream.readBits(32) & 0xffffffff);
 
-    this.checkInput();
-  }
+        hGridX = (int) subInputStream.readBits(32);
+        hGridY = (int) subInputStream.readBits(32);
 
-  private void computeSegmentDataStructure() throws IOException {
-    dataOffset = subInputStream.getStreamPosition();
-    dataHeaderLength = dataOffset - dataHeaderOffset;
-    dataLength = subInputStream.length() - dataHeaderLength;
-  }
+        hRegionX = (int) subInputStream.readBits(16) & 0xffff;
+        hRegionY = (int) subInputStream.readBits(16) & 0xffff;
 
-  private void checkInput() throws InvalidHeaderValueException {
-    if (isMMREncoded) {
-      if (hTemplate != 0) {
-        log.info("hTemplate = " + hTemplate + " (should contain the value 0)");
-      }
+        /* Segment data structure */
+        computeSegmentDataStructure();
 
-      if (hSkipEnabled) {
-        log.info("hSkipEnabled 0 " + hSkipEnabled + " (should contain the 
value false)");
-      }
+        this.checkInput();
     }
-  }
-
-  /**
-   * The procedure is described in JBIG2 ISO standard, 6.6.5.
-   * 
-   * @return The decoded {@link Bitmap} of this region.
-   * 
-   * @throws IOException if an underlying IO operation fails
-   * @throws InvalidHeaderValueException if a segment header value is invalid
-   */
-  public Bitmap getRegionBitmap() throws IOException, 
InvalidHeaderValueException {
-    if (null == halftoneRegionBitmap) {
-
-      /* 6.6.5, page 40 */
-      /* 1) */
-      halftoneRegionBitmap = new Bitmap(regionInfo.getBitmapWidth(), 
regionInfo.getBitmapHeight());
-
-      if (patterns == null) {
-        patterns = getPatterns();
-      }
-
-      if (hDefaultPixel == 1) {
-        Arrays.fill(halftoneRegionBitmap.getByteArray(), (byte) 0xff);
-      }
-
-      /* 2) */
-      /*
-       * 6.6.5.1 Computing hSkip - At the moment SKIP is not used... we are 
not able to test it.
-       */
-      // Bitmap hSkip;
-      // if (hSkipEnabled) {
-      // int hPatternHeight = (int) hPats.get(0).getHeight();
-      // int hPatternWidth = (int) hPats.get(0).getWidth();
-      // TODO: Set or get pattern width and height from referred
-      // pattern segments. The method is called like this:
-      // hSkip = computeHSkip(hPatternHeight, hPatternWidth);
-      // }
-
-      /* 3) */
-      final int bitsPerValue = (int) Math.ceil(Math.log(patterns.size()) / 
Math.log(2));
-
-      /* 4) */
-      final int[][] grayScaleValues = grayScaleDecoding(bitsPerValue);
-
-      /* 5), rendering the pattern, described in 6.6.5.2 */
-      renderPattern(grayScaleValues);
+
+    private void computeSegmentDataStructure() throws IOException
+    {
+        dataOffset = subInputStream.getStreamPosition();
+        dataHeaderLength = dataOffset - dataHeaderOffset;
+        dataLength = subInputStream.length() - dataHeaderLength;
     }
-    /* 6) */
-    return halftoneRegionBitmap;
-  }
-
-  /**
-   * This method draws the pattern into the region bitmap ({@code htReg}), as 
described in 6.6.5.2,
-   * page 42
-   */
-  private void renderPattern(final int[][] grayScaleValues) {
-    int x = 0, y = 0;
-
-    // 1)
-    for (int m = 0; m < hGridHeight; m++) {
-      // a)
-      for (int n = 0; n < hGridWidth; n++) {
-        // i)
-        x = computeX(m, n);
-        y = computeY(m, n);
-
-        // ii)
-        final Bitmap patternBitmap = patterns.get(grayScaleValues[m][n]);
-        Bitmaps.blit(patternBitmap, halftoneRegionBitmap, (x + hGridX), (y + 
hGridY), hCombinationOperator);
-      }
+
+    private void checkInput() throws InvalidHeaderValueException
+    {
+        if (isMMREncoded)
+        {
+            if (hTemplate != 0)
+            {
+                log.info("hTemplate = " + hTemplate + " (should contain the 
value 0)");
+            }
+
+            if (hSkipEnabled)
+            {
+                log.info("hSkipEnabled 0 " + hSkipEnabled + " (should contain 
the value false)");
+            }
+        }
     }
-  }
-
-  /**
-   * @throws IOException
-   * @throws InvalidHeaderValueException
-   * 
-   */
-  private ArrayList<Bitmap> getPatterns() throws InvalidHeaderValueException, 
IOException {
-    final ArrayList<Bitmap> patterns = new ArrayList<Bitmap>();
-
-    for (SegmentHeader s : segmentHeader.getRtSegments()) {
-      final PatternDictionary patternDictionary = (PatternDictionary) 
s.getSegmentData();
-      patterns.addAll(patternDictionary.getDictionary());
+
+    /**
+     * The procedure is described in JBIG2 ISO standard, 6.6.5.
+     * 
+     * @return The decoded {@link Bitmap} of this region.
+     * 
+     * @throws IOException if an underlying IO operation fails
+     * @throws InvalidHeaderValueException if a segment header value is invalid
+     */
+    public Bitmap getRegionBitmap() throws IOException, 
InvalidHeaderValueException
+    {
+        if (null == halftoneRegionBitmap)
+        {
+
+            /* 6.6.5, page 40 */
+            /* 1) */
+            halftoneRegionBitmap = new Bitmap(regionInfo.getBitmapWidth(),
+                    regionInfo.getBitmapHeight());
+
+            if (patterns == null)
+            {
+                patterns = getPatterns();
+            }
+
+            if (hDefaultPixel == 1)
+            {
+                Arrays.fill(halftoneRegionBitmap.getByteArray(), (byte) 0xff);
+            }
+
+            /* 2) */
+            /*
+             * 6.6.5.1 Computing hSkip - At the moment SKIP is not used... we 
are not able to test it.
+             */
+            // Bitmap hSkip;
+            // if (hSkipEnabled) {
+            // int hPatternHeight = (int) hPats.get(0).getHeight();
+            // int hPatternWidth = (int) hPats.get(0).getWidth();
+            // TODO: Set or get pattern width and height from referred
+            // pattern segments. The method is called like this:
+            // hSkip = computeHSkip(hPatternHeight, hPatternWidth);
+            // }
+
+            /* 3) */
+            final int bitsPerValue = (int) Math.ceil(Math.log(patterns.size()) 
/ Math.log(2));
+
+            /* 4) */
+            final int[][] grayScaleValues = grayScaleDecoding(bitsPerValue);
+
+            /* 5), rendering the pattern, described in 6.6.5.2 */
+            renderPattern(grayScaleValues);
+        }
+        /* 6) */
+        return halftoneRegionBitmap;
     }
 
-    return patterns;
-  }
-
-  /**
-   * Gray-scale image decoding procedure is special for halftone region 
decoding and is described in
-   * Annex C.5 on page 98.
-   */
-  private int[][] grayScaleDecoding(final int bitsPerValue) throws IOException 
{
-
-    short[] gbAtX = null;
-    short[] gbAtY = null;
-
-    if (!isMMREncoded) {
-      gbAtX = new short[4];
-      gbAtY = new short[4];
-      // Set AT pixel values
-      if (hTemplate <= 1)
-        gbAtX[0] = 3;
-      else if (hTemplate >= 2)
-        gbAtX[0] = 2;
-
-      gbAtY[0] = -1;
-      gbAtX[1] = -3;
-      gbAtY[1] = -1;
-      gbAtX[2] = 2;
-      gbAtY[2] = -2;
-      gbAtX[3] = -2;
-      gbAtY[3] = -2;
+    /**
+     * This method draws the pattern into the region bitmap ({@code htReg}), 
as described in 6.6.5.2, page 42
+     */
+    private void renderPattern(final int[][] grayScaleValues)
+    {
+        int x = 0, y = 0;
+
+        // 1)
+        for (int m = 0; m < hGridHeight; m++)
+        {
+            // a)
+            for (int n = 0; n < hGridWidth; n++)
+            {
+                // i)
+                x = computeX(m, n);
+                y = computeY(m, n);
+
+                // ii)
+                final Bitmap patternBitmap = 
patterns.get(grayScaleValues[m][n]);
+                Bitmaps.blit(patternBitmap, halftoneRegionBitmap, (x + 
hGridX), (y + hGridY),
+                        hCombinationOperator);
+            }
+        }
     }
 
-    Bitmap[] grayScalePlanes = new Bitmap[bitsPerValue];
+    /**
+     * @throws IOException
+     * @throws InvalidHeaderValueException
+     * 
+     */
+    private ArrayList<Bitmap> getPatterns() throws 
InvalidHeaderValueException, IOException
+    {
+        final ArrayList<Bitmap> patterns = new ArrayList<Bitmap>();
+
+        for (SegmentHeader s : segmentHeader.getRtSegments())
+        {
+            final PatternDictionary patternDictionary = (PatternDictionary) 
s.getSegmentData();
+            patterns.addAll(patternDictionary.getDictionary());
+        }
 
-    // 1)
-    GenericRegion genericRegion = new GenericRegion(subInputStream);
-    genericRegion.setParameters(isMMREncoded, dataOffset, dataLength, 
hGridHeight, hGridWidth, hTemplate, false,
-        hSkipEnabled, gbAtX, gbAtY);
+        return patterns;
+    }
 
-    // 2)
-    int j = bitsPerValue - 1;
+    /**
+     * Gray-scale image decoding procedure is special for halftone region 
decoding and is described in Annex C.5 on page
+     * 98.
+     */
+    private int[][] grayScaleDecoding(final int bitsPerValue) throws 
IOException
+    {
+
+        short[] gbAtX = null;
+        short[] gbAtY = null;
+
+        if (!isMMREncoded)
+        {
+            gbAtX = new short[4];
+            gbAtY = new short[4];
+            // Set AT pixel values
+            if (hTemplate <= 1)
+                gbAtX[0] = 3;
+            else if (hTemplate >= 2)
+                gbAtX[0] = 2;
+
+            gbAtY[0] = -1;
+            gbAtX[1] = -3;
+            gbAtY[1] = -1;
+            gbAtX[2] = 2;
+            gbAtY[2] = -2;
+            gbAtX[3] = -2;
+            gbAtY[3] = -2;
+        }
 
-    grayScalePlanes[j] = genericRegion.getRegionBitmap();
+        Bitmap[] grayScalePlanes = new Bitmap[bitsPerValue];
 
-    while (j > 0) {
-      j--;
-      genericRegion.resetBitmap();
-      // 3) a)
-      grayScalePlanes[j] = genericRegion.getRegionBitmap();
-      // 3) b)
-      grayScalePlanes = combineGrayScalePlanes(grayScalePlanes, j);
-    }
+        // 1)
+        GenericRegion genericRegion = new GenericRegion(subInputStream);
+        genericRegion.setParameters(isMMREncoded, dataOffset, dataLength, 
hGridHeight, hGridWidth,
+                hTemplate, false, hSkipEnabled, gbAtX, gbAtY);
 
-    // 4)
-    return computeGrayScaleValues(grayScalePlanes, bitsPerValue);
-  }
+        // 2)
+        int j = bitsPerValue - 1;
 
-  private Bitmap[] combineGrayScalePlanes(Bitmap[] grayScalePlanes, int j) {
-    int byteIndex = 0;
-    for (int y = 0; y < grayScalePlanes[j].getHeight(); y++) {
+        grayScalePlanes[j] = genericRegion.getRegionBitmap();
 
-      for (int x = 0; x < grayScalePlanes[j].getWidth(); x += 8) {
-        final byte newValue = grayScalePlanes[j + 1].getByte(byteIndex);
-        final byte oldValue = grayScalePlanes[j].getByte(byteIndex);
+        while (j > 0)
+        {
+            j--;
+            genericRegion.resetBitmap();
+            // 3) a)
+            grayScalePlanes[j] = genericRegion.getRegionBitmap();
+            // 3) b)
+            grayScalePlanes = combineGrayScalePlanes(grayScalePlanes, j);
+        }
 
-        grayScalePlanes[j].setByte(byteIndex++, Bitmaps.combineBytes(oldValue, 
newValue, CombinationOperator.XOR));
-      }
+        // 4)
+        return computeGrayScaleValues(grayScalePlanes, bitsPerValue);
     }
-    return grayScalePlanes;
-  }
-
-  private int[][] computeGrayScaleValues(final Bitmap[] grayScalePlanes, final 
int bitsPerValue) {
-    // Gray-scale decoding procedure, page 98
-    final int[][] grayScaleValues = new int[hGridHeight][hGridWidth];
-
-    // 4)
-    for (int y = 0; y < hGridHeight; y++) {
-      for (int x = 0; x < hGridWidth; x += 8) {
-        final int minorWidth = hGridWidth - x > 8 ? 8 : hGridWidth - x;
-        int byteIndex = grayScalePlanes[0].getByteIndex(x, y);
-
-        for (int minorX = 0; minorX < minorWidth; minorX++) {
-          final int i = minorX + x;
-          grayScaleValues[y][i] = 0;
-
-          for (int j = 0; j < bitsPerValue; j++) {
-            grayScaleValues[y][i] += ((grayScalePlanes[j].getByte(byteIndex) 
>> (7 - i & 7)) & 1) * (1 << j);
-          }
+
+    private Bitmap[] combineGrayScalePlanes(Bitmap[] grayScalePlanes, int j)
+    {
+        int byteIndex = 0;
+        for (int y = 0; y < grayScalePlanes[j].getHeight(); y++)
+        {
+
+            for (int x = 0; x < grayScalePlanes[j].getWidth(); x += 8)
+            {
+                final byte newValue = grayScalePlanes[j + 
1].getByte(byteIndex);
+                final byte oldValue = grayScalePlanes[j].getByte(byteIndex);
+
+                grayScalePlanes[j].setByte(byteIndex++,
+                        Bitmaps.combineBytes(oldValue, newValue, 
CombinationOperator.XOR));
+            }
         }
-      }
+        return grayScalePlanes;
     }
-    return grayScaleValues;
-  }
 
-  private int computeX(final int m, final int n) {
-    return shiftAndFill((hGridX + m * hRegionY + n * hRegionX));
-  }
+    private int[][] computeGrayScaleValues(final Bitmap[] grayScalePlanes, 
final int bitsPerValue)
+    {
+        // Gray-scale decoding procedure, page 98
+        final int[][] grayScaleValues = new int[hGridHeight][hGridWidth];
+
+        // 4)
+        for (int y = 0; y < hGridHeight; y++)
+        {
+            for (int x = 0; x < hGridWidth; x += 8)
+            {
+                final int minorWidth = hGridWidth - x > 8 ? 8 : hGridWidth - x;
+                int byteIndex = grayScalePlanes[0].getByteIndex(x, y);
+
+                for (int minorX = 0; minorX < minorWidth; minorX++)
+                {
+                    final int i = minorX + x;
+                    grayScaleValues[y][i] = 0;
+
+                    for (int j = 0; j < bitsPerValue; j++)
+                    {
+                        grayScaleValues[y][i] += ((grayScalePlanes[j]
+                                .getByte(byteIndex) >> (7 - i & 7)) & 1) * (1 
<< j);
+                    }
+                }
+            }
+        }
+        return grayScaleValues;
+    }
 
-  private int computeY(final int m, final int n) {
-    return shiftAndFill((hGridY + m * hRegionX - n * hRegionY));
-  }
+    private int computeX(final int m, final int n)
+    {
+        return shiftAndFill((hGridX + m * hRegionY + n * hRegionX));
+    }
 
-  private int shiftAndFill(int value) {
-    // shift value by 8 and let the leftmost 8 bits be 0
-    value >>= 8;
+    private int computeY(final int m, final int n)
+    {
+        return shiftAndFill((hGridY + m * hRegionX - n * hRegionY));
+    }
 
-    if (value < 0) {
-      // fill the leftmost 8 bits with 1
-      final int bitPosition = (int) (Math.log(Integer.highestOneBit(value)) / 
Math.log(2));
+    private int shiftAndFill(int value)
+    {
+        // shift value by 8 and let the leftmost 8 bits be 0
+        value >>= 8;
+
+        if (value < 0)
+        {
+            // fill the leftmost 8 bits with 1
+            final int bitPosition = (int) 
(Math.log(Integer.highestOneBit(value)) / Math.log(2));
+
+            for (int i = 1; i < 31 - bitPosition; i++)
+            {
+                // bit flip
+                value |= 1 << (31 - i);
+            }
+        }
 
-      for (int i = 1; i < 31 - bitPosition; i++) {
-        // bit flip
-        value |= 1 << (31 - i);
-      }
+        return value;
     }
 
-    return value;
-  }
-
-  public void init(final SegmentHeader header, final SubInputStream sis) 
throws InvalidHeaderValueException,
-      IOException {
-    this.segmentHeader = header;
-    this.subInputStream = sis;
-    this.regionInfo = new RegionSegmentInformation(subInputStream);
-    parseHeader();
-  }
+    public void init(final SegmentHeader header, final SubInputStream sis)
+            throws InvalidHeaderValueException, IOException
+    {
+        this.segmentHeader = header;
+        this.subInputStream = sis;
+        this.regionInfo = new RegionSegmentInformation(subInputStream);
+        parseHeader();
+    }
 
-  public CombinationOperator getCombinationOperator() {
-    return hCombinationOperator;
-  }
+    public CombinationOperator getCombinationOperator()
+    {
+        return hCombinationOperator;
+    }
 
-  public RegionSegmentInformation getRegionInfo() {
-    return regionInfo;
-  }
+    public RegionSegmentInformation getRegionInfo()
+    {
+        return regionInfo;
+    }
 
-  protected byte getHTemplate() {
-    return hTemplate;
-  }
+    protected byte getHTemplate()
+    {
+        return hTemplate;
+    }
 
-  protected boolean isHSkipEnabled() {
-    return hSkipEnabled;
-  }
+    protected boolean isHSkipEnabled()
+    {
+        return hSkipEnabled;
+    }
 
-  protected boolean isMMREncoded() {
-    return isMMREncoded;
-  }
+    protected boolean isMMREncoded()
+    {
+        return isMMREncoded;
+    }
 
-  protected int getHGridWidth() {
-    return hGridWidth;
-  }
+    protected int getHGridWidth()
+    {
+        return hGridWidth;
+    }
 
-  protected int getHGridHeight() {
-    return hGridHeight;
-  }
+    protected int getHGridHeight()
+    {
+        return hGridHeight;
+    }
 
-  protected int getHGridX() {
-    return hGridX;
-  }
+    protected int getHGridX()
+    {
+        return hGridX;
+    }
 
-  protected int getHGridY() {
-    return hGridY;
-  }
+    protected int getHGridY()
+    {
+        return hGridY;
+    }
 
-  protected int getHRegionX() {
-    return hRegionX;
-  }
+    protected int getHRegionX()
+    {
+        return hRegionX;
+    }
 
-  protected int getHRegionY() {
-    return hRegionY;
-  }
+    protected int getHRegionY()
+    {
+        return hRegionY;
+    }
 
-  protected byte getHDefaultPixel() {
-    return hDefaultPixel;
-  }
+    protected byte getHDefaultPixel()
+    {
+        return hDefaultPixel;
+    }
 }

Reply via email to