X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=pdf2swf%2Fxpdf%2FJBIG2Stream.cc;fp=pdf2swf%2Fxpdf%2FJBIG2Stream.cc;h=0000000000000000000000000000000000000000;hp=a90db80cbe640b038573ee2f1ce02c27ea9b0cea;hb=5a005ef586b9000810156a961b9622c903dce988;hpb=c26ca847941ca0acfc9f3b4bdc519d904ba09a39 diff --git a/pdf2swf/xpdf/JBIG2Stream.cc b/pdf2swf/xpdf/JBIG2Stream.cc deleted file mode 100644 index a90db80..0000000 --- a/pdf2swf/xpdf/JBIG2Stream.cc +++ /dev/null @@ -1,3386 +0,0 @@ -//======================================================================== -// -// JBIG2Stream.cc -// -// Copyright 2002-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include "GList.h" -#include "Error.h" -#include "JArithmeticDecoder.h" -#include "JBIG2Stream.h" - -//~ share these tables -#include "Stream-CCITT.h" - -//------------------------------------------------------------------------ - -static int contextSize[4] = { 16, 13, 10, 10 }; -static int refContextSize[2] = { 13, 10 }; - -//------------------------------------------------------------------------ -// JBIG2HuffmanTable -//------------------------------------------------------------------------ - -#define jbig2HuffmanLOW 0xfffffffd -#define jbig2HuffmanOOB 0xfffffffe -#define jbig2HuffmanEOT 0xffffffff - -struct JBIG2HuffmanTable { - int val; - Guint prefixLen; - Guint rangeLen; // can also be LOW, OOB, or EOT - Guint prefix; -}; - -JBIG2HuffmanTable huffTableA[] = { - { 0, 1, 4, 0x000 }, - { 16, 2, 8, 0x002 }, - { 272, 3, 16, 0x006 }, - { 65808, 3, 32, 0x007 }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableB[] = { - { 0, 1, 0, 0x000 }, - { 1, 2, 0, 0x002 }, - { 2, 3, 0, 0x006 }, - { 3, 4, 3, 0x00e }, - { 11, 5, 6, 0x01e }, - { 75, 6, 32, 0x03e }, - { 0, 6, jbig2HuffmanOOB, 0x03f }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableC[] = { - { 0, 1, 0, 0x000 }, - { 1, 2, 0, 0x002 }, - { 2, 3, 0, 0x006 }, - { 3, 4, 3, 0x00e }, - { 11, 5, 6, 0x01e }, - { 0, 6, jbig2HuffmanOOB, 0x03e }, - { 75, 7, 32, 0x0fe }, - { -256, 8, 8, 0x0fe }, - { -257, 8, jbig2HuffmanLOW, 0x0ff }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableD[] = { - { 1, 1, 0, 0x000 }, - { 2, 2, 0, 0x002 }, - { 3, 3, 0, 0x006 }, - { 4, 4, 3, 0x00e }, - { 12, 5, 6, 0x01e }, - { 76, 5, 32, 0x01f }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableE[] = { - { 1, 1, 0, 0x000 }, - { 2, 2, 0, 0x002 }, - { 3, 3, 0, 0x006 }, - { 4, 4, 3, 0x00e }, - { 12, 5, 6, 0x01e }, - { 76, 6, 32, 0x03e }, - { -255, 7, 8, 0x07e }, - { -256, 7, jbig2HuffmanLOW, 0x07f }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableF[] = { - { 0, 2, 7, 0x000 }, - { 128, 3, 7, 0x002 }, - { 256, 3, 8, 0x003 }, - { -1024, 4, 9, 0x008 }, - { -512, 4, 8, 0x009 }, - { -256, 4, 7, 0x00a }, - { -32, 4, 5, 0x00b }, - { 512, 4, 9, 0x00c }, - { 1024, 4, 10, 0x00d }, - { -2048, 5, 10, 0x01c }, - { -128, 5, 6, 0x01d }, - { -64, 5, 5, 0x01e }, - { -2049, 6, jbig2HuffmanLOW, 0x03e }, - { 2048, 6, 32, 0x03f }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableG[] = { - { -512, 3, 8, 0x000 }, - { 256, 3, 8, 0x001 }, - { 512, 3, 9, 0x002 }, - { 1024, 3, 10, 0x003 }, - { -1024, 4, 9, 0x008 }, - { -256, 4, 7, 0x009 }, - { -32, 4, 5, 0x00a }, - { 0, 4, 5, 0x00b }, - { 128, 4, 7, 0x00c }, - { -128, 5, 6, 0x01a }, - { -64, 5, 5, 0x01b }, - { 32, 5, 5, 0x01c }, - { 64, 5, 6, 0x01d }, - { -1025, 5, jbig2HuffmanLOW, 0x01e }, - { 2048, 5, 32, 0x01f }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableH[] = { - { 0, 2, 1, 0x000 }, - { 0, 2, jbig2HuffmanOOB, 0x001 }, - { 4, 3, 4, 0x004 }, - { -1, 4, 0, 0x00a }, - { 22, 4, 4, 0x00b }, - { 38, 4, 5, 0x00c }, - { 2, 5, 0, 0x01a }, - { 70, 5, 6, 0x01b }, - { 134, 5, 7, 0x01c }, - { 3, 6, 0, 0x03a }, - { 20, 6, 1, 0x03b }, - { 262, 6, 7, 0x03c }, - { 646, 6, 10, 0x03d }, - { -2, 7, 0, 0x07c }, - { 390, 7, 8, 0x07d }, - { -15, 8, 3, 0x0fc }, - { -5, 8, 1, 0x0fd }, - { -7, 9, 1, 0x1fc }, - { -3, 9, 0, 0x1fd }, - { -16, 9, jbig2HuffmanLOW, 0x1fe }, - { 1670, 9, 32, 0x1ff }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableI[] = { - { 0, 2, jbig2HuffmanOOB, 0x000 }, - { -1, 3, 1, 0x002 }, - { 1, 3, 1, 0x003 }, - { 7, 3, 5, 0x004 }, - { -3, 4, 1, 0x00a }, - { 43, 4, 5, 0x00b }, - { 75, 4, 6, 0x00c }, - { 3, 5, 1, 0x01a }, - { 139, 5, 7, 0x01b }, - { 267, 5, 8, 0x01c }, - { 5, 6, 1, 0x03a }, - { 39, 6, 2, 0x03b }, - { 523, 6, 8, 0x03c }, - { 1291, 6, 11, 0x03d }, - { -5, 7, 1, 0x07c }, - { 779, 7, 9, 0x07d }, - { -31, 8, 4, 0x0fc }, - { -11, 8, 2, 0x0fd }, - { -15, 9, 2, 0x1fc }, - { -7, 9, 1, 0x1fd }, - { -32, 9, jbig2HuffmanLOW, 0x1fe }, - { 3339, 9, 32, 0x1ff }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableJ[] = { - { -2, 2, 2, 0x000 }, - { 6, 2, 6, 0x001 }, - { 0, 2, jbig2HuffmanOOB, 0x002 }, - { -3, 5, 0, 0x018 }, - { 2, 5, 0, 0x019 }, - { 70, 5, 5, 0x01a }, - { 3, 6, 0, 0x036 }, - { 102, 6, 5, 0x037 }, - { 134, 6, 6, 0x038 }, - { 198, 6, 7, 0x039 }, - { 326, 6, 8, 0x03a }, - { 582, 6, 9, 0x03b }, - { 1094, 6, 10, 0x03c }, - { -21, 7, 4, 0x07a }, - { -4, 7, 0, 0x07b }, - { 4, 7, 0, 0x07c }, - { 2118, 7, 11, 0x07d }, - { -5, 8, 0, 0x0fc }, - { 5, 8, 0, 0x0fd }, - { -22, 8, jbig2HuffmanLOW, 0x0fe }, - { 4166, 8, 32, 0x0ff }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableK[] = { - { 1, 1, 0, 0x000 }, - { 2, 2, 1, 0x002 }, - { 4, 4, 0, 0x00c }, - { 5, 4, 1, 0x00d }, - { 7, 5, 1, 0x01c }, - { 9, 5, 2, 0x01d }, - { 13, 6, 2, 0x03c }, - { 17, 7, 2, 0x07a }, - { 21, 7, 3, 0x07b }, - { 29, 7, 4, 0x07c }, - { 45, 7, 5, 0x07d }, - { 77, 7, 6, 0x07e }, - { 141, 7, 32, 0x07f }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableL[] = { - { 1, 1, 0, 0x000 }, - { 2, 2, 0, 0x002 }, - { 3, 3, 1, 0x006 }, - { 5, 5, 0, 0x01c }, - { 6, 5, 1, 0x01d }, - { 8, 6, 1, 0x03c }, - { 10, 7, 0, 0x07a }, - { 11, 7, 1, 0x07b }, - { 13, 7, 2, 0x07c }, - { 17, 7, 3, 0x07d }, - { 25, 7, 4, 0x07e }, - { 41, 8, 5, 0x0fe }, - { 73, 8, 32, 0x0ff }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableM[] = { - { 1, 1, 0, 0x000 }, - { 2, 3, 0, 0x004 }, - { 7, 3, 3, 0x005 }, - { 3, 4, 0, 0x00c }, - { 5, 4, 1, 0x00d }, - { 4, 5, 0, 0x01c }, - { 15, 6, 1, 0x03a }, - { 17, 6, 2, 0x03b }, - { 21, 6, 3, 0x03c }, - { 29, 6, 4, 0x03d }, - { 45, 6, 5, 0x03e }, - { 77, 7, 6, 0x07e }, - { 141, 7, 32, 0x07f }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableN[] = { - { 0, 1, 0, 0x000 }, - { -2, 3, 0, 0x004 }, - { -1, 3, 0, 0x005 }, - { 1, 3, 0, 0x006 }, - { 2, 3, 0, 0x007 }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableO[] = { - { 0, 1, 0, 0x000 }, - { -1, 3, 0, 0x004 }, - { 1, 3, 0, 0x005 }, - { -2, 4, 0, 0x00c }, - { 2, 4, 0, 0x00d }, - { -4, 5, 1, 0x01c }, - { 3, 5, 1, 0x01d }, - { -8, 6, 2, 0x03c }, - { 5, 6, 2, 0x03d }, - { -24, 7, 4, 0x07c }, - { 9, 7, 4, 0x07d }, - { -25, 7, jbig2HuffmanLOW, 0x07e }, - { 25, 7, 32, 0x07f }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -//------------------------------------------------------------------------ -// JBIG2HuffmanDecoder -//------------------------------------------------------------------------ - -class JBIG2HuffmanDecoder { -public: - - JBIG2HuffmanDecoder(); - ~JBIG2HuffmanDecoder(); - void setStream(Stream *strA) { str = strA; } - - void reset(); - - // Returns false for OOB, otherwise sets * and returns true. - GBool decodeInt(int *x, JBIG2HuffmanTable *table); - - Guint readBits(Guint n); - Guint readBit(); - - // Sort the table by prefix length and assign prefix values. - void buildTable(JBIG2HuffmanTable *table, Guint len); - -private: - - Stream *str; - Guint buf; - Guint bufLen; -}; - -JBIG2HuffmanDecoder::JBIG2HuffmanDecoder() { - str = NULL; - reset(); -} - -JBIG2HuffmanDecoder::~JBIG2HuffmanDecoder() { -} - -void JBIG2HuffmanDecoder::reset() { - buf = 0; - bufLen = 0; -} - -//~ optimize this -GBool JBIG2HuffmanDecoder::decodeInt(int *x, JBIG2HuffmanTable *table) { - Guint i, len, prefix; - - i = 0; - len = 0; - prefix = 0; - while (table[i].rangeLen != jbig2HuffmanEOT) { - while (len < table[i].prefixLen) { - prefix = (prefix << 1) | readBit(); - ++len; - } - 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; - } - ++i; - } - return gFalse; -} - -Guint JBIG2HuffmanDecoder::readBits(Guint n) { - Guint x, mask, nLeft; - - mask = (n == 32) ? 0xffffffff : ((1 << n) - 1); - if (bufLen >= n) { - x = (buf >> (bufLen - n)) & mask; - bufLen -= n; - } else { - x = buf & ((1 << bufLen) - 1); - nLeft = n - bufLen; - bufLen = 0; - while (nLeft >= 8) { - x = (x << 8) | (str->getChar() & 0xff); - nLeft -= 8; - } - if (nLeft > 0) { - buf = str->getChar(); - bufLen = 8 - nLeft; - x = (x << nLeft) | ((buf >> bufLen) & ((1 << nLeft) - 1)); - } - } - return x; -} - -Guint JBIG2HuffmanDecoder::readBit() { - if (bufLen == 0) { - buf = str->getChar(); - bufLen = 8; - } - --bufLen; - return (buf >> bufLen) & 1; -} - -void JBIG2HuffmanDecoder::buildTable(JBIG2HuffmanTable *table, Guint len) { - 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 (; table[i].rangeLen != jbig2HuffmanEOT; ++i) { - prefix <<= table[i].prefixLen - table[i-1].prefixLen; - table[i].prefix = prefix++; - } -} - -//------------------------------------------------------------------------ -// JBIG2MMRDecoder -//------------------------------------------------------------------------ - -class JBIG2MMRDecoder { -public: - - JBIG2MMRDecoder(); - ~JBIG2MMRDecoder(); - void setStream(Stream *strA) { str = strA; } - void reset(); - int get2DCode(); - int getBlackCode(); - int getWhiteCode(); - Guint get24Bits(); - void skipTo(Guint length); - -private: - - Stream *str; - Guint buf; - Guint bufLen; - Guint nBytesRead; -}; - -JBIG2MMRDecoder::JBIG2MMRDecoder() { - str = NULL; - reset(); -} - -JBIG2MMRDecoder::~JBIG2MMRDecoder() { -} - -void JBIG2MMRDecoder::reset() { - buf = 0; - bufLen = 0; - nBytesRead = 0; -} - -int JBIG2MMRDecoder::get2DCode() { - CCITTCode *p; - - if (bufLen == 0) { - buf = str->getChar() & 0xff; - bufLen = 8; - ++nBytesRead; - p = &twoDimTab1[(buf >> 1) & 0x7f]; - } else if (bufLen == 8) { - p = &twoDimTab1[(buf >> 1) & 0x7f]; - } else { - p = &twoDimTab1[(buf << (7 - bufLen)) & 0x7f]; - if (p->bits < 0 || p->bits > (int)bufLen) { - buf = (buf << 8) | (str->getChar() & 0xff); - bufLen += 8; - ++nBytesRead; - p = &twoDimTab1[(buf >> (bufLen - 7)) & 0x7f]; - } - } - if (p->bits < 0) { - error(str->getPos(), "Bad two dim code in JBIG2 MMR stream"); - return 0; - } - bufLen -= p->bits; - return p->n; -} - -int JBIG2MMRDecoder::getWhiteCode() { - CCITTCode *p; - Guint code; - - if (bufLen == 0) { - buf = str->getChar() & 0xff; - bufLen = 8; - ++nBytesRead; - } - while (1) { - if (bufLen >= 7 && ((buf >> (bufLen - 7)) & 0x7f) == 0) { - if (bufLen <= 12) { - code = buf << (12 - bufLen); - } else { - code = buf >> (bufLen - 12); - } - p = &whiteTab1[code & 0x1f]; - } else { - if (bufLen <= 9) { - code = buf << (9 - bufLen); - } else { - code = buf >> (bufLen - 9); - } - p = &whiteTab2[code & 0x1ff]; - } - if (p->bits > 0 && p->bits <= (int)bufLen) { - bufLen -= p->bits; - return p->n; - } - if (bufLen >= 12) { - break; - } - buf = (buf << 8) | (str->getChar() & 0xff); - bufLen += 8; - ++nBytesRead; - } - error(str->getPos(), "Bad white code in JBIG2 MMR stream"); - // eat a bit and return a positive number so that the caller doesn't - // go into an infinite loop - --bufLen; - return 1; -} - -int JBIG2MMRDecoder::getBlackCode() { - CCITTCode *p; - Guint code; - - if (bufLen == 0) { - buf = str->getChar() & 0xff; - bufLen = 8; - ++nBytesRead; - } - while (1) { - 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) { - if (bufLen <= 12) { - code = buf << (12 - bufLen); - } else { - code = buf >> (bufLen - 12); - } - p = &blackTab2[(code & 0xff) - 64]; - } else { - if (bufLen <= 6) { - code = buf << (6 - bufLen); - } else { - code = buf >> (bufLen - 6); - } - p = &blackTab3[code & 0x3f]; - } - if (p->bits > 0 && p->bits <= (int)bufLen) { - bufLen -= p->bits; - return p->n; - } - if (bufLen >= 13) { - break; - } - buf = (buf << 8) | (str->getChar() & 0xff); - bufLen += 8; - ++nBytesRead; - } - error(str->getPos(), "Bad black code in JBIG2 MMR stream"); - // eat a bit and return a positive number so that the caller doesn't - // go into an infinite loop - --bufLen; - return 1; -} - -Guint JBIG2MMRDecoder::get24Bits() { - while (bufLen < 24) { - buf = (buf << 8) | (str->getChar() & 0xff); - bufLen += 8; - ++nBytesRead; - } - return (buf >> (bufLen - 24)) & 0xffffff; -} - -void JBIG2MMRDecoder::skipTo(Guint length) { - while (nBytesRead < length) { - str->getChar(); - ++nBytesRead; - } -} - -//------------------------------------------------------------------------ -// JBIG2Segment -//------------------------------------------------------------------------ - -enum JBIG2SegmentType { - jbig2SegBitmap, - jbig2SegSymbolDict, - jbig2SegPatternDict, - jbig2SegCodeTable -}; - -class JBIG2Segment { -public: - - JBIG2Segment(Guint segNumA) { segNum = segNumA; } - virtual ~JBIG2Segment() {} - void setSegNum(Guint segNumA) { segNum = segNumA; } - Guint getSegNum() { return segNum; } - virtual JBIG2SegmentType getType() = 0; - -private: - - Guint segNum; -}; - -//------------------------------------------------------------------------ -// JBIG2Bitmap -//------------------------------------------------------------------------ - -struct JBIG2BitmapPtr { - Guchar *p; - int shift; - int x; -}; - -class JBIG2Bitmap: public JBIG2Segment { -public: - - JBIG2Bitmap(Guint segNumA, int wA, int hA); - virtual ~JBIG2Bitmap(); - virtual JBIG2SegmentType getType() { return jbig2SegBitmap; } - JBIG2Bitmap *copy() { return new JBIG2Bitmap(0, this); } - JBIG2Bitmap *getSlice(Guint x, Guint y, Guint wA, Guint hA); - void expand(int newH, Guint pixel); - void clearToZero(); - void clearToOne(); - int getWidth() { return w; } - int getHeight() { return h; } - int getPixel(int x, int y) - { return (x < 0 || x >= w || y < 0 || y >= h) ? 0 : - (data[y * line + (x >> 3)] >> (7 - (x & 7))) & 1; } - void setPixel(int x, int y) - { 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; } - int getDataSize() { return h * line; } - -private: - - JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap); - - int w, h, line; - Guchar *data; -}; - -JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, int wA, int hA): - JBIG2Segment(segNumA) -{ - w = wA; - h = hA; - line = (wA + 7) >> 3; - // need to allocate one extra guard byte for use in combine() - data = (Guchar *)gmalloc(h * line + 1); - data[h * line] = 0; -} - -JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap): - JBIG2Segment(segNumA) -{ - w = bitmap->w; - h = bitmap->h; - line = bitmap->line; - // need to allocate one extra guard byte for use in combine() - data = (Guchar *)gmalloc(h * line + 1); - memcpy(data, bitmap->data, h * line); - data[h * line] = 0; -} - -JBIG2Bitmap::~JBIG2Bitmap() { - gfree(data); -} - -//~ optimize this -JBIG2Bitmap *JBIG2Bitmap::getSlice(Guint x, Guint y, Guint wA, Guint hA) { - JBIG2Bitmap *slice; - Guint xx, yy; - - slice = new JBIG2Bitmap(0, wA, hA); - slice->clearToZero(); - for (yy = 0; yy < hA; ++yy) { - for (xx = 0; xx < wA; ++xx) { - if (getPixel(x + xx, y + yy)) { - slice->setPixel(xx, yy); - } - } - } - return slice; -} - -void JBIG2Bitmap::expand(int newH, Guint pixel) { - if (newH <= h) { - return; - } - // need to allocate one extra guard byte for use in combine() - data = (Guchar *)grealloc(data, newH * line + 1); - if (pixel) { - memset(data + h * line, 0xff, (newH - h) * line); - } else { - memset(data + h * line, 0x00, (newH - h) * line); - } - h = newH; - data[h * line] = 0; -} - -void JBIG2Bitmap::clearToZero() { - memset(data, 0, h * line); -} - -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); -} - -void JBIG2Bitmap::combine(JBIG2Bitmap *bitmap, int x, int y, - Guint combOp) { - int x0, x1, y0, y1, xx, yy; - Guchar *srcPtr, *destPtr; - Guint src0, src1, src, dest, s1, s2, m1, m2, m3; - GBool oneByte; - - if (y < 0) { - y0 = -y; - } else { - y0 = 0; - } - if (y + bitmap->h > h) { - y1 = h - y; - } else { - y1 = bitmap->h; - } - if (y0 >= y1) { - return; - } - - if (x >= 0) { - x0 = x & ~7; - } else { - x0 = 0; - } - x1 = x + bitmap->w; - if (x1 > w) { - x1 = w; - } - if (x0 >= x1) { - return; - } - - s1 = x & 7; - s2 = 8 - s1; - m1 = 0xff >> (x1 & 7); - m2 = 0xff << (((x1 & 7) == 0) ? 0 : 8 - (x1 & 7)); - m3 = (0xff >> s1) & m2; - - oneByte = x0 == ((x1 - 1) & ~7); - - for (yy = y0; yy < y1; ++yy) { - - // one byte per line -- need to mask both left and right side - if (oneByte) { - if (x >= 0) { - destPtr = data + (y + yy) * line + (x >> 3); - srcPtr = bitmap->data + yy * bitmap->line; - dest = *destPtr; - src1 = *srcPtr; - switch (combOp) { - case 0: // or - dest |= (src1 >> s1) & m2; - break; - case 1: // and - dest &= ((0xff00 | src1) >> s1) | m1; - break; - case 2: // xor - dest ^= (src1 >> s1) & m2; - break; - case 3: // xnor - dest ^= ((src1 ^ 0xff) >> s1) & m2; - break; - case 4: // replace - dest = (dest & ~m3) | ((src1 >> s1) & m3); - break; - } - *destPtr = dest; - } else { - destPtr = data + (y + yy) * line; - srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3); - dest = *destPtr; - src1 = *srcPtr; - switch (combOp) { - case 0: // or - dest |= src1 & m2; - break; - case 1: // and - dest &= src1 | m1; - break; - case 2: // xor - dest ^= src1 & m2; - break; - case 3: // xnor - dest ^= (src1 ^ 0xff) & m2; - break; - case 4: // replace - dest = (src1 & m2) | (dest & m1); - break; - } - *destPtr = dest; - } - - // multiple bytes per line -- need to mask left side of left-most - // byte and right side of right-most byte - } else { - - // left-most byte - if (x >= 0) { - destPtr = data + (y + yy) * line + (x >> 3); - srcPtr = bitmap->data + yy * bitmap->line; - src1 = *srcPtr++; - dest = *destPtr; - switch (combOp) { - case 0: // or - dest |= src1 >> s1; - break; - case 1: // and - dest &= (0xff00 | src1) >> s1; - break; - case 2: // xor - dest ^= src1 >> s1; - break; - case 3: // xnor - dest ^= (src1 ^ 0xff) >> s1; - break; - case 4: // replace - dest = (dest & (0xff << s2)) | (src1 >> s1); - break; - } - *destPtr++ = dest; - xx = x0 + 8; - } else { - destPtr = data + (y + yy) * line; - srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3); - src1 = *srcPtr++; - xx = x0; - } - - // middle bytes - for (; xx < x1 - 8; xx += 8) { - dest = *destPtr; - src0 = src1; - src1 = *srcPtr++; - src = (((src0 << 8) | src1) >> s1) & 0xff; - switch (combOp) { - case 0: // or - dest |= src; - break; - case 1: // and - dest &= src; - break; - case 2: // xor - dest ^= src; - break; - case 3: // xnor - dest ^= src ^ 0xff; - break; - case 4: // replace - dest = src; - break; - } - *destPtr++ = dest; - } - - // right-most byte - // note: this last byte (src1) may not actually be used, depending - // on the values of s1, m1, and m2 - and in fact, it may be off - // the edge of the source bitmap, which means we need to allocate - // one extra guard byte at the end of each bitmap - dest = *destPtr; - src0 = src1; - src1 = *srcPtr++; - src = (((src0 << 8) | src1) >> s1) & 0xff; - switch (combOp) { - case 0: // or - dest |= src & m2; - break; - case 1: // and - dest &= src | m1; - break; - case 2: // xor - dest ^= src & m2; - break; - case 3: // xnor - dest ^= (src ^ 0xff) & m2; - break; - case 4: // replace - dest = (src & m2) | (dest & m1); - break; - } - *destPtr = dest; - } - } -} - -//------------------------------------------------------------------------ -// JBIG2SymbolDict -//------------------------------------------------------------------------ - -class JBIG2SymbolDict: public JBIG2Segment { -public: - - JBIG2SymbolDict(Guint segNumA, Guint sizeA); - virtual ~JBIG2SymbolDict(); - virtual JBIG2SegmentType getType() { return jbig2SegSymbolDict; } - Guint getSize() { return size; } - void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; } - JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; } - void setGenericRegionStats(JArithmeticDecoderStats *stats) - { genericRegionStats = stats; } - void setRefinementRegionStats(JArithmeticDecoderStats *stats) - { refinementRegionStats = stats; } - JArithmeticDecoderStats *getGenericRegionStats() - { return genericRegionStats; } - JArithmeticDecoderStats *getRefinementRegionStats() - { return refinementRegionStats; } - -private: - - Guint size; - JBIG2Bitmap **bitmaps; - JArithmeticDecoderStats *genericRegionStats; - JArithmeticDecoderStats *refinementRegionStats; -}; - -JBIG2SymbolDict::JBIG2SymbolDict(Guint segNumA, Guint sizeA): - JBIG2Segment(segNumA) -{ - size = sizeA; - bitmaps = (JBIG2Bitmap **)gmallocn(size, sizeof(JBIG2Bitmap *)); - genericRegionStats = NULL; - refinementRegionStats = NULL; -} - -JBIG2SymbolDict::~JBIG2SymbolDict() { - Guint i; - - for (i = 0; i < size; ++i) { - delete bitmaps[i]; - } - gfree(bitmaps); - if (genericRegionStats) { - delete genericRegionStats; - } - if (refinementRegionStats) { - delete refinementRegionStats; - } -} - -//------------------------------------------------------------------------ -// JBIG2PatternDict -//------------------------------------------------------------------------ - -class JBIG2PatternDict: public JBIG2Segment { -public: - - JBIG2PatternDict(Guint segNumA, Guint sizeA); - virtual ~JBIG2PatternDict(); - virtual JBIG2SegmentType getType() { return jbig2SegPatternDict; } - Guint getSize() { return size; } - void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; } - JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; } - -private: - - Guint size; - JBIG2Bitmap **bitmaps; -}; - -JBIG2PatternDict::JBIG2PatternDict(Guint segNumA, Guint sizeA): - JBIG2Segment(segNumA) -{ - size = sizeA; - bitmaps = (JBIG2Bitmap **)gmallocn(size, sizeof(JBIG2Bitmap *)); -} - -JBIG2PatternDict::~JBIG2PatternDict() { - Guint i; - - for (i = 0; i < size; ++i) { - delete bitmaps[i]; - } - gfree(bitmaps); -} - -//------------------------------------------------------------------------ -// JBIG2CodeTable -//------------------------------------------------------------------------ - -class JBIG2CodeTable: public JBIG2Segment { -public: - - JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA); - virtual ~JBIG2CodeTable(); - virtual JBIG2SegmentType getType() { return jbig2SegCodeTable; } - JBIG2HuffmanTable *getHuffTable() { return table; } - -private: - - JBIG2HuffmanTable *table; -}; - -JBIG2CodeTable::JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA): - JBIG2Segment(segNumA) -{ - table = tableA; -} - -JBIG2CodeTable::~JBIG2CodeTable() { - gfree(table); -} - -//------------------------------------------------------------------------ -// JBIG2Stream -//------------------------------------------------------------------------ - -JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStream): - FilterStream(strA) -{ - pageBitmap = NULL; - - 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 = globalSegments = new GList(); - if (globalsStream->isStream()) { - curStr = globalsStream->getStream(); - curStr->reset(); - arithDecoder->setStream(curStr); - huffDecoder->setStream(curStr); - mmrDecoder->setStream(curStr); - readSegments(); - } - - segments = NULL; - curStr = NULL; - dataPtr = dataEnd = NULL; -} - -JBIG2Stream::~JBIG2Stream() { - delete arithDecoder; - delete genericRegionStats; - delete refinementRegionStats; - delete iadhStats; - delete iadwStats; - delete iaexStats; - delete iaaiStats; - delete iadtStats; - delete iaitStats; - delete iafsStats; - delete iadsStats; - delete iardxStats; - delete iardyStats; - delete iardwStats; - delete iardhStats; - delete iariStats; - delete iaidStats; - delete huffDecoder; - delete mmrDecoder; - if (pageBitmap) { - delete pageBitmap; - } - if (segments) { - deleteGList(segments, JBIG2Segment); - } - if (globalSegments) { - deleteGList(globalSegments, JBIG2Segment); - } - delete str; -} - -void JBIG2Stream::reset() { - if (pageBitmap) { - delete pageBitmap; - pageBitmap = NULL; - } - if (segments) { - deleteGList(segments, JBIG2Segment); - } - segments = new GList(); - - curStr = str; - curStr->reset(); - arithDecoder->setStream(curStr); - huffDecoder->setStream(curStr); - mmrDecoder->setStream(curStr); - readSegments(); - - if (pageBitmap) { - dataPtr = pageBitmap->getDataPtr(); - dataEnd = dataPtr + pageBitmap->getDataSize(); - } else { - dataPtr = NULL; - } -} - -int JBIG2Stream::getChar() { - if (dataPtr && dataPtr < dataEnd) { - return (*dataPtr++ ^ 0xff) & 0xff; - } - return EOF; -} - -int JBIG2Stream::lookChar() { - if (dataPtr && dataPtr < dataEnd) { - return (*dataPtr ^ 0xff) & 0xff; - } - return EOF; -} - -GString *JBIG2Stream::getPSFilter(int psLevel, char *indent) { - return NULL; -} - -GBool JBIG2Stream::isBinary(GBool last) { - return str->isBinary(gTrue); -} - -void JBIG2Stream::readSegments() { - Guint segNum, segFlags, segType, page, segLength; - Guint refFlags, nRefSegs; - Guint *refSegs; - int c1, c2, c3; - Guint i; - - while (readULong(&segNum)) { - - // segment header flags - if (!readUByte(&segFlags)) { - goto eofError1; - } - segType = segFlags & 0x3f; - - // referred-to segment count and retention flags - if (!readUByte(&refFlags)) { - goto eofError1; - } - nRefSegs = refFlags >> 5; - if (nRefSegs == 7) { - if ((c1 = curStr->getChar()) == EOF || - (c2 = curStr->getChar()) == EOF || - (c3 = curStr->getChar()) == EOF) { - goto eofError1; - } - refFlags = (refFlags << 24) | (c1 << 16) | (c2 << 8) | c3; - nRefSegs = refFlags & 0x1fffffff; - for (i = 0; i < (nRefSegs + 9) >> 3; ++i) { - c1 = curStr->getChar(); - } - } - - // referred-to segment numbers - refSegs = (Guint *)gmallocn(nRefSegs, sizeof(Guint)); - if (segNum <= 256) { - for (i = 0; i < nRefSegs; ++i) { - if (!readUByte(&refSegs[i])) { - goto eofError2; - } - } - } else if (segNum <= 65536) { - for (i = 0; i < nRefSegs; ++i) { - if (!readUWord(&refSegs[i])) { - goto eofError2; - } - } - } else { - for (i = 0; i < nRefSegs; ++i) { - if (!readULong(&refSegs[i])) { - goto eofError2; - } - } - } - - // segment page association - if (segFlags & 0x40) { - if (!readULong(&page)) { - goto eofError2; - } - } else { - if (!readUByte(&page)) { - goto eofError2; - } - } - - // segment data length - if (!readULong(&segLength)) { - goto eofError2; - } - - // read the segment data - switch (segType) { - case 0: - if (!readSymbolDictSeg(segNum, segLength, refSegs, nRefSegs)) { - goto syntaxError; - } - break; - case 4: - readTextRegionSeg(segNum, gFalse, gFalse, segLength, refSegs, nRefSegs); - break; - case 6: - readTextRegionSeg(segNum, gTrue, gFalse, segLength, refSegs, nRefSegs); - break; - case 7: - readTextRegionSeg(segNum, gTrue, gTrue, segLength, refSegs, nRefSegs); - break; - case 16: - readPatternDictSeg(segNum, segLength); - break; - case 20: - readHalftoneRegionSeg(segNum, gFalse, gFalse, segLength, - refSegs, nRefSegs); - break; - case 22: - readHalftoneRegionSeg(segNum, gTrue, gFalse, segLength, - refSegs, nRefSegs); - break; - case 23: - readHalftoneRegionSeg(segNum, gTrue, gTrue, segLength, - refSegs, nRefSegs); - break; - case 36: - readGenericRegionSeg(segNum, gFalse, gFalse, segLength); - break; - case 38: - readGenericRegionSeg(segNum, gTrue, gFalse, segLength); - break; - case 39: - readGenericRegionSeg(segNum, gTrue, gTrue, segLength); - break; - case 40: - readGenericRefinementRegionSeg(segNum, gFalse, gFalse, segLength, - refSegs, nRefSegs); - break; - case 42: - readGenericRefinementRegionSeg(segNum, gTrue, gFalse, segLength, - refSegs, nRefSegs); - break; - case 43: - readGenericRefinementRegionSeg(segNum, gTrue, gTrue, segLength, - refSegs, nRefSegs); - break; - case 48: - readPageInfoSeg(segLength); - break; - case 50: - readEndOfStripeSeg(segLength); - break; - case 52: - readProfilesSeg(segLength); - break; - case 53: - readCodeTableSeg(segNum, segLength); - break; - case 62: - readExtensionSeg(segLength); - break; - default: - error(getPos(), "Unknown segment type in JBIG2 stream"); - for (i = 0; i < segLength; ++i) { - if ((c1 = curStr->getChar()) == EOF) { - goto eofError2; - } - } - break; - } - - gfree(refSegs); - } - - return; - - syntaxError: - gfree(refSegs); - return; - - eofError2: - gfree(refSegs); - eofError1: - error(getPos(), "Unexpected EOF in JBIG2 stream"); -} - -GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length, - Guint *refSegs, Guint nRefSegs) { - JBIG2SymbolDict *symbolDict; - JBIG2HuffmanTable *huffDHTable, *huffDWTable; - JBIG2HuffmanTable *huffBMSizeTable, *huffAggInstTable; - JBIG2Segment *seg; - GList *codeTables; - JBIG2SymbolDict *inputSymbolDict; - Guint flags, sdTemplate, sdrTemplate, huff, refAgg; - Guint huffDH, huffDW, huffBMSize, huffAggInst; - Guint contextUsed, contextRetained; - int sdATX[4], sdATY[4], sdrATX[2], sdrATY[2]; - Guint numExSyms, numNewSyms, numInputSyms, symCodeLen; - JBIG2Bitmap **bitmaps; - JBIG2Bitmap *collBitmap, *refBitmap; - Guint *symWidths; - Guint symHeight, symWidth, totalWidth, x, symID; - int dh, dw, refAggNum, refDX, refDY, bmSize; - GBool ex; - int run, cnt; - Guint i, j, k; - Guchar *p; - - // symbol dictionary flags - if (!readUWord(&flags)) { - goto eofError; - } - sdTemplate = (flags >> 10) & 3; - sdrTemplate = (flags >> 12) & 1; - huff = flags & 1; - refAgg = (flags >> 1) & 1; - huffDH = (flags >> 2) & 3; - huffDW = (flags >> 4) & 3; - huffBMSize = (flags >> 6) & 1; - huffAggInst = (flags >> 7) & 1; - contextUsed = (flags >> 8) & 1; - contextRetained = (flags >> 9) & 1; - - // symbol dictionary AT flags - if (!huff) { - if (sdTemplate == 0) { - if (!readByte(&sdATX[0]) || - !readByte(&sdATY[0]) || - !readByte(&sdATX[1]) || - !readByte(&sdATY[1]) || - !readByte(&sdATX[2]) || - !readByte(&sdATY[2]) || - !readByte(&sdATX[3]) || - !readByte(&sdATY[3])) { - goto eofError; - } - } else { - if (!readByte(&sdATX[0]) || - !readByte(&sdATY[0])) { - goto eofError; - } - } - } - - // symbol dictionary refinement AT flags - if (refAgg && !sdrTemplate) { - if (!readByte(&sdrATX[0]) || - !readByte(&sdrATY[0]) || - !readByte(&sdrATX[1]) || - !readByte(&sdrATY[1])) { - goto eofError; - } - } - - // SDNUMEXSYMS and SDNUMNEWSYMS - if (!readULong(&numExSyms) || !readULong(&numNewSyms)) { - goto eofError; - } - - // get referenced segments: input symbol dictionaries and code tables - codeTables = new GList(); - numInputSyms = 0; - for (i = 0; i < nRefSegs; ++i) { - seg = findSegment(refSegs[i]); - if (seg->getType() == jbig2SegSymbolDict) { - numInputSyms += ((JBIG2SymbolDict *)seg)->getSize(); - } else if (seg->getType() == jbig2SegCodeTable) { - codeTables->append(seg); - } - } - - // compute symbol code length - symCodeLen = 0; - i = 1; - while (i < numInputSyms + numNewSyms) { - ++symCodeLen; - i <<= 1; - } - - // get the input symbol bitmaps - bitmaps = (JBIG2Bitmap **)gmallocn(numInputSyms + numNewSyms, - sizeof(JBIG2Bitmap *)); - for (i = 0; i < numInputSyms + numNewSyms; ++i) { - bitmaps[i] = NULL; - } - k = 0; - inputSymbolDict = NULL; - for (i = 0; i < nRefSegs; ++i) { - seg = findSegment(refSegs[i]); - if (seg->getType() == jbig2SegSymbolDict) { - inputSymbolDict = (JBIG2SymbolDict *)seg; - for (j = 0; j < inputSymbolDict->getSize(); ++j) { - bitmaps[k++] = inputSymbolDict->getBitmap(j); - } - } - } - - // get the Huffman tables - huffDHTable = huffDWTable = NULL; // make gcc happy - huffBMSizeTable = huffAggInstTable = NULL; // make gcc happy - i = 0; - if (huff) { - if (huffDH == 0) { - huffDHTable = huffTableD; - } else if (huffDH == 1) { - huffDHTable = huffTableE; - } else { - huffDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffDW == 0) { - huffDWTable = huffTableB; - } else if (huffDW == 1) { - huffDWTable = huffTableC; - } else { - huffDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffBMSize == 0) { - huffBMSizeTable = huffTableA; - } else { - huffBMSizeTable = - ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffAggInst == 0) { - huffAggInstTable = huffTableA; - } else { - huffAggInstTable = - ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - } - delete codeTables; - - // set up the Huffman decoder - if (huff) { - huffDecoder->reset(); - - // set up the arithmetic decoder - } else { - if (contextUsed && inputSymbolDict) { - resetGenericStats(sdTemplate, inputSymbolDict->getGenericRegionStats()); - } else { - resetGenericStats(sdTemplate, 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) { - symWidths = (Guint *)gmallocn(numNewSyms, sizeof(Guint)); - } - - symHeight = 0; - i = 0; - while (i < numNewSyms) { - - // read the height class delta height - if (huff) { - huffDecoder->decodeInt(&dh, huffDHTable); - } else { - arithDecoder->decodeInt(&dh, iadhStats); - } - if (dh < 0 && (Guint)-dh >= symHeight) { - error(getPos(), "Bad delta-height value in JBIG2 symbol dictionary"); - goto syntaxError; - } - symHeight += dh; - symWidth = 0; - totalWidth = 0; - j = i; - - // read the symbols in this height class - while (1) { - - // read the delta width - if (huff) { - if (!huffDecoder->decodeInt(&dw, huffDWTable)) { - break; - } - } else { - if (!arithDecoder->decodeInt(&dw, iadwStats)) { - break; - } - } - if (dw < 0 && (Guint)-dw >= symWidth) { - error(getPos(), "Bad delta-height value in JBIG2 symbol dictionary"); - goto syntaxError; - } - symWidth += dw; - - // using a collective bitmap, so don't read a bitmap here - if (huff && !refAgg) { - symWidths[i] = symWidth; - totalWidth += symWidth; - - // refinement/aggregate coding - } else if (refAgg) { - if (huff) { - if (!huffDecoder->decodeInt(&refAggNum, huffAggInstTable)) { - break; - } - } else { - if (!arithDecoder->decodeInt(&refAggNum, iaaiStats)) { - 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); - huffDecoder->decodeInt(&refDY, huffTableO); - huffDecoder->decodeInt(&bmSize, huffTableA); - huffDecoder->reset(); - arithDecoder->start(); - } else { - symID = arithDecoder->decodeIAID(symCodeLen, iaidStats); - arithDecoder->decodeInt(&refDX, iardxStats); - arithDecoder->decodeInt(&refDY, iardyStats); - } - refBitmap = bitmaps[symID]; - bitmaps[numInputSyms + i] = - readGenericRefinementRegion(symWidth, symHeight, - sdrTemplate, gFalse, - refBitmap, refDX, refDY, - sdrATX, sdrATY); - //~ do we need to use the bmSize value here (in Huffman mode)? - } else { - bitmaps[numInputSyms + i] = - readTextRegion(huff, gTrue, symWidth, symHeight, - refAggNum, 0, numInputSyms + i, NULL, - symCodeLen, bitmaps, 0, 0, 0, 1, 0, - huffTableF, huffTableH, huffTableK, huffTableO, - huffTableO, huffTableO, huffTableO, huffTableA, - sdrTemplate, sdrATX, sdrATY); - } - - // non-ref/agg coding - } else { - bitmaps[numInputSyms + i] = - readGenericBitmap(gFalse, symWidth, symHeight, - sdTemplate, gFalse, gFalse, NULL, - sdATX, sdATY, 0); - } - - ++i; - } - - // read the collective bitmap - if (huff && !refAgg) { - huffDecoder->decodeInt(&bmSize, huffBMSizeTable); - 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++ = curStr->getChar(); - } - } else { - collBitmap = readGenericBitmap(gTrue, totalWidth, symHeight, - 0, gFalse, gFalse, NULL, NULL, NULL, - bmSize); - } - x = 0; - for (; j < i; ++j) { - bitmaps[numInputSyms + j] = - collBitmap->getSlice(x, 0, symWidths[j], symHeight); - x += symWidths[j]; - } - delete collBitmap; - } - } - - // create the symbol dict object - symbolDict = new JBIG2SymbolDict(segNum, numExSyms); - - // exported symbol list - i = j = 0; - ex = gFalse; - while (i < numInputSyms + numNewSyms) { - if (huff) { - huffDecoder->decodeInt(&run, huffTableA); - } else { - arithDecoder->decodeInt(&run, iaexStats); - } - if (ex) { - for (cnt = 0; cnt < run; ++cnt) { - symbolDict->setBitmap(j++, bitmaps[i++]->copy()); - } - } else { - i += run; - } - ex = !ex; - } - - for (i = 0; i < numNewSyms; ++i) { - delete bitmaps[numInputSyms + i]; - } - gfree(bitmaps); - if (symWidths) { - gfree(symWidths); - } - - // save the arithmetic decoder stats - if (!huff && contextRetained) { - symbolDict->setGenericRegionStats(genericRegionStats->copy()); - if (refAgg) { - symbolDict->setRefinementRegionStats(refinementRegionStats->copy()); - } - } - - // store the new symbol dict - segments->append(symbolDict); - - return gTrue; - - syntaxError: - for (i = 0; i < numNewSyms; ++i) { - if (bitmaps[numInputSyms + i]) { - delete bitmaps[numInputSyms + i]; - } - } - gfree(bitmaps); - if (symWidths) { - gfree(symWidths); - } - return gFalse; - - eofError: - error(getPos(), "Unexpected EOF in JBIG2 stream"); - return gFalse; -} - -void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm, - GBool lossless, Guint length, - Guint *refSegs, Guint nRefSegs) { - JBIG2Bitmap *bitmap; - JBIG2HuffmanTable runLengthTab[36]; - JBIG2HuffmanTable *symCodeTab; - JBIG2HuffmanTable *huffFSTable, *huffDSTable, *huffDTTable; - JBIG2HuffmanTable *huffRDWTable, *huffRDHTable; - JBIG2HuffmanTable *huffRDXTable, *huffRDYTable, *huffRSizeTable; - JBIG2Segment *seg; - GList *codeTables; - JBIG2SymbolDict *symbolDict; - JBIG2Bitmap **syms; - Guint w, h, x, y, segInfoFlags, extCombOp; - Guint flags, huff, refine, logStrips, refCorner, transposed; - Guint combOp, defPixel, templ; - int sOffset; - Guint huffFlags, huffFS, huffDS, huffDT; - Guint huffRDW, huffRDH, huffRDX, huffRDY, huffRSize; - Guint numInstances, numSyms, symCodeLen; - int atx[2], aty[2]; - Guint i, k, kk; - int j; - - // region segment info field - if (!readULong(&w) || !readULong(&h) || - !readULong(&x) || !readULong(&y) || - !readUByte(&segInfoFlags)) { - goto eofError; - } - extCombOp = segInfoFlags & 7; - - // rest of the text region header - if (!readUWord(&flags)) { - goto eofError; - } - huff = flags & 1; - refine = (flags >> 1) & 1; - logStrips = (flags >> 2) & 3; - refCorner = (flags >> 4) & 3; - transposed = (flags >> 6) & 1; - 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 - if (huff) { - if (!readUWord(&huffFlags)) { - goto eofError; - } - huffFS = huffFlags & 3; - huffDS = (huffFlags >> 2) & 3; - huffDT = (huffFlags >> 4) & 3; - huffRDW = (huffFlags >> 6) & 3; - huffRDH = (huffFlags >> 8) & 3; - huffRDX = (huffFlags >> 10) & 3; - huffRDY = (huffFlags >> 12) & 3; - huffRSize = (huffFlags >> 14) & 1; - } - if (refine && templ == 0) { - if (!readByte(&atx[0]) || !readByte(&aty[0]) || - !readByte(&atx[1]) || !readByte(&aty[1])) { - goto eofError; - } - } - if (!readULong(&numInstances)) { - goto eofError; - } - - // get symbol dictionaries and tables - codeTables = new GList(); - numSyms = 0; - for (i = 0; i < nRefSegs; ++i) { - if ((seg = findSegment(refSegs[i]))) { - if (seg->getType() == jbig2SegSymbolDict) { - numSyms += ((JBIG2SymbolDict *)seg)->getSize(); - } else if (seg->getType() == jbig2SegCodeTable) { - codeTables->append(seg); - } - } else { - error(getPos(), "Invalid segment reference in JBIG2 text region"); - } - } - symCodeLen = 0; - i = 1; - while (i < numSyms) { - ++symCodeLen; - i <<= 1; - } - - // get the symbol bitmaps - syms = (JBIG2Bitmap **)gmallocn(numSyms, sizeof(JBIG2Bitmap *)); - kk = 0; - for (i = 0; i < nRefSegs; ++i) { - if ((seg = findSegment(refSegs[i]))) { - if (seg->getType() == jbig2SegSymbolDict) { - symbolDict = (JBIG2SymbolDict *)seg; - for (k = 0; k < symbolDict->getSize(); ++k) { - syms[kk++] = symbolDict->getBitmap(k); - } - } - } - } - - // get the Huffman tables - huffFSTable = huffDSTable = huffDTTable = NULL; // make gcc happy - huffRDWTable = huffRDHTable = NULL; // make gcc happy - huffRDXTable = huffRDYTable = huffRSizeTable = NULL; // make gcc happy - i = 0; - if (huff) { - if (huffFS == 0) { - huffFSTable = huffTableF; - } else if (huffFS == 1) { - huffFSTable = huffTableG; - } else { - huffFSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffDS == 0) { - huffDSTable = huffTableH; - } else if (huffDS == 1) { - huffDSTable = huffTableI; - } else if (huffDS == 2) { - huffDSTable = huffTableJ; - } else { - huffDSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffDT == 0) { - huffDTTable = huffTableK; - } else if (huffDT == 1) { - huffDTTable = huffTableL; - } else if (huffDT == 2) { - huffDTTable = huffTableM; - } else { - huffDTTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffRDW == 0) { - huffRDWTable = huffTableN; - } else if (huffRDW == 1) { - huffRDWTable = huffTableO; - } else { - huffRDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffRDH == 0) { - huffRDHTable = huffTableN; - } else if (huffRDH == 1) { - huffRDHTable = huffTableO; - } else { - huffRDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffRDX == 0) { - huffRDXTable = huffTableN; - } else if (huffRDX == 1) { - huffRDXTable = huffTableO; - } else { - huffRDXTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffRDY == 0) { - huffRDYTable = huffTableN; - } else if (huffRDY == 1) { - huffRDYTable = huffTableO; - } else { - huffRDYTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffRSize == 0) { - huffRSizeTable = huffTableA; - } else { - huffRSizeTable = - ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - } - delete codeTables; - - // symbol ID Huffman decoding table - if (huff) { - huffDecoder->reset(); - for (i = 0; i < 32; ++i) { - runLengthTab[i].val = i; - runLengthTab[i].prefixLen = huffDecoder->readBits(4); - runLengthTab[i].rangeLen = 0; - } - runLengthTab[32].val = 0x103; - runLengthTab[32].prefixLen = huffDecoder->readBits(4); - runLengthTab[32].rangeLen = 2; - runLengthTab[33].val = 0x203; - runLengthTab[33].prefixLen = huffDecoder->readBits(4); - runLengthTab[33].rangeLen = 3; - 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 *)gmallocn(numSyms + 1, - sizeof(JBIG2HuffmanTable)); - for (i = 0; i < numSyms; ++i) { - symCodeTab[i].val = i; - symCodeTab[i].rangeLen = 0; - } - i = 0; - while (i < numSyms) { - huffDecoder->decodeInt(&j, runLengthTab); - if (j > 0x200) { - for (j -= 0x200; j && i < numSyms; --j) { - symCodeTab[i++].prefixLen = 0; - } - } else if (j > 0x100) { - for (j -= 0x100; j && i < numSyms; --j) { - symCodeTab[i].prefixLen = symCodeTab[i-1].prefixLen; - ++i; - } - } else { - symCodeTab[i++].prefixLen = j; - } - } - symCodeTab[numSyms].prefixLen = 0; - symCodeTab[numSyms].rangeLen = jbig2HuffmanEOT; - huffDecoder->buildTable(symCodeTab, numSyms); - huffDecoder->reset(); - - // set up the arithmetic decoder - } else { - symCodeTab = NULL; - resetIntStats(symCodeLen); - arithDecoder->start(); - } - if (refine) { - resetRefinementStats(templ, NULL); - } - - bitmap = readTextRegion(huff, refine, w, h, numInstances, - logStrips, numSyms, symCodeTab, symCodeLen, syms, - defPixel, combOp, transposed, refCorner, sOffset, - huffFSTable, huffDSTable, huffDTTable, - huffRDWTable, huffRDHTable, - huffRDXTable, huffRDYTable, huffRSizeTable, - templ, atx, aty); - - gfree(syms); - - // combine the region bitmap into the page bitmap - if (imm) { - if (pageH == 0xffffffff && y + h > curPageH) { - pageBitmap->expand(y + h, pageDefPixel); - } - pageBitmap->combine(bitmap, x, y, extCombOp); - delete bitmap; - - // store the region bitmap - } else { - bitmap->setSegNum(segNum); - segments->append(bitmap); - } - - // clean up the Huffman decoder - if (huff) { - gfree(symCodeTab); - } - - return; - - eofError: - error(getPos(), "Unexpected EOF in JBIG2 stream"); -} - -JBIG2Bitmap *JBIG2Stream::readTextRegion(GBool huff, GBool refine, - int w, int h, - Guint numInstances, - Guint logStrips, - int numSyms, - JBIG2HuffmanTable *symCodeTab, - Guint symCodeLen, - JBIG2Bitmap **syms, - Guint defPixel, Guint combOp, - Guint transposed, Guint refCorner, - int sOffset, - JBIG2HuffmanTable *huffFSTable, - JBIG2HuffmanTable *huffDSTable, - JBIG2HuffmanTable *huffDTTable, - JBIG2HuffmanTable *huffRDWTable, - JBIG2HuffmanTable *huffRDHTable, - JBIG2HuffmanTable *huffRDXTable, - JBIG2HuffmanTable *huffRDYTable, - JBIG2HuffmanTable *huffRSizeTable, - Guint templ, - int *atx, int *aty) { - JBIG2Bitmap *bitmap; - JBIG2Bitmap *symbolBitmap; - Guint strips; - int t, dt, tt, s, ds, sFirst, j; - int rdw, rdh, rdx, rdy, ri, refDX, refDY, bmSize; - Guint symID, inst, bw, bh; - - strips = 1 << logStrips; - - // allocate the bitmap - bitmap = new JBIG2Bitmap(0, w, h); - if (defPixel) { - bitmap->clearToOne(); - } else { - bitmap->clearToZero(); - } - - // decode initial T value - if (huff) { - huffDecoder->decodeInt(&t, huffDTTable); - } else { - arithDecoder->decodeInt(&t, iadtStats); - } - t *= -(int)strips; - - inst = 0; - sFirst = 0; - while (inst < numInstances) { - - // decode delta-T - if (huff) { - huffDecoder->decodeInt(&dt, huffDTTable); - } else { - arithDecoder->decodeInt(&dt, iadtStats); - } - t += dt * strips; - - // first S value - if (huff) { - huffDecoder->decodeInt(&ds, huffFSTable); - } else { - arithDecoder->decodeInt(&ds, iafsStats); - } - sFirst += ds; - s = sFirst; - - // read the instances - while (1) { - - // T value - if (strips == 1) { - dt = 0; - } else if (huff) { - dt = huffDecoder->readBits(logStrips); - } else { - arithDecoder->decodeInt(&dt, iaitStats); - } - tt = t + dt; - - // symbol ID - if (huff) { - if (symCodeTab) { - huffDecoder->decodeInt(&j, symCodeTab); - symID = (Guint)j; - } else { - symID = huffDecoder->readBits(symCodeLen); - } - } else { - symID = arithDecoder->decodeIAID(symCodeLen, iaidStats); - } - - if (symID >= (Guint)numSyms) { - error(getPos(), "Invalid symbol number in JBIG2 text region"); - } else { - - // get the symbol bitmap - symbolBitmap = NULL; - if (refine) { - if (huff) { - ri = (int)huffDecoder->readBit(); - } else { - arithDecoder->decodeInt(&ri, iariStats); - } - } else { - ri = 0; - } - if (ri) { - if (huff) { - huffDecoder->decodeInt(&rdw, huffRDWTable); - huffDecoder->decodeInt(&rdh, huffRDHTable); - huffDecoder->decodeInt(&rdx, huffRDXTable); - huffDecoder->decodeInt(&rdy, huffRDYTable); - huffDecoder->decodeInt(&bmSize, huffRSizeTable); - huffDecoder->reset(); - arithDecoder->start(); - } else { - arithDecoder->decodeInt(&rdw, iardwStats); - arithDecoder->decodeInt(&rdh, iardhStats); - arithDecoder->decodeInt(&rdx, iardxStats); - arithDecoder->decodeInt(&rdy, iardyStats); - } - refDX = ((rdw >= 0) ? rdw : rdw - 1) / 2 + rdx; - refDY = ((rdh >= 0) ? rdh : rdh - 1) / 2 + rdy; - - symbolBitmap = - readGenericRefinementRegion(rdw + syms[symID]->getWidth(), - rdh + syms[symID]->getHeight(), - templ, gFalse, syms[symID], - refDX, refDY, atx, aty); - //~ do we need to use the bmSize value here (in Huffman mode)? - } else { - symbolBitmap = syms[symID]; - } - - // combine the symbol bitmap into the region bitmap - //~ something is wrong here - refCorner shouldn't degenerate into - //~ two cases - bw = symbolBitmap->getWidth() - 1; - bh = symbolBitmap->getHeight() - 1; - if (transposed) { - switch (refCorner) { - case 0: // bottom left - bitmap->combine(symbolBitmap, tt, s, combOp); - break; - case 1: // top left - bitmap->combine(symbolBitmap, tt, s, combOp); - break; - case 2: // bottom right - bitmap->combine(symbolBitmap, tt - bw, s, combOp); - break; - case 3: // top right - bitmap->combine(symbolBitmap, tt - bw, s, combOp); - break; - } - s += bh; - } else { - switch (refCorner) { - case 0: // bottom left - bitmap->combine(symbolBitmap, s, tt - bh, combOp); - break; - case 1: // top left - bitmap->combine(symbolBitmap, s, tt, combOp); - break; - case 2: // bottom right - bitmap->combine(symbolBitmap, s, tt - bh, combOp); - break; - case 3: // top right - bitmap->combine(symbolBitmap, s, tt, combOp); - break; - } - s += bw; - } - if (ri) { - delete symbolBitmap; - } - } - - // next instance - ++inst; - - // next S value - if (huff) { - if (!huffDecoder->decodeInt(&ds, huffDSTable)) { - break; - } - } else { - if (!arithDecoder->decodeInt(&ds, iadsStats)) { - break; - } - } - s += sOffset + ds; - } - } - - return bitmap; -} - -void JBIG2Stream::readPatternDictSeg(Guint segNum, Guint length) { - JBIG2PatternDict *patternDict; - JBIG2Bitmap *bitmap; - Guint flags, patternW, patternH, grayMax, templ, mmr; - int atx[4], aty[4]; - Guint i, x; - - // halftone dictionary flags, pattern width and height, max gray value - if (!readUByte(&flags) || - !readUByte(&patternW) || - !readUByte(&patternH) || - !readULong(&grayMax)) { - goto eofError; - } - templ = (flags >> 1) & 3; - mmr = flags & 1; - - // set up the arithmetic decoder - if (!mmr) { - resetGenericStats(templ, NULL); - arithDecoder->start(); - } - - // read the bitmap - 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); - - // create the pattern dict object - patternDict = new JBIG2PatternDict(segNum, grayMax + 1); - - // split up the bitmap - x = 0; - for (i = 0; i <= grayMax; ++i) { - patternDict->setBitmap(i, bitmap->getSlice(x, 0, patternW, patternH)); - x += patternW; - } - - // free memory - delete bitmap; - - // store the new pattern dict - segments->append(patternDict); - - return; - - eofError: - error(getPos(), "Unexpected EOF in JBIG2 stream"); -} - -void JBIG2Stream::readHalftoneRegionSeg(Guint segNum, GBool imm, - GBool lossless, Guint length, - Guint *refSegs, Guint nRefSegs) { - JBIG2Bitmap *bitmap; - JBIG2Segment *seg; - JBIG2PatternDict *patternDict; - JBIG2Bitmap *skipBitmap; - Guint *grayImg; - JBIG2Bitmap *grayBitmap; - JBIG2Bitmap *patternBitmap; - Guint w, h, x, y, segInfoFlags, extCombOp; - Guint flags, mmr, templ, enableSkip, combOp; - Guint gridW, gridH, stepX, stepY, patW, patH; - int atx[4], aty[4]; - int gridX, gridY, xx, yy, bit, j; - Guint bpp, m, n, i; - - // region segment info field - if (!readULong(&w) || !readULong(&h) || - !readULong(&x) || !readULong(&y) || - !readUByte(&segInfoFlags)) { - goto eofError; - } - extCombOp = segInfoFlags & 7; - - // rest of the halftone region header - if (!readUByte(&flags)) { - goto eofError; - } - mmr = flags & 1; - templ = (flags >> 1) & 3; - enableSkip = (flags >> 3) & 1; - combOp = (flags >> 4) & 7; - if (!readULong(&gridW) || !readULong(&gridH) || - !readLong(&gridX) || !readLong(&gridY) || - !readUWord(&stepX) || !readUWord(&stepY)) { - goto eofError; - } - - // get pattern dictionary - if (nRefSegs != 1) { - error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment"); - return; - } - seg = findSegment(refSegs[0]); - if (seg->getType() != jbig2SegPatternDict) { - error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment"); - return; - } - patternDict = (JBIG2PatternDict *)seg; - bpp = 0; - i = 1; - while (i < patternDict->getSize()) { - ++bpp; - i <<= 1; - } - patW = patternDict->getBitmap(0)->getWidth(); - patH = patternDict->getBitmap(0)->getHeight(); - - // set up the arithmetic decoder - if (!mmr) { - resetGenericStats(templ, NULL); - arithDecoder->start(); - } - - // allocate the bitmap - bitmap = new JBIG2Bitmap(segNum, w, h); - if (flags & 0x80) { // HDEFPIXEL - bitmap->clearToOne(); - } else { - bitmap->clearToZero(); - } - - // compute the skip bitmap - skipBitmap = NULL; - if (enableSkip) { - skipBitmap = new JBIG2Bitmap(0, gridW, gridH); - skipBitmap->clearToZero(); - for (m = 0; m < gridH; ++m) { - xx = gridX + m * stepY; - yy = gridY + m * stepX; - for (n = 0; n < gridW; ++n) { - if (((xx + (int)patW) >> 8) <= 0 || (xx >> 8) >= (int)w || - ((yy + (int)patH) >> 8) <= 0 || (yy >> 8) >= (int)h) { - skipBitmap->setPixel(n, m); - } - } - } - } - - // read the gray-scale image - grayImg = (Guint *)gmallocn(gridW * gridH, sizeof(Guint)); - memset(grayImg, 0, gridW * gridH * sizeof(Guint)); - atx[0] = templ <= 1 ? 3 : 2; aty[0] = -1; - atx[1] = -3; aty[1] = -1; - atx[2] = 2; aty[2] = -2; - atx[3] = -2; aty[3] = -2; - for (j = bpp - 1; j >= 0; --j) { - grayBitmap = readGenericBitmap(mmr, gridW, gridH, templ, gFalse, - enableSkip, skipBitmap, atx, aty, -1); - i = 0; - for (m = 0; m < gridH; ++m) { - for (n = 0; n < gridW; ++n) { - bit = grayBitmap->getPixel(n, m) ^ (grayImg[i] & 1); - grayImg[i] = (grayImg[i] << 1) | bit; - ++i; - } - } - delete grayBitmap; - } - - // decode the image - i = 0; - for (m = 0; m < gridH; ++m) { - xx = gridX + m * stepY; - yy = gridY + m * stepX; - for (n = 0; n < gridW; ++n) { - if (!(enableSkip && skipBitmap->getPixel(n, m))) { - patternBitmap = patternDict->getBitmap(grayImg[i]); - bitmap->combine(patternBitmap, xx >> 8, yy >> 8, combOp); - } - xx += stepX; - yy -= stepY; - ++i; - } - } - - gfree(grayImg); - - // combine the region bitmap into the page bitmap - if (imm) { - if (pageH == 0xffffffff && y + h > curPageH) { - pageBitmap->expand(y + h, pageDefPixel); - } - pageBitmap->combine(bitmap, x, y, extCombOp); - delete bitmap; - - // store the region bitmap - } else { - segments->append(bitmap); - } - - return; - - eofError: - error(getPos(), "Unexpected EOF in JBIG2 stream"); -} - -void JBIG2Stream::readGenericRegionSeg(Guint segNum, GBool imm, - GBool lossless, Guint length) { - JBIG2Bitmap *bitmap; - Guint w, h, x, y, segInfoFlags, extCombOp; - Guint flags, mmr, templ, tpgdOn; - int atx[4], aty[4]; - - // region segment info field - if (!readULong(&w) || !readULong(&h) || - !readULong(&x) || !readULong(&y) || - !readUByte(&segInfoFlags)) { - goto eofError; - } - extCombOp = segInfoFlags & 7; - - // rest of the generic region segment header - if (!readUByte(&flags)) { - goto eofError; - } - mmr = flags & 1; - templ = (flags >> 1) & 3; - tpgdOn = (flags >> 3) & 1; - - // AT flags - if (!mmr) { - if (templ == 0) { - if (!readByte(&atx[0]) || - !readByte(&aty[0]) || - !readByte(&atx[1]) || - !readByte(&aty[1]) || - !readByte(&atx[2]) || - !readByte(&aty[2]) || - !readByte(&atx[3]) || - !readByte(&aty[3])) { - goto eofError; - } - } else { - if (!readByte(&atx[0]) || - !readByte(&aty[0])) { - goto eofError; - } - } - } - - // set up the arithmetic decoder - if (!mmr) { - resetGenericStats(templ, NULL); - arithDecoder->start(); - } - - // read the bitmap - bitmap = readGenericBitmap(mmr, w, h, templ, tpgdOn, gFalse, - NULL, atx, aty, mmr ? 0 : length - 18); - - // combine the region bitmap into the page bitmap - if (imm) { - if (pageH == 0xffffffff && y + h > curPageH) { - pageBitmap->expand(y + h, pageDefPixel); - } - pageBitmap->combine(bitmap, x, y, extCombOp); - delete bitmap; - - // store the region bitmap - } else { - bitmap->setSegNum(segNum); - segments->append(bitmap); - } - - return; - - eofError: - error(getPos(), "Unexpected EOF in JBIG2 stream"); -} - -JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h, - int templ, GBool tpgdOn, - GBool useSkip, JBIG2Bitmap *skip, - int *atx, int *aty, - int mmrDataLength) { - 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; - - bitmap = new JBIG2Bitmap(0, w, h); - bitmap->clearToZero(); - - //----- MMR decode - - if (mmr) { - - mmrDecoder->reset(); - refLine = (int *)gmallocn(w + 2, sizeof(int)); - codingLine = (int *)gmallocn(w + 2, sizeof(int)); - codingLine[0] = codingLine[1] = w; - - for (y = 0; y < h; ++y) { - - // copy coding line to ref line - for (i = 0; codingLine[i] < w; ++i) { - refLine[i] = codingLine[i]; - } - refLine[i] = refLine[i + 1] = w; - - // decode a line - refI = 0; // b1 = refLine[refI] - codingI = 0; // a1 = codingLine[codingI] - a0 = 0; - do { - code1 = mmrDecoder->get2DCode(); - switch (code1) { - case twoDimPass: - if (refLine[refI] < w) { - a0 = refLine[refI + 1]; - refI += 2; - } - break; - case twoDimHoriz: - if (codingI & 1) { - code1 = 0; - do { - code1 += code3 = mmrDecoder->getBlackCode(); - } while (code3 >= 64); - code2 = 0; - do { - code2 += code3 = mmrDecoder->getWhiteCode(); - } while (code3 >= 64); - } else { - code1 = 0; - do { - code1 += code3 = mmrDecoder->getWhiteCode(); - } while (code3 >= 64); - code2 = 0; - do { - code2 += code3 = mmrDecoder->getBlackCode(); - } while (code3 >= 64); - } - 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: - a0 = codingLine[codingI++] = refLine[refI]; - if (refLine[refI] < w) { - ++refI; - } - break; - case twoDimVertR1: - a0 = codingLine[codingI++] = refLine[refI] + 1; - if (refLine[refI] < w) { - ++refI; - while (refLine[refI] <= a0 && refLine[refI] < w) { - refI += 2; - } - } - break; - case twoDimVertR2: - a0 = codingLine[codingI++] = refLine[refI] + 2; - if (refLine[refI] < w) { - ++refI; - while (refLine[refI] <= a0 && refLine[refI] < w) { - refI += 2; - } - } - break; - case twoDimVertR3: - a0 = codingLine[codingI++] = refLine[refI] + 3; - if (refLine[refI] < w) { - ++refI; - while (refLine[refI] <= a0 && refLine[refI] < w) { - refI += 2; - } - } - break; - case twoDimVertL1: - a0 = codingLine[codingI++] = refLine[refI] - 1; - if (refI > 0) { - --refI; - } else { - ++refI; - } - while (refLine[refI] <= a0 && refLine[refI] < w) { - refI += 2; - } - break; - case twoDimVertL2: - a0 = codingLine[codingI++] = refLine[refI] - 2; - if (refI > 0) { - --refI; - } else { - ++refI; - } - while (refLine[refI] <= a0 && refLine[refI] < w) { - refI += 2; - } - break; - case twoDimVertL3: - a0 = codingLine[codingI++] = refLine[refI] - 3; - if (refI > 0) { - --refI; - } else { - ++refI; - } - while (refLine[refI] <= a0 && refLine[refI] < w) { - refI += 2; - } - break; - default: - error(getPos(), "Illegal code in JBIG2 MMR bitmap data"); - break; - } - } while (a0 < w); - codingLine[codingI++] = w; - - // convert the run lengths to a bitmap line - i = 0; - while (codingLine[i] < w) { - for (x = codingLine[i]; x < codingLine[i+1]; ++x) { - bitmap->setPixel(x, y); - } - i += 2; - } - } - - if (mmrDataLength >= 0) { - mmrDecoder->skipTo(mmrDataLength); - } else { - if (mmrDecoder->get24Bits() != 0x001001) { - error(getPos(), "Missing EOFB in JBIG2 MMR bitmap data"); - } - } - - gfree(refLine); - gfree(codingLine); - - //----- arithmetic decode - - } else { - // set up the typical row context - ltpCX = 0; // make gcc happy - if (tpgdOn) { - switch (templ) { - case 0: - ltpCX = 0x3953; // 001 11001 0101 0011 - break; - case 1: - ltpCX = 0x079a; // 0011 11001 101 0 - break; - case 2: - ltpCX = 0x0e3; // 001 1100 01 1 - break; - case 3: - ltpCX = 0x18a; // 01100 0101 1 - break; - } - } - - ltp = 0; - cx = cx0 = cx1 = cx2 = 0; // make gcc happy - for (y = 0; y < h; ++y) { - - // check for a "typical" (duplicate) row - if (tpgdOn) { - if (arithDecoder->decodeBit(ltpCX, genericRegionStats)) { - ltp = !ltp; - } - if (ltp) { - bitmap->duplicateRow(y, y-1); - continue; - } - } - - switch (templ) { - case 0: - - // 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: - - // 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: - - // 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; - - case 3: - - // 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); - - // decode the row - for (x = 0; x < w; ++x) { - - // build the context - cx = (cx1 << 5) | (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 - cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f; - cx2 = ((cx2 << 1) | pix) & 0x0f; - } - break; - } - } - } - - return bitmap; -} - -void JBIG2Stream::readGenericRefinementRegionSeg(Guint segNum, GBool imm, - GBool lossless, Guint length, - Guint *refSegs, - Guint nRefSegs) { - JBIG2Bitmap *bitmap, *refBitmap; - Guint w, h, x, y, segInfoFlags, extCombOp; - Guint flags, templ, tpgrOn; - int atx[2], aty[2]; - JBIG2Segment *seg; - - // region segment info field - if (!readULong(&w) || !readULong(&h) || - !readULong(&x) || !readULong(&y) || - !readUByte(&segInfoFlags)) { - goto eofError; - } - extCombOp = segInfoFlags & 7; - - // rest of the generic refinement region segment header - if (!readUByte(&flags)) { - goto eofError; - } - templ = flags & 1; - tpgrOn = (flags >> 1) & 1; - - // AT flags - if (!templ) { - if (!readByte(&atx[0]) || !readByte(&aty[0]) || - !readByte(&atx[1]) || !readByte(&aty[1])) { - goto eofError; - } - } - - // resize the page bitmap if needed - if (nRefSegs == 0 || imm) { - if (pageH == 0xffffffff && y + h > curPageH) { - pageBitmap->expand(y + h, pageDefPixel); - } - } - - // get referenced bitmap - if (nRefSegs > 1) { - error(getPos(), "Bad reference in JBIG2 generic refinement segment"); - return; - } - if (nRefSegs == 1) { - seg = findSegment(refSegs[0]); - if (seg->getType() != jbig2SegBitmap) { - error(getPos(), "Bad bitmap reference in JBIG2 generic refinement segment"); - return; - } - refBitmap = (JBIG2Bitmap *)seg; - } else { - refBitmap = pageBitmap->getSlice(x, y, w, h); - } - - // set up the arithmetic decoder - resetRefinementStats(templ, NULL); - arithDecoder->start(); - - // read - bitmap = readGenericRefinementRegion(w, h, templ, tpgrOn, - refBitmap, 0, 0, atx, aty); - - // combine the region bitmap into the page bitmap - if (imm) { - pageBitmap->combine(bitmap, x, y, extCombOp); - delete bitmap; - - // store the region bitmap - } else { - bitmap->setSegNum(segNum); - segments->append(bitmap); - } - - // delete the referenced bitmap - if (nRefSegs == 1) { - discardSegment(refSegs[0]); - } else { - delete refBitmap; - } - - return; - - eofError: - error(getPos(), "Unexpected EOF in JBIG2 stream"); -} - -JBIG2Bitmap *JBIG2Stream::readGenericRefinementRegion(int w, int h, - int templ, GBool tpgrOn, - JBIG2Bitmap *refBitmap, - int refDX, int refDY, - int *atx, int *aty) { - 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); - bitmap->clearToZero(); - - // set up the typical row context - if (templ) { - ltpCX = 0x008; - } else { - ltpCX = 0x0010; - } - - ltp = 0; - for (y = 0; y < h; ++y) { - - if (templ) { - - // 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) { - 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; - } - } - - // 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); - } - } - - } 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); - } - - 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); - } - } - } - } - - return bitmap; -} - -void JBIG2Stream::readPageInfoSeg(Guint length) { - Guint xRes, yRes, flags, striping; - - if (!readULong(&pageW) || !readULong(&pageH) || - !readULong(&xRes) || !readULong(&yRes) || - !readUByte(&flags) || !readUWord(&striping)) { - goto eofError; - } - pageDefPixel = (flags >> 2) & 1; - defCombOp = (flags >> 3) & 3; - - // allocate the page bitmap - if (pageH == 0xffffffff) { - curPageH = striping & 0x7fff; - } else { - curPageH = pageH; - } - pageBitmap = new JBIG2Bitmap(0, pageW, curPageH); - - // default pixel value - if (pageDefPixel) { - pageBitmap->clearToOne(); - } else { - pageBitmap->clearToZero(); - } - - return; - - eofError: - error(getPos(), "Unexpected EOF in JBIG2 stream"); -} - -void JBIG2Stream::readEndOfStripeSeg(Guint length) { - Guint i; - - // skip the segment - for (i = 0; i < length; ++i) { - curStr->getChar(); - } -} - -void JBIG2Stream::readProfilesSeg(Guint length) { - Guint i; - - // skip the segment - for (i = 0; i < length; ++i) { - curStr->getChar(); - } -} - -void JBIG2Stream::readCodeTableSeg(Guint segNum, Guint length) { - JBIG2HuffmanTable *huffTab; - Guint flags, oob, prefixBits, rangeBits; - int lowVal, highVal, val; - Guint huffTabSize, i; - - if (!readUByte(&flags) || !readLong(&lowVal) || !readLong(&highVal)) { - goto eofError; - } - oob = flags & 1; - prefixBits = ((flags >> 1) & 7) + 1; - rangeBits = ((flags >> 4) & 7) + 1; - - huffDecoder->reset(); - huffTabSize = 8; - huffTab = (JBIG2HuffmanTable *) - gmallocn(huffTabSize, sizeof(JBIG2HuffmanTable)); - i = 0; - val = lowVal; - while (val < highVal) { - if (i == huffTabSize) { - huffTabSize *= 2; - huffTab = (JBIG2HuffmanTable *) - greallocn(huffTab, huffTabSize, sizeof(JBIG2HuffmanTable)); - } - huffTab[i].val = val; - huffTab[i].prefixLen = huffDecoder->readBits(prefixBits); - huffTab[i].rangeLen = huffDecoder->readBits(rangeBits); - val += 1 << huffTab[i].rangeLen; - ++i; - } - if (i + oob + 3 > huffTabSize) { - huffTabSize = i + oob + 3; - huffTab = (JBIG2HuffmanTable *) - greallocn(huffTab, huffTabSize, sizeof(JBIG2HuffmanTable)); - } - huffTab[i].val = lowVal - 1; - huffTab[i].prefixLen = huffDecoder->readBits(prefixBits); - huffTab[i].rangeLen = jbig2HuffmanLOW; - ++i; - huffTab[i].val = highVal; - huffTab[i].prefixLen = huffDecoder->readBits(prefixBits); - huffTab[i].rangeLen = 32; - ++i; - if (oob) { - huffTab[i].val = 0; - huffTab[i].prefixLen = huffDecoder->readBits(prefixBits); - huffTab[i].rangeLen = jbig2HuffmanOOB; - ++i; - } - huffTab[i].val = 0; - huffTab[i].prefixLen = 0; - huffTab[i].rangeLen = jbig2HuffmanEOT; - huffDecoder->buildTable(huffTab, i); - - // create and store the new table segment - segments->append(new JBIG2CodeTable(segNum, huffTab)); - - return; - - eofError: - error(getPos(), "Unexpected EOF in JBIG2 stream"); -} - -void JBIG2Stream::readExtensionSeg(Guint length) { - Guint i; - - // skip the segment - for (i = 0; i < length; ++i) { - curStr->getChar(); - } -} - -JBIG2Segment *JBIG2Stream::findSegment(Guint segNum) { - JBIG2Segment *seg; - int i; - - for (i = 0; i < globalSegments->getLength(); ++i) { - seg = (JBIG2Segment *)globalSegments->get(i); - if (seg->getSegNum() == segNum) { - return seg; - } - } - for (i = 0; i < segments->getLength(); ++i) { - seg = (JBIG2Segment *)segments->get(i); - if (seg->getSegNum() == segNum) { - return seg; - } - } - return NULL; -} - -void JBIG2Stream::discardSegment(Guint segNum) { - JBIG2Segment *seg; - int i; - - for (i = 0; i < globalSegments->getLength(); ++i) { - seg = (JBIG2Segment *)globalSegments->get(i); - if (seg->getSegNum() == segNum) { - globalSegments->del(i); - return; - } - } - for (i = 0; i < segments->getLength(); ++i) { - seg = (JBIG2Segment *)segments->get(i); - if (seg->getSegNum() == segNum) { - segments->del(i); - return; - } - } -} - -void JBIG2Stream::resetGenericStats(Guint templ, - JArithmeticDecoderStats *prevStats) { - int size; - - size = contextSize[templ]; - if (prevStats && prevStats->getContextSize() == size) { - if (genericRegionStats->getContextSize() == size) { - genericRegionStats->copyFrom(prevStats); - } else { - delete genericRegionStats; - genericRegionStats = prevStats->copy(); - } - } else { - if (genericRegionStats->getContextSize() == size) { - genericRegionStats->reset(); - } else { - delete genericRegionStats; - genericRegionStats = new JArithmeticDecoderStats(1 << size); - } - } -} - -void JBIG2Stream::resetRefinementStats(Guint templ, - JArithmeticDecoderStats *prevStats) { - int size; - - size = refContextSize[templ]; - if (prevStats && prevStats->getContextSize() == size) { - if (refinementRegionStats->getContextSize() == size) { - refinementRegionStats->copyFrom(prevStats); - } else { - delete refinementRegionStats; - refinementRegionStats = prevStats->copy(); - } - } else { - if (refinementRegionStats->getContextSize() == size) { - refinementRegionStats->reset(); - } else { - delete refinementRegionStats; - refinementRegionStats = new JArithmeticDecoderStats(1 << size); - } - } -} - -void JBIG2Stream::resetIntStats(int symCodeLen) { - iadhStats->reset(); - iadwStats->reset(); - iaexStats->reset(); - iaaiStats->reset(); - iadtStats->reset(); - iaitStats->reset(); - iafsStats->reset(); - iadsStats->reset(); - iardxStats->reset(); - iardyStats->reset(); - iardwStats->reset(); - iardhStats->reset(); - iariStats->reset(); - if (iaidStats->getContextSize() == symCodeLen + 1) { - iaidStats->reset(); - } else { - delete iaidStats; - iaidStats = new JArithmeticDecoderStats(1 << (symCodeLen + 1)); - } -} - -GBool JBIG2Stream::readUByte(Guint *x) { - int c0; - - if ((c0 = curStr->getChar()) == EOF) { - return gFalse; - } - *x = (Guint)c0; - return gTrue; -} - -GBool JBIG2Stream::readByte(int *x) { - int c0; - - if ((c0 = curStr->getChar()) == EOF) { - return gFalse; - } - *x = c0; - if (c0 & 0x80) { - *x |= -1 - 0xff; - } - return gTrue; -} - -GBool JBIG2Stream::readUWord(Guint *x) { - int c0, c1; - - if ((c0 = curStr->getChar()) == EOF || - (c1 = curStr->getChar()) == EOF) { - return gFalse; - } - *x = (Guint)((c0 << 8) | c1); - return gTrue; -} - -GBool JBIG2Stream::readULong(Guint *x) { - int c0, c1, c2, c3; - - if ((c0 = curStr->getChar()) == EOF || - (c1 = curStr->getChar()) == EOF || - (c2 = curStr->getChar()) == EOF || - (c3 = curStr->getChar()) == EOF) { - return gFalse; - } - *x = (Guint)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3); - return gTrue; -} - -GBool JBIG2Stream::readLong(int *x) { - int c0, c1, c2, c3; - - if ((c0 = curStr->getChar()) == EOF || - (c1 = curStr->getChar()) == EOF || - (c2 = curStr->getChar()) == EOF || - (c3 = curStr->getChar()) == EOF) { - return gFalse; - } - *x = ((c0 << 24) | (c1 << 16) | (c2 << 8) | c3); - if (c0 & 0x80) { - *x |= -1 - (int)0xffffffff; - } - return gTrue; -}