X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;ds=sidebyside;f=pdf%2Fxpdf%2FJBIG2Stream.cc;h=c1bf4f78d0433bd9133e35d6a317de6824be1f0f;hb=e48cf2858b65aa026771a48d2b315cbc663d8234;hp=716fee1cabff4aa80fc0697c523320762793fa13;hpb=6112dfe4b45b0305c7a6f61bd8a847f69f892cbb;p=evince.git diff --git a/pdf/xpdf/JBIG2Stream.cc b/pdf/xpdf/JBIG2Stream.cc index 716fee1c..c1bf4f78 100644 --- a/pdf/xpdf/JBIG2Stream.cc +++ b/pdf/xpdf/JBIG2Stream.cc @@ -2,7 +2,7 @@ // // JBIG2Stream.cc // -// Copyright 2002 Glyph & Cog, LLC +// Copyright 2002-2003 Glyph & Cog, LLC // //======================================================================== @@ -15,6 +15,7 @@ #include #include "GList.h" #include "Error.h" +#include "JArithmeticDecoder.h" #include "JBIG2Stream.h" //~ share these tables @@ -25,327 +26,6 @@ static int contextSize[4] = { 16, 13, 10, 10 }; static int refContextSize[2] = { 13, 10 }; -//------------------------------------------------------------------------ -// JBIG2ArithmeticDecoderStats -//------------------------------------------------------------------------ - -class JBIG2ArithmeticDecoderStats { -public: - - JBIG2ArithmeticDecoderStats(int contextSizeA); - ~JBIG2ArithmeticDecoderStats(); - JBIG2ArithmeticDecoderStats *copy(); - void reset(); - int getContextSize() { return contextSize; } - void copyFrom(JBIG2ArithmeticDecoderStats *stats); - -private: - - Guchar *cxTab; // cxTab[cx] = (i[cx] << 1) + mps[cx] - int contextSize; - - friend class JBIG2ArithmeticDecoder; -}; - -JBIG2ArithmeticDecoderStats::JBIG2ArithmeticDecoderStats(int contextSizeA) { - contextSize = contextSizeA; - cxTab = (Guchar *)gmalloc((1 << contextSize) * sizeof(Guchar)); - reset(); -} - -JBIG2ArithmeticDecoderStats::~JBIG2ArithmeticDecoderStats() { - gfree(cxTab); -} - -JBIG2ArithmeticDecoderStats *JBIG2ArithmeticDecoderStats::copy() { - JBIG2ArithmeticDecoderStats *stats; - - stats = new JBIG2ArithmeticDecoderStats(contextSize); - memcpy(stats->cxTab, cxTab, 1 << contextSize); - return stats; -} - -void JBIG2ArithmeticDecoderStats::reset() { - memset(cxTab, 0, 1 << contextSize); -} - -void JBIG2ArithmeticDecoderStats::copyFrom( - JBIG2ArithmeticDecoderStats *stats) { - memcpy(cxTab, stats->cxTab, 1 << contextSize); -} - -//------------------------------------------------------------------------ -// JBIG2ArithmeticDecoder -//------------------------------------------------------------------------ - -class JBIG2ArithmeticDecoder { -public: - - JBIG2ArithmeticDecoder(); - ~JBIG2ArithmeticDecoder(); - void setStream(Stream *strA) { str = strA; } - void start(); - int decodeBit(Guint context, JBIG2ArithmeticDecoderStats *stats); - int decodeByte(Guint context, JBIG2ArithmeticDecoderStats *stats); - - // Returns false for OOB, otherwise sets * and returns true. - GBool decodeInt(int *x, JBIG2ArithmeticDecoderStats *stats); - - Guint decodeIAID(Guint codeLen, - JBIG2ArithmeticDecoderStats *stats); - -private: - - int decodeIntBit(JBIG2ArithmeticDecoderStats *stats); - void byteIn(); - - static Guint qeTab[47]; - static int nmpsTab[47]; - static int nlpsTab[47]; - static int switchTab[47]; - - Guint buf0, buf1; - Guint c, a; - int ct; - - Guint prev; // for the integer decoder - - Stream *str; -}; - -Guint JBIG2ArithmeticDecoder::qeTab[47] = { - 0x56010000, 0x34010000, 0x18010000, 0x0AC10000, - 0x05210000, 0x02210000, 0x56010000, 0x54010000, - 0x48010000, 0x38010000, 0x30010000, 0x24010000, - 0x1C010000, 0x16010000, 0x56010000, 0x54010000, - 0x51010000, 0x48010000, 0x38010000, 0x34010000, - 0x30010000, 0x28010000, 0x24010000, 0x22010000, - 0x1C010000, 0x18010000, 0x16010000, 0x14010000, - 0x12010000, 0x11010000, 0x0AC10000, 0x09C10000, - 0x08A10000, 0x05210000, 0x04410000, 0x02A10000, - 0x02210000, 0x01410000, 0x01110000, 0x00850000, - 0x00490000, 0x00250000, 0x00150000, 0x00090000, - 0x00050000, 0x00010000, 0x56010000 -}; - -int JBIG2ArithmeticDecoder::nmpsTab[47] = { - 1, 2, 3, 4, 5, 38, 7, 8, 9, 10, 11, 12, 13, 29, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 45, 46 -}; - -int JBIG2ArithmeticDecoder::nlpsTab[47] = { - 1, 6, 9, 12, 29, 33, 6, 14, 14, 14, 17, 18, 20, 21, 14, 14, - 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 46 -}; - -int JBIG2ArithmeticDecoder::switchTab[47] = { - 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -JBIG2ArithmeticDecoder::JBIG2ArithmeticDecoder() { - str = NULL; -} - -JBIG2ArithmeticDecoder::~JBIG2ArithmeticDecoder() { -} - -void JBIG2ArithmeticDecoder::start() { - buf0 = (Guint)str->getChar() & 0xff; - buf1 = (Guint)str->getChar() & 0xff; - - // INITDEC - c = (buf0 ^ 0xff) << 16; - byteIn(); - c <<= 7; - ct -= 7; - a = 0x80000000; -} - -int JBIG2ArithmeticDecoder::decodeBit(Guint context, - JBIG2ArithmeticDecoderStats *stats) { - int bit; - Guint qe; - int iCX, mpsCX; - - iCX = stats->cxTab[context] >> 1; - mpsCX = stats->cxTab[context] & 1; - qe = qeTab[iCX]; - a -= qe; - if (c < a) { - if (a & 0x80000000) { - bit = mpsCX; - } else { - // MPS_EXCHANGE - if (a < qe) { - bit = 1 - mpsCX; - if (switchTab[iCX]) { - stats->cxTab[context] = (nlpsTab[iCX] << 1) | (1 - mpsCX); - } else { - stats->cxTab[context] = (nlpsTab[iCX] << 1) | mpsCX; - } - } else { - bit = mpsCX; - stats->cxTab[context] = (nmpsTab[iCX] << 1) | mpsCX; - } - // RENORMD - do { - if (ct == 0) { - byteIn(); - } - a <<= 1; - c <<= 1; - --ct; - } while (!(a & 0x80000000)); - } - } else { - c -= a; - // LPS_EXCHANGE - if (a < qe) { - bit = mpsCX; - stats->cxTab[context] = (nmpsTab[iCX] << 1) | mpsCX; - } else { - bit = 1 - mpsCX; - if (switchTab[iCX]) { - stats->cxTab[context] = (nlpsTab[iCX] << 1) | (1 - mpsCX); - } else { - stats->cxTab[context] = (nlpsTab[iCX] << 1) | mpsCX; - } - } - a = qe; - // RENORMD - do { - if (ct == 0) { - byteIn(); - } - a <<= 1; - c <<= 1; - --ct; - } while (!(a & 0x80000000)); - } - return bit; -} - -int JBIG2ArithmeticDecoder::decodeByte(Guint context, - JBIG2ArithmeticDecoderStats *stats) { - int byte; - int i; - - byte = 0; - for (i = 0; i < 8; ++i) { - byte = (byte << 1) | decodeBit(context, stats); - } - return byte; -} - -GBool JBIG2ArithmeticDecoder::decodeInt(int *x, - JBIG2ArithmeticDecoderStats *stats) { - int s; - Guint v; - int i; - - prev = 1; - s = decodeIntBit(stats); - if (decodeIntBit(stats)) { - if (decodeIntBit(stats)) { - if (decodeIntBit(stats)) { - if (decodeIntBit(stats)) { - if (decodeIntBit(stats)) { - v = 0; - for (i = 0; i < 32; ++i) { - v = (v << 1) | decodeIntBit(stats); - } - v += 4436; - } else { - v = 0; - for (i = 0; i < 12; ++i) { - v = (v << 1) | decodeIntBit(stats); - } - v += 340; - } - } else { - v = 0; - for (i = 0; i < 8; ++i) { - v = (v << 1) | decodeIntBit(stats); - } - v += 84; - } - } else { - v = 0; - for (i = 0; i < 6; ++i) { - v = (v << 1) | decodeIntBit(stats); - } - v += 20; - } - } else { - v = decodeIntBit(stats); - v = (v << 1) | decodeIntBit(stats); - v = (v << 1) | decodeIntBit(stats); - v = (v << 1) | decodeIntBit(stats); - v += 4; - } - } else { - v = decodeIntBit(stats); - v = (v << 1) | decodeIntBit(stats); - } - - if (s) { - if (v == 0) { - return gFalse; - } - *x = -(int)v; - } else { - *x = (int)v; - } - return gTrue; -} - -int JBIG2ArithmeticDecoder::decodeIntBit(JBIG2ArithmeticDecoderStats *stats) { - int bit; - - bit = decodeBit(prev, stats); - if (prev < 0x100) { - prev = (prev << 1) | bit; - } else { - prev = (((prev << 1) | bit) & 0x1ff) | 0x100; - } - return bit; -} - -Guint JBIG2ArithmeticDecoder::decodeIAID(Guint codeLen, - JBIG2ArithmeticDecoderStats *stats) { - Guint i; - int bit; - - prev = 1; - for (i = 0; i < codeLen; ++i) { - bit = decodeBit(prev, stats); - prev = (prev << 1) | bit; - } - return prev - (1 << codeLen); -} - -void JBIG2ArithmeticDecoder::byteIn() { - if (buf0 == 0xff) { - if (buf1 > 0x8f) { - ct = 8; - } else { - buf0 = buf1; - buf1 = (Guint)str->getChar() & 0xff; - c = c + 0xfe00 - (buf0 << 9); - ct = 7; - } - } else { - buf0 = buf1; - buf1 = (Guint)str->getChar() & 0xff; - c = c + 0xff00 - (buf0 << 8); - ct = 8; - } -} - //------------------------------------------------------------------------ // JBIG2HuffmanTable //------------------------------------------------------------------------ @@ -655,25 +335,22 @@ GBool JBIG2HuffmanDecoder::decodeInt(int *x, JBIG2HuffmanTable *table) { len = 0; prefix = 0; while (table[i].rangeLen != jbig2HuffmanEOT) { - //~ if buildTable removes the entries with prefixLen=0, this is unneeded - if (table[i].prefixLen > 0) { - while (len < table[i].prefixLen) { - prefix = (prefix << 1) | readBit(); - ++len; + while (len < table[i].prefixLen) { + prefix = (prefix << 1) | readBit(); + ++len; + } + if (prefix == table[i].prefix) { + if (table[i].rangeLen == jbig2HuffmanOOB) { + return gFalse; } - if (prefix == table[i].prefix) { - if (table[i].rangeLen == jbig2HuffmanOOB) { - return gFalse; - } - if (table[i].rangeLen == jbig2HuffmanLOW) { - *x = table[i].val - readBits(32); - } else if (table[i].rangeLen > 0) { - *x = table[i].val + readBits(table[i].rangeLen); - } else { - *x = table[i].val; - } - return gTrue; + if (table[i].rangeLen == jbig2HuffmanLOW) { + *x = table[i].val - readBits(32); + } else if (table[i].rangeLen > 0) { + *x = table[i].val + readBits(table[i].rangeLen); + } else { + *x = table[i].val; } + return gTrue; } ++i; } @@ -713,22 +390,41 @@ Guint JBIG2HuffmanDecoder::readBit() { return (buf >> bufLen) & 1; } -static int cmpHuffmanTabEntries(const void *p1, const void *p2) { - return ((JBIG2HuffmanTable *)p1)->prefixLen - - ((JBIG2HuffmanTable *)p2)->prefixLen; -} - -//~ should remove entries with prefixLen = 0 void JBIG2HuffmanDecoder::buildTable(JBIG2HuffmanTable *table, Guint len) { - Guint i, prefix; - - qsort(table, len, sizeof(JBIG2HuffmanTable), &cmpHuffmanTabEntries); - for (i = 0; i < len && table[i].prefixLen == 0; ++i) { - table[i].prefix = 0; + Guint i, j, k, prefix; + JBIG2HuffmanTable tab; + + // stable selection sort: + // - entries with prefixLen > 0, in ascending prefixLen order + // - entry with prefixLen = 0, rangeLen = EOT + // - all other entries with prefixLen = 0 + // (on entry, table[len] has prefixLen = 0, rangeLen = EOT) + for (i = 0; i < len; ++i) { + for (j = i; j < len && table[j].prefixLen == 0; ++j) ; + if (j == len) { + break; + } + for (k = j + 1; k < len; ++k) { + if (table[k].prefixLen > 0 && + table[k].prefixLen < table[j].prefixLen) { + j = k; + } + } + if (j != i) { + tab = table[j]; + for (k = j; k > i; --k) { + table[k] = table[k - 1]; + } + table[i] = tab; + } } + table[i] = table[len]; + + // assign prefixes + i = 0; prefix = 0; table[i++].prefix = prefix++; - for (; i < len; ++i) { + for (; table[i].rangeLen != jbig2HuffmanEOT; ++i) { prefix <<= table[i].prefixLen - table[i-1].prefixLen; table[i].prefix = prefix++; } @@ -810,7 +506,7 @@ int JBIG2MMRDecoder::getWhiteCode() { ++nBytesRead; } while (1) { - if (bufLen > 7 && ((buf >> (bufLen - 7)) & 0x7f) == 0) { + if (bufLen >= 7 && ((buf >> (bufLen - 7)) & 0x7f) == 0) { if (bufLen <= 12) { code = buf << (12 - bufLen); } else { @@ -825,7 +521,7 @@ int JBIG2MMRDecoder::getWhiteCode() { } p = &whiteTab2[code & 0x1ff]; } - if (p->bits > 0 && p->bits < (int)bufLen) { + if (p->bits > 0 && p->bits <= (int)bufLen) { bufLen -= p->bits; return p->n; } @@ -853,14 +549,14 @@ int JBIG2MMRDecoder::getBlackCode() { ++nBytesRead; } while (1) { - if (bufLen > 6 && ((buf >> (bufLen - 6)) & 0x3f) == 0) { + if (bufLen >= 6 && ((buf >> (bufLen - 6)) & 0x3f) == 0) { if (bufLen <= 13) { code = buf << (13 - bufLen); } else { code = buf >> (bufLen - 13); } p = &blackTab1[code & 0x7f]; - } else if (bufLen > 4 && ((buf >> (bufLen - 4)) & 0x0f) == 0) { + } else if (bufLen >= 4 && ((buf >> (bufLen - 4)) & 0x0f) == 0) { if (bufLen <= 12) { code = buf << (12 - bufLen); } else { @@ -875,7 +571,7 @@ int JBIG2MMRDecoder::getBlackCode() { } p = &blackTab3[code & 0x3f]; } - if (p->bits > 0 && p->bits < (int)bufLen) { + if (p->bits > 0 && p->bits <= (int)bufLen) { bufLen -= p->bits; return p->n; } @@ -938,6 +634,12 @@ private: // JBIG2Bitmap //------------------------------------------------------------------------ +struct JBIG2BitmapPtr { + Guchar *p; + int shift; + int x; +}; + class JBIG2Bitmap: public JBIG2Segment { public: @@ -958,6 +660,8 @@ public: { data[y * line + (x >> 3)] |= 1 << (7 - (x & 7)); } void clearPixel(int x, int y) { data[y * line + (x >> 3)] &= 0x7f7f >> (x & 7); } + void getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr); + int nextPixel(JBIG2BitmapPtr *ptr); void duplicateRow(int yDest, int ySrc); void combine(JBIG2Bitmap *bitmap, int x, int y, Guint combOp); Guchar *getDataPtr() { return data; } @@ -1032,6 +736,42 @@ void JBIG2Bitmap::clearToOne() { memset(data, 0xff, h * line); } +inline void JBIG2Bitmap::getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr) { + if (y < 0 || y >= h || x >= w) { + ptr->p = NULL; + } else if (x < 0) { + ptr->p = &data[y * line]; + ptr->shift = 7; + ptr->x = x; + } else { + ptr->p = &data[y * line + (x >> 3)]; + ptr->shift = 7 - (x & 7); + ptr->x = x; + } +} + +inline int JBIG2Bitmap::nextPixel(JBIG2BitmapPtr *ptr) { + int pix; + + if (!ptr->p) { + pix = 0; + } else if (ptr->x < 0) { + ++ptr->x; + pix = 0; + } else { + pix = (*ptr->p >> ptr->shift) & 1; + if (++ptr->x == w) { + ptr->p = NULL; + } else if (ptr->shift == 0) { + ++ptr->p; + ptr->shift = 7; + } else { + --ptr->shift; + } + } + return pix; +} + void JBIG2Bitmap::duplicateRow(int yDest, int ySrc) { memcpy(data + yDest * line, data + ySrc * line, line); } @@ -1232,21 +972,21 @@ public: Guint getSize() { return size; } void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; } JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; } - void setGenericRegionStats(JBIG2ArithmeticDecoderStats *stats) + void setGenericRegionStats(JArithmeticDecoderStats *stats) { genericRegionStats = stats; } - void setRefinementRegionStats(JBIG2ArithmeticDecoderStats *stats) + void setRefinementRegionStats(JArithmeticDecoderStats *stats) { refinementRegionStats = stats; } - JBIG2ArithmeticDecoderStats *getGenericRegionStats() + JArithmeticDecoderStats *getGenericRegionStats() { return genericRegionStats; } - JBIG2ArithmeticDecoderStats *getRefinementRegionStats() + JArithmeticDecoderStats *getRefinementRegionStats() { return refinementRegionStats; } private: Guint size; JBIG2Bitmap **bitmaps; - JBIG2ArithmeticDecoderStats *genericRegionStats; - JBIG2ArithmeticDecoderStats *refinementRegionStats; + JArithmeticDecoderStats *genericRegionStats; + JArithmeticDecoderStats *refinementRegionStats; }; JBIG2SymbolDict::JBIG2SymbolDict(Guint segNumA, Guint sizeA): @@ -1345,27 +1085,27 @@ JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStream): { pageBitmap = NULL; - arithDecoder = new JBIG2ArithmeticDecoder(); - genericRegionStats = new JBIG2ArithmeticDecoderStats(1); - refinementRegionStats = new JBIG2ArithmeticDecoderStats(1); - iadhStats = new JBIG2ArithmeticDecoderStats(9); - iadwStats = new JBIG2ArithmeticDecoderStats(9); - iaexStats = new JBIG2ArithmeticDecoderStats(9); - iaaiStats = new JBIG2ArithmeticDecoderStats(9); - iadtStats = new JBIG2ArithmeticDecoderStats(9); - iaitStats = new JBIG2ArithmeticDecoderStats(9); - iafsStats = new JBIG2ArithmeticDecoderStats(9); - iadsStats = new JBIG2ArithmeticDecoderStats(9); - iardxStats = new JBIG2ArithmeticDecoderStats(9); - iardyStats = new JBIG2ArithmeticDecoderStats(9); - iardwStats = new JBIG2ArithmeticDecoderStats(9); - iardhStats = new JBIG2ArithmeticDecoderStats(9); - iariStats = new JBIG2ArithmeticDecoderStats(9); - iaidStats = new JBIG2ArithmeticDecoderStats(1); + arithDecoder = new JArithmeticDecoder(); + genericRegionStats = new JArithmeticDecoderStats(1 << 1); + refinementRegionStats = new JArithmeticDecoderStats(1 << 1); + iadhStats = new JArithmeticDecoderStats(1 << 9); + iadwStats = new JArithmeticDecoderStats(1 << 9); + iaexStats = new JArithmeticDecoderStats(1 << 9); + iaaiStats = new JArithmeticDecoderStats(1 << 9); + iadtStats = new JArithmeticDecoderStats(1 << 9); + iaitStats = new JArithmeticDecoderStats(1 << 9); + iafsStats = new JArithmeticDecoderStats(1 << 9); + iadsStats = new JArithmeticDecoderStats(1 << 9); + iardxStats = new JArithmeticDecoderStats(1 << 9); + iardyStats = new JArithmeticDecoderStats(1 << 9); + iardwStats = new JArithmeticDecoderStats(1 << 9); + iardhStats = new JArithmeticDecoderStats(1 << 9); + iariStats = new JArithmeticDecoderStats(1 << 9); + iaidStats = new JArithmeticDecoderStats(1 << 1); huffDecoder = new JBIG2HuffmanDecoder(); mmrDecoder = new JBIG2MMRDecoder(); - segments = new GList(); + segments = globalSegments = new GList(); if (globalsStream->isStream()) { curStr = globalsStream->getStream(); curStr->reset(); @@ -1374,7 +1114,6 @@ JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStream): mmrDecoder->setStream(curStr); readSegments(); } - globalSegments = segments; segments = NULL; curStr = NULL; @@ -1452,7 +1191,7 @@ int JBIG2Stream::lookChar() { return EOF; } -GString *JBIG2Stream::getPSFilter(char *indent) { +GString *JBIG2Stream::getPSFilter(int psLevel, char *indent) { return NULL; } @@ -1768,20 +1507,23 @@ void JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length, } else { if (contextUsed && inputSymbolDict) { resetGenericStats(sdTemplate, inputSymbolDict->getGenericRegionStats()); - if (refAgg) { - resetRefinementStats(sdrTemplate, - inputSymbolDict->getRefinementRegionStats()); - } } else { resetGenericStats(sdTemplate, NULL); - if (refAgg) { - resetRefinementStats(sdrTemplate, NULL); - } } resetIntStats(symCodeLen); arithDecoder->start(); } + // set up the arithmetic decoder for refinement/aggregation + if (refAgg) { + if (contextUsed && inputSymbolDict) { + resetRefinementStats(sdrTemplate, + inputSymbolDict->getRefinementRegionStats()); + } else { + resetRefinementStats(sdrTemplate, NULL); + } + } + // allocate symbol widths storage symWidths = NULL; if (huff && !refAgg) { @@ -1834,7 +1576,13 @@ void JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length, break; } } +#if 0 //~ This special case was added about a year before the final draft + //~ of the JBIG2 spec was released. I have encountered some old + //~ JBIG2 images that predate it. + if (0) { +#else if (refAggNum == 1) { +#endif if (huff) { symID = huffDecoder->readBits(symCodeLen); huffDecoder->decodeInt(&refDX, huffTableO); @@ -1878,15 +1626,13 @@ void JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length, // read the collective bitmap if (huff && !refAgg) { huffDecoder->decodeInt(&bmSize, huffBMSizeTable); - if (huff) { - huffDecoder->reset(); - } + huffDecoder->reset(); if (bmSize == 0) { collBitmap = new JBIG2Bitmap(0, totalWidth, symHeight); bmSize = symHeight * ((totalWidth + 7) >> 3); p = collBitmap->getDataPtr(); for (k = 0; k < (Guint)bmSize; ++k) { - *p++ = str->getChar(); + *p++ = curStr->getChar(); } } else { collBitmap = readGenericBitmap(gTrue, totalWidth, symHeight, @@ -1924,7 +1670,7 @@ void JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length, } ex = !ex; } - + for (i = 0; i < numNewSyms; ++i) { delete bitmaps[numInputSyms + i]; } @@ -1965,7 +1711,8 @@ void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm, JBIG2Bitmap **syms; Guint w, h, x, y, segInfoFlags, extCombOp; Guint flags, huff, refine, logStrips, refCorner, transposed; - Guint combOp, defPixel, sOffset, templ; + Guint combOp, defPixel, templ; + int sOffset; Guint huffFlags, huffFS, huffDS, huffDT; Guint huffRDW, huffRDH, huffRDX, huffRDY, huffRSize; Guint numInstances, numSyms, symCodeLen; @@ -1993,6 +1740,9 @@ void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm, combOp = (flags >> 7) & 3; defPixel = (flags >> 9) & 1; sOffset = (flags >> 10) & 0x1f; + if (sOffset & 0x10) { + sOffset |= -1 - 0x0f; + } templ = (flags >> 15) & 1; huffFS = huffDS = huffDT = 0; // make gcc happy huffRDW = huffRDH = huffRDX = huffRDY = huffRSize = 0; // make gcc happy @@ -2135,6 +1885,7 @@ void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm, runLengthTab[34].val = 0x20b; runLengthTab[34].prefixLen = huffDecoder->readBits(4); runLengthTab[34].rangeLen = 7; + runLengthTab[35].prefixLen = 0; runLengthTab[35].rangeLen = jbig2HuffmanEOT; huffDecoder->buildTable(runLengthTab, 35); symCodeTab = (JBIG2HuffmanTable *)gmalloc((numSyms + 1) * @@ -2158,8 +1909,8 @@ void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm, } else { symCodeTab[i++].prefixLen = j; } - } + symCodeTab[numSyms].prefixLen = 0; symCodeTab[numSyms].rangeLen = jbig2HuffmanEOT; huffDecoder->buildTable(symCodeTab, numSyms); huffDecoder->reset(); @@ -2168,11 +1919,11 @@ void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm, } else { symCodeTab = NULL; resetIntStats(symCodeLen); - if (refine) { - resetRefinementStats(templ, NULL); - } arithDecoder->start(); } + if (refine) { + resetRefinementStats(templ, NULL); + } bitmap = readTextRegion(huff, refine, w, h, numInstances, logStrips, numSyms, symCodeTab, symCodeLen, syms, @@ -2219,7 +1970,7 @@ JBIG2Bitmap *JBIG2Stream::readTextRegion(GBool huff, GBool refine, JBIG2Bitmap **syms, Guint defPixel, Guint combOp, Guint transposed, Guint refCorner, - Guint sOffset, + int sOffset, JBIG2HuffmanTable *huffFSTable, JBIG2HuffmanTable *huffDSTable, JBIG2HuffmanTable *huffDTTable, @@ -2253,7 +2004,7 @@ JBIG2Bitmap *JBIG2Stream::readTextRegion(GBool huff, GBool refine, } else { arithDecoder->decodeInt(&t, iadtStats); } - t *= -strips; + t *= -(int)strips; inst = 0; sFirst = 0; @@ -2426,10 +2177,10 @@ void JBIG2Stream::readPatternDictSeg(Guint segNum, Guint length) { } // read the bitmap - atx[0] = -patternW; aty[0] = 0; - atx[1] = -3; aty[1] = -1; - atx[2] = 2; aty[2] = -2; - atx[3] = -2; aty[3] = -2; + atx[0] = -(int)patternW; aty[0] = 0; + atx[1] = -3; aty[1] = -1; + atx[2] = 2; aty[2] = -2; + atx[3] = -2; aty[3] = -2; bitmap = readGenericBitmap(mmr, (grayMax + 1) * patternW, patternH, templ, gFalse, gFalse, NULL, atx, aty, length - 7); @@ -2686,6 +2437,8 @@ JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h, JBIG2Bitmap *bitmap; GBool ltp; Guint ltpCX, cx, cx0, cx1, cx2; + JBIG2BitmapPtr cxPtr0, cxPtr1; + JBIG2BitmapPtr atPtr0, atPtr1, atPtr2, atPtr3; int *refLine, *codingLine; int code1, code2, code3; int x, y, a0, pix, i, refI, codingI; @@ -2743,10 +2496,12 @@ JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h, code2 += code3 = mmrDecoder->getBlackCode(); } while (code3 >= 64); } - a0 = codingLine[codingI++] = a0 + code1; - a0 = codingLine[codingI++] = a0 + code2; - while (refLine[refI] <= a0 && refLine[refI] < w) { - refI += 2; + if (code1 > 0 || code2 > 0) { + a0 = codingLine[codingI++] = a0 + code1; + a0 = codingLine[codingI++] = a0 + code2; + while (refLine[refI] <= a0 && refLine[refI] < w) { + refI += 2; + } } break; case twoDimVert0: @@ -2880,99 +2635,151 @@ JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h, } } - // set up the context switch (templ) { case 0: - cx0 = (bitmap->getPixel(0, y-2) << 1) | - bitmap->getPixel(1, y-2); - cx1 = (bitmap->getPixel(0, y-1) << 2) | - (bitmap->getPixel(1, y-1) << 1) | - bitmap->getPixel(2, y-1); + + // set up the context + bitmap->getPixelPtr(0, y-2, &cxPtr0); + cx0 = bitmap->nextPixel(&cxPtr0); + cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0); + bitmap->getPixelPtr(0, y-1, &cxPtr1); + cx1 = bitmap->nextPixel(&cxPtr1); + cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1); + cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1); cx2 = 0; + bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0); + bitmap->getPixelPtr(atx[1], y + aty[1], &atPtr1); + bitmap->getPixelPtr(atx[2], y + aty[2], &atPtr2); + bitmap->getPixelPtr(atx[3], y + aty[3], &atPtr3); + + // decode the row + for (x = 0; x < w; ++x) { + + // build the context + cx = (cx0 << 13) | (cx1 << 8) | (cx2 << 4) | + (bitmap->nextPixel(&atPtr0) << 3) | + (bitmap->nextPixel(&atPtr1) << 2) | + (bitmap->nextPixel(&atPtr2) << 1) | + bitmap->nextPixel(&atPtr3); + + // check for a skipped pixel + if (useSkip && skip->getPixel(x, y)) { + pix = 0; + + // decode the pixel + } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) { + bitmap->setPixel(x, y); + } + + // update the context + cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x07; + cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f; + cx2 = ((cx2 << 1) | pix) & 0x0f; + } break; + case 1: - cx0 = (bitmap->getPixel(0, y-2) << 2) | - (bitmap->getPixel(1, y-2) << 1) | - bitmap->getPixel(2, y-2); - cx1 = (bitmap->getPixel(0, y-1) << 2) | - (bitmap->getPixel(1, y-1) << 1) | - bitmap->getPixel(2, y-1); + + // set up the context + bitmap->getPixelPtr(0, y-2, &cxPtr0); + cx0 = bitmap->nextPixel(&cxPtr0); + cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0); + cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0); + bitmap->getPixelPtr(0, y-1, &cxPtr1); + cx1 = bitmap->nextPixel(&cxPtr1); + cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1); + cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1); cx2 = 0; + bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0); + + // decode the row + for (x = 0; x < w; ++x) { + + // build the context + cx = (cx0 << 9) | (cx1 << 4) | (cx2 << 1) | + bitmap->nextPixel(&atPtr0); + + // check for a skipped pixel + if (useSkip && skip->getPixel(x, y)) { + pix = 0; + + // decode the pixel + } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) { + bitmap->setPixel(x, y); + } + + // update the context + cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x0f; + cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f; + cx2 = ((cx2 << 1) | pix) & 0x07; + } break; + case 2: - cx0 = (bitmap->getPixel(0, y-2) << 1) | - bitmap->getPixel(1, y-2); - cx1 = (bitmap->getPixel(0, y-1) << 1) | - bitmap->getPixel(1, y-1); - cx2 = 0; - break; - case 3: - cx1 = (bitmap->getPixel(0, y-1) << 1) | - bitmap->getPixel(1, y-1); + + // set up the context + bitmap->getPixelPtr(0, y-2, &cxPtr0); + cx0 = bitmap->nextPixel(&cxPtr0); + cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0); + bitmap->getPixelPtr(0, y-1, &cxPtr1); + cx1 = bitmap->nextPixel(&cxPtr1); + cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1); cx2 = 0; + bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0); + + // decode the row + for (x = 0; x < w; ++x) { + + // build the context + cx = (cx0 << 7) | (cx1 << 3) | (cx2 << 1) | + bitmap->nextPixel(&atPtr0); + + // check for a skipped pixel + if (useSkip && skip->getPixel(x, y)) { + pix = 0; + + // decode the pixel + } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) { + bitmap->setPixel(x, y); + } + + // update the context + cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x07; + cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x0f; + cx2 = ((cx2 << 1) | pix) & 0x03; + } break; - } - // decode the row - for (x = 0; x < w; ++x) { + case 3: - // check for a skipped pixel - if (useSkip && skip->getPixel(x, y)) { - pix = 0; + // set up the context + bitmap->getPixelPtr(0, y-1, &cxPtr1); + cx1 = bitmap->nextPixel(&cxPtr1); + cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1); + cx2 = 0; + bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0); - } else { + // decode the row + for (x = 0; x < w; ++x) { // build the context - switch (templ) { - case 0: - cx = (cx0 << 13) | (cx1 << 8) | (cx2 << 4) | - (bitmap->getPixel(x + atx[0], y + aty[0]) << 3) | - (bitmap->getPixel(x + atx[1], y + aty[1]) << 2) | - (bitmap->getPixel(x + atx[2], y + aty[2]) << 1) | - bitmap->getPixel(x + atx[3], y + aty[3]); - break; - case 1: - cx = (cx0 << 9) | (cx1 << 4) | (cx2 << 1) | - bitmap->getPixel(x + atx[0], y + aty[0]); - break; - case 2: - cx = (cx0 << 7) | (cx1 << 3) | (cx2 << 1) | - bitmap->getPixel(x + atx[0], y + aty[0]); - break; - case 3: - cx = (cx1 << 5) | (cx2 << 1) | - bitmap->getPixel(x + atx[0], y + aty[0]); - break; - } + cx = (cx1 << 5) | (cx2 << 1) | + bitmap->nextPixel(&atPtr0); + + // check for a skipped pixel + if (useSkip && skip->getPixel(x, y)) { + pix = 0; // decode the pixel - if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) { + } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) { bitmap->setPixel(x, y); } - } - // update the context - switch (templ) { - case 0: - cx0 = ((cx0 << 1) | bitmap->getPixel(x+2, y-2)) & 0x07; - cx1 = ((cx1 << 1) | bitmap->getPixel(x+3, y-1)) & 0x1f; - cx2 = ((cx2 << 1) | pix) & 0x0f; - break; - case 1: - cx0 = ((cx0 << 1) | bitmap->getPixel(x+3, y-2)) & 0x0f; - cx1 = ((cx1 << 1) | bitmap->getPixel(x+3, y-1)) & 0x1f; - cx2 = ((cx2 << 1) | pix) & 0x07; - break; - case 2: - cx0 = ((cx0 << 1) | bitmap->getPixel(x+2, y-2)) & 0x07; - cx1 = ((cx1 << 1) | bitmap->getPixel(x+2, y-1)) & 0x0f; - cx2 = ((cx2 << 1) | pix) & 0x03; - break; - case 3: - cx1 = ((cx1 << 1) | bitmap->getPixel(x+2, y-1)) & 0x1f; - cx2 = ((cx2 << 1) | pix) & 0x0f; - break; + // update the context + cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f; + cx2 = ((cx2 << 1) | pix) & 0x0f; } + break; } } } @@ -3076,6 +2883,8 @@ JBIG2Bitmap *JBIG2Stream::readGenericRefinementRegion(int w, int h, JBIG2Bitmap *bitmap; GBool ltp; Guint ltpCX, cx, cx0, cx2, cx3, cx4, tpgrCX0, tpgrCX1, tpgrCX2; + JBIG2BitmapPtr cxPtr0, cxPtr1, cxPtr2, cxPtr3, cxPtr4, cxPtr5, cxPtr6; + JBIG2BitmapPtr tpgrCXPtr0, tpgrCXPtr1, tpgrCXPtr2; int x, y, pix; bitmap = new JBIG2Bitmap(0, w, h); @@ -3091,87 +2900,144 @@ JBIG2Bitmap *JBIG2Stream::readGenericRefinementRegion(int w, int h, ltp = 0; for (y = 0; y < h; ++y) { - // set up the context if (templ) { - cx0 = bitmap->getPixel(0, y-1); - cx2 = 0; // unused - cx3 = (refBitmap->getPixel(-1-refDX, y-refDY) << 1) | - refBitmap->getPixel(-refDX, y-refDY); - cx4 = refBitmap->getPixel(-refDX, y+1-refDY); - } else { - cx0 = bitmap->getPixel(0, y-1); - cx2 = refBitmap->getPixel(-refDX, y-1-refDY); - cx3 = (refBitmap->getPixel(-1-refDX, y-refDY) << 1) | - refBitmap->getPixel(-refDX, y-refDY); - cx4 = (refBitmap->getPixel(-1-refDX, y+1-refDY) << 1) | - refBitmap->getPixel(-refDX, y+1-refDY); - } - - // set up the typical prediction context - tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy - if (tpgrOn) { - tpgrCX0 = (refBitmap->getPixel(-1-refDX, y-1-refDY) << 2) | - (refBitmap->getPixel(-refDX, y-1-refDY) << 1) | - refBitmap->getPixel(1-refDX, y-1-refDY); - tpgrCX1 = (refBitmap->getPixel(-1-refDX, y-refDY) << 2) | - (refBitmap->getPixel(-refDX, y-refDY) << 1) | - refBitmap->getPixel(1-refDX, y-refDY); - tpgrCX2 = (refBitmap->getPixel(-1-refDX, y+1-refDY) << 2) | - (refBitmap->getPixel(-refDX, y+1-refDY) << 1) | - refBitmap->getPixel(1-refDX, y+1-refDY); - } - - for (x = 0; x < w; ++x) { - - // update the context - if (templ) { - cx0 = ((cx0 << 1) | bitmap->getPixel(x+1, y-1)) & 7; - cx3 = ((cx3 << 1) | refBitmap->getPixel(x+1-refDX, y-refDY)) & 7; - cx4 = ((cx4 << 1) | refBitmap->getPixel(x+1-refDX, y+1-refDY)) & 3; - } else { - cx0 = ((cx0 << 1) | bitmap->getPixel(x+1, y-1)) & 3; - cx2 = ((cx2 << 1) | refBitmap->getPixel(x+1-refDX, y-1-refDY)) & 3; - cx3 = ((cx3 << 1) | refBitmap->getPixel(x+1-refDX, y-refDY)) & 7; - cx4 = ((cx4 << 1) | refBitmap->getPixel(x+1-refDX, y+1-refDY)) & 7; - } + // set up the context + bitmap->getPixelPtr(0, y-1, &cxPtr0); + cx0 = bitmap->nextPixel(&cxPtr0); + bitmap->getPixelPtr(-1, y, &cxPtr1); + refBitmap->getPixelPtr(-refDX, y-1-refDY, &cxPtr2); + refBitmap->getPixelPtr(-1-refDX, y-refDY, &cxPtr3); + cx3 = refBitmap->nextPixel(&cxPtr3); + cx3 = (cx3 << 1) | refBitmap->nextPixel(&cxPtr3); + refBitmap->getPixelPtr(-refDX, y+1-refDY, &cxPtr4); + cx4 = refBitmap->nextPixel(&cxPtr4); + + // set up the typical prediction context + tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy if (tpgrOn) { - // update the typical predictor context - tpgrCX0 = ((tpgrCX0 << 1) | - refBitmap->getPixel(x+1-refDX, y-1-refDY)) & 7; - tpgrCX1 = ((tpgrCX1 << 1) | - refBitmap->getPixel(x+1-refDX, y-refDY)) & 7; - tpgrCX2 = ((tpgrCX2 << 1) | - refBitmap->getPixel(x+1-refDX, y+1-refDY)) & 7; - - // check for a "typical" pixel - if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) { - ltp = !ltp; + refBitmap->getPixelPtr(-1-refDX, y-1-refDY, &tpgrCXPtr0); + tpgrCX0 = refBitmap->nextPixel(&tpgrCXPtr0); + tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0); + tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0); + refBitmap->getPixelPtr(-1-refDX, y-refDY, &tpgrCXPtr1); + tpgrCX1 = refBitmap->nextPixel(&tpgrCXPtr1); + tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1); + tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1); + refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &tpgrCXPtr2); + tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2); + tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2); + tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2); + } + + for (x = 0; x < w; ++x) { + + // update the context + cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 7; + cx3 = ((cx3 << 1) | refBitmap->nextPixel(&cxPtr3)) & 7; + cx4 = ((cx4 << 1) | refBitmap->nextPixel(&cxPtr4)) & 3; + + if (tpgrOn) { + // update the typical predictor context + tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0)) & 7; + tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1)) & 7; + tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2)) & 7; + + // check for a "typical" pixel + if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) { + ltp = !ltp; + } + if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) { + bitmap->clearPixel(x, y); + continue; + } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) { + bitmap->setPixel(x, y); + continue; + } } - if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) { - bitmap->clearPixel(x, y); - continue; - } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) { + + // build the context + cx = (cx0 << 7) | (bitmap->nextPixel(&cxPtr1) << 6) | + (refBitmap->nextPixel(&cxPtr2) << 5) | + (cx3 << 2) | cx4; + + // decode the pixel + if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) { bitmap->setPixel(x, y); - continue; } } - // build the context - if (templ) { - cx = (cx0 << 7) | (bitmap->getPixel(x-1, y) << 6) | - (refBitmap->getPixel(x-refDX, y-1-refDY) << 5) | - (cx3 << 2) | cx4; - } else { - cx = (cx0 << 11) | (bitmap->getPixel(x-1, y) << 10) | - (cx2 << 8) | (cx3 << 5) | (cx4 << 2) | - (bitmap->getPixel(x+atx[0], y+aty[0]) << 1) | - refBitmap->getPixel(x+atx[1]-refDX, y+aty[1]-refDY); + } else { + + // set up the context + bitmap->getPixelPtr(0, y-1, &cxPtr0); + cx0 = bitmap->nextPixel(&cxPtr0); + bitmap->getPixelPtr(-1, y, &cxPtr1); + refBitmap->getPixelPtr(-refDX, y-1-refDY, &cxPtr2); + cx2 = refBitmap->nextPixel(&cxPtr2); + refBitmap->getPixelPtr(-1-refDX, y-refDY, &cxPtr3); + cx3 = refBitmap->nextPixel(&cxPtr3); + cx3 = (cx3 << 1) | refBitmap->nextPixel(&cxPtr3); + refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &cxPtr4); + cx4 = refBitmap->nextPixel(&cxPtr4); + cx4 = (cx4 << 1) | refBitmap->nextPixel(&cxPtr4); + bitmap->getPixelPtr(atx[0], y+aty[0], &cxPtr5); + refBitmap->getPixelPtr(atx[1]-refDX, y+aty[1]-refDY, &cxPtr6); + + // set up the typical prediction context + tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy + if (tpgrOn) { + refBitmap->getPixelPtr(-1-refDX, y-1-refDY, &tpgrCXPtr0); + tpgrCX0 = refBitmap->nextPixel(&tpgrCXPtr0); + tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0); + tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0); + refBitmap->getPixelPtr(-1-refDX, y-refDY, &tpgrCXPtr1); + tpgrCX1 = refBitmap->nextPixel(&tpgrCXPtr1); + tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1); + tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1); + refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &tpgrCXPtr2); + tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2); + tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2); + tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2); } - // decode the pixel - if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) { - bitmap->setPixel(x, y); + for (x = 0; x < w; ++x) { + + // update the context + cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 3; + cx2 = ((cx2 << 1) | refBitmap->nextPixel(&cxPtr2)) & 3; + cx3 = ((cx3 << 1) | refBitmap->nextPixel(&cxPtr3)) & 7; + cx4 = ((cx4 << 1) | refBitmap->nextPixel(&cxPtr4)) & 7; + + if (tpgrOn) { + // update the typical predictor context + tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0)) & 7; + tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1)) & 7; + tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2)) & 7; + + // check for a "typical" pixel + if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) { + ltp = !ltp; + } + if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) { + bitmap->clearPixel(x, y); + continue; + } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) { + bitmap->setPixel(x, y); + continue; + } + } + + // build the context + cx = (cx0 << 11) | (bitmap->nextPixel(&cxPtr1) << 10) | + (cx2 << 8) | (cx3 << 5) | (cx4 << 2) | + (bitmap->nextPixel(&cxPtr5) << 1) | + refBitmap->nextPixel(&cxPtr6); + + // decode the pixel + if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) { + bitmap->setPixel(x, y); + } } } } @@ -3239,8 +3105,8 @@ void JBIG2Stream::readCodeTableSeg(Guint segNum, Guint length) { goto eofError; } oob = flags & 1; - prefixBits = (flags >> 1) & 7; - rangeBits = (flags >> 4) & 7; + prefixBits = ((flags >> 1) & 7) + 1; + rangeBits = ((flags >> 4) & 7) + 1; huffDecoder->reset(); huffTabSize = 8; @@ -3282,7 +3148,6 @@ void JBIG2Stream::readCodeTableSeg(Guint segNum, Guint length) { huffTab[i].val = 0; huffTab[i].prefixLen = 0; huffTab[i].rangeLen = jbig2HuffmanEOT; - ++i; huffDecoder->buildTable(huffTab, i); // create and store the new table segment @@ -3336,14 +3201,14 @@ void JBIG2Stream::discardSegment(Guint segNum) { for (i = 0; i < segments->getLength(); ++i) { seg = (JBIG2Segment *)segments->get(i); if (seg->getSegNum() == segNum) { - globalSegments->del(i); + segments->del(i); return; } } } void JBIG2Stream::resetGenericStats(Guint templ, - JBIG2ArithmeticDecoderStats *prevStats) { + JArithmeticDecoderStats *prevStats) { int size; size = contextSize[templ]; @@ -3359,14 +3224,13 @@ void JBIG2Stream::resetGenericStats(Guint templ, genericRegionStats->reset(); } else { delete genericRegionStats; - genericRegionStats = new JBIG2ArithmeticDecoderStats(size); + genericRegionStats = new JArithmeticDecoderStats(1 << size); } } } -void JBIG2Stream::resetRefinementStats( - Guint templ, - JBIG2ArithmeticDecoderStats *prevStats) { +void JBIG2Stream::resetRefinementStats(Guint templ, + JArithmeticDecoderStats *prevStats) { int size; size = refContextSize[templ]; @@ -3382,7 +3246,7 @@ void JBIG2Stream::resetRefinementStats( refinementRegionStats->reset(); } else { delete refinementRegionStats; - refinementRegionStats = new JBIG2ArithmeticDecoderStats(size); + refinementRegionStats = new JArithmeticDecoderStats(1 << size); } } } @@ -3405,7 +3269,7 @@ void JBIG2Stream::resetIntStats(int symCodeLen) { iaidStats->reset(); } else { delete iaidStats; - iaidStats = new JBIG2ArithmeticDecoderStats(symCodeLen + 1); + iaidStats = new JArithmeticDecoderStats(1 << (symCodeLen + 1)); } } @@ -3467,7 +3331,7 @@ GBool JBIG2Stream::readLong(int *x) { } *x = ((c0 << 24) | (c1 << 16) | (c2 << 8) | c3); if (c0 & 0x80) { - *x |= -1 - 0xffffffff; + *x |= -1 - (int)0xffffffff; } return gTrue; }