1
//========================================================================
5
// Copyright 2002-2003 Glyph & Cog, LLC
7
//========================================================================
11
#ifdef USE_GCC_PRAGMAS
12
#pragma implementation
19
#include "JArithmeticDecoder.h"
20
#include "JBIG2Stream.h"
22
//~ share these tables
23
#include "Stream-CCITT.h"
25
//------------------------------------------------------------------------
27
static int contextSize[4] = { 16, 13, 10, 10 };
28
static int refContextSize[2] = { 13, 10 };
30
//------------------------------------------------------------------------
32
//------------------------------------------------------------------------
34
#define jbig2HuffmanLOW 0xfffffffd
35
#define jbig2HuffmanOOB 0xfffffffe
36
#define jbig2HuffmanEOT 0xffffffff
38
struct JBIG2HuffmanTable {
41
Guint rangeLen; // can also be LOW, OOB, or EOT
45
JBIG2HuffmanTable huffTableA[] = {
48
{ 272, 3, 16, 0x006 },
49
{ 65808, 3, 32, 0x007 },
50
{ 0, 0, jbig2HuffmanEOT, 0 }
53
JBIG2HuffmanTable huffTableB[] = {
60
{ 0, 6, jbig2HuffmanOOB, 0x03f },
61
{ 0, 0, jbig2HuffmanEOT, 0 }
64
JBIG2HuffmanTable huffTableC[] = {
70
{ 0, 6, jbig2HuffmanOOB, 0x03e },
72
{ -256, 8, 8, 0x0fe },
73
{ -257, 8, jbig2HuffmanLOW, 0x0ff },
74
{ 0, 0, jbig2HuffmanEOT, 0 }
77
JBIG2HuffmanTable huffTableD[] = {
84
{ 0, 0, jbig2HuffmanEOT, 0 }
87
JBIG2HuffmanTable huffTableE[] = {
94
{ -255, 7, 8, 0x07e },
95
{ -256, 7, jbig2HuffmanLOW, 0x07f },
96
{ 0, 0, jbig2HuffmanEOT, 0 }
99
JBIG2HuffmanTable huffTableF[] = {
101
{ 128, 3, 7, 0x002 },
102
{ 256, 3, 8, 0x003 },
103
{ -1024, 4, 9, 0x008 },
104
{ -512, 4, 8, 0x009 },
105
{ -256, 4, 7, 0x00a },
106
{ -32, 4, 5, 0x00b },
107
{ 512, 4, 9, 0x00c },
108
{ 1024, 4, 10, 0x00d },
109
{ -2048, 5, 10, 0x01c },
110
{ -128, 5, 6, 0x01d },
111
{ -64, 5, 5, 0x01e },
112
{ -2049, 6, jbig2HuffmanLOW, 0x03e },
113
{ 2048, 6, 32, 0x03f },
114
{ 0, 0, jbig2HuffmanEOT, 0 }
117
JBIG2HuffmanTable huffTableG[] = {
118
{ -512, 3, 8, 0x000 },
119
{ 256, 3, 8, 0x001 },
120
{ 512, 3, 9, 0x002 },
121
{ 1024, 3, 10, 0x003 },
122
{ -1024, 4, 9, 0x008 },
123
{ -256, 4, 7, 0x009 },
124
{ -32, 4, 5, 0x00a },
126
{ 128, 4, 7, 0x00c },
127
{ -128, 5, 6, 0x01a },
128
{ -64, 5, 5, 0x01b },
131
{ -1025, 5, jbig2HuffmanLOW, 0x01e },
132
{ 2048, 5, 32, 0x01f },
133
{ 0, 0, jbig2HuffmanEOT, 0 }
136
JBIG2HuffmanTable huffTableH[] = {
138
{ 0, 2, jbig2HuffmanOOB, 0x001 },
145
{ 134, 5, 7, 0x01c },
148
{ 262, 6, 7, 0x03c },
149
{ 646, 6, 10, 0x03d },
151
{ 390, 7, 8, 0x07d },
152
{ -15, 8, 3, 0x0fc },
156
{ -16, 9, jbig2HuffmanLOW, 0x1fe },
157
{ 1670, 9, 32, 0x1ff },
158
{ 0, 0, jbig2HuffmanEOT, 0 }
161
JBIG2HuffmanTable huffTableI[] = {
162
{ 0, 2, jbig2HuffmanOOB, 0x000 },
170
{ 139, 5, 7, 0x01b },
171
{ 267, 5, 8, 0x01c },
174
{ 523, 6, 8, 0x03c },
175
{ 1291, 6, 11, 0x03d },
177
{ 779, 7, 9, 0x07d },
178
{ -31, 8, 4, 0x0fc },
179
{ -11, 8, 2, 0x0fd },
180
{ -15, 9, 2, 0x1fc },
182
{ -32, 9, jbig2HuffmanLOW, 0x1fe },
183
{ 3339, 9, 32, 0x1ff },
184
{ 0, 0, jbig2HuffmanEOT, 0 }
187
JBIG2HuffmanTable huffTableJ[] = {
190
{ 0, 2, jbig2HuffmanOOB, 0x002 },
195
{ 102, 6, 5, 0x037 },
196
{ 134, 6, 6, 0x038 },
197
{ 198, 6, 7, 0x039 },
198
{ 326, 6, 8, 0x03a },
199
{ 582, 6, 9, 0x03b },
200
{ 1094, 6, 10, 0x03c },
201
{ -21, 7, 4, 0x07a },
204
{ 2118, 7, 11, 0x07d },
207
{ -22, 8, jbig2HuffmanLOW, 0x0fe },
208
{ 4166, 8, 32, 0x0ff },
209
{ 0, 0, jbig2HuffmanEOT, 0 }
212
JBIG2HuffmanTable huffTableK[] = {
225
{ 141, 7, 32, 0x07f },
226
{ 0, 0, jbig2HuffmanEOT, 0 }
229
JBIG2HuffmanTable huffTableL[] = {
242
{ 73, 8, 32, 0x0ff },
243
{ 0, 0, jbig2HuffmanEOT, 0 }
246
JBIG2HuffmanTable huffTableM[] = {
259
{ 141, 7, 32, 0x07f },
260
{ 0, 0, jbig2HuffmanEOT, 0 }
263
JBIG2HuffmanTable huffTableN[] = {
269
{ 0, 0, jbig2HuffmanEOT, 0 }
272
JBIG2HuffmanTable huffTableO[] = {
282
{ -24, 7, 4, 0x07c },
284
{ -25, 7, jbig2HuffmanLOW, 0x07e },
285
{ 25, 7, 32, 0x07f },
286
{ 0, 0, jbig2HuffmanEOT, 0 }
289
//------------------------------------------------------------------------
290
// JBIG2HuffmanDecoder
291
//------------------------------------------------------------------------
293
class JBIG2HuffmanDecoder {
296
JBIG2HuffmanDecoder();
297
~JBIG2HuffmanDecoder();
298
void setStream(Stream *strA) { str = strA; }
302
// Returns false for OOB, otherwise sets *<x> and returns true.
303
GBool decodeInt(int *x, JBIG2HuffmanTable *table);
305
Guint readBits(Guint n);
308
// Sort the table by prefix length and assign prefix values.
309
void buildTable(JBIG2HuffmanTable *table, Guint len);
318
JBIG2HuffmanDecoder::JBIG2HuffmanDecoder() {
323
JBIG2HuffmanDecoder::~JBIG2HuffmanDecoder() {
326
void JBIG2HuffmanDecoder::reset() {
332
GBool JBIG2HuffmanDecoder::decodeInt(int *x, JBIG2HuffmanTable *table) {
333
Guint i, len, prefix;
338
while (table[i].rangeLen != jbig2HuffmanEOT) {
339
while (len < table[i].prefixLen) {
340
prefix = (prefix << 1) | readBit();
343
if (prefix == table[i].prefix) {
344
if (table[i].rangeLen == jbig2HuffmanOOB) {
347
if (table[i].rangeLen == jbig2HuffmanLOW) {
348
*x = table[i].val - readBits(32);
349
} else if (table[i].rangeLen > 0) {
350
*x = table[i].val + readBits(table[i].rangeLen);
361
Guint JBIG2HuffmanDecoder::readBits(Guint n) {
362
Guint x, mask, nLeft;
364
mask = (n == 32) ? 0xffffffff : ((1 << n) - 1);
366
x = (buf >> (bufLen - n)) & mask;
369
x = buf & ((1 << bufLen) - 1);
373
x = (x << 8) | (str->getChar() & 0xff);
377
buf = str->getChar();
379
x = (x << nLeft) | ((buf >> bufLen) & ((1 << nLeft) - 1));
385
Guint JBIG2HuffmanDecoder::readBit() {
387
buf = str->getChar();
391
return (buf >> bufLen) & 1;
394
void JBIG2HuffmanDecoder::buildTable(JBIG2HuffmanTable *table, Guint len) {
395
Guint i, j, k, prefix;
396
JBIG2HuffmanTable tab;
398
// stable selection sort:
399
// - entries with prefixLen > 0, in ascending prefixLen order
400
// - entry with prefixLen = 0, rangeLen = EOT
401
// - all other entries with prefixLen = 0
402
// (on entry, table[len] has prefixLen = 0, rangeLen = EOT)
403
for (i = 0; i < len; ++i) {
404
for (j = i; j < len && table[j].prefixLen == 0; ++j) ;
408
for (k = j + 1; k < len; ++k) {
409
if (table[k].prefixLen > 0 &&
410
table[k].prefixLen < table[j].prefixLen) {
416
for (k = j; k > i; --k) {
417
table[k] = table[k - 1];
422
table[i] = table[len];
427
table[i++].prefix = prefix++;
428
for (; table[i].rangeLen != jbig2HuffmanEOT; ++i) {
429
prefix <<= table[i].prefixLen - table[i-1].prefixLen;
430
table[i].prefix = prefix++;
434
//------------------------------------------------------------------------
436
//------------------------------------------------------------------------
438
class JBIG2MMRDecoder {
443
void setStream(Stream *strA) { str = strA; }
449
void skipTo(Guint length);
459
JBIG2MMRDecoder::JBIG2MMRDecoder() {
464
JBIG2MMRDecoder::~JBIG2MMRDecoder() {
467
void JBIG2MMRDecoder::reset() {
473
int JBIG2MMRDecoder::get2DCode() {
477
buf = str->getChar() & 0xff;
480
p = &twoDimTab1[(buf >> 1) & 0x7f];
481
} else if (bufLen == 8) {
482
p = &twoDimTab1[(buf >> 1) & 0x7f];
484
p = &twoDimTab1[(buf << (7 - bufLen)) & 0x7f];
485
if (p->bits < 0 || p->bits > (int)bufLen) {
486
buf = (buf << 8) | (str->getChar() & 0xff);
489
p = &twoDimTab1[(buf >> (bufLen - 7)) & 0x7f];
493
error(str->getPos(), "Bad two dim code in JBIG2 MMR stream");
500
int JBIG2MMRDecoder::getWhiteCode() {
505
buf = str->getChar() & 0xff;
510
if (bufLen >= 7 && ((buf >> (bufLen - 7)) & 0x7f) == 0) {
512
code = buf << (12 - bufLen);
514
code = buf >> (bufLen - 12);
516
p = &whiteTab1[code & 0x1f];
519
code = buf << (9 - bufLen);
521
code = buf >> (bufLen - 9);
523
p = &whiteTab2[code & 0x1ff];
525
if (p->bits > 0 && p->bits <= (int)bufLen) {
532
buf = (buf << 8) | (str->getChar() & 0xff);
536
error(str->getPos(), "Bad white code in JBIG2 MMR stream");
537
// eat a bit and return a positive number so that the caller doesn't
538
// go into an infinite loop
543
int JBIG2MMRDecoder::getBlackCode() {
548
buf = str->getChar() & 0xff;
553
if (bufLen >= 6 && ((buf >> (bufLen - 6)) & 0x3f) == 0) {
555
code = buf << (13 - bufLen);
557
code = buf >> (bufLen - 13);
559
p = &blackTab1[code & 0x7f];
560
} else if (bufLen >= 4 && ((buf >> (bufLen - 4)) & 0x0f) == 0) {
562
code = buf << (12 - bufLen);
564
code = buf >> (bufLen - 12);
566
p = &blackTab2[(code & 0xff) - 64];
569
code = buf << (6 - bufLen);
571
code = buf >> (bufLen - 6);
573
p = &blackTab3[code & 0x3f];
575
if (p->bits > 0 && p->bits <= (int)bufLen) {
582
buf = (buf << 8) | (str->getChar() & 0xff);
586
error(str->getPos(), "Bad black code in JBIG2 MMR stream");
587
// eat a bit and return a positive number so that the caller doesn't
588
// go into an infinite loop
593
Guint JBIG2MMRDecoder::get24Bits() {
594
while (bufLen < 24) {
595
buf = (buf << 8) | (str->getChar() & 0xff);
599
return (buf >> (bufLen - 24)) & 0xffffff;
602
void JBIG2MMRDecoder::skipTo(Guint length) {
603
while (nBytesRead < length) {
609
//------------------------------------------------------------------------
611
//------------------------------------------------------------------------
613
enum JBIG2SegmentType {
623
JBIG2Segment(Guint segNumA) { segNum = segNumA; }
624
virtual ~JBIG2Segment() {}
625
void setSegNum(Guint segNumA) { segNum = segNumA; }
626
Guint getSegNum() { return segNum; }
627
virtual JBIG2SegmentType getType() = 0;
634
//------------------------------------------------------------------------
636
//------------------------------------------------------------------------
638
struct JBIG2BitmapPtr {
644
class JBIG2Bitmap: public JBIG2Segment {
647
JBIG2Bitmap(Guint segNumA, int wA, int hA);
648
virtual ~JBIG2Bitmap();
649
virtual JBIG2SegmentType getType() { return jbig2SegBitmap; }
650
JBIG2Bitmap *copy() { return new JBIG2Bitmap(0, this); }
651
JBIG2Bitmap *getSlice(Guint x, Guint y, Guint wA, Guint hA);
652
void expand(int newH, Guint pixel);
655
int getWidth() { return w; }
656
int getHeight() { return h; }
657
int getPixel(int x, int y)
658
{ return (x < 0 || x >= w || y < 0 || y >= h) ? 0 :
659
(data[y * line + (x >> 3)] >> (7 - (x & 7))) & 1; }
660
void setPixel(int x, int y)
661
{ data[y * line + (x >> 3)] |= 1 << (7 - (x & 7)); }
662
void clearPixel(int x, int y)
663
{ data[y * line + (x >> 3)] &= 0x7f7f >> (x & 7); }
664
void getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr);
665
int nextPixel(JBIG2BitmapPtr *ptr);
666
void duplicateRow(int yDest, int ySrc);
667
void combine(JBIG2Bitmap *bitmap, int x, int y, Guint combOp);
668
Guchar *getDataPtr() { return data; }
669
int getDataSize() { return h * line; }
673
JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap);
679
JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, int wA, int hA):
680
JBIG2Segment(segNumA)
684
line = (wA + 7) >> 3;
685
if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) {
689
// need to allocate one extra guard byte for use in combine()
690
data = (Guchar *)gmalloc(h * line + 1);
694
JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap):
695
JBIG2Segment(segNumA)
700
if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) {
704
// need to allocate one extra guard byte for use in combine()
705
data = (Guchar *)gmalloc(h * line + 1);
706
memcpy(data, bitmap->data, h * line);
710
JBIG2Bitmap::~JBIG2Bitmap() {
715
JBIG2Bitmap *JBIG2Bitmap::getSlice(Guint x, Guint y, Guint wA, Guint hA) {
719
slice = new JBIG2Bitmap(0, wA, hA);
720
slice->clearToZero();
721
for (yy = 0; yy < hA; ++yy) {
722
for (xx = 0; xx < wA; ++xx) {
723
if (getPixel(x + xx, y + yy)) {
724
slice->setPixel(xx, yy);
731
void JBIG2Bitmap::expand(int newH, Guint pixel) {
732
if (newH <= h || line <= 0 || newH >= (INT_MAX - 1) / line) {
735
// need to allocate one extra guard byte for use in combine()
736
data = (Guchar *)grealloc(data, newH * line + 1);
738
memset(data + h * line, 0xff, (newH - h) * line);
740
memset(data + h * line, 0x00, (newH - h) * line);
746
void JBIG2Bitmap::clearToZero() {
747
memset(data, 0, h * line);
750
void JBIG2Bitmap::clearToOne() {
751
memset(data, 0xff, h * line);
754
inline void JBIG2Bitmap::getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr) {
755
if (y < 0 || y >= h || x >= w) {
758
ptr->p = &data[y * line];
762
ptr->p = &data[y * line + (x >> 3)];
763
ptr->shift = 7 - (x & 7);
768
inline int JBIG2Bitmap::nextPixel(JBIG2BitmapPtr *ptr) {
773
} else if (ptr->x < 0) {
777
pix = (*ptr->p >> ptr->shift) & 1;
780
} else if (ptr->shift == 0) {
790
void JBIG2Bitmap::duplicateRow(int yDest, int ySrc) {
791
memcpy(data + yDest * line, data + ySrc * line, line);
794
void JBIG2Bitmap::combine(JBIG2Bitmap *bitmap, int x, int y,
796
int x0, x1, y0, y1, xx, yy;
797
Guchar *srcPtr, *destPtr;
798
Guint src0, src1, src, dest, s1, s2, m1, m2, m3;
806
if (y + bitmap->h > h) {
830
m1 = 0xff >> (x1 & 7);
831
m2 = 0xff << (((x1 & 7) == 0) ? 0 : 8 - (x1 & 7));
832
m3 = (0xff >> s1) & m2;
834
oneByte = x0 == ((x1 - 1) & ~7);
836
for (yy = y0; yy < y1; ++yy) {
838
// one byte per line -- need to mask both left and right side
841
destPtr = data + (y + yy) * line + (x >> 3);
842
srcPtr = bitmap->data + yy * bitmap->line;
847
dest |= (src1 >> s1) & m2;
850
dest &= ((0xff00 | src1) >> s1) | m1;
853
dest ^= (src1 >> s1) & m2;
856
dest ^= ((src1 ^ 0xff) >> s1) & m2;
859
dest = (dest & ~m3) | ((src1 >> s1) & m3);
864
destPtr = data + (y + yy) * line;
865
srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3);
879
dest ^= (src1 ^ 0xff) & m2;
882
dest = (src1 & m2) | (dest & m1);
888
// multiple bytes per line -- need to mask left side of left-most
889
// byte and right side of right-most byte
894
destPtr = data + (y + yy) * line + (x >> 3);
895
srcPtr = bitmap->data + yy * bitmap->line;
903
dest &= (0xff00 | src1) >> s1;
909
dest ^= (src1 ^ 0xff) >> s1;
912
dest = (dest & (0xff << s2)) | (src1 >> s1);
918
destPtr = data + (y + yy) * line;
919
srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3);
925
for (; xx < x1 - 8; xx += 8) {
929
src = (((src0 << 8) | src1) >> s1) & 0xff;
951
// note: this last byte (src1) may not actually be used, depending
952
// on the values of s1, m1, and m2 - and in fact, it may be off
953
// the edge of the source bitmap, which means we need to allocate
954
// one extra guard byte at the end of each bitmap
958
src = (((src0 << 8) | src1) >> s1) & 0xff;
970
dest ^= (src ^ 0xff) & m2;
973
dest = (src & m2) | (dest & m1);
981
//------------------------------------------------------------------------
983
//------------------------------------------------------------------------
985
class JBIG2SymbolDict: public JBIG2Segment {
988
JBIG2SymbolDict(Guint segNumA, Guint sizeA);
989
virtual ~JBIG2SymbolDict();
990
virtual JBIG2SegmentType getType() { return jbig2SegSymbolDict; }
991
Guint getSize() { return size; }
992
void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; }
993
JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; }
994
void setGenericRegionStats(JArithmeticDecoderStats *stats)
995
{ genericRegionStats = stats; }
996
void setRefinementRegionStats(JArithmeticDecoderStats *stats)
997
{ refinementRegionStats = stats; }
998
JArithmeticDecoderStats *getGenericRegionStats()
999
{ return genericRegionStats; }
1000
JArithmeticDecoderStats *getRefinementRegionStats()
1001
{ return refinementRegionStats; }
1006
JBIG2Bitmap **bitmaps;
1007
JArithmeticDecoderStats *genericRegionStats;
1008
JArithmeticDecoderStats *refinementRegionStats;
1011
JBIG2SymbolDict::JBIG2SymbolDict(Guint segNumA, Guint sizeA):
1012
JBIG2Segment(segNumA)
1015
bitmaps = (JBIG2Bitmap **)gmallocn(size, sizeof(JBIG2Bitmap *));
1016
genericRegionStats = NULL;
1017
refinementRegionStats = NULL;
1020
JBIG2SymbolDict::~JBIG2SymbolDict() {
1023
for (i = 0; i < size; ++i) {
1027
if (genericRegionStats) {
1028
delete genericRegionStats;
1030
if (refinementRegionStats) {
1031
delete refinementRegionStats;
1035
//------------------------------------------------------------------------
1037
//------------------------------------------------------------------------
1039
class JBIG2PatternDict: public JBIG2Segment {
1042
JBIG2PatternDict(Guint segNumA, Guint sizeA);
1043
virtual ~JBIG2PatternDict();
1044
virtual JBIG2SegmentType getType() { return jbig2SegPatternDict; }
1045
Guint getSize() { return size; }
1046
void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; }
1047
JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; }
1052
JBIG2Bitmap **bitmaps;
1055
JBIG2PatternDict::JBIG2PatternDict(Guint segNumA, Guint sizeA):
1056
JBIG2Segment(segNumA)
1059
bitmaps = (JBIG2Bitmap **)gmallocn(size, sizeof(JBIG2Bitmap *));
1062
JBIG2PatternDict::~JBIG2PatternDict() {
1065
for (i = 0; i < size; ++i) {
1071
//------------------------------------------------------------------------
1073
//------------------------------------------------------------------------
1075
class JBIG2CodeTable: public JBIG2Segment {
1078
JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA);
1079
virtual ~JBIG2CodeTable();
1080
virtual JBIG2SegmentType getType() { return jbig2SegCodeTable; }
1081
JBIG2HuffmanTable *getHuffTable() { return table; }
1085
JBIG2HuffmanTable *table;
1088
JBIG2CodeTable::JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA):
1089
JBIG2Segment(segNumA)
1094
JBIG2CodeTable::~JBIG2CodeTable() {
1098
//------------------------------------------------------------------------
1100
//------------------------------------------------------------------------
1102
JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStreamA):
1107
arithDecoder = new JArithmeticDecoder();
1108
genericRegionStats = new JArithmeticDecoderStats(1 << 1);
1109
refinementRegionStats = new JArithmeticDecoderStats(1 << 1);
1110
iadhStats = new JArithmeticDecoderStats(1 << 9);
1111
iadwStats = new JArithmeticDecoderStats(1 << 9);
1112
iaexStats = new JArithmeticDecoderStats(1 << 9);
1113
iaaiStats = new JArithmeticDecoderStats(1 << 9);
1114
iadtStats = new JArithmeticDecoderStats(1 << 9);
1115
iaitStats = new JArithmeticDecoderStats(1 << 9);
1116
iafsStats = new JArithmeticDecoderStats(1 << 9);
1117
iadsStats = new JArithmeticDecoderStats(1 << 9);
1118
iardxStats = new JArithmeticDecoderStats(1 << 9);
1119
iardyStats = new JArithmeticDecoderStats(1 << 9);
1120
iardwStats = new JArithmeticDecoderStats(1 << 9);
1121
iardhStats = new JArithmeticDecoderStats(1 << 9);
1122
iariStats = new JArithmeticDecoderStats(1 << 9);
1123
iaidStats = new JArithmeticDecoderStats(1 << 1);
1124
huffDecoder = new JBIG2HuffmanDecoder();
1125
mmrDecoder = new JBIG2MMRDecoder();
1127
globalsStreamA->copy(&globalsStream);
1128
segments = globalSegments = NULL;
1130
dataPtr = dataEnd = NULL;
1133
JBIG2Stream::~JBIG2Stream() {
1135
globalsStream.free();
1136
delete arithDecoder;
1137
delete genericRegionStats;
1138
delete refinementRegionStats;
1158
void JBIG2Stream::reset() {
1159
// read the globals stream
1160
globalSegments = new GList();
1161
if (globalsStream.isStream()) {
1162
segments = globalSegments;
1163
curStr = globalsStream.getStream();
1165
arithDecoder->setStream(curStr);
1166
huffDecoder->setStream(curStr);
1167
mmrDecoder->setStream(curStr);
1172
// read the main stream
1173
segments = new GList();
1176
arithDecoder->setStream(curStr);
1177
huffDecoder->setStream(curStr);
1178
mmrDecoder->setStream(curStr);
1182
dataPtr = pageBitmap->getDataPtr();
1183
dataEnd = dataPtr + pageBitmap->getDataSize();
1185
dataPtr = dataEnd = NULL;
1189
void JBIG2Stream::close() {
1195
deleteGList(segments, JBIG2Segment);
1198
if (globalSegments) {
1199
deleteGList(globalSegments, JBIG2Segment);
1200
globalSegments = NULL;
1202
dataPtr = dataEnd = NULL;
1203
FilterStream::close();
1206
int JBIG2Stream::getChar() {
1207
if (dataPtr && dataPtr < dataEnd) {
1208
return (*dataPtr++ ^ 0xff) & 0xff;
1213
int JBIG2Stream::lookChar() {
1214
if (dataPtr && dataPtr < dataEnd) {
1215
return (*dataPtr ^ 0xff) & 0xff;
1220
GString *JBIG2Stream::getPSFilter(int psLevel, char *indent) {
1224
GBool JBIG2Stream::isBinary(GBool last) {
1225
return str->isBinary(gTrue);
1228
void JBIG2Stream::readSegments() {
1229
Guint segNum, segFlags, segType, page, segLength;
1230
Guint refFlags, nRefSegs;
1235
while (readULong(&segNum)) {
1237
// segment header flags
1238
if (!readUByte(&segFlags)) {
1241
segType = segFlags & 0x3f;
1243
// referred-to segment count and retention flags
1244
if (!readUByte(&refFlags)) {
1247
nRefSegs = refFlags >> 5;
1248
if (nRefSegs == 7) {
1249
if ((c1 = curStr->getChar()) == EOF ||
1250
(c2 = curStr->getChar()) == EOF ||
1251
(c3 = curStr->getChar()) == EOF) {
1254
refFlags = (refFlags << 24) | (c1 << 16) | (c2 << 8) | c3;
1255
nRefSegs = refFlags & 0x1fffffff;
1256
for (i = 0; i < (nRefSegs + 9) >> 3; ++i) {
1257
c1 = curStr->getChar();
1261
// referred-to segment numbers
1262
refSegs = (Guint *)gmallocn(nRefSegs, sizeof(Guint));
1263
if (segNum <= 256) {
1264
for (i = 0; i < nRefSegs; ++i) {
1265
if (!readUByte(&refSegs[i])) {
1269
} else if (segNum <= 65536) {
1270
for (i = 0; i < nRefSegs; ++i) {
1271
if (!readUWord(&refSegs[i])) {
1276
for (i = 0; i < nRefSegs; ++i) {
1277
if (!readULong(&refSegs[i])) {
1283
// segment page association
1284
if (segFlags & 0x40) {
1285
if (!readULong(&page)) {
1289
if (!readUByte(&page)) {
1294
// segment data length
1295
if (!readULong(&segLength)) {
1299
// read the segment data
1302
if (!readSymbolDictSeg(segNum, segLength, refSegs, nRefSegs)) {
1307
readTextRegionSeg(segNum, gFalse, gFalse, segLength, refSegs, nRefSegs);
1310
readTextRegionSeg(segNum, gTrue, gFalse, segLength, refSegs, nRefSegs);
1313
readTextRegionSeg(segNum, gTrue, gTrue, segLength, refSegs, nRefSegs);
1316
readPatternDictSeg(segNum, segLength);
1319
readHalftoneRegionSeg(segNum, gFalse, gFalse, segLength,
1323
readHalftoneRegionSeg(segNum, gTrue, gFalse, segLength,
1327
readHalftoneRegionSeg(segNum, gTrue, gTrue, segLength,
1331
readGenericRegionSeg(segNum, gFalse, gFalse, segLength);
1334
readGenericRegionSeg(segNum, gTrue, gFalse, segLength);
1337
readGenericRegionSeg(segNum, gTrue, gTrue, segLength);
1340
readGenericRefinementRegionSeg(segNum, gFalse, gFalse, segLength,
1344
readGenericRefinementRegionSeg(segNum, gTrue, gFalse, segLength,
1348
readGenericRefinementRegionSeg(segNum, gTrue, gTrue, segLength,
1352
readPageInfoSeg(segLength);
1355
readEndOfStripeSeg(segLength);
1358
readProfilesSeg(segLength);
1361
readCodeTableSeg(segNum, segLength);
1364
readExtensionSeg(segLength);
1367
error(getPos(), "Unknown segment type in JBIG2 stream");
1368
for (i = 0; i < segLength; ++i) {
1369
if ((c1 = curStr->getChar()) == EOF) {
1388
error(getPos(), "Unexpected EOF in JBIG2 stream");
1391
GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
1392
Guint *refSegs, Guint nRefSegs) {
1393
JBIG2SymbolDict *symbolDict;
1394
JBIG2HuffmanTable *huffDHTable, *huffDWTable;
1395
JBIG2HuffmanTable *huffBMSizeTable, *huffAggInstTable;
1398
JBIG2SymbolDict *inputSymbolDict;
1399
Guint flags, sdTemplate, sdrTemplate, huff, refAgg;
1400
Guint huffDH, huffDW, huffBMSize, huffAggInst;
1401
Guint contextUsed, contextRetained;
1402
int sdATX[4], sdATY[4], sdrATX[2], sdrATY[2];
1403
Guint numExSyms, numNewSyms, numInputSyms, symCodeLen;
1404
JBIG2Bitmap **bitmaps;
1405
JBIG2Bitmap *collBitmap, *refBitmap;
1407
Guint symHeight, symWidth, totalWidth, x, symID;
1408
int dh, dw, refAggNum, refDX, refDY, bmSize;
1414
// symbol dictionary flags
1415
if (!readUWord(&flags)) {
1418
sdTemplate = (flags >> 10) & 3;
1419
sdrTemplate = (flags >> 12) & 1;
1421
refAgg = (flags >> 1) & 1;
1422
huffDH = (flags >> 2) & 3;
1423
huffDW = (flags >> 4) & 3;
1424
huffBMSize = (flags >> 6) & 1;
1425
huffAggInst = (flags >> 7) & 1;
1426
contextUsed = (flags >> 8) & 1;
1427
contextRetained = (flags >> 9) & 1;
1429
// symbol dictionary AT flags
1431
if (sdTemplate == 0) {
1432
if (!readByte(&sdATX[0]) ||
1433
!readByte(&sdATY[0]) ||
1434
!readByte(&sdATX[1]) ||
1435
!readByte(&sdATY[1]) ||
1436
!readByte(&sdATX[2]) ||
1437
!readByte(&sdATY[2]) ||
1438
!readByte(&sdATX[3]) ||
1439
!readByte(&sdATY[3])) {
1443
if (!readByte(&sdATX[0]) ||
1444
!readByte(&sdATY[0])) {
1450
// symbol dictionary refinement AT flags
1451
if (refAgg && !sdrTemplate) {
1452
if (!readByte(&sdrATX[0]) ||
1453
!readByte(&sdrATY[0]) ||
1454
!readByte(&sdrATX[1]) ||
1455
!readByte(&sdrATY[1])) {
1460
// SDNUMEXSYMS and SDNUMNEWSYMS
1461
if (!readULong(&numExSyms) || !readULong(&numNewSyms)) {
1465
// get referenced segments: input symbol dictionaries and code tables
1466
codeTables = new GList();
1468
for (i = 0; i < nRefSegs; ++i) {
1469
seg = findSegment(refSegs[i]);
1470
if (seg->getType() == jbig2SegSymbolDict) {
1471
numInputSyms += ((JBIG2SymbolDict *)seg)->getSize();
1472
} else if (seg->getType() == jbig2SegCodeTable) {
1473
codeTables->append(seg);
1477
// compute symbol code length
1480
while (i < numInputSyms + numNewSyms) {
1485
// get the input symbol bitmaps
1486
bitmaps = (JBIG2Bitmap **)gmallocn(numInputSyms + numNewSyms,
1487
sizeof(JBIG2Bitmap *));
1488
for (i = 0; i < numInputSyms + numNewSyms; ++i) {
1492
inputSymbolDict = NULL;
1493
for (i = 0; i < nRefSegs; ++i) {
1494
seg = findSegment(refSegs[i]);
1495
if (seg->getType() == jbig2SegSymbolDict) {
1496
inputSymbolDict = (JBIG2SymbolDict *)seg;
1497
for (j = 0; j < inputSymbolDict->getSize(); ++j) {
1498
bitmaps[k++] = inputSymbolDict->getBitmap(j);
1503
// get the Huffman tables
1504
huffDHTable = huffDWTable = NULL; // make gcc happy
1505
huffBMSizeTable = huffAggInstTable = NULL; // make gcc happy
1509
huffDHTable = huffTableD;
1510
} else if (huffDH == 1) {
1511
huffDHTable = huffTableE;
1513
huffDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1516
huffDWTable = huffTableB;
1517
} else if (huffDW == 1) {
1518
huffDWTable = huffTableC;
1520
huffDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1522
if (huffBMSize == 0) {
1523
huffBMSizeTable = huffTableA;
1526
((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1528
if (huffAggInst == 0) {
1529
huffAggInstTable = huffTableA;
1532
((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1537
// set up the Huffman decoder
1539
huffDecoder->reset();
1541
// set up the arithmetic decoder
1543
if (contextUsed && inputSymbolDict) {
1544
resetGenericStats(sdTemplate, inputSymbolDict->getGenericRegionStats());
1546
resetGenericStats(sdTemplate, NULL);
1548
resetIntStats(symCodeLen);
1549
arithDecoder->start();
1552
// set up the arithmetic decoder for refinement/aggregation
1554
if (contextUsed && inputSymbolDict) {
1555
resetRefinementStats(sdrTemplate,
1556
inputSymbolDict->getRefinementRegionStats());
1558
resetRefinementStats(sdrTemplate, NULL);
1562
// allocate symbol widths storage
1564
if (huff && !refAgg) {
1565
symWidths = (Guint *)gmallocn(numNewSyms, sizeof(Guint));
1570
while (i < numNewSyms) {
1572
// read the height class delta height
1574
huffDecoder->decodeInt(&dh, huffDHTable);
1576
arithDecoder->decodeInt(&dh, iadhStats);
1578
if (dh < 0 && (Guint)-dh >= symHeight) {
1579
error(getPos(), "Bad delta-height value in JBIG2 symbol dictionary");
1587
// read the symbols in this height class
1590
// read the delta width
1592
if (!huffDecoder->decodeInt(&dw, huffDWTable)) {
1596
if (!arithDecoder->decodeInt(&dw, iadwStats)) {
1600
if (dw < 0 && (Guint)-dw >= symWidth) {
1601
error(getPos(), "Bad delta-height value in JBIG2 symbol dictionary");
1606
// using a collective bitmap, so don't read a bitmap here
1607
if (huff && !refAgg) {
1608
symWidths[i] = symWidth;
1609
totalWidth += symWidth;
1611
// refinement/aggregate coding
1612
} else if (refAgg) {
1614
if (!huffDecoder->decodeInt(&refAggNum, huffAggInstTable)) {
1618
if (!arithDecoder->decodeInt(&refAggNum, iaaiStats)) {
1622
#if 0 //~ This special case was added about a year before the final draft
1623
//~ of the JBIG2 spec was released. I have encountered some old
1624
//~ JBIG2 images that predate it.
1627
if (refAggNum == 1) {
1630
symID = huffDecoder->readBits(symCodeLen);
1631
huffDecoder->decodeInt(&refDX, huffTableO);
1632
huffDecoder->decodeInt(&refDY, huffTableO);
1633
huffDecoder->decodeInt(&bmSize, huffTableA);
1634
huffDecoder->reset();
1635
arithDecoder->start();
1637
symID = arithDecoder->decodeIAID(symCodeLen, iaidStats);
1638
arithDecoder->decodeInt(&refDX, iardxStats);
1639
arithDecoder->decodeInt(&refDY, iardyStats);
1641
refBitmap = bitmaps[symID];
1642
bitmaps[numInputSyms + i] =
1643
readGenericRefinementRegion(symWidth, symHeight,
1644
sdrTemplate, gFalse,
1645
refBitmap, refDX, refDY,
1647
//~ do we need to use the bmSize value here (in Huffman mode)?
1649
bitmaps[numInputSyms + i] =
1650
readTextRegion(huff, gTrue, symWidth, symHeight,
1651
refAggNum, 0, numInputSyms + i, NULL,
1652
symCodeLen, bitmaps, 0, 0, 0, 1, 0,
1653
huffTableF, huffTableH, huffTableK, huffTableO,
1654
huffTableO, huffTableO, huffTableO, huffTableA,
1655
sdrTemplate, sdrATX, sdrATY);
1658
// non-ref/agg coding
1660
bitmaps[numInputSyms + i] =
1661
readGenericBitmap(gFalse, symWidth, symHeight,
1662
sdTemplate, gFalse, gFalse, NULL,
1669
// read the collective bitmap
1670
if (huff && !refAgg) {
1671
huffDecoder->decodeInt(&bmSize, huffBMSizeTable);
1672
huffDecoder->reset();
1674
collBitmap = new JBIG2Bitmap(0, totalWidth, symHeight);
1675
bmSize = symHeight * ((totalWidth + 7) >> 3);
1676
p = collBitmap->getDataPtr();
1677
for (k = 0; k < (Guint)bmSize; ++k) {
1678
*p++ = curStr->getChar();
1681
collBitmap = readGenericBitmap(gTrue, totalWidth, symHeight,
1682
0, gFalse, gFalse, NULL, NULL, NULL,
1686
for (; j < i; ++j) {
1687
bitmaps[numInputSyms + j] =
1688
collBitmap->getSlice(x, 0, symWidths[j], symHeight);
1695
// create the symbol dict object
1696
symbolDict = new JBIG2SymbolDict(segNum, numExSyms);
1698
// exported symbol list
1701
while (i < numInputSyms + numNewSyms) {
1703
huffDecoder->decodeInt(&run, huffTableA);
1705
arithDecoder->decodeInt(&run, iaexStats);
1708
for (cnt = 0; cnt < run; ++cnt) {
1709
symbolDict->setBitmap(j++, bitmaps[i++]->copy());
1717
for (i = 0; i < numNewSyms; ++i) {
1718
delete bitmaps[numInputSyms + i];
1725
// save the arithmetic decoder stats
1726
if (!huff && contextRetained) {
1727
symbolDict->setGenericRegionStats(genericRegionStats->copy());
1729
symbolDict->setRefinementRegionStats(refinementRegionStats->copy());
1733
// store the new symbol dict
1734
segments->append(symbolDict);
1739
for (i = 0; i < numNewSyms; ++i) {
1740
if (bitmaps[numInputSyms + i]) {
1741
delete bitmaps[numInputSyms + i];
1751
error(getPos(), "Unexpected EOF in JBIG2 stream");
1755
void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
1756
GBool lossless, Guint length,
1757
Guint *refSegs, Guint nRefSegs) {
1758
JBIG2Bitmap *bitmap;
1759
JBIG2HuffmanTable runLengthTab[36];
1760
JBIG2HuffmanTable *symCodeTab;
1761
JBIG2HuffmanTable *huffFSTable, *huffDSTable, *huffDTTable;
1762
JBIG2HuffmanTable *huffRDWTable, *huffRDHTable;
1763
JBIG2HuffmanTable *huffRDXTable, *huffRDYTable, *huffRSizeTable;
1766
JBIG2SymbolDict *symbolDict;
1768
Guint w, h, x, y, segInfoFlags, extCombOp;
1769
Guint flags, huff, refine, logStrips, refCorner, transposed;
1770
Guint combOp, defPixel, templ;
1772
Guint huffFlags, huffFS, huffDS, huffDT;
1773
Guint huffRDW, huffRDH, huffRDX, huffRDY, huffRSize;
1774
Guint numInstances, numSyms, symCodeLen;
1779
// region segment info field
1780
if (!readULong(&w) || !readULong(&h) ||
1781
!readULong(&x) || !readULong(&y) ||
1782
!readUByte(&segInfoFlags)) {
1785
extCombOp = segInfoFlags & 7;
1787
// rest of the text region header
1788
if (!readUWord(&flags)) {
1792
refine = (flags >> 1) & 1;
1793
logStrips = (flags >> 2) & 3;
1794
refCorner = (flags >> 4) & 3;
1795
transposed = (flags >> 6) & 1;
1796
combOp = (flags >> 7) & 3;
1797
defPixel = (flags >> 9) & 1;
1798
sOffset = (flags >> 10) & 0x1f;
1799
if (sOffset & 0x10) {
1800
sOffset |= -1 - 0x0f;
1802
templ = (flags >> 15) & 1;
1803
huffFS = huffDS = huffDT = 0; // make gcc happy
1804
huffRDW = huffRDH = huffRDX = huffRDY = huffRSize = 0; // make gcc happy
1806
if (!readUWord(&huffFlags)) {
1809
huffFS = huffFlags & 3;
1810
huffDS = (huffFlags >> 2) & 3;
1811
huffDT = (huffFlags >> 4) & 3;
1812
huffRDW = (huffFlags >> 6) & 3;
1813
huffRDH = (huffFlags >> 8) & 3;
1814
huffRDX = (huffFlags >> 10) & 3;
1815
huffRDY = (huffFlags >> 12) & 3;
1816
huffRSize = (huffFlags >> 14) & 1;
1818
if (refine && templ == 0) {
1819
if (!readByte(&atx[0]) || !readByte(&aty[0]) ||
1820
!readByte(&atx[1]) || !readByte(&aty[1])) {
1824
if (!readULong(&numInstances)) {
1828
// get symbol dictionaries and tables
1829
codeTables = new GList();
1831
for (i = 0; i < nRefSegs; ++i) {
1832
if ((seg = findSegment(refSegs[i]))) {
1833
if (seg->getType() == jbig2SegSymbolDict) {
1834
numSyms += ((JBIG2SymbolDict *)seg)->getSize();
1835
} else if (seg->getType() == jbig2SegCodeTable) {
1836
codeTables->append(seg);
1839
error(getPos(), "Invalid segment reference in JBIG2 text region");
1844
while (i < numSyms) {
1849
// get the symbol bitmaps
1850
syms = (JBIG2Bitmap **)gmallocn(numSyms, sizeof(JBIG2Bitmap *));
1852
for (i = 0; i < nRefSegs; ++i) {
1853
if ((seg = findSegment(refSegs[i]))) {
1854
if (seg->getType() == jbig2SegSymbolDict) {
1855
symbolDict = (JBIG2SymbolDict *)seg;
1856
for (k = 0; k < symbolDict->getSize(); ++k) {
1857
syms[kk++] = symbolDict->getBitmap(k);
1863
// get the Huffman tables
1864
huffFSTable = huffDSTable = huffDTTable = NULL; // make gcc happy
1865
huffRDWTable = huffRDHTable = NULL; // make gcc happy
1866
huffRDXTable = huffRDYTable = huffRSizeTable = NULL; // make gcc happy
1870
huffFSTable = huffTableF;
1871
} else if (huffFS == 1) {
1872
huffFSTable = huffTableG;
1874
huffFSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1877
huffDSTable = huffTableH;
1878
} else if (huffDS == 1) {
1879
huffDSTable = huffTableI;
1880
} else if (huffDS == 2) {
1881
huffDSTable = huffTableJ;
1883
huffDSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1886
huffDTTable = huffTableK;
1887
} else if (huffDT == 1) {
1888
huffDTTable = huffTableL;
1889
} else if (huffDT == 2) {
1890
huffDTTable = huffTableM;
1892
huffDTTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1895
huffRDWTable = huffTableN;
1896
} else if (huffRDW == 1) {
1897
huffRDWTable = huffTableO;
1899
huffRDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1902
huffRDHTable = huffTableN;
1903
} else if (huffRDH == 1) {
1904
huffRDHTable = huffTableO;
1906
huffRDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1909
huffRDXTable = huffTableN;
1910
} else if (huffRDX == 1) {
1911
huffRDXTable = huffTableO;
1913
huffRDXTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1916
huffRDYTable = huffTableN;
1917
} else if (huffRDY == 1) {
1918
huffRDYTable = huffTableO;
1920
huffRDYTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1922
if (huffRSize == 0) {
1923
huffRSizeTable = huffTableA;
1926
((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1931
// symbol ID Huffman decoding table
1933
huffDecoder->reset();
1934
for (i = 0; i < 32; ++i) {
1935
runLengthTab[i].val = i;
1936
runLengthTab[i].prefixLen = huffDecoder->readBits(4);
1937
runLengthTab[i].rangeLen = 0;
1939
runLengthTab[32].val = 0x103;
1940
runLengthTab[32].prefixLen = huffDecoder->readBits(4);
1941
runLengthTab[32].rangeLen = 2;
1942
runLengthTab[33].val = 0x203;
1943
runLengthTab[33].prefixLen = huffDecoder->readBits(4);
1944
runLengthTab[33].rangeLen = 3;
1945
runLengthTab[34].val = 0x20b;
1946
runLengthTab[34].prefixLen = huffDecoder->readBits(4);
1947
runLengthTab[34].rangeLen = 7;
1948
runLengthTab[35].prefixLen = 0;
1949
runLengthTab[35].rangeLen = jbig2HuffmanEOT;
1950
huffDecoder->buildTable(runLengthTab, 35);
1951
symCodeTab = (JBIG2HuffmanTable *)gmallocn(numSyms + 1,
1952
sizeof(JBIG2HuffmanTable));
1953
for (i = 0; i < numSyms; ++i) {
1954
symCodeTab[i].val = i;
1955
symCodeTab[i].rangeLen = 0;
1958
while (i < numSyms) {
1959
huffDecoder->decodeInt(&j, runLengthTab);
1961
for (j -= 0x200; j && i < numSyms; --j) {
1962
symCodeTab[i++].prefixLen = 0;
1964
} else if (j > 0x100) {
1965
for (j -= 0x100; j && i < numSyms; --j) {
1966
symCodeTab[i].prefixLen = symCodeTab[i-1].prefixLen;
1970
symCodeTab[i++].prefixLen = j;
1973
symCodeTab[numSyms].prefixLen = 0;
1974
symCodeTab[numSyms].rangeLen = jbig2HuffmanEOT;
1975
huffDecoder->buildTable(symCodeTab, numSyms);
1976
huffDecoder->reset();
1978
// set up the arithmetic decoder
1981
resetIntStats(symCodeLen);
1982
arithDecoder->start();
1985
resetRefinementStats(templ, NULL);
1988
bitmap = readTextRegion(huff, refine, w, h, numInstances,
1989
logStrips, numSyms, symCodeTab, symCodeLen, syms,
1990
defPixel, combOp, transposed, refCorner, sOffset,
1991
huffFSTable, huffDSTable, huffDTTable,
1992
huffRDWTable, huffRDHTable,
1993
huffRDXTable, huffRDYTable, huffRSizeTable,
1998
// combine the region bitmap into the page bitmap
2000
if (pageH == 0xffffffff && y + h > curPageH) {
2001
pageBitmap->expand(y + h, pageDefPixel);
2003
pageBitmap->combine(bitmap, x, y, extCombOp);
2006
// store the region bitmap
2008
bitmap->setSegNum(segNum);
2009
segments->append(bitmap);
2012
// clean up the Huffman decoder
2020
error(getPos(), "Unexpected EOF in JBIG2 stream");
2023
JBIG2Bitmap *JBIG2Stream::readTextRegion(GBool huff, GBool refine,
2028
JBIG2HuffmanTable *symCodeTab,
2031
Guint defPixel, Guint combOp,
2032
Guint transposed, Guint refCorner,
2034
JBIG2HuffmanTable *huffFSTable,
2035
JBIG2HuffmanTable *huffDSTable,
2036
JBIG2HuffmanTable *huffDTTable,
2037
JBIG2HuffmanTable *huffRDWTable,
2038
JBIG2HuffmanTable *huffRDHTable,
2039
JBIG2HuffmanTable *huffRDXTable,
2040
JBIG2HuffmanTable *huffRDYTable,
2041
JBIG2HuffmanTable *huffRSizeTable,
2043
int *atx, int *aty) {
2044
JBIG2Bitmap *bitmap;
2045
JBIG2Bitmap *symbolBitmap;
2047
int t, dt, tt, s, ds, sFirst, j;
2048
int rdw, rdh, rdx, rdy, ri, refDX, refDY, bmSize;
2049
Guint symID, inst, bw, bh;
2051
strips = 1 << logStrips;
2053
// allocate the bitmap
2054
bitmap = new JBIG2Bitmap(0, w, h);
2056
bitmap->clearToOne();
2058
bitmap->clearToZero();
2061
// decode initial T value
2063
huffDecoder->decodeInt(&t, huffDTTable);
2065
arithDecoder->decodeInt(&t, iadtStats);
2071
while (inst < numInstances) {
2075
huffDecoder->decodeInt(&dt, huffDTTable);
2077
arithDecoder->decodeInt(&dt, iadtStats);
2083
huffDecoder->decodeInt(&ds, huffFSTable);
2085
arithDecoder->decodeInt(&ds, iafsStats);
2090
// read the instances
2097
dt = huffDecoder->readBits(logStrips);
2099
arithDecoder->decodeInt(&dt, iaitStats);
2106
huffDecoder->decodeInt(&j, symCodeTab);
2109
symID = huffDecoder->readBits(symCodeLen);
2112
symID = arithDecoder->decodeIAID(symCodeLen, iaidStats);
2115
if (symID >= (Guint)numSyms) {
2116
error(getPos(), "Invalid symbol number in JBIG2 text region");
2119
// get the symbol bitmap
2120
symbolBitmap = NULL;
2123
ri = (int)huffDecoder->readBit();
2125
arithDecoder->decodeInt(&ri, iariStats);
2132
huffDecoder->decodeInt(&rdw, huffRDWTable);
2133
huffDecoder->decodeInt(&rdh, huffRDHTable);
2134
huffDecoder->decodeInt(&rdx, huffRDXTable);
2135
huffDecoder->decodeInt(&rdy, huffRDYTable);
2136
huffDecoder->decodeInt(&bmSize, huffRSizeTable);
2137
huffDecoder->reset();
2138
arithDecoder->start();
2140
arithDecoder->decodeInt(&rdw, iardwStats);
2141
arithDecoder->decodeInt(&rdh, iardhStats);
2142
arithDecoder->decodeInt(&rdx, iardxStats);
2143
arithDecoder->decodeInt(&rdy, iardyStats);
2145
refDX = ((rdw >= 0) ? rdw : rdw - 1) / 2 + rdx;
2146
refDY = ((rdh >= 0) ? rdh : rdh - 1) / 2 + rdy;
2149
readGenericRefinementRegion(rdw + syms[symID]->getWidth(),
2150
rdh + syms[symID]->getHeight(),
2151
templ, gFalse, syms[symID],
2152
refDX, refDY, atx, aty);
2153
//~ do we need to use the bmSize value here (in Huffman mode)?
2155
symbolBitmap = syms[symID];
2158
// combine the symbol bitmap into the region bitmap
2159
//~ something is wrong here - refCorner shouldn't degenerate into
2161
bw = symbolBitmap->getWidth() - 1;
2162
bh = symbolBitmap->getHeight() - 1;
2164
switch (refCorner) {
2165
case 0: // bottom left
2166
bitmap->combine(symbolBitmap, tt, s, combOp);
2169
bitmap->combine(symbolBitmap, tt, s, combOp);
2171
case 2: // bottom right
2172
bitmap->combine(symbolBitmap, tt - bw, s, combOp);
2174
case 3: // top right
2175
bitmap->combine(symbolBitmap, tt - bw, s, combOp);
2180
switch (refCorner) {
2181
case 0: // bottom left
2182
bitmap->combine(symbolBitmap, s, tt - bh, combOp);
2185
bitmap->combine(symbolBitmap, s, tt, combOp);
2187
case 2: // bottom right
2188
bitmap->combine(symbolBitmap, s, tt - bh, combOp);
2190
case 3: // top right
2191
bitmap->combine(symbolBitmap, s, tt, combOp);
2197
delete symbolBitmap;
2206
if (!huffDecoder->decodeInt(&ds, huffDSTable)) {
2210
if (!arithDecoder->decodeInt(&ds, iadsStats)) {
2221
void JBIG2Stream::readPatternDictSeg(Guint segNum, Guint length) {
2222
JBIG2PatternDict *patternDict;
2223
JBIG2Bitmap *bitmap;
2224
Guint flags, patternW, patternH, grayMax, templ, mmr;
2228
// halftone dictionary flags, pattern width and height, max gray value
2229
if (!readUByte(&flags) ||
2230
!readUByte(&patternW) ||
2231
!readUByte(&patternH) ||
2232
!readULong(&grayMax)) {
2235
templ = (flags >> 1) & 3;
2238
// set up the arithmetic decoder
2240
resetGenericStats(templ, NULL);
2241
arithDecoder->start();
2245
atx[0] = -(int)patternW; aty[0] = 0;
2246
atx[1] = -3; aty[1] = -1;
2247
atx[2] = 2; aty[2] = -2;
2248
atx[3] = -2; aty[3] = -2;
2249
bitmap = readGenericBitmap(mmr, (grayMax + 1) * patternW, patternH,
2250
templ, gFalse, gFalse, NULL,
2251
atx, aty, length - 7);
2253
// create the pattern dict object
2254
patternDict = new JBIG2PatternDict(segNum, grayMax + 1);
2256
// split up the bitmap
2258
for (i = 0; i <= grayMax; ++i) {
2259
patternDict->setBitmap(i, bitmap->getSlice(x, 0, patternW, patternH));
2266
// store the new pattern dict
2267
segments->append(patternDict);
2272
error(getPos(), "Unexpected EOF in JBIG2 stream");
2275
void JBIG2Stream::readHalftoneRegionSeg(Guint segNum, GBool imm,
2276
GBool lossless, Guint length,
2277
Guint *refSegs, Guint nRefSegs) {
2278
JBIG2Bitmap *bitmap;
2280
JBIG2PatternDict *patternDict;
2281
JBIG2Bitmap *skipBitmap;
2283
JBIG2Bitmap *grayBitmap;
2284
JBIG2Bitmap *patternBitmap;
2285
Guint w, h, x, y, segInfoFlags, extCombOp;
2286
Guint flags, mmr, templ, enableSkip, combOp;
2287
Guint gridW, gridH, stepX, stepY, patW, patH;
2289
int gridX, gridY, xx, yy, bit, j;
2292
// region segment info field
2293
if (!readULong(&w) || !readULong(&h) ||
2294
!readULong(&x) || !readULong(&y) ||
2295
!readUByte(&segInfoFlags)) {
2298
extCombOp = segInfoFlags & 7;
2300
// rest of the halftone region header
2301
if (!readUByte(&flags)) {
2305
templ = (flags >> 1) & 3;
2306
enableSkip = (flags >> 3) & 1;
2307
combOp = (flags >> 4) & 7;
2308
if (!readULong(&gridW) || !readULong(&gridH) ||
2309
!readLong(&gridX) || !readLong(&gridY) ||
2310
!readUWord(&stepX) || !readUWord(&stepY)) {
2313
if (w == 0 || h == 0 || w >= INT_MAX / h) {
2314
error(getPos(), "Bad bitmap size in JBIG2 halftone segment");
2317
if (gridH == 0 || gridW >= INT_MAX / gridH) {
2318
error(getPos(), "Bad grid size in JBIG2 halftone segment");
2322
// get pattern dictionary
2323
if (nRefSegs != 1) {
2324
error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
2327
seg = findSegment(refSegs[0]);
2328
if (seg->getType() != jbig2SegPatternDict) {
2329
error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
2332
patternDict = (JBIG2PatternDict *)seg;
2335
while (i < patternDict->getSize()) {
2339
patW = patternDict->getBitmap(0)->getWidth();
2340
patH = patternDict->getBitmap(0)->getHeight();
2342
// set up the arithmetic decoder
2344
resetGenericStats(templ, NULL);
2345
arithDecoder->start();
2348
// allocate the bitmap
2349
bitmap = new JBIG2Bitmap(segNum, w, h);
2350
if (flags & 0x80) { // HDEFPIXEL
2351
bitmap->clearToOne();
2353
bitmap->clearToZero();
2356
// compute the skip bitmap
2359
skipBitmap = new JBIG2Bitmap(0, gridW, gridH);
2360
skipBitmap->clearToZero();
2361
for (m = 0; m < gridH; ++m) {
2362
for (n = 0; n < gridW; ++n) {
2363
xx = gridX + m * stepY + n * stepX;
2364
yy = gridY + m * stepX - n * stepY;
2365
if (((xx + (int)patW) >> 8) <= 0 || (xx >> 8) >= (int)w ||
2366
((yy + (int)patH) >> 8) <= 0 || (yy >> 8) >= (int)h) {
2367
skipBitmap->setPixel(n, m);
2373
// read the gray-scale image
2374
grayImg = (Guint *)gmallocn(gridW * gridH, sizeof(Guint));
2375
memset(grayImg, 0, gridW * gridH * sizeof(Guint));
2376
atx[0] = templ <= 1 ? 3 : 2; aty[0] = -1;
2377
atx[1] = -3; aty[1] = -1;
2378
atx[2] = 2; aty[2] = -2;
2379
atx[3] = -2; aty[3] = -2;
2380
for (j = bpp - 1; j >= 0; --j) {
2381
grayBitmap = readGenericBitmap(mmr, gridW, gridH, templ, gFalse,
2382
enableSkip, skipBitmap, atx, aty, -1);
2384
for (m = 0; m < gridH; ++m) {
2385
for (n = 0; n < gridW; ++n) {
2386
bit = grayBitmap->getPixel(n, m) ^ (grayImg[i] & 1);
2387
grayImg[i] = (grayImg[i] << 1) | bit;
2396
for (m = 0; m < gridH; ++m) {
2397
xx = gridX + m * stepY;
2398
yy = gridY + m * stepX;
2399
for (n = 0; n < gridW; ++n) {
2400
if (!(enableSkip && skipBitmap->getPixel(n, m))) {
2401
patternBitmap = patternDict->getBitmap(grayImg[i]);
2402
bitmap->combine(patternBitmap, xx >> 8, yy >> 8, combOp);
2415
// combine the region bitmap into the page bitmap
2417
if (pageH == 0xffffffff && y + h > curPageH) {
2418
pageBitmap->expand(y + h, pageDefPixel);
2420
pageBitmap->combine(bitmap, x, y, extCombOp);
2423
// store the region bitmap
2425
segments->append(bitmap);
2431
error(getPos(), "Unexpected EOF in JBIG2 stream");
2434
void JBIG2Stream::readGenericRegionSeg(Guint segNum, GBool imm,
2435
GBool lossless, Guint length) {
2436
JBIG2Bitmap *bitmap;
2437
Guint w, h, x, y, segInfoFlags, extCombOp;
2438
Guint flags, mmr, templ, tpgdOn;
2441
// region segment info field
2442
if (!readULong(&w) || !readULong(&h) ||
2443
!readULong(&x) || !readULong(&y) ||
2444
!readUByte(&segInfoFlags)) {
2447
extCombOp = segInfoFlags & 7;
2449
// rest of the generic region segment header
2450
if (!readUByte(&flags)) {
2454
templ = (flags >> 1) & 3;
2455
tpgdOn = (flags >> 3) & 1;
2460
if (!readByte(&atx[0]) ||
2461
!readByte(&aty[0]) ||
2462
!readByte(&atx[1]) ||
2463
!readByte(&aty[1]) ||
2464
!readByte(&atx[2]) ||
2465
!readByte(&aty[2]) ||
2466
!readByte(&atx[3]) ||
2467
!readByte(&aty[3])) {
2471
if (!readByte(&atx[0]) ||
2472
!readByte(&aty[0])) {
2478
// set up the arithmetic decoder
2480
resetGenericStats(templ, NULL);
2481
arithDecoder->start();
2485
bitmap = readGenericBitmap(mmr, w, h, templ, tpgdOn, gFalse,
2486
NULL, atx, aty, mmr ? 0 : length - 18);
2488
// combine the region bitmap into the page bitmap
2490
if (pageH == 0xffffffff && y + h > curPageH) {
2491
pageBitmap->expand(y + h, pageDefPixel);
2493
pageBitmap->combine(bitmap, x, y, extCombOp);
2496
// store the region bitmap
2498
bitmap->setSegNum(segNum);
2499
segments->append(bitmap);
2505
error(getPos(), "Unexpected EOF in JBIG2 stream");
2508
JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h,
2509
int templ, GBool tpgdOn,
2510
GBool useSkip, JBIG2Bitmap *skip,
2512
int mmrDataLength) {
2513
JBIG2Bitmap *bitmap;
2515
Guint ltpCX, cx, cx0, cx1, cx2;
2516
JBIG2BitmapPtr cxPtr0, cxPtr1;
2517
JBIG2BitmapPtr atPtr0, atPtr1, atPtr2, atPtr3;
2518
int *refLine, *codingLine;
2519
int code1, code2, code3;
2520
int x, y, a0, pix, i, refI, codingI;
2522
bitmap = new JBIG2Bitmap(0, w, h);
2523
bitmap->clearToZero();
2529
mmrDecoder->reset();
2530
refLine = (int *)gmallocn(w + 2, sizeof(int));
2531
codingLine = (int *)gmallocn(w + 2, sizeof(int));
2532
codingLine[0] = codingLine[1] = w;
2534
for (y = 0; y < h; ++y) {
2536
// copy coding line to ref line
2537
for (i = 0; codingLine[i] < w; ++i) {
2538
refLine[i] = codingLine[i];
2540
refLine[i] = refLine[i + 1] = w;
2543
refI = 0; // b1 = refLine[refI]
2544
codingI = 0; // a1 = codingLine[codingI]
2547
code1 = mmrDecoder->get2DCode();
2550
if (refLine[refI] < w) {
2551
a0 = refLine[refI + 1];
2559
code1 += code3 = mmrDecoder->getBlackCode();
2560
} while (code3 >= 64);
2563
code2 += code3 = mmrDecoder->getWhiteCode();
2564
} while (code3 >= 64);
2568
code1 += code3 = mmrDecoder->getWhiteCode();
2569
} while (code3 >= 64);
2572
code2 += code3 = mmrDecoder->getBlackCode();
2573
} while (code3 >= 64);
2575
if (code1 > 0 || code2 > 0) {
2576
a0 = codingLine[codingI++] = a0 + code1;
2577
a0 = codingLine[codingI++] = a0 + code2;
2578
while (refLine[refI] <= a0 && refLine[refI] < w) {
2584
a0 = codingLine[codingI++] = refLine[refI];
2585
if (refLine[refI] < w) {
2590
a0 = codingLine[codingI++] = refLine[refI] + 1;
2591
if (refLine[refI] < w) {
2593
while (refLine[refI] <= a0 && refLine[refI] < w) {
2599
a0 = codingLine[codingI++] = refLine[refI] + 2;
2600
if (refLine[refI] < w) {
2602
while (refLine[refI] <= a0 && refLine[refI] < w) {
2608
a0 = codingLine[codingI++] = refLine[refI] + 3;
2609
if (refLine[refI] < w) {
2611
while (refLine[refI] <= a0 && refLine[refI] < w) {
2617
a0 = codingLine[codingI++] = refLine[refI] - 1;
2623
while (refLine[refI] <= a0 && refLine[refI] < w) {
2628
a0 = codingLine[codingI++] = refLine[refI] - 2;
2634
while (refLine[refI] <= a0 && refLine[refI] < w) {
2639
a0 = codingLine[codingI++] = refLine[refI] - 3;
2645
while (refLine[refI] <= a0 && refLine[refI] < w) {
2650
error(getPos(), "Illegal code in JBIG2 MMR bitmap data");
2654
codingLine[codingI++] = w;
2656
// convert the run lengths to a bitmap line
2658
while (codingLine[i] < w) {
2659
for (x = codingLine[i]; x < codingLine[i+1]; ++x) {
2660
bitmap->setPixel(x, y);
2666
if (mmrDataLength >= 0) {
2667
mmrDecoder->skipTo(mmrDataLength);
2669
if (mmrDecoder->get24Bits() != 0x001001) {
2670
error(getPos(), "Missing EOFB in JBIG2 MMR bitmap data");
2677
//----- arithmetic decode
2680
// set up the typical row context
2681
ltpCX = 0; // make gcc happy
2685
ltpCX = 0x3953; // 001 11001 0101 0011
2688
ltpCX = 0x079a; // 0011 11001 101 0
2691
ltpCX = 0x0e3; // 001 1100 01 1
2694
ltpCX = 0x18a; // 01100 0101 1
2700
cx = cx0 = cx1 = cx2 = 0; // make gcc happy
2701
for (y = 0; y < h; ++y) {
2703
// check for a "typical" (duplicate) row
2705
if (arithDecoder->decodeBit(ltpCX, genericRegionStats)) {
2709
bitmap->duplicateRow(y, y-1);
2717
// set up the context
2718
bitmap->getPixelPtr(0, y-2, &cxPtr0);
2719
cx0 = bitmap->nextPixel(&cxPtr0);
2720
cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
2721
bitmap->getPixelPtr(0, y-1, &cxPtr1);
2722
cx1 = bitmap->nextPixel(&cxPtr1);
2723
cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
2724
cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
2726
bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
2727
bitmap->getPixelPtr(atx[1], y + aty[1], &atPtr1);
2728
bitmap->getPixelPtr(atx[2], y + aty[2], &atPtr2);
2729
bitmap->getPixelPtr(atx[3], y + aty[3], &atPtr3);
2732
for (x = 0; x < w; ++x) {
2734
// build the context
2735
cx = (cx0 << 13) | (cx1 << 8) | (cx2 << 4) |
2736
(bitmap->nextPixel(&atPtr0) << 3) |
2737
(bitmap->nextPixel(&atPtr1) << 2) |
2738
(bitmap->nextPixel(&atPtr2) << 1) |
2739
bitmap->nextPixel(&atPtr3);
2741
// check for a skipped pixel
2742
if (useSkip && skip->getPixel(x, y)) {
2746
} else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
2747
bitmap->setPixel(x, y);
2750
// update the context
2751
cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x07;
2752
cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f;
2753
cx2 = ((cx2 << 1) | pix) & 0x0f;
2759
// set up the context
2760
bitmap->getPixelPtr(0, y-2, &cxPtr0);
2761
cx0 = bitmap->nextPixel(&cxPtr0);
2762
cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
2763
cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
2764
bitmap->getPixelPtr(0, y-1, &cxPtr1);
2765
cx1 = bitmap->nextPixel(&cxPtr1);
2766
cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
2767
cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
2769
bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
2772
for (x = 0; x < w; ++x) {
2774
// build the context
2775
cx = (cx0 << 9) | (cx1 << 4) | (cx2 << 1) |
2776
bitmap->nextPixel(&atPtr0);
2778
// check for a skipped pixel
2779
if (useSkip && skip->getPixel(x, y)) {
2783
} else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
2784
bitmap->setPixel(x, y);
2787
// update the context
2788
cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x0f;
2789
cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f;
2790
cx2 = ((cx2 << 1) | pix) & 0x07;
2796
// set up the context
2797
bitmap->getPixelPtr(0, y-2, &cxPtr0);
2798
cx0 = bitmap->nextPixel(&cxPtr0);
2799
cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0);
2800
bitmap->getPixelPtr(0, y-1, &cxPtr1);
2801
cx1 = bitmap->nextPixel(&cxPtr1);
2802
cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
2804
bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
2807
for (x = 0; x < w; ++x) {
2809
// build the context
2810
cx = (cx0 << 7) | (cx1 << 3) | (cx2 << 1) |
2811
bitmap->nextPixel(&atPtr0);
2813
// check for a skipped pixel
2814
if (useSkip && skip->getPixel(x, y)) {
2818
} else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
2819
bitmap->setPixel(x, y);
2822
// update the context
2823
cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x07;
2824
cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x0f;
2825
cx2 = ((cx2 << 1) | pix) & 0x03;
2831
// set up the context
2832
bitmap->getPixelPtr(0, y-1, &cxPtr1);
2833
cx1 = bitmap->nextPixel(&cxPtr1);
2834
cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1);
2836
bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0);
2839
for (x = 0; x < w; ++x) {
2841
// build the context
2842
cx = (cx1 << 5) | (cx2 << 1) |
2843
bitmap->nextPixel(&atPtr0);
2845
// check for a skipped pixel
2846
if (useSkip && skip->getPixel(x, y)) {
2850
} else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
2851
bitmap->setPixel(x, y);
2854
// update the context
2855
cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f;
2856
cx2 = ((cx2 << 1) | pix) & 0x0f;
2866
void JBIG2Stream::readGenericRefinementRegionSeg(Guint segNum, GBool imm,
2867
GBool lossless, Guint length,
2870
JBIG2Bitmap *bitmap, *refBitmap;
2871
Guint w, h, x, y, segInfoFlags, extCombOp;
2872
Guint flags, templ, tpgrOn;
2876
// region segment info field
2877
if (!readULong(&w) || !readULong(&h) ||
2878
!readULong(&x) || !readULong(&y) ||
2879
!readUByte(&segInfoFlags)) {
2882
extCombOp = segInfoFlags & 7;
2884
// rest of the generic refinement region segment header
2885
if (!readUByte(&flags)) {
2889
tpgrOn = (flags >> 1) & 1;
2893
if (!readByte(&atx[0]) || !readByte(&aty[0]) ||
2894
!readByte(&atx[1]) || !readByte(&aty[1])) {
2899
// resize the page bitmap if needed
2900
if (nRefSegs == 0 || imm) {
2901
if (pageH == 0xffffffff && y + h > curPageH) {
2902
pageBitmap->expand(y + h, pageDefPixel);
2906
// get referenced bitmap
2908
error(getPos(), "Bad reference in JBIG2 generic refinement segment");
2911
if (nRefSegs == 1) {
2912
seg = findSegment(refSegs[0]);
2913
if (seg->getType() != jbig2SegBitmap) {
2914
error(getPos(), "Bad bitmap reference in JBIG2 generic refinement segment");
2917
refBitmap = (JBIG2Bitmap *)seg;
2919
refBitmap = pageBitmap->getSlice(x, y, w, h);
2922
// set up the arithmetic decoder
2923
resetRefinementStats(templ, NULL);
2924
arithDecoder->start();
2927
bitmap = readGenericRefinementRegion(w, h, templ, tpgrOn,
2928
refBitmap, 0, 0, atx, aty);
2930
// combine the region bitmap into the page bitmap
2932
pageBitmap->combine(bitmap, x, y, extCombOp);
2935
// store the region bitmap
2937
bitmap->setSegNum(segNum);
2938
segments->append(bitmap);
2941
// delete the referenced bitmap
2942
if (nRefSegs == 1) {
2943
discardSegment(refSegs[0]);
2951
error(getPos(), "Unexpected EOF in JBIG2 stream");
2954
JBIG2Bitmap *JBIG2Stream::readGenericRefinementRegion(int w, int h,
2955
int templ, GBool tpgrOn,
2956
JBIG2Bitmap *refBitmap,
2957
int refDX, int refDY,
2958
int *atx, int *aty) {
2959
JBIG2Bitmap *bitmap;
2961
Guint ltpCX, cx, cx0, cx2, cx3, cx4, tpgrCX0, tpgrCX1, tpgrCX2;
2962
JBIG2BitmapPtr cxPtr0, cxPtr1, cxPtr2, cxPtr3, cxPtr4, cxPtr5, cxPtr6;
2963
JBIG2BitmapPtr tpgrCXPtr0, tpgrCXPtr1, tpgrCXPtr2;
2966
bitmap = new JBIG2Bitmap(0, w, h);
2967
bitmap->clearToZero();
2969
// set up the typical row context
2977
for (y = 0; y < h; ++y) {
2981
// set up the context
2982
bitmap->getPixelPtr(0, y-1, &cxPtr0);
2983
cx0 = bitmap->nextPixel(&cxPtr0);
2984
bitmap->getPixelPtr(-1, y, &cxPtr1);
2985
refBitmap->getPixelPtr(-refDX, y-1-refDY, &cxPtr2);
2986
refBitmap->getPixelPtr(-1-refDX, y-refDY, &cxPtr3);
2987
cx3 = refBitmap->nextPixel(&cxPtr3);
2988
cx3 = (cx3 << 1) | refBitmap->nextPixel(&cxPtr3);
2989
refBitmap->getPixelPtr(-refDX, y+1-refDY, &cxPtr4);
2990
cx4 = refBitmap->nextPixel(&cxPtr4);
2992
// set up the typical prediction context
2993
tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy
2995
refBitmap->getPixelPtr(-1-refDX, y-1-refDY, &tpgrCXPtr0);
2996
tpgrCX0 = refBitmap->nextPixel(&tpgrCXPtr0);
2997
tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
2998
tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
2999
refBitmap->getPixelPtr(-1-refDX, y-refDY, &tpgrCXPtr1);
3000
tpgrCX1 = refBitmap->nextPixel(&tpgrCXPtr1);
3001
tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
3002
tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
3003
refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &tpgrCXPtr2);
3004
tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2);
3005
tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
3006
tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
3009
for (x = 0; x < w; ++x) {
3011
// update the context
3012
cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 7;
3013
cx3 = ((cx3 << 1) | refBitmap->nextPixel(&cxPtr3)) & 7;
3014
cx4 = ((cx4 << 1) | refBitmap->nextPixel(&cxPtr4)) & 3;
3017
// update the typical predictor context
3018
tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0)) & 7;
3019
tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1)) & 7;
3020
tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2)) & 7;
3022
// check for a "typical" pixel
3023
if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) {
3026
if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) {
3027
bitmap->clearPixel(x, y);
3029
} else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) {
3030
bitmap->setPixel(x, y);
3035
// build the context
3036
cx = (cx0 << 7) | (bitmap->nextPixel(&cxPtr1) << 6) |
3037
(refBitmap->nextPixel(&cxPtr2) << 5) |
3041
if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) {
3042
bitmap->setPixel(x, y);
3048
// set up the context
3049
bitmap->getPixelPtr(0, y-1, &cxPtr0);
3050
cx0 = bitmap->nextPixel(&cxPtr0);
3051
bitmap->getPixelPtr(-1, y, &cxPtr1);
3052
refBitmap->getPixelPtr(-refDX, y-1-refDY, &cxPtr2);
3053
cx2 = refBitmap->nextPixel(&cxPtr2);
3054
refBitmap->getPixelPtr(-1-refDX, y-refDY, &cxPtr3);
3055
cx3 = refBitmap->nextPixel(&cxPtr3);
3056
cx3 = (cx3 << 1) | refBitmap->nextPixel(&cxPtr3);
3057
refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &cxPtr4);
3058
cx4 = refBitmap->nextPixel(&cxPtr4);
3059
cx4 = (cx4 << 1) | refBitmap->nextPixel(&cxPtr4);
3060
bitmap->getPixelPtr(atx[0], y+aty[0], &cxPtr5);
3061
refBitmap->getPixelPtr(atx[1]-refDX, y+aty[1]-refDY, &cxPtr6);
3063
// set up the typical prediction context
3064
tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy
3066
refBitmap->getPixelPtr(-1-refDX, y-1-refDY, &tpgrCXPtr0);
3067
tpgrCX0 = refBitmap->nextPixel(&tpgrCXPtr0);
3068
tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
3069
tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
3070
refBitmap->getPixelPtr(-1-refDX, y-refDY, &tpgrCXPtr1);
3071
tpgrCX1 = refBitmap->nextPixel(&tpgrCXPtr1);
3072
tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
3073
tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
3074
refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &tpgrCXPtr2);
3075
tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2);
3076
tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
3077
tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
3080
for (x = 0; x < w; ++x) {
3082
// update the context
3083
cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 3;
3084
cx2 = ((cx2 << 1) | refBitmap->nextPixel(&cxPtr2)) & 3;
3085
cx3 = ((cx3 << 1) | refBitmap->nextPixel(&cxPtr3)) & 7;
3086
cx4 = ((cx4 << 1) | refBitmap->nextPixel(&cxPtr4)) & 7;
3089
// update the typical predictor context
3090
tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0)) & 7;
3091
tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1)) & 7;
3092
tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2)) & 7;
3094
// check for a "typical" pixel
3095
if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) {
3098
if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) {
3099
bitmap->clearPixel(x, y);
3101
} else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) {
3102
bitmap->setPixel(x, y);
3107
// build the context
3108
cx = (cx0 << 11) | (bitmap->nextPixel(&cxPtr1) << 10) |
3109
(cx2 << 8) | (cx3 << 5) | (cx4 << 2) |
3110
(bitmap->nextPixel(&cxPtr5) << 1) |
3111
refBitmap->nextPixel(&cxPtr6);
3114
if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) {
3115
bitmap->setPixel(x, y);
3124
void JBIG2Stream::readPageInfoSeg(Guint length) {
3125
Guint xRes, yRes, flags, striping;
3127
if (!readULong(&pageW) || !readULong(&pageH) ||
3128
!readULong(&xRes) || !readULong(&yRes) ||
3129
!readUByte(&flags) || !readUWord(&striping)) {
3132
pageDefPixel = (flags >> 2) & 1;
3133
defCombOp = (flags >> 3) & 3;
3135
// allocate the page bitmap
3136
if (pageH == 0xffffffff) {
3137
curPageH = striping & 0x7fff;
3141
pageBitmap = new JBIG2Bitmap(0, pageW, curPageH);
3143
// default pixel value
3145
pageBitmap->clearToOne();
3147
pageBitmap->clearToZero();
3153
error(getPos(), "Unexpected EOF in JBIG2 stream");
3156
void JBIG2Stream::readEndOfStripeSeg(Guint length) {
3160
for (i = 0; i < length; ++i) {
3165
void JBIG2Stream::readProfilesSeg(Guint length) {
3169
for (i = 0; i < length; ++i) {
3174
void JBIG2Stream::readCodeTableSeg(Guint segNum, Guint length) {
3175
JBIG2HuffmanTable *huffTab;
3176
Guint flags, oob, prefixBits, rangeBits;
3177
int lowVal, highVal, val;
3178
Guint huffTabSize, i;
3180
if (!readUByte(&flags) || !readLong(&lowVal) || !readLong(&highVal)) {
3184
prefixBits = ((flags >> 1) & 7) + 1;
3185
rangeBits = ((flags >> 4) & 7) + 1;
3187
huffDecoder->reset();
3189
huffTab = (JBIG2HuffmanTable *)
3190
gmallocn(huffTabSize, sizeof(JBIG2HuffmanTable));
3193
while (val < highVal) {
3194
if (i == huffTabSize) {
3196
huffTab = (JBIG2HuffmanTable *)
3197
greallocn(huffTab, huffTabSize, sizeof(JBIG2HuffmanTable));
3199
huffTab[i].val = val;
3200
huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
3201
huffTab[i].rangeLen = huffDecoder->readBits(rangeBits);
3202
val += 1 << huffTab[i].rangeLen;
3205
if (i + oob + 3 > huffTabSize) {
3206
huffTabSize = i + oob + 3;
3207
huffTab = (JBIG2HuffmanTable *)
3208
greallocn(huffTab, huffTabSize, sizeof(JBIG2HuffmanTable));
3210
huffTab[i].val = lowVal - 1;
3211
huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
3212
huffTab[i].rangeLen = jbig2HuffmanLOW;
3214
huffTab[i].val = highVal;
3215
huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
3216
huffTab[i].rangeLen = 32;
3220
huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
3221
huffTab[i].rangeLen = jbig2HuffmanOOB;
3225
huffTab[i].prefixLen = 0;
3226
huffTab[i].rangeLen = jbig2HuffmanEOT;
3227
huffDecoder->buildTable(huffTab, i);
3229
// create and store the new table segment
3230
segments->append(new JBIG2CodeTable(segNum, huffTab));
3235
error(getPos(), "Unexpected EOF in JBIG2 stream");
3238
void JBIG2Stream::readExtensionSeg(Guint length) {
3242
for (i = 0; i < length; ++i) {
3247
JBIG2Segment *JBIG2Stream::findSegment(Guint segNum) {
3251
for (i = 0; i < globalSegments->getLength(); ++i) {
3252
seg = (JBIG2Segment *)globalSegments->get(i);
3253
if (seg->getSegNum() == segNum) {
3257
for (i = 0; i < segments->getLength(); ++i) {
3258
seg = (JBIG2Segment *)segments->get(i);
3259
if (seg->getSegNum() == segNum) {
3266
void JBIG2Stream::discardSegment(Guint segNum) {
3270
for (i = 0; i < globalSegments->getLength(); ++i) {
3271
seg = (JBIG2Segment *)globalSegments->get(i);
3272
if (seg->getSegNum() == segNum) {
3273
globalSegments->del(i);
3277
for (i = 0; i < segments->getLength(); ++i) {
3278
seg = (JBIG2Segment *)segments->get(i);
3279
if (seg->getSegNum() == segNum) {
3286
void JBIG2Stream::resetGenericStats(Guint templ,
3287
JArithmeticDecoderStats *prevStats) {
3290
size = contextSize[templ];
3291
if (prevStats && prevStats->getContextSize() == size) {
3292
if (genericRegionStats->getContextSize() == size) {
3293
genericRegionStats->copyFrom(prevStats);
3295
delete genericRegionStats;
3296
genericRegionStats = prevStats->copy();
3299
if (genericRegionStats->getContextSize() == size) {
3300
genericRegionStats->reset();
3302
delete genericRegionStats;
3303
genericRegionStats = new JArithmeticDecoderStats(1 << size);
3308
void JBIG2Stream::resetRefinementStats(Guint templ,
3309
JArithmeticDecoderStats *prevStats) {
3312
size = refContextSize[templ];
3313
if (prevStats && prevStats->getContextSize() == size) {
3314
if (refinementRegionStats->getContextSize() == size) {
3315
refinementRegionStats->copyFrom(prevStats);
3317
delete refinementRegionStats;
3318
refinementRegionStats = prevStats->copy();
3321
if (refinementRegionStats->getContextSize() == size) {
3322
refinementRegionStats->reset();
3324
delete refinementRegionStats;
3325
refinementRegionStats = new JArithmeticDecoderStats(1 << size);
3330
void JBIG2Stream::resetIntStats(int symCodeLen) {
3339
iardxStats->reset();
3340
iardyStats->reset();
3341
iardwStats->reset();
3342
iardhStats->reset();
3344
if (iaidStats->getContextSize() == 1 << (symCodeLen + 1)) {
3348
iaidStats = new JArithmeticDecoderStats(1 << (symCodeLen + 1));
3352
GBool JBIG2Stream::readUByte(Guint *x) {
3355
if ((c0 = curStr->getChar()) == EOF) {
3362
GBool JBIG2Stream::readByte(int *x) {
3365
if ((c0 = curStr->getChar()) == EOF) {
3375
GBool JBIG2Stream::readUWord(Guint *x) {
3378
if ((c0 = curStr->getChar()) == EOF ||
3379
(c1 = curStr->getChar()) == EOF) {
3382
*x = (Guint)((c0 << 8) | c1);
3386
GBool JBIG2Stream::readULong(Guint *x) {
3389
if ((c0 = curStr->getChar()) == EOF ||
3390
(c1 = curStr->getChar()) == EOF ||
3391
(c2 = curStr->getChar()) == EOF ||
3392
(c3 = curStr->getChar()) == EOF) {
3395
*x = (Guint)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
3399
GBool JBIG2Stream::readLong(int *x) {
3402
if ((c0 = curStr->getChar()) == EOF ||
3403
(c1 = curStr->getChar()) == EOF ||
3404
(c2 = curStr->getChar()) == EOF ||
3405
(c3 = curStr->getChar()) == EOF) {
3408
*x = ((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
3410
*x |= -1 - (int)0xffffffff;