This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pdfbox-jbig2.git
The following commit(s) were added to refs/heads/master by this push:
new 359e197 PDFBOX-6162: Extract GenericRefinementRegion decoding logic
into GenericRefinementRegionDecodingProcedure for modularity and correctness
359e197 is described below
commit 359e1975e9b3e048da90db04f3a8dc86f558a29b
Author: Maruan Sahyoun <[email protected]>
AuthorDate: Thu Apr 23 10:06:09 2026 +0200
PDFBOX-6162: Extract GenericRefinementRegion decoding logic into
GenericRefinementRegionDecodingProcedure for modularity and correctness
---
.../GenericRefinementRegionDecodingProcedure.java} | 443 ++++---------
.../jbig2/segments/GenericRefinementRegion.java | 719 +--------------------
2 files changed, 160 insertions(+), 1002 deletions(-)
diff --git
a/src/main/java/org/apache/pdfbox/jbig2/segments/GenericRefinementRegion.java
b/src/main/java/org/apache/pdfbox/jbig2/decoder/GenericRefinementRegionDecodingProcedure.java
similarity index 68%
copy from
src/main/java/org/apache/pdfbox/jbig2/segments/GenericRefinementRegion.java
copy to
src/main/java/org/apache/pdfbox/jbig2/decoder/GenericRefinementRegionDecodingProcedure.java
index 32650c5..d712cd0 100644
---
a/src/main/java/org/apache/pdfbox/jbig2/segments/GenericRefinementRegion.java
+++
b/src/main/java/org/apache/pdfbox/jbig2/decoder/GenericRefinementRegionDecodingProcedure.java
@@ -15,75 +15,53 @@
* limitations under the License.
*/
-package org.apache.pdfbox.jbig2.segments;
+package org.apache.pdfbox.jbig2.decoder;
-import java.awt.Rectangle;
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.err.IntegerMaxValueException;
-import org.apache.pdfbox.jbig2.err.InvalidHeaderValueException;
-import org.apache.pdfbox.jbig2.image.Bitmaps;
-import org.apache.pdfbox.jbig2.io.SubInputStream;
-import org.apache.pdfbox.jbig2.util.CombinationOperator;
+import org.apache.pdfbox.jbig2.segments.GenericRefinementRegion;
/**
- * Reusable implementation of the JBIG2 generic refinement region decoding
- * procedure as defined in ITU-T T.88 (JBIG2), §6.3.
+ * Implements the JBIG2 Generic Refinement Region decoding procedure
+ * as defined in ITU-T T.88, §6.3 including the core decoding loop
+ * defined in §6.3.5.6.
*
- * <p>This class implements only the <b>decoding algorithm</b> for a generic
- * refinement region. It does not inherently define how parameters are
obtained;
- * instead, it relies on the caller to supply or initialize the required
inputs.
- * Different parts of the JBIG2 specification reuse this same procedure with
- * different parameter sources:</p>
+ * <p>This class is purely algorithmic. It has no knowledge of how its inputs
+ * are obtained and no dependency on segment headers or input streams.
+ * The entry point is the static {@link #decode decode()} method; callers
+ * supply the {@link ArithmeticDecoder} and {@link CX} context model directly,
+ * so they decide whether to create fresh instances or share existing ones:</p>
*
* <ul>
- * <li><b>Generic refinement region segment</b> (§7.4.7):
- * <ul>
- * <li>Parameters are parsed from the segment header via {@link
#init(...)}.</li>
- * <li>The reference bitmap is derived from referred-to segments or the
page buffer.</li>
- * <li>Per Table 35, {@code GRREFERENCEDX} and {@code GRREFERENCEDY} are
fixed to 0.</li>
- * </ul>
- * </li>
- *
- * <li><b>Symbol dictionary refinement / aggregation</b> (§6.5.8.2):
- * <ul>
- * <li>Parameters (including reference bitmap and offsets {@code RDX},
{@code RDY})
- * are decoded as part of the symbol dictionary procedure.</li>
- * <li>These parameters must be supplied via {@link
#setParameters(...)}.</li>
- * </ul>
- * </li>
- *
- * <li><b>Text region refinement</b> (§6.4, reusing §6.3):
- * <ul>
- * <li>Used indirectly by {@link TextRegion} when symbols are refined or
aggregated.</li>
- * <li>All parameters are provided programmatically, similar to the
symbol dictionary case.</li>
- * </ul>
- * </li>
- * </ul>
- *
- * <p><b>Usage patterns:</b></p>
- * <ul>
- * <li><b>Header-driven (segment-based):</b>
- * Initialize via {@link #init(SegmentHeader, SubInputStream)}.
- * In this mode, refinement offsets are implicitly zero as defined by
Table 35.</li>
- *
- * <li><b>Parameter-driven (dictionary/text region):</b>
- * Call {@link #setParameters(...)} before {@link #getRegionBitmap()} to
supply
- * all required decoding parameters explicitly.</li>
+ * <li><b>{@link GenericRefinementRegion}</b> — creates its own
+ * {@code ArithmeticDecoder} and {@code CX}, then calls {@code
decode()}.</li>
+ * <li><b>Symbol dictionary refinement (§6.5.8.2)</b> — passes the
+ * parent dictionary's shared {@code ArithmeticDecoder} and {@code
CX}.</li>
+ * <li><b>Text region refinement (§6.4)</b> — passes the parent text
+ * region's shared {@code ArithmeticDecoder} and {@code CX}.</li>
* </ul>
*
- * <p><b>Important:</b> This class does not explicitly enforce which mode is
used.
- * Correct behavior depends on the caller selecting the appropriate
initialization
- * path. Mixing header-based initialization with explicit parameter setting may
- * lead to undefined results.</p>
+ * <p>This class cannot be instantiated by callers. The private constructor and
+ * the internal {@link #run} method exist solely to let the many private helper
+ * methods share state through fields rather than through long parameter
lists.</p>
*/
-public class GenericRefinementRegion implements Region
+public class GenericRefinementRegionDecodingProcedure
{
+
+ //
-------------------------------------------------------------------------
+ // Template strategy — bit-context formation for each template type
+ //
-------------------------------------------------------------------------
+
+ /**
+ * Encapsulates the template-specific operations: context bit formation
+ * ({@link #form}) and initial CX index selection ({@link #setIndex}).
+ *
+ * <p>The two concrete implementations ({@link #T0}, {@link #T1})
correspond
+ * to GRTEMPLATE values 0 and 1 as defined in §6.3.3 / Figures 14–15.</p>
+ */
public static abstract class Template
{
protected abstract short form(short c1, short c2, short c3, short c4,
short c5);
@@ -93,7 +71,6 @@ public class GenericRefinementRegion implements Region
private static class Template0 extends Template
{
-
@Override
protected short form(short c1, short c2, short c3, short c4, short c5)
{
@@ -106,12 +83,10 @@ public class GenericRefinementRegion implements Region
// Figure 14, page 22
cx.setIndex(0x100);
}
-
}
private static class Template1 extends Template
{
-
@Override
protected short form(short c1, short c2, short c3, short c4, short c5)
{
@@ -124,248 +99,171 @@ public class GenericRefinementRegion implements Region
// Figure 15, page 22
cx.setIndex(0x080);
}
-
}
- private static final Template T0 = new Template0();
- private static final Template T1 = new Template1();
+ /** Singleton template 0 instance (stateless). */
+ public static final Template T0 = new Template0();
- private SubInputStream subInputStream;
+ /** Singleton template 1 instance (stateless). */
+ public static final Template T1 = new Template1();
- private SegmentHeader segmentHeader;
+ //
-------------------------------------------------------------------------
+ // Decoder state — injected at construction, shared across calls
+ //
-------------------------------------------------------------------------
- /** Region segment information flags, 7.4.1 */
- private RegionSegmentInformation regionInfo;
+ private final ArithmeticDecoder arithDecoder;
+ private final CX cx;
- /** Generic refinement region segment flags, 7.4.7.2 */
- private boolean isTPGROn;
- private short templateID;
+ //
-------------------------------------------------------------------------
+ // Per-decode working state — reset by each decode() call
+ //
-------------------------------------------------------------------------
+ private short templateID;
private Template template;
- /** Generic refinement region segment AT flags, 7.4.7.3 */
- private short grAtX[];
- private short grAtY[];
-
- /** Decoded data as pixel values (use row stride/width to wrap line) */
- private Bitmap regionBitmap;
-
- /** Variables for decoding */
+ private boolean isTPGROn;
private Bitmap referenceBitmap;
private int referenceDX;
private int referenceDY;
-
- private ArithmeticDecoder arithDecoder;
- private CX cx;
-
- /**
- * If true, AT pixels are not on their nominal location and have to be
overridden.
- */
+ private short[] grAtX;
+ private short[] grAtY;
private boolean override;
private boolean[] grAtOverride;
- private Bitmap pageBitmap;
+ /** The bitmap being built; held as a field to avoid passing it
everywhere. */
+ private Bitmap regionBitmap;
- public GenericRefinementRegion()
- {
- }
+ //
-------------------------------------------------------------------------
+ // Construction — private; callers use the static decode() entry point
+ //
-------------------------------------------------------------------------
- public GenericRefinementRegion(final SubInputStream subInputStream)
+ private GenericRefinementRegionDecodingProcedure(final ArithmeticDecoder
arithDecoder, final CX cx)
{
- this.subInputStream = subInputStream;
- this.regionInfo = new RegionSegmentInformation(subInputStream);
+ this.arithDecoder = arithDecoder;
+ this.cx = cx;
}
- public GenericRefinementRegion(final SubInputStream subInputStream,
- final SegmentHeader segmentHeader)
- {
- this.subInputStream = subInputStream;
- this.segmentHeader = segmentHeader;
- this.regionInfo = new RegionSegmentInformation(subInputStream);
- }
+ //
-------------------------------------------------------------------------
+ // Public static API
+ //
-------------------------------------------------------------------------
/**
- * Parses the flags described in JBIG2 ISO standard:
- * <ul>
- * <li>7.4.7.2 Generic refinement region segment flags</li>
- * <li>7.4.7.3 Generic refinement region segment AT flags</li>
- * </ul>
- *
- * @throws IOException
+ * Executes the Generic Refinement Region decoding procedure (§6.3.5.6) and
+ * returns the decoded bitmap.
+ *
+ * <p>A short-lived {@code GenericRefinementProcedure} instance is created
+ * internally so that the many private helper methods can share state
through
+ * fields rather than through long parameter lists. No state survives the
+ * return of this method.</p>
+ *
+ * @param arithDecoder the arithmetic decoder — shared with the parent
+ * when called from a symbol dictionary or text
region,
+ * or freshly created when called from a standalone
segment
+ * @param cx the context model — shared or fresh, as above
+ * @param width decoded bitmap width (GRW)
+ * @param height decoded bitmap height (GRH)
+ * @param grTemplate template index: 0 or 1 (GRTEMPLATE)
+ * @param isTPGROn whether typical prediction is enabled (TPGRON)
+ * @param referenceBitmap the reference / base bitmap (GRREFERENCE)
+ * @param referenceDX horizontal offset of reference bitmap
(GRREFERENCEDX)
+ * @param referenceDY vertical offset of reference bitmap
(GRREFERENCEDY)
+ * @param grAtX AT pixel X offsets (only used when grTemplate ==
0)
+ * @param grAtY AT pixel Y offsets (only used when grTemplate ==
0)
+ * @return the decoded bitmap
+ * @throws IOException if an underlying I/O operation fails
*/
- private void parseHeader() throws IOException
+ public static Bitmap decode(final ArithmeticDecoder arithDecoder, final CX
cx,
+ final int width, final int height, final short grTemplate,
+ final boolean isTPGROn, final Bitmap referenceBitmap,
+ final int referenceDX, final int referenceDY,
+ final short[] grAtX, final short[] grAtY) throws IOException
{
- regionInfo.parseHeader();
+ return new GenericRefinementRegionDecodingProcedure(arithDecoder, cx)
+ .run(width, height, grTemplate, isTPGROn, referenceBitmap,
+ referenceDX, referenceDY, grAtX, grAtY);
+ }
- /* Bit 2-7 */
- subInputStream.readBits(6); // Dirty read...
+ //
-------------------------------------------------------------------------
+ // Private execution — all helpers share state through instance fields
+ //
-------------------------------------------------------------------------
- /* Bit 1 */
- if (subInputStream.readBit() == 1)
- {
- isTPGROn = true;
- }
+ private Bitmap run(final int width, final int height, final short
grTemplate,
+ final boolean isTPGROn, final Bitmap referenceBitmap,
+ final int referenceDX, final int referenceDY,
+ final short[] grAtX, final short[] grAtY) throws IOException
+ {
+ this.templateID = grTemplate;
+ this.template = (grTemplate == 0) ? T0 : T1;
+ this.isTPGROn = isTPGROn;
+ this.referenceBitmap = referenceBitmap;
+ this.referenceDX = referenceDX;
+ this.referenceDY = referenceDY;
+ this.grAtX = grAtX;
+ this.grAtY = grAtY;
+ this.override = false;
+ this.grAtOverride = null;
- /* Bit 0 */
- templateID = (short) subInputStream.readBit();
+ /* 6.3.5.6 - 2) */
+ regionBitmap = new Bitmap(width, height);
- switch (templateID)
+ if (templateID == 0)
{
- case 0:
- template = T0;
- readAtPixels();
- break;
- case 1:
- template = T1;
- break;
+ // AT pixels are only relevant for template 0
+ updateOverride();
}
- }
-
- // 7.4.7.3 Generic refinement region segment AT flags
- private void readAtPixels() throws IOException
- {
- grAtX = new short[2];
- grAtY = new short[2];
-
- /* Byte 0 */
- grAtX[0] = subInputStream.readByte();
- /* Byte 1 */
- grAtY[0] = subInputStream.readByte();
- /* Byte 2 */
- grAtX[1] = subInputStream.readByte();
- /* Byte 3 */
- grAtY[1] = subInputStream.readByte();
- }
-
- /**
- * Decode using a template and arithmetic coding, as described in 6.3.5.6
- *
- * @throws IOException if an underlying IO operation fails
- * @throws InvalidHeaderValueException if a segment header value is invalid
- * @throws IntegerMaxValueException if the maximum value limit of an
integer is exceeded
- */
- @Override
- public Bitmap getRegionBitmap()
- throws IOException, IntegerMaxValueException,
InvalidHeaderValueException
- {
- if (null == regionBitmap)
- {
- /* 6.3.5.6 - 1) */
- int isLineTypicalPredicted = 0; // LTP
- if (referenceBitmap == null)
- {
- // Get the reference bitmap, which is the base of refinement
process
- referenceBitmap = getGrReference();
- }
+ final int paddedWidth = (width + 7) & -8;
+ final int deltaRefStride = isTPGROn ? -referenceDY *
referenceBitmap.getRowStride() : 0;
+ final int yOffset = deltaRefStride + 1;
- if (arithDecoder == null)
- {
- arithDecoder = new ArithmeticDecoder(subInputStream);
- }
+ /* 6.3.5.6 - 1) */
+ int isLineTypicalPredicted = 0; // LTP
- if (cx == null)
+ /* 6.3.5.6 - 3) */
+ for (int y = 0; y < height; y++)
+ {
+ /* 6.3.5.6 - 3 b) */
+ if (isTPGROn)
{
- cx = new CX(8192, 1);
+ isLineTypicalPredicted ^= decodeSLTP();
}
- /* 6.3.5.6 - 2) */
- regionBitmap = new Bitmap(regionInfo.getBitmapWidth(),
regionInfo.getBitmapHeight());
-
- if (templateID == 0)
+ if (isLineTypicalPredicted == 0)
{
- // AT pixel may only occur in template 0
- updateOverride();
+ /* 6.3.5.6 - 3 c) */
+ decodeOptimized(y, width, regionBitmap.getRowStride(),
+ referenceBitmap.getRowStride(), paddedWidth,
deltaRefStride, yOffset);
}
-
- final int paddedWidth = (regionBitmap.getWidth() + 7) & -8;
- final int deltaRefStride = isTPGROn ? -referenceDY *
referenceBitmap.getRowStride() : 0;
- final int yOffset = deltaRefStride + 1;
-
- /* 6.3.5.6 - 3 */
- for (int y = 0; y < regionBitmap.getHeight(); y++)
+ else
{
- /* 6.3.5.6 - 3 b) */
- if (isTPGROn)
- {
- isLineTypicalPredicted ^= decodeSLTP();
- }
-
- if (isLineTypicalPredicted == 0)
- {
- /* 6.3.5.6 - 3 c) */
- decodeOptimized(y, regionBitmap.getWidth(),
regionBitmap.getRowStride(),
- referenceBitmap.getRowStride(), paddedWidth,
deltaRefStride, yOffset);
- }
- else
- {
- /* 6.3.5.6 - 3 d) */
- decodeTypicalPredictedLine(y, regionBitmap.getWidth(),
- regionBitmap.getRowStride(),
referenceBitmap.getRowStride(),
- paddedWidth, deltaRefStride);
- }
+ /* 6.3.5.6 - 3 d) */
+ decodeTypicalPredictedLine(y, width,
regionBitmap.getRowStride(),
+ referenceBitmap.getRowStride(), paddedWidth,
deltaRefStride);
}
}
+
/* 6.3.5.6 - 4) */
return regionBitmap;
}
+ //
-------------------------------------------------------------------------
+ // Private decoding helpers (§6.3.5.6 sub-steps)
+ //
-------------------------------------------------------------------------
+
private int decodeSLTP() throws IOException
{
template.setIndex(cx);
return arithDecoder.decode(cx);
}
- /**
- * Call this to pass the page bitmap in case there is no reference bitmap.
- *
- * @param pageBitmap
- */
- public void setPageBitmap(Bitmap pageBitmap)
- {
- this.pageBitmap = pageBitmap;
- }
-
- private Bitmap getGrReference()
- throws IntegerMaxValueException, InvalidHeaderValueException,
IOException
- {
- final SegmentHeader[] segments = segmentHeader.getRtSegments();
- if (segments == null)
- {
- if (CombinationOperator.REPLACE !=
regionInfo.getCombinationOperator())
- {
- // 7.4.7.5 1) "If this segment does not refer to another
region segment
- // then its external combination operator must be
REPLACE"
- throw new InvalidHeaderValueException("REPLACE combination
operator expected");
- }
- // See page 79:
- // "The region segment is an immediate refinement region segment
that refers to no other segments.
- // In this case, the region segment is acting as a refinement of
part of the page buffer."
- // 7.4.7.4 Reference bitmap selection:
- // If this segment does not refer to another region segment, set
GRREFERENCE to be a bitmap containing the current
- // contents of the page buffer (see clause 8), restricted to the
area of the page buffer
- // specified by this segment’s region segment information field.
- Rectangle roi = new Rectangle(regionInfo.getXLocation(),
- regionInfo.getYLocation(),
- regionInfo.getBitmapWidth(),
- regionInfo.getBitmapHeight());
- return Bitmaps.extract(roi, pageBitmap);
- }
- final Region region = (Region) segments[0].getSegmentData();
-
- return region.getRegionBitmap();
- }
-
private void decodeOptimized(final int lineNumber, final int width, final
int rowStride,
final int refRowStride, final int paddedWidth, final int
deltaRefStride,
final int lineOffset) throws IOException
{
-
- // Offset of the reference bitmap with respect to the bitmap being
decoded
- // For example: if referenceDY = -1, y is 1 HIGHER that currY
+ // Offset of the reference bitmap with respect to the bitmap being
decoded.
+ // For example: if referenceDY = -1, y is 1 HIGHER than currY.
final int currentLine = lineNumber - referenceDY;
final int referenceByteIndex =
referenceBitmap.getByteIndex(Math.max(0, -referenceDX),
currentLine);
-
final int byteIndex = regionBitmap.getByteIndex(Math.max(0,
referenceDX), lineNumber);
switch (templateID)
@@ -379,7 +277,6 @@ public class GenericRefinementRegion implements Region
lineOffset, byteIndex, currentLine, referenceByteIndex,
T1);
break;
}
-
}
private void decodeTemplate(final int lineNumber, final int width, final
int rowStride,
@@ -560,7 +457,6 @@ public class GenericRefinementRegion implements Region
{
w4 <<= 1;
}
-
}
}
@@ -603,13 +499,10 @@ public class GenericRefinementRegion implements Region
final int rowStride, final int refRowStride, final int paddedWidth,
final int deltaRefStride) throws IOException
{
-
- // Offset of the reference bitmap with respect to the bitmap being
- // decoded
- // For example: if grReferenceDY = -1, y is 1 HIGHER that currY
+ // Offset of the reference bitmap with respect to the bitmap being
decoded.
+ // For example: if grReferenceDY = -1, y is 1 HIGHER than currY.
final int currentLine = lineNumber - referenceDY;
final int refByteIndex = referenceBitmap.getByteIndex(0, currentLine);
-
final int byteIndex = regionBitmap.getByteIndex(0, lineNumber);
switch (templateID)
@@ -739,7 +632,6 @@ public class GenericRefinementRegion implements Region
if (!isPixelTypicalPredicted)
{
// iii) - is like 3 c) but for one pixel only
-
if (override)
{
overriddenContext = overrideAtTemplate0(context, x +
minorX, lineNumber,
@@ -922,7 +814,7 @@ public class GenericRefinementRegion implements Region
// The AT pixel RA2 can be located anywhere in the range (–128,
–128) to (127, 127)
// in the reference bitmap. Make sure that we do use the reference
bitmap.
context |= getPixel(referenceBitmap, x + grAtX[1] + referenceDX,
- y + grAtY[1] + referenceDY) << 12;
+ y + grAtY[1] + referenceDY) << 12;
}
return context;
}
@@ -937,55 +829,6 @@ public class GenericRefinementRegion implements Region
{
return 0;
}
-
return b.getPixel(x, y);
}
-
- @Override
- public void init(final SegmentHeader header, final SubInputStream sis)
throws IOException
- {
- this.segmentHeader = header;
- this.subInputStream = sis;
- this.regionInfo = new RegionSegmentInformation(subInputStream);
- parseHeader();
- }
-
- protected void setParameters(final CX cx, final ArithmeticDecoder
arithmeticDecoder,
- final short grTemplate, final int regionWidth, final int
regionHeight,
- final Bitmap grReference, final int grReferenceDX, final int
grReferenceDY,
- final boolean isTPGRon, final short[] grAtX, final short[] grAtY)
- {
-
- if (null != cx)
- {
- this.cx = cx;
- }
-
- if (null != arithmeticDecoder)
- {
- this.arithDecoder = arithmeticDecoder;
- }
-
- this.templateID = grTemplate;
-
- this.regionInfo.setBitmapWidth(regionWidth);
- this.regionInfo.setBitmapHeight(regionHeight);
-
- this.referenceBitmap = grReference;
- this.referenceDX = grReferenceDX;
- this.referenceDY = grReferenceDY;
-
- this.isTPGROn = isTPGRon;
-
- this.grAtX = grAtX;
- this.grAtY = grAtY;
-
- this.regionBitmap = null;
- }
-
- @Override
- public RegionSegmentInformation getRegionInfo()
- {
- return regionInfo;
- }
}
diff --git
a/src/main/java/org/apache/pdfbox/jbig2/segments/GenericRefinementRegion.java
b/src/main/java/org/apache/pdfbox/jbig2/segments/GenericRefinementRegion.java
index 32650c5..12aeac9 100644
---
a/src/main/java/org/apache/pdfbox/jbig2/segments/GenericRefinementRegion.java
+++
b/src/main/java/org/apache/pdfbox/jbig2/segments/GenericRefinementRegion.java
@@ -23,6 +23,7 @@ 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.GenericRefinementRegionDecodingProcedure;
import org.apache.pdfbox.jbig2.decoder.arithmetic.ArithmeticDecoder;
import org.apache.pdfbox.jbig2.decoder.arithmetic.CX;
import org.apache.pdfbox.jbig2.err.IntegerMaxValueException;
@@ -91,45 +92,6 @@ public class GenericRefinementRegion implements Region
protected abstract void setIndex(CX cx);
}
- private static class Template0 extends Template
- {
-
- @Override
- protected short form(short c1, short c2, short c3, short c4, short c5)
- {
- return (short) ((c1 << 10) | (c2 << 7) | (c3 << 4) | (c4 << 1) |
c5);
- }
-
- @Override
- protected void setIndex(CX cx)
- {
- // Figure 14, page 22
- cx.setIndex(0x100);
- }
-
- }
-
- private static class Template1 extends Template
- {
-
- @Override
- protected short form(short c1, short c2, short c3, short c4, short c5)
- {
- return (short) (((c1 & 0x02) << 8) | (c2 << 6) | ((c3 & 0x03) <<
4) | (c4 << 1) | c5);
- }
-
- @Override
- protected void setIndex(CX cx)
- {
- // Figure 15, page 22
- cx.setIndex(0x080);
- }
-
- }
-
- private static final Template T0 = new Template0();
- private static final Template T1 = new Template1();
-
private SubInputStream subInputStream;
private SegmentHeader segmentHeader;
@@ -141,14 +103,10 @@ public class GenericRefinementRegion implements Region
private boolean isTPGROn;
private short templateID;
- private Template template;
/** Generic refinement region segment AT flags, 7.4.7.3 */
private short grAtX[];
private short grAtY[];
- /** Decoded data as pixel values (use row stride/width to wrap line) */
- private Bitmap regionBitmap;
-
/** Variables for decoding */
private Bitmap referenceBitmap;
private int referenceDX;
@@ -157,12 +115,6 @@ public class GenericRefinementRegion implements Region
private ArithmeticDecoder arithDecoder;
private CX cx;
- /**
- * If true, AT pixels are not on their nominal location and have to be
overridden.
- */
- private boolean override;
- private boolean[] grAtOverride;
-
private Bitmap pageBitmap;
public GenericRefinementRegion()
@@ -211,11 +163,9 @@ public class GenericRefinementRegion implements Region
switch (templateID)
{
case 0:
- template = T0;
readAtPixels();
break;
case 1:
- template = T1;
break;
}
}
@@ -245,74 +195,27 @@ public class GenericRefinementRegion implements Region
*/
@Override
public Bitmap getRegionBitmap()
- throws IOException, IntegerMaxValueException,
InvalidHeaderValueException
- {
- if (null == regionBitmap)
- {
- /* 6.3.5.6 - 1) */
- int isLineTypicalPredicted = 0; // LTP
-
- if (referenceBitmap == null)
- {
- // Get the reference bitmap, which is the base of refinement
process
- referenceBitmap = getGrReference();
- }
-
- if (arithDecoder == null)
- {
- arithDecoder = new ArithmeticDecoder(subInputStream);
- }
-
- if (cx == null)
- {
- cx = new CX(8192, 1);
- }
-
- /* 6.3.5.6 - 2) */
- regionBitmap = new Bitmap(regionInfo.getBitmapWidth(),
regionInfo.getBitmapHeight());
+ throws IOException, IntegerMaxValueException,
InvalidHeaderValueException {
- if (templateID == 0)
- {
- // AT pixel may only occur in template 0
- updateOverride();
- }
+ if (referenceBitmap == null) {
+ // Get the reference bitmap, which is the base of refinement
process
+ referenceBitmap = getGrReference();
+ }
- final int paddedWidth = (regionBitmap.getWidth() + 7) & -8;
- final int deltaRefStride = isTPGROn ? -referenceDY *
referenceBitmap.getRowStride() : 0;
- final int yOffset = deltaRefStride + 1;
+ if (arithDecoder == null) {
+ arithDecoder = new ArithmeticDecoder(subInputStream);
+ }
- /* 6.3.5.6 - 3 */
- for (int y = 0; y < regionBitmap.getHeight(); y++)
- {
- /* 6.3.5.6 - 3 b) */
- if (isTPGROn)
- {
- isLineTypicalPredicted ^= decodeSLTP();
- }
-
- if (isLineTypicalPredicted == 0)
- {
- /* 6.3.5.6 - 3 c) */
- decodeOptimized(y, regionBitmap.getWidth(),
regionBitmap.getRowStride(),
- referenceBitmap.getRowStride(), paddedWidth,
deltaRefStride, yOffset);
- }
- else
- {
- /* 6.3.5.6 - 3 d) */
- decodeTypicalPredictedLine(y, regionBitmap.getWidth(),
- regionBitmap.getRowStride(),
referenceBitmap.getRowStride(),
- paddedWidth, deltaRefStride);
- }
- }
+ if (cx == null) {
+ cx = new CX(8192, 1);
}
- /* 6.3.5.6 - 4) */
- return regionBitmap;
- }
- private int decodeSLTP() throws IOException
- {
- template.setIndex(cx);
- return arithDecoder.decode(cx);
+ return GenericRefinementRegionDecodingProcedure.decode(
+ arithDecoder, cx,
+ regionInfo.getBitmapWidth(), regionInfo.getBitmapHeight(),
+ templateID, isTPGROn, referenceBitmap, referenceDX, referenceDY,
+ grAtX, grAtY
+ );
}
/**
@@ -355,592 +258,6 @@ public class GenericRefinementRegion implements Region
return region.getRegionBitmap();
}
- private void decodeOptimized(final int lineNumber, final int width, final
int rowStride,
- final int refRowStride, final int paddedWidth, final int
deltaRefStride,
- final int lineOffset) throws IOException
- {
-
- // Offset of the reference bitmap with respect to the bitmap being
decoded
- // For example: if referenceDY = -1, y is 1 HIGHER that currY
- final int currentLine = lineNumber - referenceDY;
- final int referenceByteIndex =
referenceBitmap.getByteIndex(Math.max(0, -referenceDX),
- currentLine);
-
- final int byteIndex = regionBitmap.getByteIndex(Math.max(0,
referenceDX), lineNumber);
-
- switch (templateID)
- {
- case 0:
- decodeTemplate(lineNumber, width, rowStride, refRowStride,
paddedWidth, deltaRefStride,
- lineOffset, byteIndex, currentLine, referenceByteIndex,
T0);
- break;
- case 1:
- decodeTemplate(lineNumber, width, rowStride, refRowStride,
paddedWidth, deltaRefStride,
- lineOffset, byteIndex, currentLine, referenceByteIndex,
T1);
- break;
- }
-
- }
-
- private void decodeTemplate(final int lineNumber, final int width, final
int rowStride,
- final int refRowStride, final int paddedWidth, final int
deltaRefStride,
- final int lineOffset, int byteIndex, final int currentLine, int
refByteIndex,
- Template templateFormation) throws IOException
- {
- short c1, c2, c3, c4, c5;
-
- int w1, w2, w3, w4;
- w1 = w2 = w3 = w4 = 0;
-
- if (currentLine >= 1 && (currentLine - 1) <
referenceBitmap.getHeight())
- w1 = referenceBitmap.getByteAsInteger(refByteIndex - refRowStride);
- if (currentLine >= 0 && currentLine < referenceBitmap.getHeight())
- w2 = referenceBitmap.getByteAsInteger(refByteIndex);
- if (currentLine >= -1 && currentLine + 1 < referenceBitmap.getHeight())
- w3 = referenceBitmap.getByteAsInteger(refByteIndex + refRowStride);
- refByteIndex++;
-
- if (lineNumber >= 1)
- {
- w4 = regionBitmap.getByteAsInteger(byteIndex - rowStride);
- }
- byteIndex++;
-
- final int modReferenceDX = referenceDX % 8;
- final int shiftOffset = 6 + modReferenceDX;
- final int modRefByteIdx = refByteIndex % refRowStride;
-
- if (shiftOffset >= 0)
- {
- c1 = (short) ((shiftOffset >= 8 ? 0 : w1 >>> shiftOffset) & 0x07);
- c2 = (short) ((shiftOffset >= 8 ? 0 : w2 >>> shiftOffset) & 0x07);
- c3 = (short) ((shiftOffset >= 8 ? 0 : w3 >>> shiftOffset) & 0x07);
- if (shiftOffset == 6 && modRefByteIdx > 1)
- {
- if (currentLine >= 1 && (currentLine - 1) <
referenceBitmap.getHeight())
- {
- c1 |= referenceBitmap.getByteAsInteger(refByteIndex -
refRowStride - 2) << 2
- & 0x04;
- }
- if (currentLine >= 0 && currentLine <
referenceBitmap.getHeight())
- {
- c2 |= referenceBitmap.getByteAsInteger(refByteIndex - 2)
<< 2 & 0x04;
- }
- if (currentLine >= -1 && currentLine + 1 <
referenceBitmap.getHeight())
- {
- c3 |= referenceBitmap.getByteAsInteger(refByteIndex +
refRowStride - 2) << 2
- & 0x04;
- }
- }
- if (shiftOffset == 0)
- {
- w1 = w2 = w3 = 0;
- if (modRefByteIdx < refRowStride - 1)
- {
- if (currentLine >= 1 && (currentLine - 1) <
referenceBitmap.getHeight())
- w1 = referenceBitmap.getByteAsInteger(refByteIndex -
refRowStride);
- if (currentLine >= 0 && currentLine <
referenceBitmap.getHeight())
- w2 = referenceBitmap.getByteAsInteger(refByteIndex);
- if (currentLine >= -1 && currentLine + 1 <
referenceBitmap.getHeight())
- w3 = referenceBitmap.getByteAsInteger(refByteIndex +
refRowStride);
- }
- refByteIndex++;
- }
- }
- else
- {
- c1 = (short) ((w1 << 1) & 0x07);
- c2 = (short) ((w2 << 1) & 0x07);
- c3 = (short) ((w3 << 1) & 0x07);
- w1 = w2 = w3 = 0;
- if (modRefByteIdx < refRowStride - 1)
- {
- if (currentLine >= 1 && (currentLine - 1) <
referenceBitmap.getHeight())
- w1 = referenceBitmap.getByteAsInteger(refByteIndex -
refRowStride);
- if (currentLine >= 0 && currentLine <
referenceBitmap.getHeight())
- w2 = referenceBitmap.getByteAsInteger(refByteIndex);
- if (currentLine >= -1 && currentLine + 1 <
referenceBitmap.getHeight())
- w3 = referenceBitmap.getByteAsInteger(refByteIndex +
refRowStride);
- refByteIndex++;
- }
- c1 |= (short) ((w1 >>> 7) & 0x07);
- c2 |= (short) ((w2 >>> 7) & 0x07);
- c3 |= (short) ((w3 >>> 7) & 0x07);
- }
-
- c4 = (short) (w4 >>> 6);
- c5 = 0;
-
- final int modBitsToTrim = (2 - modReferenceDX) % 8;
- w1 <<= modBitsToTrim;
- w2 <<= modBitsToTrim;
- w3 <<= modBitsToTrim;
-
- w4 <<= 2;
-
- for (int x = 0; x < width; x++)
- {
- final int minorX = x & 0x07;
-
- final short tval = templateFormation.form(c1, c2, c3, c4, c5);
-
- if (override)
- {
- cx.setIndex(overrideAtTemplate0(tval, x, lineNumber,
- regionBitmap.getByte(regionBitmap.getByteIndex(x,
lineNumber)), minorX));
- }
- else
- {
- cx.setIndex(tval);
- }
- final int bit = arithDecoder.decode(cx);
- regionBitmap.setPixel(x, lineNumber, (byte) bit);
-
- c1 = (short) (((c1 << 1) | 0x01 & (w1 >>> 7)) & 0x07);
- c2 = (short) (((c2 << 1) | 0x01 & (w2 >>> 7)) & 0x07);
- c3 = (short) (((c3 << 1) | 0x01 & (w3 >>> 7)) & 0x07);
- c4 = (short) (((c4 << 1) | 0x01 & (w4 >>> 7)) & 0x07);
- c5 = (short) bit;
-
- if ((x - referenceDX) % 8 == 5)
- {
- if (((x - referenceDX) / 8) + 1 >=
referenceBitmap.getRowStride())
- {
- w1 = w2 = w3 = 0;
- }
- else
- {
- if (currentLine >= 1 && (currentLine - 1 <
referenceBitmap.getHeight()))
- {
- w1 = referenceBitmap.getByteAsInteger(refByteIndex -
refRowStride);
- }
- else
- {
- w1 = 0;
- }
- if (currentLine >= 0 && currentLine <
referenceBitmap.getHeight())
- {
- w2 = referenceBitmap.getByteAsInteger(refByteIndex);
- }
- else
- {
- w2 = 0;
- }
- if (currentLine >= -1 && (currentLine + 1) <
referenceBitmap.getHeight())
- {
- w3 = referenceBitmap.getByteAsInteger(refByteIndex +
refRowStride);
- }
- else
- {
- w3 = 0;
- }
- }
- refByteIndex++;
- }
- else
- {
- w1 <<= 1;
- w2 <<= 1;
- w3 <<= 1;
- }
-
- if (minorX == 5 && lineNumber >= 1)
- {
- if ((x >> 3) + 1 >= regionBitmap.getRowStride())
- {
- w4 = 0;
- }
- else
- {
- w4 = regionBitmap.getByteAsInteger(byteIndex - rowStride);
- }
- byteIndex++;
- }
- else
- {
- w4 <<= 1;
- }
-
- }
- }
-
- private void updateOverride()
- {
- if (grAtX == null || grAtY == null)
- {
- return;
- }
-
- if (grAtX.length != grAtY.length)
- {
- return;
- }
-
- grAtOverride = new boolean[grAtX.length];
-
- switch (templateID)
- {
- case 0:
- if (!(grAtX[0] == -1 && grAtY[0] == -1))
- {
- grAtOverride[0] = true;
- override = true;
- }
-
- if (!(grAtX[1] == -1 && grAtY[1] == -1))
- {
- grAtOverride[1] = true;
- override = true;
- }
- break;
- case 1:
- override = false;
- break;
- }
- }
-
- private void decodeTypicalPredictedLine(final int lineNumber, final int
width,
- final int rowStride, final int refRowStride, final int paddedWidth,
- final int deltaRefStride) throws IOException
- {
-
- // Offset of the reference bitmap with respect to the bitmap being
- // decoded
- // For example: if grReferenceDY = -1, y is 1 HIGHER that currY
- final int currentLine = lineNumber - referenceDY;
- final int refByteIndex = referenceBitmap.getByteIndex(0, currentLine);
-
- final int byteIndex = regionBitmap.getByteIndex(0, lineNumber);
-
- switch (templateID)
- {
- case 0:
- decodeTypicalPredictedLineTemplate0(lineNumber, width, rowStride,
refRowStride,
- paddedWidth, deltaRefStride, byteIndex, currentLine,
refByteIndex);
- break;
- case 1:
- decodeTypicalPredictedLineTemplate1(lineNumber, width, rowStride,
refRowStride,
- paddedWidth, deltaRefStride, byteIndex, currentLine,
refByteIndex);
- break;
- }
- }
-
- private void decodeTypicalPredictedLineTemplate0(final int lineNumber,
final int width,
- final int rowStride, final int refRowStride, final int paddedWidth,
- final int deltaRefStride, int byteIndex, final int currentLine,
int refByteIndex)
- throws IOException
- {
- int context;
- int overriddenContext;
-
- int previousLine;
- int previousReferenceLine;
- int currentReferenceLine;
- int nextReferenceLine;
-
- if (lineNumber > 0)
- {
- previousLine = regionBitmap.getByteAsInteger(byteIndex -
rowStride);
- }
- else
- {
- previousLine = 0;
- }
-
- if (currentLine > 0 && currentLine <= referenceBitmap.getHeight())
- {
- previousReferenceLine = referenceBitmap
- .getByteAsInteger(refByteIndex - refRowStride +
deltaRefStride) << 4;
- }
- else
- {
- previousReferenceLine = 0;
- }
-
- if (currentLine >= 0 && currentLine < referenceBitmap.getHeight())
- {
- currentReferenceLine = referenceBitmap
- .getByteAsInteger(refByteIndex + deltaRefStride) << 1;
- }
- else
- {
- currentReferenceLine = 0;
- }
-
- if (currentLine > -2 && currentLine < (referenceBitmap.getHeight() -
1))
- {
- nextReferenceLine = referenceBitmap
- .getByteAsInteger(refByteIndex + refRowStride +
deltaRefStride);
- }
- else
- {
- nextReferenceLine = 0;
- }
-
- context = ((previousLine >> 5) & 0x6) | ((nextReferenceLine >> 2) &
0x30)
- | (currentReferenceLine & 0x180) | (previousReferenceLine &
0xc00);
-
- int nextByte;
- for (int x = 0; x < paddedWidth; x = nextByte)
- {
- byte result = 0;
- nextByte = x + 8;
- final int minorWidth = width - x > 8 ? 8 : width - x;
- final boolean readNextByte = nextByte < width;
- final boolean refReadNextByte = nextByte <
referenceBitmap.getWidth();
-
- final int yOffset = deltaRefStride + 1;
-
- if (lineNumber > 0)
- {
- previousLine = (previousLine << 8) | (readNextByte
- ? regionBitmap.getByteAsInteger(byteIndex - rowStride
+ 1) : 0);
- }
-
- if (currentLine > 0 && currentLine <= referenceBitmap.getHeight())
- {
- previousReferenceLine = (previousReferenceLine << 8)
- | (refReadNextByte ? referenceBitmap
- .getByteAsInteger(refByteIndex - refRowStride
+ yOffset) << 4 : 0);
- }
-
- if (currentLine >= 0 && currentLine < referenceBitmap.getHeight())
- {
- currentReferenceLine = (currentReferenceLine << 8) |
(refReadNextByte
- ? referenceBitmap.getByteAsInteger(refByteIndex +
yOffset) << 1 : 0);
- }
-
- if (currentLine > -2 && currentLine < (referenceBitmap.getHeight()
- 1))
- {
- nextReferenceLine = (nextReferenceLine << 8) | (refReadNextByte
- ? referenceBitmap.getByteAsInteger(refByteIndex +
refRowStride + yOffset)
- : 0);
- }
-
- for (int minorX = 0; minorX < minorWidth; minorX++)
- {
- boolean isPixelTypicalPredicted = false;
- int bit = 0;
-
- // i)
- final int bitmapValue = (context >> 4) & 0x1FF;
-
- if (bitmapValue == 0x1ff)
- {
- isPixelTypicalPredicted = true;
- bit = 1;
- }
- else if (bitmapValue == 0x00)
- {
- isPixelTypicalPredicted = true;
- bit = 0;
- }
-
- if (!isPixelTypicalPredicted)
- {
- // iii) - is like 3 c) but for one pixel only
-
- if (override)
- {
- overriddenContext = overrideAtTemplate0(context, x +
minorX, lineNumber,
- result, minorX);
- cx.setIndex(overriddenContext);
- }
- else
- {
- cx.setIndex(context);
- }
- bit = arithDecoder.decode(cx);
- }
-
- final int toShift = 7 - minorX;
- result |= bit << toShift;
-
- context = ((context & 0xdb6) << 1) | bit | ((previousLine >>
toShift + 5) & 0x002)
- | ((nextReferenceLine >> toShift + 2) & 0x010)
- | ((currentReferenceLine >> toShift) & 0x080)
- | ((previousReferenceLine >> toShift) & 0x400);
- }
- regionBitmap.setByte(byteIndex++, result);
- refByteIndex++;
- }
- }
-
- private void decodeTypicalPredictedLineTemplate1(final int lineNumber,
final int width,
- final int rowStride, final int refRowStride, final int paddedWidth,
- final int deltaRefStride, int byteIndex, final int currentLine,
int refByteIndex)
- throws IOException
- {
- int context;
- int grReferenceValue;
-
- int previousLine;
- int previousReferenceLine;
- int currentReferenceLine;
- int nextReferenceLine;
-
- if (lineNumber > 0)
- {
- previousLine = regionBitmap.getByteAsInteger(byteIndex -
rowStride);
- }
- else
- {
- previousLine = 0;
- }
-
- if (currentLine > 0 && currentLine <= referenceBitmap.getHeight())
- {
- previousReferenceLine = referenceBitmap
- .getByteAsInteger(refByteIndex - refRowStride +
deltaRefStride) << 2;
- }
- else
- {
- previousReferenceLine = 0;
- }
-
- if (currentLine >= 0 && currentLine < referenceBitmap.getHeight())
- {
- currentReferenceLine =
referenceBitmap.getByteAsInteger(refByteIndex + deltaRefStride);
- }
- else
- {
- currentReferenceLine = 0;
- }
-
- if (currentLine > -2 && currentLine < (referenceBitmap.getHeight() -
1))
- {
- nextReferenceLine = referenceBitmap
- .getByteAsInteger(refByteIndex + refRowStride +
deltaRefStride);
- }
- else
- {
- nextReferenceLine = 0;
- }
-
- context = ((previousLine >> 5) & 0x6) | ((nextReferenceLine >> 2) &
0x30)
- | (currentReferenceLine & 0xc0) | (previousReferenceLine &
0x200);
-
- grReferenceValue = ((nextReferenceLine >> 2) & 0x70) |
(currentReferenceLine & 0xc0)
- | (previousReferenceLine & 0x700);
-
- int nextByte;
- for (int x = 0; x < paddedWidth; x = nextByte)
- {
- byte result = 0;
- nextByte = x + 8;
- final int minorWidth = width - x > 8 ? 8 : width - x;
- final boolean readNextByte = nextByte < width;
- final boolean refReadNextByte = nextByte <
referenceBitmap.getWidth();
-
- final int yOffset = deltaRefStride + 1;
-
- if (lineNumber > 0)
- {
- previousLine = (previousLine << 8) | (readNextByte
- ? regionBitmap.getByteAsInteger(byteIndex - rowStride
+ 1) : 0);
- }
-
- if (currentLine > 0 && currentLine <= referenceBitmap.getHeight())
- {
- previousReferenceLine = (previousReferenceLine << 8)
- | (refReadNextByte ? referenceBitmap
- .getByteAsInteger(refByteIndex - refRowStride
+ yOffset) << 2 : 0);
- }
-
- if (currentLine >= 0 && currentLine < referenceBitmap.getHeight())
- {
- currentReferenceLine = (currentReferenceLine << 8) |
(refReadNextByte
- ? referenceBitmap.getByteAsInteger(refByteIndex +
yOffset) : 0);
- }
-
- if (currentLine > -2 && currentLine < (referenceBitmap.getHeight()
- 1))
- {
- nextReferenceLine = (nextReferenceLine << 8) | (refReadNextByte
- ? referenceBitmap.getByteAsInteger(refByteIndex +
refRowStride + yOffset)
- : 0);
- }
-
- for (int minorX = 0; minorX < minorWidth; minorX++)
- {
- int bit = 0;
-
- // i)
- final int bitmapValue = (grReferenceValue >> 4) & 0x1ff;
-
- if (bitmapValue == 0x1ff)
- {
- bit = 1;
- }
- else if (bitmapValue == 0x00)
- {
- bit = 0;
- }
- else
- {
- cx.setIndex(context);
- bit = arithDecoder.decode(cx);
- }
-
- final int toShift = 7 - minorX;
- result |= bit << toShift;
-
- context = ((context & 0x0d6) << 1) | bit | ((previousLine >>
toShift + 5) & 0x002)
- | ((nextReferenceLine >> toShift + 2) & 0x010)
- | ((currentReferenceLine >> toShift) & 0x040)
- | ((previousReferenceLine >> toShift) & 0x200);
-
- grReferenceValue = ((grReferenceValue & 0x0db) << 1)
- | ((nextReferenceLine >> toShift + 2) & 0x010)
- | ((currentReferenceLine >> toShift) & 0x080)
- | ((previousReferenceLine >> toShift) & 0x400);
- }
- regionBitmap.setByte(byteIndex++, result);
- refByteIndex++;
- }
- }
-
- private int overrideAtTemplate0(int context, final int x, final int y,
final int result,
- final int minorX) throws IOException
- {
- if (grAtOverride[0])
- {
- context &= 0xfff7;
- if (grAtY[0] == 0 && grAtX[0] >= -minorX)
- {
- context |= (result >> (7 - (minorX + grAtX[0])) & 0x1) << 3;
- }
- else
- {
- context |= getPixel(regionBitmap, x + grAtX[0], y + grAtY[0])
<< 3;
- }
- }
-
- if (grAtOverride[1])
- {
- context &= 0xefff;
- // 6.3.5.3
- // The AT pixel RA2 can be located anywhere in the range (–128,
–128) to (127, 127)
- // in the reference bitmap. Make sure that we do use the reference
bitmap.
- context |= getPixel(referenceBitmap, x + grAtX[1] + referenceDX,
- y + grAtY[1] + referenceDY) << 12;
- }
- return context;
- }
-
- private byte getPixel(final Bitmap b, final int x, final int y) throws
IOException
- {
- if (x < 0 || x >= b.getWidth())
- {
- return 0;
- }
- if (y < 0 || y >= b.getHeight())
- {
- return 0;
- }
-
- return b.getPixel(x, y);
- }
-
@Override
public void init(final SegmentHeader header, final SubInputStream sis)
throws IOException
{
@@ -979,8 +296,6 @@ public class GenericRefinementRegion implements Region
this.grAtX = grAtX;
this.grAtY = grAtY;
-
- this.regionBitmap = null;
}
@Override