1 //========================================================================
5 // Copyright 2002 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
18 #include "JBIG2Stream.h"
20 //~ share these tables
21 #include "Stream-CCITT.h"
23 //------------------------------------------------------------------------
25 static int contextSize[4] = { 16, 13, 10, 10 };
26 static int refContextSize[2] = { 13, 10 };
28 //------------------------------------------------------------------------
29 // JBIG2ArithmeticDecoderStats
30 //------------------------------------------------------------------------
32 class JBIG2ArithmeticDecoderStats {
35 JBIG2ArithmeticDecoderStats(int contextSizeA);
36 ~JBIG2ArithmeticDecoderStats();
37 JBIG2ArithmeticDecoderStats *copy();
39 int getContextSize() { return contextSize; }
40 void copyFrom(JBIG2ArithmeticDecoderStats *stats);
44 Guchar *cxTab; // cxTab[cx] = (i[cx] << 1) + mps[cx]
47 friend class JBIG2ArithmeticDecoder;
50 JBIG2ArithmeticDecoderStats::JBIG2ArithmeticDecoderStats(int contextSizeA) {
51 contextSize = contextSizeA;
52 cxTab = (Guchar *)gmalloc((1 << contextSize) * sizeof(Guchar));
56 JBIG2ArithmeticDecoderStats::~JBIG2ArithmeticDecoderStats() {
60 JBIG2ArithmeticDecoderStats *JBIG2ArithmeticDecoderStats::copy() {
61 JBIG2ArithmeticDecoderStats *stats;
63 stats = new JBIG2ArithmeticDecoderStats(contextSize);
64 memcpy(stats->cxTab, cxTab, 1 << contextSize);
68 void JBIG2ArithmeticDecoderStats::reset() {
69 memset(cxTab, 0, 1 << contextSize);
72 void JBIG2ArithmeticDecoderStats::copyFrom(
73 JBIG2ArithmeticDecoderStats *stats) {
74 memcpy(cxTab, stats->cxTab, 1 << contextSize);
77 //------------------------------------------------------------------------
78 // JBIG2ArithmeticDecoder
79 //------------------------------------------------------------------------
81 class JBIG2ArithmeticDecoder {
84 JBIG2ArithmeticDecoder();
85 ~JBIG2ArithmeticDecoder();
86 void setStream(Stream *strA) { str = strA; }
88 int decodeBit(Guint context, JBIG2ArithmeticDecoderStats *stats);
89 int decodeByte(Guint context, JBIG2ArithmeticDecoderStats *stats);
91 // Returns false for OOB, otherwise sets *<x> and returns true.
92 GBool decodeInt(int *x, JBIG2ArithmeticDecoderStats *stats);
94 Guint decodeIAID(Guint codeLen,
95 JBIG2ArithmeticDecoderStats *stats);
99 int decodeIntBit(JBIG2ArithmeticDecoderStats *stats);
102 static Guint qeTab[47];
103 static int nmpsTab[47];
104 static int nlpsTab[47];
105 static int switchTab[47];
111 Guint prev; // for the integer decoder
116 Guint JBIG2ArithmeticDecoder::qeTab[47] = {
117 0x56010000, 0x34010000, 0x18010000, 0x0AC10000,
118 0x05210000, 0x02210000, 0x56010000, 0x54010000,
119 0x48010000, 0x38010000, 0x30010000, 0x24010000,
120 0x1C010000, 0x16010000, 0x56010000, 0x54010000,
121 0x51010000, 0x48010000, 0x38010000, 0x34010000,
122 0x30010000, 0x28010000, 0x24010000, 0x22010000,
123 0x1C010000, 0x18010000, 0x16010000, 0x14010000,
124 0x12010000, 0x11010000, 0x0AC10000, 0x09C10000,
125 0x08A10000, 0x05210000, 0x04410000, 0x02A10000,
126 0x02210000, 0x01410000, 0x01110000, 0x00850000,
127 0x00490000, 0x00250000, 0x00150000, 0x00090000,
128 0x00050000, 0x00010000, 0x56010000
131 int JBIG2ArithmeticDecoder::nmpsTab[47] = {
132 1, 2, 3, 4, 5, 38, 7, 8, 9, 10, 11, 12, 13, 29, 15, 16,
133 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
134 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 45, 46
137 int JBIG2ArithmeticDecoder::nlpsTab[47] = {
138 1, 6, 9, 12, 29, 33, 6, 14, 14, 14, 17, 18, 20, 21, 14, 14,
139 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
140 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 46
143 int JBIG2ArithmeticDecoder::switchTab[47] = {
144 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0,
145 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
146 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
149 JBIG2ArithmeticDecoder::JBIG2ArithmeticDecoder() {
153 JBIG2ArithmeticDecoder::~JBIG2ArithmeticDecoder() {
156 void JBIG2ArithmeticDecoder::start() {
157 buf0 = (Guint)str->getChar() & 0xff;
158 buf1 = (Guint)str->getChar() & 0xff;
161 c = (buf0 ^ 0xff) << 16;
168 int JBIG2ArithmeticDecoder::decodeBit(Guint context,
169 JBIG2ArithmeticDecoderStats *stats) {
174 iCX = stats->cxTab[context] >> 1;
175 mpsCX = stats->cxTab[context] & 1;
179 if (a & 0x80000000) {
185 if (switchTab[iCX]) {
186 stats->cxTab[context] = (nlpsTab[iCX] << 1) | (1 - mpsCX);
188 stats->cxTab[context] = (nlpsTab[iCX] << 1) | mpsCX;
192 stats->cxTab[context] = (nmpsTab[iCX] << 1) | mpsCX;
202 } while (!(a & 0x80000000));
209 stats->cxTab[context] = (nmpsTab[iCX] << 1) | mpsCX;
212 if (switchTab[iCX]) {
213 stats->cxTab[context] = (nlpsTab[iCX] << 1) | (1 - mpsCX);
215 stats->cxTab[context] = (nlpsTab[iCX] << 1) | mpsCX;
227 } while (!(a & 0x80000000));
232 int JBIG2ArithmeticDecoder::decodeByte(Guint context,
233 JBIG2ArithmeticDecoderStats *stats) {
238 for (i = 0; i < 8; ++i) {
239 byte = (byte << 1) | decodeBit(context, stats);
244 GBool JBIG2ArithmeticDecoder::decodeInt(int *x,
245 JBIG2ArithmeticDecoderStats *stats) {
251 s = decodeIntBit(stats);
252 if (decodeIntBit(stats)) {
253 if (decodeIntBit(stats)) {
254 if (decodeIntBit(stats)) {
255 if (decodeIntBit(stats)) {
256 if (decodeIntBit(stats)) {
258 for (i = 0; i < 32; ++i) {
259 v = (v << 1) | decodeIntBit(stats);
264 for (i = 0; i < 12; ++i) {
265 v = (v << 1) | decodeIntBit(stats);
271 for (i = 0; i < 8; ++i) {
272 v = (v << 1) | decodeIntBit(stats);
278 for (i = 0; i < 6; ++i) {
279 v = (v << 1) | decodeIntBit(stats);
284 v = decodeIntBit(stats);
285 v = (v << 1) | decodeIntBit(stats);
286 v = (v << 1) | decodeIntBit(stats);
287 v = (v << 1) | decodeIntBit(stats);
291 v = decodeIntBit(stats);
292 v = (v << 1) | decodeIntBit(stats);
306 int JBIG2ArithmeticDecoder::decodeIntBit(JBIG2ArithmeticDecoderStats *stats) {
309 bit = decodeBit(prev, stats);
311 prev = (prev << 1) | bit;
313 prev = (((prev << 1) | bit) & 0x1ff) | 0x100;
318 Guint JBIG2ArithmeticDecoder::decodeIAID(Guint codeLen,
319 JBIG2ArithmeticDecoderStats *stats) {
324 for (i = 0; i < codeLen; ++i) {
325 bit = decodeBit(prev, stats);
326 prev = (prev << 1) | bit;
328 return prev - (1 << codeLen);
331 void JBIG2ArithmeticDecoder::byteIn() {
337 buf1 = (Guint)str->getChar() & 0xff;
338 c = c + 0xfe00 - (buf0 << 9);
343 buf1 = (Guint)str->getChar() & 0xff;
344 c = c + 0xff00 - (buf0 << 8);
349 //------------------------------------------------------------------------
351 //------------------------------------------------------------------------
353 #define jbig2HuffmanLOW 0xfffffffd
354 #define jbig2HuffmanOOB 0xfffffffe
355 #define jbig2HuffmanEOT 0xffffffff
357 struct JBIG2HuffmanTable {
360 Guint rangeLen; // can also be LOW, OOB, or EOT
364 JBIG2HuffmanTable huffTableA[] = {
367 { 272, 3, 16, 0x006 },
368 { 65808, 3, 32, 0x007 },
369 { 0, 0, jbig2HuffmanEOT, 0 }
372 JBIG2HuffmanTable huffTableB[] = {
378 { 75, 6, 32, 0x03e },
379 { 0, 6, jbig2HuffmanOOB, 0x03f },
380 { 0, 0, jbig2HuffmanEOT, 0 }
383 JBIG2HuffmanTable huffTableC[] = {
389 { 0, 6, jbig2HuffmanOOB, 0x03e },
390 { 75, 7, 32, 0x0fe },
391 { -256, 8, 8, 0x0fe },
392 { -257, 8, jbig2HuffmanLOW, 0x0ff },
393 { 0, 0, jbig2HuffmanEOT, 0 }
396 JBIG2HuffmanTable huffTableD[] = {
402 { 76, 5, 32, 0x01f },
403 { 0, 0, jbig2HuffmanEOT, 0 }
406 JBIG2HuffmanTable huffTableE[] = {
412 { 76, 6, 32, 0x03e },
413 { -255, 7, 8, 0x07e },
414 { -256, 7, jbig2HuffmanLOW, 0x07f },
415 { 0, 0, jbig2HuffmanEOT, 0 }
418 JBIG2HuffmanTable huffTableF[] = {
420 { 128, 3, 7, 0x002 },
421 { 256, 3, 8, 0x003 },
422 { -1024, 4, 9, 0x008 },
423 { -512, 4, 8, 0x009 },
424 { -256, 4, 7, 0x00a },
425 { -32, 4, 5, 0x00b },
426 { 512, 4, 9, 0x00c },
427 { 1024, 4, 10, 0x00d },
428 { -2048, 5, 10, 0x01c },
429 { -128, 5, 6, 0x01d },
430 { -64, 5, 5, 0x01e },
431 { -2049, 6, jbig2HuffmanLOW, 0x03e },
432 { 2048, 6, 32, 0x03f },
433 { 0, 0, jbig2HuffmanEOT, 0 }
436 JBIG2HuffmanTable huffTableG[] = {
437 { -512, 3, 8, 0x000 },
438 { 256, 3, 8, 0x001 },
439 { 512, 3, 9, 0x002 },
440 { 1024, 3, 10, 0x003 },
441 { -1024, 4, 9, 0x008 },
442 { -256, 4, 7, 0x009 },
443 { -32, 4, 5, 0x00a },
445 { 128, 4, 7, 0x00c },
446 { -128, 5, 6, 0x01a },
447 { -64, 5, 5, 0x01b },
450 { -1025, 5, jbig2HuffmanLOW, 0x01e },
451 { 2048, 5, 32, 0x01f },
452 { 0, 0, jbig2HuffmanEOT, 0 }
455 JBIG2HuffmanTable huffTableH[] = {
457 { 0, 2, jbig2HuffmanOOB, 0x001 },
464 { 134, 5, 7, 0x01c },
467 { 262, 6, 7, 0x03c },
468 { 646, 6, 10, 0x03d },
470 { 390, 7, 8, 0x07d },
471 { -15, 8, 3, 0x0fc },
475 { -16, 9, jbig2HuffmanLOW, 0x1fe },
476 { 1670, 9, 32, 0x1ff },
477 { 0, 0, jbig2HuffmanEOT, 0 }
480 JBIG2HuffmanTable huffTableI[] = {
481 { 0, 2, jbig2HuffmanOOB, 0x000 },
489 { 139, 5, 7, 0x01b },
490 { 267, 5, 8, 0x01c },
493 { 523, 6, 8, 0x03c },
494 { 1291, 6, 11, 0x03d },
496 { 779, 7, 9, 0x07d },
497 { -31, 8, 4, 0x0fc },
498 { -11, 8, 2, 0x0fd },
499 { -15, 9, 2, 0x1fc },
501 { -32, 9, jbig2HuffmanLOW, 0x1fe },
502 { 3339, 9, 32, 0x1ff },
503 { 0, 0, jbig2HuffmanEOT, 0 }
506 JBIG2HuffmanTable huffTableJ[] = {
509 { 0, 2, jbig2HuffmanOOB, 0x002 },
514 { 102, 6, 5, 0x037 },
515 { 134, 6, 6, 0x038 },
516 { 198, 6, 7, 0x039 },
517 { 326, 6, 8, 0x03a },
518 { 582, 6, 9, 0x03b },
519 { 1094, 6, 10, 0x03c },
520 { -21, 7, 4, 0x07a },
523 { 2118, 7, 11, 0x07d },
526 { -22, 8, jbig2HuffmanLOW, 0x0fe },
527 { 4166, 8, 32, 0x0ff },
528 { 0, 0, jbig2HuffmanEOT, 0 }
531 JBIG2HuffmanTable huffTableK[] = {
544 { 141, 7, 32, 0x07f },
545 { 0, 0, jbig2HuffmanEOT, 0 }
548 JBIG2HuffmanTable huffTableL[] = {
561 { 73, 8, 32, 0x0ff },
562 { 0, 0, jbig2HuffmanEOT, 0 }
565 JBIG2HuffmanTable huffTableM[] = {
578 { 141, 7, 32, 0x07f },
579 { 0, 0, jbig2HuffmanEOT, 0 }
582 JBIG2HuffmanTable huffTableN[] = {
588 { 0, 0, jbig2HuffmanEOT, 0 }
591 JBIG2HuffmanTable huffTableO[] = {
601 { -24, 7, 4, 0x07c },
603 { -25, 7, jbig2HuffmanLOW, 0x07e },
604 { 25, 7, 32, 0x07f },
605 { 0, 0, jbig2HuffmanEOT, 0 }
608 //------------------------------------------------------------------------
609 // JBIG2HuffmanDecoder
610 //------------------------------------------------------------------------
612 class JBIG2HuffmanDecoder {
615 JBIG2HuffmanDecoder();
616 ~JBIG2HuffmanDecoder();
617 void setStream(Stream *strA) { str = strA; }
621 // Returns false for OOB, otherwise sets *<x> and returns true.
622 GBool decodeInt(int *x, JBIG2HuffmanTable *table);
624 Guint readBits(Guint n);
627 // Sort the table by prefix length and assign prefix values.
628 void buildTable(JBIG2HuffmanTable *table, Guint len);
637 JBIG2HuffmanDecoder::JBIG2HuffmanDecoder() {
642 JBIG2HuffmanDecoder::~JBIG2HuffmanDecoder() {
645 void JBIG2HuffmanDecoder::reset() {
651 GBool JBIG2HuffmanDecoder::decodeInt(int *x, JBIG2HuffmanTable *table) {
652 Guint i, len, prefix;
657 while (table[i].rangeLen != jbig2HuffmanEOT) {
658 //~ if buildTable removes the entries with prefixLen=0, this is unneeded
659 if (table[i].prefixLen > 0) {
660 while (len < table[i].prefixLen) {
661 prefix = (prefix << 1) | readBit();
664 if (prefix == table[i].prefix) {
665 if (table[i].rangeLen == jbig2HuffmanOOB) {
668 if (table[i].rangeLen == jbig2HuffmanLOW) {
669 *x = table[i].val - readBits(32);
670 } else if (table[i].rangeLen > 0) {
671 *x = table[i].val + readBits(table[i].rangeLen);
683 Guint JBIG2HuffmanDecoder::readBits(Guint n) {
684 Guint x, mask, nLeft;
686 mask = (n == 32) ? 0xffffffff : ((1 << n) - 1);
688 x = (buf >> (bufLen - n)) & mask;
691 x = buf & ((1 << bufLen) - 1);
695 x = (x << 8) | (str->getChar() & 0xff);
699 buf = str->getChar();
701 x = (x << nLeft) | ((buf >> bufLen) & ((1 << nLeft) - 1));
707 Guint JBIG2HuffmanDecoder::readBit() {
709 buf = str->getChar();
713 return (buf >> bufLen) & 1;
716 static int cmpHuffmanTabEntries(const void *p1, const void *p2) {
717 return ((JBIG2HuffmanTable *)p1)->prefixLen
718 - ((JBIG2HuffmanTable *)p2)->prefixLen;
721 //~ should remove entries with prefixLen = 0
722 void JBIG2HuffmanDecoder::buildTable(JBIG2HuffmanTable *table, Guint len) {
725 qsort(table, len, sizeof(JBIG2HuffmanTable), &cmpHuffmanTabEntries);
726 for (i = 0; i < len && table[i].prefixLen == 0; ++i) {
730 table[i++].prefix = prefix++;
731 for (; i < len; ++i) {
732 prefix <<= table[i].prefixLen - table[i-1].prefixLen;
733 table[i].prefix = prefix++;
737 //------------------------------------------------------------------------
739 //------------------------------------------------------------------------
741 class JBIG2MMRDecoder {
746 void setStream(Stream *strA) { str = strA; }
752 void skipTo(Guint length);
762 JBIG2MMRDecoder::JBIG2MMRDecoder() {
767 JBIG2MMRDecoder::~JBIG2MMRDecoder() {
770 void JBIG2MMRDecoder::reset() {
776 int JBIG2MMRDecoder::get2DCode() {
780 buf = str->getChar() & 0xff;
783 p = &twoDimTab1[(buf >> 1) & 0x7f];
784 } else if (bufLen == 8) {
785 p = &twoDimTab1[(buf >> 1) & 0x7f];
787 p = &twoDimTab1[(buf << (7 - bufLen)) & 0x7f];
788 if (p->bits < 0 || p->bits > (int)bufLen) {
789 buf = (buf << 8) | (str->getChar() & 0xff);
792 p = &twoDimTab1[(buf >> (bufLen - 7)) & 0x7f];
796 error(str->getPos(), "Bad two dim code in JBIG2 MMR stream");
803 int JBIG2MMRDecoder::getWhiteCode() {
808 buf = str->getChar() & 0xff;
813 if (bufLen > 7 && ((buf >> (bufLen - 7)) & 0x7f) == 0) {
815 code = buf << (12 - bufLen);
817 code = buf >> (bufLen - 12);
819 p = &whiteTab1[code & 0x1f];
822 code = buf << (9 - bufLen);
824 code = buf >> (bufLen - 9);
826 p = &whiteTab2[code & 0x1ff];
828 if (p->bits > 0 && p->bits < (int)bufLen) {
835 buf = (buf << 8) | (str->getChar() & 0xff);
839 error(str->getPos(), "Bad white code in JBIG2 MMR stream");
840 // eat a bit and return a positive number so that the caller doesn't
841 // go into an infinite loop
846 int JBIG2MMRDecoder::getBlackCode() {
851 buf = str->getChar() & 0xff;
856 if (bufLen > 6 && ((buf >> (bufLen - 6)) & 0x3f) == 0) {
858 code = buf << (13 - bufLen);
860 code = buf >> (bufLen - 13);
862 p = &blackTab1[code & 0x7f];
863 } else if (bufLen > 4 && ((buf >> (bufLen - 4)) & 0x0f) == 0) {
865 code = buf << (12 - bufLen);
867 code = buf >> (bufLen - 12);
869 p = &blackTab2[(code & 0xff) - 64];
872 code = buf << (6 - bufLen);
874 code = buf >> (bufLen - 6);
876 p = &blackTab3[code & 0x3f];
878 if (p->bits > 0 && p->bits < (int)bufLen) {
885 buf = (buf << 8) | (str->getChar() & 0xff);
889 error(str->getPos(), "Bad black code in JBIG2 MMR stream");
890 // eat a bit and return a positive number so that the caller doesn't
891 // go into an infinite loop
896 Guint JBIG2MMRDecoder::get24Bits() {
897 while (bufLen < 24) {
898 buf = (buf << 8) | (str->getChar() & 0xff);
902 return (buf >> (bufLen - 24)) & 0xffffff;
905 void JBIG2MMRDecoder::skipTo(Guint length) {
906 while (nBytesRead < length) {
912 //------------------------------------------------------------------------
914 //------------------------------------------------------------------------
916 enum JBIG2SegmentType {
926 JBIG2Segment(Guint segNumA) { segNum = segNumA; }
927 virtual ~JBIG2Segment() {}
928 void setSegNum(Guint segNumA) { segNum = segNumA; }
929 Guint getSegNum() { return segNum; }
930 virtual JBIG2SegmentType getType() = 0;
937 //------------------------------------------------------------------------
939 //------------------------------------------------------------------------
941 class JBIG2Bitmap: public JBIG2Segment {
944 JBIG2Bitmap(Guint segNumA, int wA, int hA);
945 virtual ~JBIG2Bitmap();
946 virtual JBIG2SegmentType getType() { return jbig2SegBitmap; }
947 JBIG2Bitmap *copy() { return new JBIG2Bitmap(0, this); }
948 JBIG2Bitmap *getSlice(Guint x, Guint y, Guint wA, Guint hA);
949 void expand(int newH, Guint pixel);
952 int getWidth() { return w; }
953 int getHeight() { return h; }
954 int getPixel(int x, int y)
955 { return (x < 0 || x >= w || y < 0 || y >= h) ? 0 :
956 (data[y * line + (x >> 3)] >> (7 - (x & 7))) & 1; }
957 void setPixel(int x, int y)
958 { data[y * line + (x >> 3)] |= 1 << (7 - (x & 7)); }
959 void clearPixel(int x, int y)
960 { data[y * line + (x >> 3)] &= 0x7f7f >> (x & 7); }
961 void duplicateRow(int yDest, int ySrc);
962 void combine(JBIG2Bitmap *bitmap, int x, int y, Guint combOp);
963 Guchar *getDataPtr() { return data; }
964 int getDataSize() { return h * line; }
968 JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap);
974 JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, int wA, int hA):
975 JBIG2Segment(segNumA)
979 line = (wA + 7) >> 3;
980 data = (Guchar *)gmalloc(h * line);
983 JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap):
984 JBIG2Segment(segNumA)
989 data = (Guchar *)gmalloc(h * line);
990 memcpy(data, bitmap->data, h * line);
993 JBIG2Bitmap::~JBIG2Bitmap() {
998 JBIG2Bitmap *JBIG2Bitmap::getSlice(Guint x, Guint y, Guint wA, Guint hA) {
1002 slice = new JBIG2Bitmap(0, wA, hA);
1003 slice->clearToZero();
1004 for (yy = 0; yy < hA; ++yy) {
1005 for (xx = 0; xx < wA; ++xx) {
1006 if (getPixel(x + xx, y + yy)) {
1007 slice->setPixel(xx, yy);
1014 void JBIG2Bitmap::expand(int newH, Guint pixel) {
1018 data = (Guchar *)grealloc(data, newH * line);
1020 memset(data + h * line, 0xff, (newH - h) * line);
1022 memset(data + h * line, 0x00, (newH - h) * line);
1027 void JBIG2Bitmap::clearToZero() {
1028 memset(data, 0, h * line);
1031 void JBIG2Bitmap::clearToOne() {
1032 memset(data, 0xff, h * line);
1035 void JBIG2Bitmap::duplicateRow(int yDest, int ySrc) {
1036 memcpy(data + yDest * line, data + ySrc * line, line);
1039 void JBIG2Bitmap::combine(JBIG2Bitmap *bitmap, int x, int y,
1041 int x0, x1, y0, y1, xx, yy;
1042 Guchar *srcPtr, *destPtr;
1043 Guint src0, src1, src, dest, s1, s2, m1, m2, m3;
1051 if (y + bitmap->h > h) {
1075 m1 = 0xff >> (x1 & 7);
1076 m2 = 0xff << (((x1 & 7) == 0) ? 0 : 8 - (x1 & 7));
1077 m3 = (0xff >> s1) & m2;
1079 oneByte = x0 == ((x1 - 1) & ~7);
1081 for (yy = y0; yy < y1; ++yy) {
1083 // one byte per line -- need to mask both left and right side
1086 destPtr = data + (y + yy) * line + (x >> 3);
1087 srcPtr = bitmap->data + yy * bitmap->line;
1092 dest |= (src1 >> s1) & m2;
1095 dest &= ((0xff00 | src1) >> s1) | m1;
1098 dest ^= (src1 >> s1) & m2;
1101 dest ^= ((src1 ^ 0xff) >> s1) & m2;
1104 dest = (dest & ~m3) | ((src1 >> s1) & m3);
1109 destPtr = data + (y + yy) * line;
1110 srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3);
1124 dest ^= (src1 ^ 0xff) & m2;
1127 dest = (src1 & m2) | (dest & m1);
1133 // multiple bytes per line -- need to mask left side of left-most
1134 // byte and right side of right-most byte
1139 destPtr = data + (y + yy) * line + (x >> 3);
1140 srcPtr = bitmap->data + yy * bitmap->line;
1148 dest &= (0xff00 | src1) >> s1;
1154 dest ^= (src1 ^ 0xff) >> s1;
1157 dest = (dest & (0xff << s2)) | (src1 >> s1);
1163 destPtr = data + (y + yy) * line;
1164 srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3);
1170 for (; xx < x1 - 8; xx += 8) {
1174 src = (((src0 << 8) | src1) >> s1) & 0xff;
1199 src = (((src0 << 8) | src1) >> s1) & 0xff;
1211 dest ^= (src ^ 0xff) & m2;
1214 dest = (src & m2) | (dest & m1);
1222 //------------------------------------------------------------------------
1224 //------------------------------------------------------------------------
1226 class JBIG2SymbolDict: public JBIG2Segment {
1229 JBIG2SymbolDict(Guint segNumA, Guint sizeA);
1230 virtual ~JBIG2SymbolDict();
1231 virtual JBIG2SegmentType getType() { return jbig2SegSymbolDict; }
1232 Guint getSize() { return size; }
1233 void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; }
1234 JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; }
1235 void setGenericRegionStats(JBIG2ArithmeticDecoderStats *stats)
1236 { genericRegionStats = stats; }
1237 void setRefinementRegionStats(JBIG2ArithmeticDecoderStats *stats)
1238 { refinementRegionStats = stats; }
1239 JBIG2ArithmeticDecoderStats *getGenericRegionStats()
1240 { return genericRegionStats; }
1241 JBIG2ArithmeticDecoderStats *getRefinementRegionStats()
1242 { return refinementRegionStats; }
1247 JBIG2Bitmap **bitmaps;
1248 JBIG2ArithmeticDecoderStats *genericRegionStats;
1249 JBIG2ArithmeticDecoderStats *refinementRegionStats;
1252 JBIG2SymbolDict::JBIG2SymbolDict(Guint segNumA, Guint sizeA):
1253 JBIG2Segment(segNumA)
1256 bitmaps = (JBIG2Bitmap **)gmalloc(size * sizeof(JBIG2Bitmap *));
1257 genericRegionStats = NULL;
1258 refinementRegionStats = NULL;
1261 JBIG2SymbolDict::~JBIG2SymbolDict() {
1264 for (i = 0; i < size; ++i) {
1268 if (genericRegionStats) {
1269 delete genericRegionStats;
1271 if (refinementRegionStats) {
1272 delete refinementRegionStats;
1276 //------------------------------------------------------------------------
1278 //------------------------------------------------------------------------
1280 class JBIG2PatternDict: public JBIG2Segment {
1283 JBIG2PatternDict(Guint segNumA, Guint sizeA);
1284 virtual ~JBIG2PatternDict();
1285 virtual JBIG2SegmentType getType() { return jbig2SegPatternDict; }
1286 Guint getSize() { return size; }
1287 void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; }
1288 JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; }
1293 JBIG2Bitmap **bitmaps;
1296 JBIG2PatternDict::JBIG2PatternDict(Guint segNumA, Guint sizeA):
1297 JBIG2Segment(segNumA)
1300 bitmaps = (JBIG2Bitmap **)gmalloc(size * sizeof(JBIG2Bitmap *));
1303 JBIG2PatternDict::~JBIG2PatternDict() {
1306 for (i = 0; i < size; ++i) {
1312 //------------------------------------------------------------------------
1314 //------------------------------------------------------------------------
1316 class JBIG2CodeTable: public JBIG2Segment {
1319 JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA);
1320 virtual ~JBIG2CodeTable();
1321 virtual JBIG2SegmentType getType() { return jbig2SegCodeTable; }
1322 JBIG2HuffmanTable *getHuffTable() { return table; }
1326 JBIG2HuffmanTable *table;
1329 JBIG2CodeTable::JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA):
1330 JBIG2Segment(segNumA)
1335 JBIG2CodeTable::~JBIG2CodeTable() {
1339 //------------------------------------------------------------------------
1341 //------------------------------------------------------------------------
1343 JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStream):
1348 arithDecoder = new JBIG2ArithmeticDecoder();
1349 genericRegionStats = new JBIG2ArithmeticDecoderStats(1);
1350 refinementRegionStats = new JBIG2ArithmeticDecoderStats(1);
1351 iadhStats = new JBIG2ArithmeticDecoderStats(9);
1352 iadwStats = new JBIG2ArithmeticDecoderStats(9);
1353 iaexStats = new JBIG2ArithmeticDecoderStats(9);
1354 iaaiStats = new JBIG2ArithmeticDecoderStats(9);
1355 iadtStats = new JBIG2ArithmeticDecoderStats(9);
1356 iaitStats = new JBIG2ArithmeticDecoderStats(9);
1357 iafsStats = new JBIG2ArithmeticDecoderStats(9);
1358 iadsStats = new JBIG2ArithmeticDecoderStats(9);
1359 iardxStats = new JBIG2ArithmeticDecoderStats(9);
1360 iardyStats = new JBIG2ArithmeticDecoderStats(9);
1361 iardwStats = new JBIG2ArithmeticDecoderStats(9);
1362 iardhStats = new JBIG2ArithmeticDecoderStats(9);
1363 iariStats = new JBIG2ArithmeticDecoderStats(9);
1364 iaidStats = new JBIG2ArithmeticDecoderStats(1);
1365 huffDecoder = new JBIG2HuffmanDecoder();
1366 mmrDecoder = new JBIG2MMRDecoder();
1368 segments = new GList();
1369 if (globalsStream->isStream()) {
1370 curStr = globalsStream->getStream();
1372 arithDecoder->setStream(curStr);
1373 huffDecoder->setStream(curStr);
1374 mmrDecoder->setStream(curStr);
1377 globalSegments = segments;
1381 dataPtr = dataEnd = NULL;
1384 JBIG2Stream::~JBIG2Stream() {
1385 delete arithDecoder;
1386 delete genericRegionStats;
1387 delete refinementRegionStats;
1408 deleteGList(segments, JBIG2Segment);
1410 if (globalSegments) {
1411 deleteGList(globalSegments, JBIG2Segment);
1416 void JBIG2Stream::reset() {
1422 deleteGList(segments, JBIG2Segment);
1424 segments = new GList();
1428 arithDecoder->setStream(curStr);
1429 huffDecoder->setStream(curStr);
1430 mmrDecoder->setStream(curStr);
1434 dataPtr = pageBitmap->getDataPtr();
1435 dataEnd = dataPtr + pageBitmap->getDataSize();
1441 int JBIG2Stream::getChar() {
1442 if (dataPtr && dataPtr < dataEnd) {
1443 return (*dataPtr++ ^ 0xff) & 0xff;
1448 int JBIG2Stream::lookChar() {
1449 if (dataPtr && dataPtr < dataEnd) {
1450 return (*dataPtr ^ 0xff) & 0xff;
1455 GString *JBIG2Stream::getPSFilter(char *indent) {
1459 GBool JBIG2Stream::isBinary(GBool last) {
1460 return str->isBinary(gTrue);
1463 void JBIG2Stream::readSegments() {
1464 Guint segNum, segFlags, segType, page, segLength;
1465 Guint refFlags, nRefSegs;
1470 while (readULong(&segNum)) {
1472 // segment header flags
1473 if (!readUByte(&segFlags)) {
1476 segType = segFlags & 0x3f;
1478 // referred-to segment count and retention flags
1479 if (!readUByte(&refFlags)) {
1482 nRefSegs = refFlags >> 5;
1483 if (nRefSegs == 7) {
1484 if ((c1 = curStr->getChar()) == EOF ||
1485 (c2 = curStr->getChar()) == EOF ||
1486 (c3 = curStr->getChar()) == EOF) {
1489 refFlags = (refFlags << 24) | (c1 << 16) | (c2 << 8) | c3;
1490 nRefSegs = refFlags & 0x1fffffff;
1491 for (i = 0; i < (nRefSegs + 9) >> 3; ++i) {
1492 c1 = curStr->getChar();
1496 // referred-to segment numbers
1497 refSegs = (Guint *)gmalloc(nRefSegs * sizeof(Guint));
1498 if (segNum <= 256) {
1499 for (i = 0; i < nRefSegs; ++i) {
1500 if (!readUByte(&refSegs[i])) {
1504 } else if (segNum <= 65536) {
1505 for (i = 0; i < nRefSegs; ++i) {
1506 if (!readUWord(&refSegs[i])) {
1511 for (i = 0; i < nRefSegs; ++i) {
1512 if (!readULong(&refSegs[i])) {
1518 // segment page association
1519 if (segFlags & 0x40) {
1520 if (!readULong(&page)) {
1524 if (!readUByte(&page)) {
1529 // segment data length
1530 if (!readULong(&segLength)) {
1534 // read the segment data
1537 readSymbolDictSeg(segNum, segLength, refSegs, nRefSegs);
1540 readTextRegionSeg(segNum, gFalse, gFalse, segLength, refSegs, nRefSegs);
1543 readTextRegionSeg(segNum, gTrue, gFalse, segLength, refSegs, nRefSegs);
1546 readTextRegionSeg(segNum, gTrue, gTrue, segLength, refSegs, nRefSegs);
1549 readPatternDictSeg(segNum, segLength);
1552 readHalftoneRegionSeg(segNum, gFalse, gFalse, segLength,
1556 readHalftoneRegionSeg(segNum, gTrue, gFalse, segLength,
1560 readHalftoneRegionSeg(segNum, gTrue, gTrue, segLength,
1564 readGenericRegionSeg(segNum, gFalse, gFalse, segLength);
1567 readGenericRegionSeg(segNum, gTrue, gFalse, segLength);
1570 readGenericRegionSeg(segNum, gTrue, gTrue, segLength);
1573 readGenericRefinementRegionSeg(segNum, gFalse, gFalse, segLength,
1577 readGenericRefinementRegionSeg(segNum, gTrue, gFalse, segLength,
1581 readGenericRefinementRegionSeg(segNum, gTrue, gTrue, segLength,
1585 readPageInfoSeg(segLength);
1588 readEndOfStripeSeg(segLength);
1591 readProfilesSeg(segLength);
1594 readCodeTableSeg(segNum, segLength);
1597 readExtensionSeg(segLength);
1600 error(getPos(), "Unknown segment type in JBIG2 stream");
1601 for (i = 0; i < segLength; ++i) {
1602 if ((c1 = curStr->getChar()) == EOF) {
1617 error(getPos(), "Unexpected EOF in JBIG2 stream");
1620 void JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
1621 Guint *refSegs, Guint nRefSegs) {
1622 JBIG2SymbolDict *symbolDict;
1623 JBIG2HuffmanTable *huffDHTable, *huffDWTable;
1624 JBIG2HuffmanTable *huffBMSizeTable, *huffAggInstTable;
1627 JBIG2SymbolDict *inputSymbolDict;
1628 Guint flags, sdTemplate, sdrTemplate, huff, refAgg;
1629 Guint huffDH, huffDW, huffBMSize, huffAggInst;
1630 Guint contextUsed, contextRetained;
1631 int sdATX[4], sdATY[4], sdrATX[2], sdrATY[2];
1632 Guint numExSyms, numNewSyms, numInputSyms, symCodeLen;
1633 JBIG2Bitmap **bitmaps;
1634 JBIG2Bitmap *collBitmap, *refBitmap;
1636 Guint symHeight, symWidth, totalWidth, x, symID;
1637 int dh, dw, refAggNum, refDX, refDY, bmSize;
1643 // symbol dictionary flags
1644 if (!readUWord(&flags)) {
1647 sdTemplate = (flags >> 10) & 3;
1648 sdrTemplate = (flags >> 12) & 1;
1650 refAgg = (flags >> 1) & 1;
1651 huffDH = (flags >> 2) & 3;
1652 huffDW = (flags >> 4) & 3;
1653 huffBMSize = (flags >> 6) & 1;
1654 huffAggInst = (flags >> 7) & 1;
1655 contextUsed = (flags >> 8) & 1;
1656 contextRetained = (flags >> 9) & 1;
1658 // symbol dictionary AT flags
1660 if (sdTemplate == 0) {
1661 if (!readByte(&sdATX[0]) ||
1662 !readByte(&sdATY[0]) ||
1663 !readByte(&sdATX[1]) ||
1664 !readByte(&sdATY[1]) ||
1665 !readByte(&sdATX[2]) ||
1666 !readByte(&sdATY[2]) ||
1667 !readByte(&sdATX[3]) ||
1668 !readByte(&sdATY[3])) {
1672 if (!readByte(&sdATX[0]) ||
1673 !readByte(&sdATY[0])) {
1679 // symbol dictionary refinement AT flags
1680 if (refAgg && !sdrTemplate) {
1681 if (!readByte(&sdrATX[0]) ||
1682 !readByte(&sdrATY[0]) ||
1683 !readByte(&sdrATX[1]) ||
1684 !readByte(&sdrATY[1])) {
1689 // SDNUMEXSYMS and SDNUMNEWSYMS
1690 if (!readULong(&numExSyms) || !readULong(&numNewSyms)) {
1694 // get referenced segments: input symbol dictionaries and code tables
1695 codeTables = new GList();
1697 for (i = 0; i < nRefSegs; ++i) {
1698 seg = findSegment(refSegs[i]);
1699 if (seg->getType() == jbig2SegSymbolDict) {
1700 numInputSyms += ((JBIG2SymbolDict *)seg)->getSize();
1701 } else if (seg->getType() == jbig2SegCodeTable) {
1702 codeTables->append(seg);
1706 // compute symbol code length
1709 while (i < numInputSyms + numNewSyms) {
1714 // get the input symbol bitmaps
1715 bitmaps = (JBIG2Bitmap **)gmalloc((numInputSyms + numNewSyms) *
1716 sizeof(JBIG2Bitmap *));
1718 inputSymbolDict = NULL;
1719 for (i = 0; i < nRefSegs; ++i) {
1720 seg = findSegment(refSegs[i]);
1721 if (seg->getType() == jbig2SegSymbolDict) {
1722 inputSymbolDict = (JBIG2SymbolDict *)seg;
1723 for (j = 0; j < inputSymbolDict->getSize(); ++j) {
1724 bitmaps[k++] = inputSymbolDict->getBitmap(j);
1729 // get the Huffman tables
1730 huffDHTable = huffDWTable = NULL; // make gcc happy
1731 huffBMSizeTable = huffAggInstTable = NULL; // make gcc happy
1735 huffDHTable = huffTableD;
1736 } else if (huffDH == 1) {
1737 huffDHTable = huffTableE;
1739 huffDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1742 huffDWTable = huffTableB;
1743 } else if (huffDW == 1) {
1744 huffDWTable = huffTableC;
1746 huffDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1748 if (huffBMSize == 0) {
1749 huffBMSizeTable = huffTableA;
1752 ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1754 if (huffAggInst == 0) {
1755 huffAggInstTable = huffTableA;
1758 ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1763 // set up the Huffman decoder
1765 huffDecoder->reset();
1767 // set up the arithmetic decoder
1769 if (contextUsed && inputSymbolDict) {
1770 resetGenericStats(sdTemplate, inputSymbolDict->getGenericRegionStats());
1772 resetRefinementStats(sdrTemplate,
1773 inputSymbolDict->getRefinementRegionStats());
1776 resetGenericStats(sdTemplate, NULL);
1778 resetRefinementStats(sdrTemplate, NULL);
1781 resetIntStats(symCodeLen);
1782 arithDecoder->start();
1785 // allocate symbol widths storage
1787 if (huff && !refAgg) {
1788 symWidths = (Guint *)gmalloc(numNewSyms * sizeof(Guint));
1793 while (i < numNewSyms) {
1795 // read the height class delta height
1797 huffDecoder->decodeInt(&dh, huffDHTable);
1799 arithDecoder->decodeInt(&dh, iadhStats);
1806 // read the symbols in this height class
1809 // read the delta width
1811 if (!huffDecoder->decodeInt(&dw, huffDWTable)) {
1815 if (!arithDecoder->decodeInt(&dw, iadwStats)) {
1821 // using a collective bitmap, so don't read a bitmap here
1822 if (huff && !refAgg) {
1823 symWidths[i] = symWidth;
1824 totalWidth += symWidth;
1826 // refinement/aggregate coding
1827 } else if (refAgg) {
1829 if (!huffDecoder->decodeInt(&refAggNum, huffAggInstTable)) {
1833 if (!arithDecoder->decodeInt(&refAggNum, iaaiStats)) {
1837 if (refAggNum == 1) {
1839 symID = huffDecoder->readBits(symCodeLen);
1840 huffDecoder->decodeInt(&refDX, huffTableO);
1841 huffDecoder->decodeInt(&refDY, huffTableO);
1842 huffDecoder->decodeInt(&bmSize, huffTableA);
1843 huffDecoder->reset();
1844 arithDecoder->start();
1846 symID = arithDecoder->decodeIAID(symCodeLen, iaidStats);
1847 arithDecoder->decodeInt(&refDX, iardxStats);
1848 arithDecoder->decodeInt(&refDY, iardyStats);
1850 refBitmap = bitmaps[symID];
1851 bitmaps[numInputSyms + i] =
1852 readGenericRefinementRegion(symWidth, symHeight,
1853 sdrTemplate, gFalse,
1854 refBitmap, refDX, refDY,
1856 //~ do we need to use the bmSize value here (in Huffman mode)?
1858 bitmaps[numInputSyms + i] =
1859 readTextRegion(huff, gTrue, symWidth, symHeight,
1860 refAggNum, 0, numInputSyms + i, NULL,
1861 symCodeLen, bitmaps, 0, 0, 0, 1, 0,
1862 huffTableF, huffTableH, huffTableK, huffTableO,
1863 huffTableO, huffTableO, huffTableO, huffTableA,
1864 sdrTemplate, sdrATX, sdrATY);
1867 // non-ref/agg coding
1869 bitmaps[numInputSyms + i] =
1870 readGenericBitmap(gFalse, symWidth, symHeight,
1871 sdTemplate, gFalse, gFalse, NULL,
1878 // read the collective bitmap
1879 if (huff && !refAgg) {
1880 huffDecoder->decodeInt(&bmSize, huffBMSizeTable);
1882 huffDecoder->reset();
1885 collBitmap = new JBIG2Bitmap(0, totalWidth, symHeight);
1886 bmSize = symHeight * ((totalWidth + 7) >> 3);
1887 p = collBitmap->getDataPtr();
1888 for (k = 0; k < (Guint)bmSize; ++k) {
1889 *p++ = str->getChar();
1892 collBitmap = readGenericBitmap(gTrue, totalWidth, symHeight,
1893 0, gFalse, gFalse, NULL, NULL, NULL,
1897 for (; j < i; ++j) {
1898 bitmaps[numInputSyms + j] =
1899 collBitmap->getSlice(x, 0, symWidths[j], symHeight);
1906 // create the symbol dict object
1907 symbolDict = new JBIG2SymbolDict(segNum, numExSyms);
1909 // exported symbol list
1912 while (i < numInputSyms + numNewSyms) {
1914 huffDecoder->decodeInt(&run, huffTableA);
1916 arithDecoder->decodeInt(&run, iaexStats);
1919 for (cnt = 0; cnt < run; ++cnt) {
1920 symbolDict->setBitmap(j++, bitmaps[i++]->copy());
1928 for (i = 0; i < numNewSyms; ++i) {
1929 delete bitmaps[numInputSyms + i];
1936 // save the arithmetic decoder stats
1937 if (!huff && contextRetained) {
1938 symbolDict->setGenericRegionStats(genericRegionStats->copy());
1940 symbolDict->setRefinementRegionStats(refinementRegionStats->copy());
1944 // store the new symbol dict
1945 segments->append(symbolDict);
1950 error(getPos(), "Unexpected EOF in JBIG2 stream");
1953 void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
1954 GBool lossless, Guint length,
1955 Guint *refSegs, Guint nRefSegs) {
1956 JBIG2Bitmap *bitmap;
1957 JBIG2HuffmanTable runLengthTab[36];
1958 JBIG2HuffmanTable *symCodeTab;
1959 JBIG2HuffmanTable *huffFSTable, *huffDSTable, *huffDTTable;
1960 JBIG2HuffmanTable *huffRDWTable, *huffRDHTable;
1961 JBIG2HuffmanTable *huffRDXTable, *huffRDYTable, *huffRSizeTable;
1964 JBIG2SymbolDict *symbolDict;
1966 Guint w, h, x, y, segInfoFlags, extCombOp;
1967 Guint flags, huff, refine, logStrips, refCorner, transposed;
1968 Guint combOp, defPixel, sOffset, templ;
1969 Guint huffFlags, huffFS, huffDS, huffDT;
1970 Guint huffRDW, huffRDH, huffRDX, huffRDY, huffRSize;
1971 Guint numInstances, numSyms, symCodeLen;
1976 // region segment info field
1977 if (!readULong(&w) || !readULong(&h) ||
1978 !readULong(&x) || !readULong(&y) ||
1979 !readUByte(&segInfoFlags)) {
1982 extCombOp = segInfoFlags & 7;
1984 // rest of the text region header
1985 if (!readUWord(&flags)) {
1989 refine = (flags >> 1) & 1;
1990 logStrips = (flags >> 2) & 3;
1991 refCorner = (flags >> 4) & 3;
1992 transposed = (flags >> 6) & 1;
1993 combOp = (flags >> 7) & 3;
1994 defPixel = (flags >> 9) & 1;
1995 sOffset = (flags >> 10) & 0x1f;
1996 templ = (flags >> 15) & 1;
1997 huffFS = huffDS = huffDT = 0; // make gcc happy
1998 huffRDW = huffRDH = huffRDX = huffRDY = huffRSize = 0; // make gcc happy
2000 if (!readUWord(&huffFlags)) {
2003 huffFS = huffFlags & 3;
2004 huffDS = (huffFlags >> 2) & 3;
2005 huffDT = (huffFlags >> 4) & 3;
2006 huffRDW = (huffFlags >> 6) & 3;
2007 huffRDH = (huffFlags >> 8) & 3;
2008 huffRDX = (huffFlags >> 10) & 3;
2009 huffRDY = (huffFlags >> 12) & 3;
2010 huffRSize = (huffFlags >> 14) & 1;
2012 if (refine && templ == 0) {
2013 if (!readByte(&atx[0]) || !readByte(&aty[0]) ||
2014 !readByte(&atx[1]) || !readByte(&aty[1])) {
2018 if (!readULong(&numInstances)) {
2022 // get symbol dictionaries and tables
2023 codeTables = new GList();
2025 for (i = 0; i < nRefSegs; ++i) {
2026 seg = findSegment(refSegs[i]);
2027 if (seg->getType() == jbig2SegSymbolDict) {
2028 numSyms += ((JBIG2SymbolDict *)seg)->getSize();
2029 } else if (seg->getType() == jbig2SegCodeTable) {
2030 codeTables->append(seg);
2035 while (i < numSyms) {
2040 // get the symbol bitmaps
2041 syms = (JBIG2Bitmap **)gmalloc(numSyms * sizeof(JBIG2Bitmap *));
2043 for (i = 0; i < nRefSegs; ++i) {
2044 seg = findSegment(refSegs[i]);
2045 if (seg->getType() == jbig2SegSymbolDict) {
2046 symbolDict = (JBIG2SymbolDict *)seg;
2047 for (k = 0; k < symbolDict->getSize(); ++k) {
2048 syms[kk++] = symbolDict->getBitmap(k);
2053 // get the Huffman tables
2054 huffFSTable = huffDSTable = huffDTTable = NULL; // make gcc happy
2055 huffRDWTable = huffRDHTable = NULL; // make gcc happy
2056 huffRDXTable = huffRDYTable = huffRSizeTable = NULL; // make gcc happy
2060 huffFSTable = huffTableF;
2061 } else if (huffFS == 1) {
2062 huffFSTable = huffTableG;
2064 huffFSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2067 huffDSTable = huffTableH;
2068 } else if (huffDS == 1) {
2069 huffDSTable = huffTableI;
2070 } else if (huffDS == 2) {
2071 huffDSTable = huffTableJ;
2073 huffDSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2076 huffDTTable = huffTableK;
2077 } else if (huffDT == 1) {
2078 huffDTTable = huffTableL;
2079 } else if (huffDT == 2) {
2080 huffDTTable = huffTableM;
2082 huffDTTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2085 huffRDWTable = huffTableN;
2086 } else if (huffRDW == 1) {
2087 huffRDWTable = huffTableO;
2089 huffRDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2092 huffRDHTable = huffTableN;
2093 } else if (huffRDH == 1) {
2094 huffRDHTable = huffTableO;
2096 huffRDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2099 huffRDXTable = huffTableN;
2100 } else if (huffRDX == 1) {
2101 huffRDXTable = huffTableO;
2103 huffRDXTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2106 huffRDYTable = huffTableN;
2107 } else if (huffRDY == 1) {
2108 huffRDYTable = huffTableO;
2110 huffRDYTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2112 if (huffRSize == 0) {
2113 huffRSizeTable = huffTableA;
2116 ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2121 // symbol ID Huffman decoding table
2123 huffDecoder->reset();
2124 for (i = 0; i < 32; ++i) {
2125 runLengthTab[i].val = i;
2126 runLengthTab[i].prefixLen = huffDecoder->readBits(4);
2127 runLengthTab[i].rangeLen = 0;
2129 runLengthTab[32].val = 0x103;
2130 runLengthTab[32].prefixLen = huffDecoder->readBits(4);
2131 runLengthTab[32].rangeLen = 2;
2132 runLengthTab[33].val = 0x203;
2133 runLengthTab[33].prefixLen = huffDecoder->readBits(4);
2134 runLengthTab[33].rangeLen = 3;
2135 runLengthTab[34].val = 0x20b;
2136 runLengthTab[34].prefixLen = huffDecoder->readBits(4);
2137 runLengthTab[34].rangeLen = 7;
2138 runLengthTab[35].rangeLen = jbig2HuffmanEOT;
2139 huffDecoder->buildTable(runLengthTab, 35);
2140 symCodeTab = (JBIG2HuffmanTable *)gmalloc((numSyms + 1) *
2141 sizeof(JBIG2HuffmanTable));
2142 for (i = 0; i < numSyms; ++i) {
2143 symCodeTab[i].val = i;
2144 symCodeTab[i].rangeLen = 0;
2147 while (i < numSyms) {
2148 huffDecoder->decodeInt(&j, runLengthTab);
2150 for (j -= 0x200; j && i < numSyms; --j) {
2151 symCodeTab[i++].prefixLen = 0;
2153 } else if (j > 0x100) {
2154 for (j -= 0x100; j && i < numSyms; --j) {
2155 symCodeTab[i].prefixLen = symCodeTab[i-1].prefixLen;
2159 symCodeTab[i++].prefixLen = j;
2163 symCodeTab[numSyms].rangeLen = jbig2HuffmanEOT;
2164 huffDecoder->buildTable(symCodeTab, numSyms);
2165 huffDecoder->reset();
2167 // set up the arithmetic decoder
2170 resetIntStats(symCodeLen);
2172 resetRefinementStats(templ, NULL);
2174 arithDecoder->start();
2177 bitmap = readTextRegion(huff, refine, w, h, numInstances,
2178 logStrips, numSyms, symCodeTab, symCodeLen, syms,
2179 defPixel, combOp, transposed, refCorner, sOffset,
2180 huffFSTable, huffDSTable, huffDTTable,
2181 huffRDWTable, huffRDHTable,
2182 huffRDXTable, huffRDYTable, huffRSizeTable,
2187 // combine the region bitmap into the page bitmap
2189 if (pageH == 0xffffffff && y + h > curPageH) {
2190 pageBitmap->expand(y + h, pageDefPixel);
2192 pageBitmap->combine(bitmap, x, y, extCombOp);
2195 // store the region bitmap
2197 bitmap->setSegNum(segNum);
2198 segments->append(bitmap);
2201 // clean up the Huffman decoder
2209 error(getPos(), "Unexpected EOF in JBIG2 stream");
2212 JBIG2Bitmap *JBIG2Stream::readTextRegion(GBool huff, GBool refine,
2217 JBIG2HuffmanTable *symCodeTab,
2220 Guint defPixel, Guint combOp,
2221 Guint transposed, Guint refCorner,
2223 JBIG2HuffmanTable *huffFSTable,
2224 JBIG2HuffmanTable *huffDSTable,
2225 JBIG2HuffmanTable *huffDTTable,
2226 JBIG2HuffmanTable *huffRDWTable,
2227 JBIG2HuffmanTable *huffRDHTable,
2228 JBIG2HuffmanTable *huffRDXTable,
2229 JBIG2HuffmanTable *huffRDYTable,
2230 JBIG2HuffmanTable *huffRSizeTable,
2232 int *atx, int *aty) {
2233 JBIG2Bitmap *bitmap;
2234 JBIG2Bitmap *symbolBitmap;
2236 int t, dt, tt, s, ds, sFirst, j;
2237 int rdw, rdh, rdx, rdy, ri, refDX, refDY, bmSize;
2238 Guint symID, inst, bw, bh;
2240 strips = 1 << logStrips;
2242 // allocate the bitmap
2243 bitmap = new JBIG2Bitmap(0, w, h);
2245 bitmap->clearToOne();
2247 bitmap->clearToZero();
2250 // decode initial T value
2252 huffDecoder->decodeInt(&t, huffDTTable);
2254 arithDecoder->decodeInt(&t, iadtStats);
2260 while (inst < numInstances) {
2264 huffDecoder->decodeInt(&dt, huffDTTable);
2266 arithDecoder->decodeInt(&dt, iadtStats);
2272 huffDecoder->decodeInt(&ds, huffFSTable);
2274 arithDecoder->decodeInt(&ds, iafsStats);
2279 // read the instances
2286 dt = huffDecoder->readBits(logStrips);
2288 arithDecoder->decodeInt(&dt, iaitStats);
2295 huffDecoder->decodeInt(&j, symCodeTab);
2298 symID = huffDecoder->readBits(symCodeLen);
2301 symID = arithDecoder->decodeIAID(symCodeLen, iaidStats);
2304 // get the symbol bitmap
2305 symbolBitmap = NULL;
2308 ri = (int)huffDecoder->readBit();
2310 arithDecoder->decodeInt(&ri, iariStats);
2317 huffDecoder->decodeInt(&rdw, huffRDWTable);
2318 huffDecoder->decodeInt(&rdh, huffRDHTable);
2319 huffDecoder->decodeInt(&rdx, huffRDXTable);
2320 huffDecoder->decodeInt(&rdy, huffRDYTable);
2321 huffDecoder->decodeInt(&bmSize, huffRSizeTable);
2322 huffDecoder->reset();
2323 arithDecoder->start();
2325 arithDecoder->decodeInt(&rdw, iardwStats);
2326 arithDecoder->decodeInt(&rdh, iardhStats);
2327 arithDecoder->decodeInt(&rdx, iardxStats);
2328 arithDecoder->decodeInt(&rdy, iardyStats);
2330 refDX = ((rdw >= 0) ? rdw : rdw - 1) / 2 + rdx;
2331 refDY = ((rdh >= 0) ? rdh : rdh - 1) / 2 + rdy;
2334 readGenericRefinementRegion(rdw + syms[symID]->getWidth(),
2335 rdh + syms[symID]->getHeight(),
2336 templ, gFalse, syms[symID],
2337 refDX, refDY, atx, aty);
2338 //~ do we need to use the bmSize value here (in Huffman mode)?
2340 symbolBitmap = syms[symID];
2343 // combine the symbol bitmap into the region bitmap
2344 //~ something is wrong here - refCorner shouldn't degenerate into
2346 bw = symbolBitmap->getWidth() - 1;
2347 bh = symbolBitmap->getHeight() - 1;
2349 switch (refCorner) {
2350 case 0: // bottom left
2351 bitmap->combine(symbolBitmap, tt, s, combOp);
2354 bitmap->combine(symbolBitmap, tt, s, combOp);
2356 case 2: // bottom right
2357 bitmap->combine(symbolBitmap, tt - bw, s, combOp);
2359 case 3: // top right
2360 bitmap->combine(symbolBitmap, tt - bw, s, combOp);
2365 switch (refCorner) {
2366 case 0: // bottom left
2367 bitmap->combine(symbolBitmap, s, tt - bh, combOp);
2370 bitmap->combine(symbolBitmap, s, tt, combOp);
2372 case 2: // bottom right
2373 bitmap->combine(symbolBitmap, s, tt - bh, combOp);
2375 case 3: // top right
2376 bitmap->combine(symbolBitmap, s, tt, combOp);
2382 delete symbolBitmap;
2390 if (!huffDecoder->decodeInt(&ds, huffDSTable)) {
2394 if (!arithDecoder->decodeInt(&ds, iadsStats)) {
2405 void JBIG2Stream::readPatternDictSeg(Guint segNum, Guint length) {
2406 JBIG2PatternDict *patternDict;
2407 JBIG2Bitmap *bitmap;
2408 Guint flags, patternW, patternH, grayMax, templ, mmr;
2412 // halftone dictionary flags, pattern width and height, max gray value
2413 if (!readUByte(&flags) ||
2414 !readUByte(&patternW) ||
2415 !readUByte(&patternH) ||
2416 !readULong(&grayMax)) {
2419 templ = (flags >> 1) & 3;
2422 // set up the arithmetic decoder
2424 resetGenericStats(templ, NULL);
2425 arithDecoder->start();
2429 atx[0] = -patternW; aty[0] = 0;
2430 atx[1] = -3; aty[1] = -1;
2431 atx[2] = 2; aty[2] = -2;
2432 atx[3] = -2; aty[3] = -2;
2433 bitmap = readGenericBitmap(mmr, (grayMax + 1) * patternW, patternH,
2434 templ, gFalse, gFalse, NULL,
2435 atx, aty, length - 7);
2437 // create the pattern dict object
2438 patternDict = new JBIG2PatternDict(segNum, grayMax + 1);
2440 // split up the bitmap
2442 for (i = 0; i <= grayMax; ++i) {
2443 patternDict->setBitmap(i, bitmap->getSlice(x, 0, patternW, patternH));
2450 // store the new pattern dict
2451 segments->append(patternDict);
2456 error(getPos(), "Unexpected EOF in JBIG2 stream");
2459 void JBIG2Stream::readHalftoneRegionSeg(Guint segNum, GBool imm,
2460 GBool lossless, Guint length,
2461 Guint *refSegs, Guint nRefSegs) {
2462 JBIG2Bitmap *bitmap;
2464 JBIG2PatternDict *patternDict;
2465 JBIG2Bitmap *skipBitmap;
2467 JBIG2Bitmap *grayBitmap;
2468 JBIG2Bitmap *patternBitmap;
2469 Guint w, h, x, y, segInfoFlags, extCombOp;
2470 Guint flags, mmr, templ, enableSkip, combOp;
2471 Guint gridW, gridH, stepX, stepY, patW, patH;
2473 int gridX, gridY, xx, yy, bit, j;
2476 // region segment info field
2477 if (!readULong(&w) || !readULong(&h) ||
2478 !readULong(&x) || !readULong(&y) ||
2479 !readUByte(&segInfoFlags)) {
2482 extCombOp = segInfoFlags & 7;
2484 // rest of the halftone region header
2485 if (!readUByte(&flags)) {
2489 templ = (flags >> 1) & 3;
2490 enableSkip = (flags >> 3) & 1;
2491 combOp = (flags >> 4) & 7;
2492 if (!readULong(&gridW) || !readULong(&gridH) ||
2493 !readLong(&gridX) || !readLong(&gridY) ||
2494 !readUWord(&stepX) || !readUWord(&stepY)) {
2498 // get pattern dictionary
2499 if (nRefSegs != 1) {
2500 error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
2503 seg = findSegment(refSegs[0]);
2504 if (seg->getType() != jbig2SegPatternDict) {
2505 error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
2508 patternDict = (JBIG2PatternDict *)seg;
2511 while (i < patternDict->getSize()) {
2515 patW = patternDict->getBitmap(0)->getWidth();
2516 patH = patternDict->getBitmap(0)->getHeight();
2518 // set up the arithmetic decoder
2520 resetGenericStats(templ, NULL);
2521 arithDecoder->start();
2524 // allocate the bitmap
2525 bitmap = new JBIG2Bitmap(segNum, w, h);
2526 if (flags & 0x80) { // HDEFPIXEL
2527 bitmap->clearToOne();
2529 bitmap->clearToZero();
2532 // compute the skip bitmap
2535 skipBitmap = new JBIG2Bitmap(0, gridW, gridH);
2536 skipBitmap->clearToZero();
2537 for (m = 0; m < gridH; ++m) {
2538 xx = gridX + m * stepY;
2539 yy = gridY + m * stepX;
2540 for (n = 0; n < gridW; ++n) {
2541 if (((xx + (int)patW) >> 8) <= 0 || (xx >> 8) >= (int)w ||
2542 ((yy + (int)patH) >> 8) <= 0 || (yy >> 8) >= (int)h) {
2543 skipBitmap->setPixel(n, m);
2549 // read the gray-scale image
2550 grayImg = (Guint *)gmalloc(gridW * gridH * sizeof(Guint));
2551 memset(grayImg, 0, gridW * gridH * sizeof(Guint));
2552 atx[0] = templ <= 1 ? 3 : 2; aty[0] = -1;
2553 atx[1] = -3; aty[1] = -1;
2554 atx[2] = 2; aty[2] = -2;
2555 atx[3] = -2; aty[3] = -2;
2556 for (j = bpp - 1; j >= 0; --j) {
2557 grayBitmap = readGenericBitmap(mmr, gridW, gridH, templ, gFalse,
2558 enableSkip, skipBitmap, atx, aty, -1);
2560 for (m = 0; m < gridH; ++m) {
2561 for (n = 0; n < gridW; ++n) {
2562 bit = grayBitmap->getPixel(n, m) ^ (grayImg[i] & 1);
2563 grayImg[i] = (grayImg[i] << 1) | bit;
2572 for (m = 0; m < gridH; ++m) {
2573 xx = gridX + m * stepY;
2574 yy = gridY + m * stepX;
2575 for (n = 0; n < gridW; ++n) {
2576 if (!(enableSkip && skipBitmap->getPixel(n, m))) {
2577 patternBitmap = patternDict->getBitmap(grayImg[i]);
2578 bitmap->combine(patternBitmap, xx >> 8, yy >> 8, combOp);
2588 // combine the region bitmap into the page bitmap
2590 if (pageH == 0xffffffff && y + h > curPageH) {
2591 pageBitmap->expand(y + h, pageDefPixel);
2593 pageBitmap->combine(bitmap, x, y, extCombOp);
2596 // store the region bitmap
2598 segments->append(bitmap);
2604 error(getPos(), "Unexpected EOF in JBIG2 stream");
2607 void JBIG2Stream::readGenericRegionSeg(Guint segNum, GBool imm,
2608 GBool lossless, Guint length) {
2609 JBIG2Bitmap *bitmap;
2610 Guint w, h, x, y, segInfoFlags, extCombOp;
2611 Guint flags, mmr, templ, tpgdOn;
2614 // region segment info field
2615 if (!readULong(&w) || !readULong(&h) ||
2616 !readULong(&x) || !readULong(&y) ||
2617 !readUByte(&segInfoFlags)) {
2620 extCombOp = segInfoFlags & 7;
2622 // rest of the generic region segment header
2623 if (!readUByte(&flags)) {
2627 templ = (flags >> 1) & 3;
2628 tpgdOn = (flags >> 3) & 1;
2633 if (!readByte(&atx[0]) ||
2634 !readByte(&aty[0]) ||
2635 !readByte(&atx[1]) ||
2636 !readByte(&aty[1]) ||
2637 !readByte(&atx[2]) ||
2638 !readByte(&aty[2]) ||
2639 !readByte(&atx[3]) ||
2640 !readByte(&aty[3])) {
2644 if (!readByte(&atx[0]) ||
2645 !readByte(&aty[0])) {
2651 // set up the arithmetic decoder
2653 resetGenericStats(templ, NULL);
2654 arithDecoder->start();
2658 bitmap = readGenericBitmap(mmr, w, h, templ, tpgdOn, gFalse,
2659 NULL, atx, aty, mmr ? 0 : length - 18);
2661 // combine the region bitmap into the page bitmap
2663 if (pageH == 0xffffffff && y + h > curPageH) {
2664 pageBitmap->expand(y + h, pageDefPixel);
2666 pageBitmap->combine(bitmap, x, y, extCombOp);
2669 // store the region bitmap
2671 bitmap->setSegNum(segNum);
2672 segments->append(bitmap);
2678 error(getPos(), "Unexpected EOF in JBIG2 stream");
2681 JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h,
2682 int templ, GBool tpgdOn,
2683 GBool useSkip, JBIG2Bitmap *skip,
2685 int mmrDataLength) {
2686 JBIG2Bitmap *bitmap;
2688 Guint ltpCX, cx, cx0, cx1, cx2;
2689 int *refLine, *codingLine;
2690 int code1, code2, code3;
2691 int x, y, a0, pix, i, refI, codingI;
2693 bitmap = new JBIG2Bitmap(0, w, h);
2694 bitmap->clearToZero();
2700 mmrDecoder->reset();
2701 refLine = (int *)gmalloc((w + 2) * sizeof(int));
2702 codingLine = (int *)gmalloc((w + 2) * sizeof(int));
2703 codingLine[0] = codingLine[1] = w;
2705 for (y = 0; y < h; ++y) {
2707 // copy coding line to ref line
2708 for (i = 0; codingLine[i] < w; ++i) {
2709 refLine[i] = codingLine[i];
2711 refLine[i] = refLine[i + 1] = w;
2714 refI = 0; // b1 = refLine[refI]
2715 codingI = 0; // a1 = codingLine[codingI]
2718 code1 = mmrDecoder->get2DCode();
2721 if (refLine[refI] < w) {
2722 a0 = refLine[refI + 1];
2730 code1 += code3 = mmrDecoder->getBlackCode();
2731 } while (code3 >= 64);
2734 code2 += code3 = mmrDecoder->getWhiteCode();
2735 } while (code3 >= 64);
2739 code1 += code3 = mmrDecoder->getWhiteCode();
2740 } while (code3 >= 64);
2743 code2 += code3 = mmrDecoder->getBlackCode();
2744 } while (code3 >= 64);
2746 a0 = codingLine[codingI++] = a0 + code1;
2747 a0 = codingLine[codingI++] = a0 + code2;
2748 while (refLine[refI] <= a0 && refLine[refI] < w) {
2753 a0 = codingLine[codingI++] = refLine[refI];
2754 if (refLine[refI] < w) {
2759 a0 = codingLine[codingI++] = refLine[refI] + 1;
2760 if (refLine[refI] < w) {
2762 while (refLine[refI] <= a0 && refLine[refI] < w) {
2768 a0 = codingLine[codingI++] = refLine[refI] + 2;
2769 if (refLine[refI] < w) {
2771 while (refLine[refI] <= a0 && refLine[refI] < w) {
2777 a0 = codingLine[codingI++] = refLine[refI] + 3;
2778 if (refLine[refI] < w) {
2780 while (refLine[refI] <= a0 && refLine[refI] < w) {
2786 a0 = codingLine[codingI++] = refLine[refI] - 1;
2792 while (refLine[refI] <= a0 && refLine[refI] < w) {
2797 a0 = codingLine[codingI++] = refLine[refI] - 2;
2803 while (refLine[refI] <= a0 && refLine[refI] < w) {
2808 a0 = codingLine[codingI++] = refLine[refI] - 3;
2814 while (refLine[refI] <= a0 && refLine[refI] < w) {
2819 error(getPos(), "Illegal code in JBIG2 MMR bitmap data");
2823 codingLine[codingI++] = w;
2825 // convert the run lengths to a bitmap line
2827 while (codingLine[i] < w) {
2828 for (x = codingLine[i]; x < codingLine[i+1]; ++x) {
2829 bitmap->setPixel(x, y);
2835 if (mmrDataLength >= 0) {
2836 mmrDecoder->skipTo(mmrDataLength);
2838 if (mmrDecoder->get24Bits() != 0x001001) {
2839 error(getPos(), "Missing EOFB in JBIG2 MMR bitmap data");
2846 //----- arithmetic decode
2849 // set up the typical row context
2850 ltpCX = 0; // make gcc happy
2854 ltpCX = 0x3953; // 001 11001 0101 0011
2857 ltpCX = 0x079a; // 0011 11001 101 0
2860 ltpCX = 0x0e3; // 001 1100 01 1
2863 ltpCX = 0x18a; // 01100 0101 1
2869 cx = cx0 = cx1 = cx2 = 0; // make gcc happy
2870 for (y = 0; y < h; ++y) {
2872 // check for a "typical" (duplicate) row
2874 if (arithDecoder->decodeBit(ltpCX, genericRegionStats)) {
2878 bitmap->duplicateRow(y, y-1);
2883 // set up the context
2886 cx0 = (bitmap->getPixel(0, y-2) << 1) |
2887 bitmap->getPixel(1, y-2);
2888 cx1 = (bitmap->getPixel(0, y-1) << 2) |
2889 (bitmap->getPixel(1, y-1) << 1) |
2890 bitmap->getPixel(2, y-1);
2894 cx0 = (bitmap->getPixel(0, y-2) << 2) |
2895 (bitmap->getPixel(1, y-2) << 1) |
2896 bitmap->getPixel(2, y-2);
2897 cx1 = (bitmap->getPixel(0, y-1) << 2) |
2898 (bitmap->getPixel(1, y-1) << 1) |
2899 bitmap->getPixel(2, y-1);
2903 cx0 = (bitmap->getPixel(0, y-2) << 1) |
2904 bitmap->getPixel(1, y-2);
2905 cx1 = (bitmap->getPixel(0, y-1) << 1) |
2906 bitmap->getPixel(1, y-1);
2910 cx1 = (bitmap->getPixel(0, y-1) << 1) |
2911 bitmap->getPixel(1, y-1);
2917 for (x = 0; x < w; ++x) {
2919 // check for a skipped pixel
2920 if (useSkip && skip->getPixel(x, y)) {
2925 // build the context
2928 cx = (cx0 << 13) | (cx1 << 8) | (cx2 << 4) |
2929 (bitmap->getPixel(x + atx[0], y + aty[0]) << 3) |
2930 (bitmap->getPixel(x + atx[1], y + aty[1]) << 2) |
2931 (bitmap->getPixel(x + atx[2], y + aty[2]) << 1) |
2932 bitmap->getPixel(x + atx[3], y + aty[3]);
2935 cx = (cx0 << 9) | (cx1 << 4) | (cx2 << 1) |
2936 bitmap->getPixel(x + atx[0], y + aty[0]);
2939 cx = (cx0 << 7) | (cx1 << 3) | (cx2 << 1) |
2940 bitmap->getPixel(x + atx[0], y + aty[0]);
2943 cx = (cx1 << 5) | (cx2 << 1) |
2944 bitmap->getPixel(x + atx[0], y + aty[0]);
2949 if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
2950 bitmap->setPixel(x, y);
2954 // update the context
2957 cx0 = ((cx0 << 1) | bitmap->getPixel(x+2, y-2)) & 0x07;
2958 cx1 = ((cx1 << 1) | bitmap->getPixel(x+3, y-1)) & 0x1f;
2959 cx2 = ((cx2 << 1) | pix) & 0x0f;
2962 cx0 = ((cx0 << 1) | bitmap->getPixel(x+3, y-2)) & 0x0f;
2963 cx1 = ((cx1 << 1) | bitmap->getPixel(x+3, y-1)) & 0x1f;
2964 cx2 = ((cx2 << 1) | pix) & 0x07;
2967 cx0 = ((cx0 << 1) | bitmap->getPixel(x+2, y-2)) & 0x07;
2968 cx1 = ((cx1 << 1) | bitmap->getPixel(x+2, y-1)) & 0x0f;
2969 cx2 = ((cx2 << 1) | pix) & 0x03;
2972 cx1 = ((cx1 << 1) | bitmap->getPixel(x+2, y-1)) & 0x1f;
2973 cx2 = ((cx2 << 1) | pix) & 0x0f;
2983 void JBIG2Stream::readGenericRefinementRegionSeg(Guint segNum, GBool imm,
2984 GBool lossless, Guint length,
2987 JBIG2Bitmap *bitmap, *refBitmap;
2988 Guint w, h, x, y, segInfoFlags, extCombOp;
2989 Guint flags, templ, tpgrOn;
2993 // region segment info field
2994 if (!readULong(&w) || !readULong(&h) ||
2995 !readULong(&x) || !readULong(&y) ||
2996 !readUByte(&segInfoFlags)) {
2999 extCombOp = segInfoFlags & 7;
3001 // rest of the generic refinement region segment header
3002 if (!readUByte(&flags)) {
3006 tpgrOn = (flags >> 1) & 1;
3010 if (!readByte(&atx[0]) || !readByte(&aty[0]) ||
3011 !readByte(&atx[1]) || !readByte(&aty[1])) {
3016 // resize the page bitmap if needed
3017 if (nRefSegs == 0 || imm) {
3018 if (pageH == 0xffffffff && y + h > curPageH) {
3019 pageBitmap->expand(y + h, pageDefPixel);
3023 // get referenced bitmap
3025 error(getPos(), "Bad reference in JBIG2 generic refinement segment");
3028 if (nRefSegs == 1) {
3029 seg = findSegment(refSegs[0]);
3030 if (seg->getType() != jbig2SegBitmap) {
3031 error(getPos(), "Bad bitmap reference in JBIG2 generic refinement segment");
3034 refBitmap = (JBIG2Bitmap *)seg;
3036 refBitmap = pageBitmap->getSlice(x, y, w, h);
3039 // set up the arithmetic decoder
3040 resetRefinementStats(templ, NULL);
3041 arithDecoder->start();
3044 bitmap = readGenericRefinementRegion(w, h, templ, tpgrOn,
3045 refBitmap, 0, 0, atx, aty);
3047 // combine the region bitmap into the page bitmap
3049 pageBitmap->combine(bitmap, x, y, extCombOp);
3052 // store the region bitmap
3054 bitmap->setSegNum(segNum);
3055 segments->append(bitmap);
3058 // delete the referenced bitmap
3059 if (nRefSegs == 1) {
3060 discardSegment(refSegs[0]);
3068 error(getPos(), "Unexpected EOF in JBIG2 stream");
3071 JBIG2Bitmap *JBIG2Stream::readGenericRefinementRegion(int w, int h,
3072 int templ, GBool tpgrOn,
3073 JBIG2Bitmap *refBitmap,
3074 int refDX, int refDY,
3075 int *atx, int *aty) {
3076 JBIG2Bitmap *bitmap;
3078 Guint ltpCX, cx, cx0, cx2, cx3, cx4, tpgrCX0, tpgrCX1, tpgrCX2;
3081 bitmap = new JBIG2Bitmap(0, w, h);
3082 bitmap->clearToZero();
3084 // set up the typical row context
3092 for (y = 0; y < h; ++y) {
3094 // set up the context
3096 cx0 = bitmap->getPixel(0, y-1);
3098 cx3 = (refBitmap->getPixel(-1-refDX, y-refDY) << 1) |
3099 refBitmap->getPixel(-refDX, y-refDY);
3100 cx4 = refBitmap->getPixel(-refDX, y+1-refDY);
3102 cx0 = bitmap->getPixel(0, y-1);
3103 cx2 = refBitmap->getPixel(-refDX, y-1-refDY);
3104 cx3 = (refBitmap->getPixel(-1-refDX, y-refDY) << 1) |
3105 refBitmap->getPixel(-refDX, y-refDY);
3106 cx4 = (refBitmap->getPixel(-1-refDX, y+1-refDY) << 1) |
3107 refBitmap->getPixel(-refDX, y+1-refDY);
3110 // set up the typical prediction context
3111 tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy
3113 tpgrCX0 = (refBitmap->getPixel(-1-refDX, y-1-refDY) << 2) |
3114 (refBitmap->getPixel(-refDX, y-1-refDY) << 1) |
3115 refBitmap->getPixel(1-refDX, y-1-refDY);
3116 tpgrCX1 = (refBitmap->getPixel(-1-refDX, y-refDY) << 2) |
3117 (refBitmap->getPixel(-refDX, y-refDY) << 1) |
3118 refBitmap->getPixel(1-refDX, y-refDY);
3119 tpgrCX2 = (refBitmap->getPixel(-1-refDX, y+1-refDY) << 2) |
3120 (refBitmap->getPixel(-refDX, y+1-refDY) << 1) |
3121 refBitmap->getPixel(1-refDX, y+1-refDY);
3124 for (x = 0; x < w; ++x) {
3126 // update the context
3128 cx0 = ((cx0 << 1) | bitmap->getPixel(x+1, y-1)) & 7;
3129 cx3 = ((cx3 << 1) | refBitmap->getPixel(x+1-refDX, y-refDY)) & 7;
3130 cx4 = ((cx4 << 1) | refBitmap->getPixel(x+1-refDX, y+1-refDY)) & 3;
3132 cx0 = ((cx0 << 1) | bitmap->getPixel(x+1, y-1)) & 3;
3133 cx2 = ((cx2 << 1) | refBitmap->getPixel(x+1-refDX, y-1-refDY)) & 3;
3134 cx3 = ((cx3 << 1) | refBitmap->getPixel(x+1-refDX, y-refDY)) & 7;
3135 cx4 = ((cx4 << 1) | refBitmap->getPixel(x+1-refDX, y+1-refDY)) & 7;
3139 // update the typical predictor context
3140 tpgrCX0 = ((tpgrCX0 << 1) |
3141 refBitmap->getPixel(x+1-refDX, y-1-refDY)) & 7;
3142 tpgrCX1 = ((tpgrCX1 << 1) |
3143 refBitmap->getPixel(x+1-refDX, y-refDY)) & 7;
3144 tpgrCX2 = ((tpgrCX2 << 1) |
3145 refBitmap->getPixel(x+1-refDX, y+1-refDY)) & 7;
3147 // check for a "typical" pixel
3148 if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) {
3151 if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) {
3152 bitmap->clearPixel(x, y);
3154 } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) {
3155 bitmap->setPixel(x, y);
3160 // build the context
3162 cx = (cx0 << 7) | (bitmap->getPixel(x-1, y) << 6) |
3163 (refBitmap->getPixel(x-refDX, y-1-refDY) << 5) |
3166 cx = (cx0 << 11) | (bitmap->getPixel(x-1, y) << 10) |
3167 (cx2 << 8) | (cx3 << 5) | (cx4 << 2) |
3168 (bitmap->getPixel(x+atx[0], y+aty[0]) << 1) |
3169 refBitmap->getPixel(x+atx[1]-refDX, y+aty[1]-refDY);
3173 if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) {
3174 bitmap->setPixel(x, y);
3182 void JBIG2Stream::readPageInfoSeg(Guint length) {
3183 Guint xRes, yRes, flags, striping;
3185 if (!readULong(&pageW) || !readULong(&pageH) ||
3186 !readULong(&xRes) || !readULong(&yRes) ||
3187 !readUByte(&flags) || !readUWord(&striping)) {
3190 pageDefPixel = (flags >> 2) & 1;
3191 defCombOp = (flags >> 3) & 3;
3193 // allocate the page bitmap
3194 if (pageH == 0xffffffff) {
3195 curPageH = striping & 0x7fff;
3199 pageBitmap = new JBIG2Bitmap(0, pageW, curPageH);
3201 // default pixel value
3203 pageBitmap->clearToOne();
3205 pageBitmap->clearToZero();
3211 error(getPos(), "Unexpected EOF in JBIG2 stream");
3214 void JBIG2Stream::readEndOfStripeSeg(Guint length) {
3218 for (i = 0; i < length; ++i) {
3223 void JBIG2Stream::readProfilesSeg(Guint length) {
3227 for (i = 0; i < length; ++i) {
3232 void JBIG2Stream::readCodeTableSeg(Guint segNum, Guint length) {
3233 JBIG2HuffmanTable *huffTab;
3234 Guint flags, oob, prefixBits, rangeBits;
3235 int lowVal, highVal, val;
3236 Guint huffTabSize, i;
3238 if (!readUByte(&flags) || !readLong(&lowVal) || !readLong(&highVal)) {
3242 prefixBits = (flags >> 1) & 7;
3243 rangeBits = (flags >> 4) & 7;
3245 huffDecoder->reset();
3247 huffTab = (JBIG2HuffmanTable *)
3248 gmalloc(huffTabSize * sizeof(JBIG2HuffmanTable));
3251 while (val < highVal) {
3252 if (i == huffTabSize) {
3254 huffTab = (JBIG2HuffmanTable *)
3255 grealloc(huffTab, huffTabSize * sizeof(JBIG2HuffmanTable));
3257 huffTab[i].val = val;
3258 huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
3259 huffTab[i].rangeLen = huffDecoder->readBits(rangeBits);
3260 val += 1 << huffTab[i].rangeLen;
3263 if (i + oob + 3 > huffTabSize) {
3264 huffTabSize = i + oob + 3;
3265 huffTab = (JBIG2HuffmanTable *)
3266 grealloc(huffTab, huffTabSize * sizeof(JBIG2HuffmanTable));
3268 huffTab[i].val = lowVal - 1;
3269 huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
3270 huffTab[i].rangeLen = jbig2HuffmanLOW;
3272 huffTab[i].val = highVal;
3273 huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
3274 huffTab[i].rangeLen = 32;
3278 huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
3279 huffTab[i].rangeLen = jbig2HuffmanOOB;
3283 huffTab[i].prefixLen = 0;
3284 huffTab[i].rangeLen = jbig2HuffmanEOT;
3286 huffDecoder->buildTable(huffTab, i);
3288 // create and store the new table segment
3289 segments->append(new JBIG2CodeTable(segNum, huffTab));
3294 error(getPos(), "Unexpected EOF in JBIG2 stream");
3297 void JBIG2Stream::readExtensionSeg(Guint length) {
3301 for (i = 0; i < length; ++i) {
3306 JBIG2Segment *JBIG2Stream::findSegment(Guint segNum) {
3310 for (i = 0; i < globalSegments->getLength(); ++i) {
3311 seg = (JBIG2Segment *)globalSegments->get(i);
3312 if (seg->getSegNum() == segNum) {
3316 for (i = 0; i < segments->getLength(); ++i) {
3317 seg = (JBIG2Segment *)segments->get(i);
3318 if (seg->getSegNum() == segNum) {
3325 void JBIG2Stream::discardSegment(Guint segNum) {
3329 for (i = 0; i < globalSegments->getLength(); ++i) {
3330 seg = (JBIG2Segment *)globalSegments->get(i);
3331 if (seg->getSegNum() == segNum) {
3332 globalSegments->del(i);
3336 for (i = 0; i < segments->getLength(); ++i) {
3337 seg = (JBIG2Segment *)segments->get(i);
3338 if (seg->getSegNum() == segNum) {
3339 globalSegments->del(i);
3345 void JBIG2Stream::resetGenericStats(Guint templ,
3346 JBIG2ArithmeticDecoderStats *prevStats) {
3349 size = contextSize[templ];
3350 if (prevStats && prevStats->getContextSize() == size) {
3351 if (genericRegionStats->getContextSize() == size) {
3352 genericRegionStats->copyFrom(prevStats);
3354 delete genericRegionStats;
3355 genericRegionStats = prevStats->copy();
3358 if (genericRegionStats->getContextSize() == size) {
3359 genericRegionStats->reset();
3361 delete genericRegionStats;
3362 genericRegionStats = new JBIG2ArithmeticDecoderStats(size);
3367 void JBIG2Stream::resetRefinementStats(
3369 JBIG2ArithmeticDecoderStats *prevStats) {
3372 size = refContextSize[templ];
3373 if (prevStats && prevStats->getContextSize() == size) {
3374 if (refinementRegionStats->getContextSize() == size) {
3375 refinementRegionStats->copyFrom(prevStats);
3377 delete refinementRegionStats;
3378 refinementRegionStats = prevStats->copy();
3381 if (refinementRegionStats->getContextSize() == size) {
3382 refinementRegionStats->reset();
3384 delete refinementRegionStats;
3385 refinementRegionStats = new JBIG2ArithmeticDecoderStats(size);
3390 void JBIG2Stream::resetIntStats(int symCodeLen) {
3399 iardxStats->reset();
3400 iardyStats->reset();
3401 iardwStats->reset();
3402 iardhStats->reset();
3404 if (iaidStats->getContextSize() == symCodeLen + 1) {
3408 iaidStats = new JBIG2ArithmeticDecoderStats(symCodeLen + 1);
3412 GBool JBIG2Stream::readUByte(Guint *x) {
3415 if ((c0 = curStr->getChar()) == EOF) {
3422 GBool JBIG2Stream::readByte(int *x) {
3425 if ((c0 = curStr->getChar()) == EOF) {
3435 GBool JBIG2Stream::readUWord(Guint *x) {
3438 if ((c0 = curStr->getChar()) == EOF ||
3439 (c1 = curStr->getChar()) == EOF) {
3442 *x = (Guint)((c0 << 8) | c1);
3446 GBool JBIG2Stream::readULong(Guint *x) {
3449 if ((c0 = curStr->getChar()) == EOF ||
3450 (c1 = curStr->getChar()) == EOF ||
3451 (c2 = curStr->getChar()) == EOF ||
3452 (c3 = curStr->getChar()) == EOF) {
3455 *x = (Guint)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
3459 GBool JBIG2Stream::readLong(int *x) {
3462 if ((c0 = curStr->getChar()) == EOF ||
3463 (c1 = curStr->getChar()) == EOF ||
3464 (c2 = curStr->getChar()) == EOF ||
3465 (c3 = curStr->getChar()) == EOF) {
3468 *x = ((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
3470 *x |= -1 - 0xffffffff;