1 //========================================================================
5 // Copyright 2002-2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
18 #include "JArithmeticDecoder.h"
19 #include "JBIG2Stream.h"
21 //~ share these tables
22 #include "Stream-CCITT.h"
24 //------------------------------------------------------------------------
26 static int contextSize
[4] = { 16, 13, 10, 10 };
27 static int refContextSize
[2] = { 13, 10 };
29 //------------------------------------------------------------------------
31 //------------------------------------------------------------------------
33 #define jbig2HuffmanLOW 0xfffffffd
34 #define jbig2HuffmanOOB 0xfffffffe
35 #define jbig2HuffmanEOT 0xffffffff
37 struct JBIG2HuffmanTable
{
40 Guint rangeLen
; // can also be LOW, OOB, or EOT
44 JBIG2HuffmanTable huffTableA
[] = {
47 { 272, 3, 16, 0x006 },
48 { 65808, 3, 32, 0x007 },
49 { 0, 0, jbig2HuffmanEOT
, 0 }
52 JBIG2HuffmanTable huffTableB
[] = {
59 { 0, 6, jbig2HuffmanOOB
, 0x03f },
60 { 0, 0, jbig2HuffmanEOT
, 0 }
63 JBIG2HuffmanTable huffTableC
[] = {
69 { 0, 6, jbig2HuffmanOOB
, 0x03e },
71 { -256, 8, 8, 0x0fe },
72 { -257, 8, jbig2HuffmanLOW
, 0x0ff },
73 { 0, 0, jbig2HuffmanEOT
, 0 }
76 JBIG2HuffmanTable huffTableD
[] = {
83 { 0, 0, jbig2HuffmanEOT
, 0 }
86 JBIG2HuffmanTable huffTableE
[] = {
93 { -255, 7, 8, 0x07e },
94 { -256, 7, jbig2HuffmanLOW
, 0x07f },
95 { 0, 0, jbig2HuffmanEOT
, 0 }
98 JBIG2HuffmanTable huffTableF
[] = {
100 { 128, 3, 7, 0x002 },
101 { 256, 3, 8, 0x003 },
102 { -1024, 4, 9, 0x008 },
103 { -512, 4, 8, 0x009 },
104 { -256, 4, 7, 0x00a },
105 { -32, 4, 5, 0x00b },
106 { 512, 4, 9, 0x00c },
107 { 1024, 4, 10, 0x00d },
108 { -2048, 5, 10, 0x01c },
109 { -128, 5, 6, 0x01d },
110 { -64, 5, 5, 0x01e },
111 { -2049, 6, jbig2HuffmanLOW
, 0x03e },
112 { 2048, 6, 32, 0x03f },
113 { 0, 0, jbig2HuffmanEOT
, 0 }
116 JBIG2HuffmanTable huffTableG
[] = {
117 { -512, 3, 8, 0x000 },
118 { 256, 3, 8, 0x001 },
119 { 512, 3, 9, 0x002 },
120 { 1024, 3, 10, 0x003 },
121 { -1024, 4, 9, 0x008 },
122 { -256, 4, 7, 0x009 },
123 { -32, 4, 5, 0x00a },
125 { 128, 4, 7, 0x00c },
126 { -128, 5, 6, 0x01a },
127 { -64, 5, 5, 0x01b },
130 { -1025, 5, jbig2HuffmanLOW
, 0x01e },
131 { 2048, 5, 32, 0x01f },
132 { 0, 0, jbig2HuffmanEOT
, 0 }
135 JBIG2HuffmanTable huffTableH
[] = {
137 { 0, 2, jbig2HuffmanOOB
, 0x001 },
144 { 134, 5, 7, 0x01c },
147 { 262, 6, 7, 0x03c },
148 { 646, 6, 10, 0x03d },
150 { 390, 7, 8, 0x07d },
151 { -15, 8, 3, 0x0fc },
155 { -16, 9, jbig2HuffmanLOW
, 0x1fe },
156 { 1670, 9, 32, 0x1ff },
157 { 0, 0, jbig2HuffmanEOT
, 0 }
160 JBIG2HuffmanTable huffTableI
[] = {
161 { 0, 2, jbig2HuffmanOOB
, 0x000 },
169 { 139, 5, 7, 0x01b },
170 { 267, 5, 8, 0x01c },
173 { 523, 6, 8, 0x03c },
174 { 1291, 6, 11, 0x03d },
176 { 779, 7, 9, 0x07d },
177 { -31, 8, 4, 0x0fc },
178 { -11, 8, 2, 0x0fd },
179 { -15, 9, 2, 0x1fc },
181 { -32, 9, jbig2HuffmanLOW
, 0x1fe },
182 { 3339, 9, 32, 0x1ff },
183 { 0, 0, jbig2HuffmanEOT
, 0 }
186 JBIG2HuffmanTable huffTableJ
[] = {
189 { 0, 2, jbig2HuffmanOOB
, 0x002 },
194 { 102, 6, 5, 0x037 },
195 { 134, 6, 6, 0x038 },
196 { 198, 6, 7, 0x039 },
197 { 326, 6, 8, 0x03a },
198 { 582, 6, 9, 0x03b },
199 { 1094, 6, 10, 0x03c },
200 { -21, 7, 4, 0x07a },
203 { 2118, 7, 11, 0x07d },
206 { -22, 8, jbig2HuffmanLOW
, 0x0fe },
207 { 4166, 8, 32, 0x0ff },
208 { 0, 0, jbig2HuffmanEOT
, 0 }
211 JBIG2HuffmanTable huffTableK
[] = {
224 { 141, 7, 32, 0x07f },
225 { 0, 0, jbig2HuffmanEOT
, 0 }
228 JBIG2HuffmanTable huffTableL
[] = {
241 { 73, 8, 32, 0x0ff },
242 { 0, 0, jbig2HuffmanEOT
, 0 }
245 JBIG2HuffmanTable huffTableM
[] = {
258 { 141, 7, 32, 0x07f },
259 { 0, 0, jbig2HuffmanEOT
, 0 }
262 JBIG2HuffmanTable huffTableN
[] = {
268 { 0, 0, jbig2HuffmanEOT
, 0 }
271 JBIG2HuffmanTable huffTableO
[] = {
281 { -24, 7, 4, 0x07c },
283 { -25, 7, jbig2HuffmanLOW
, 0x07e },
284 { 25, 7, 32, 0x07f },
285 { 0, 0, jbig2HuffmanEOT
, 0 }
288 //------------------------------------------------------------------------
289 // JBIG2HuffmanDecoder
290 //------------------------------------------------------------------------
292 class JBIG2HuffmanDecoder
{
295 JBIG2HuffmanDecoder();
296 ~JBIG2HuffmanDecoder();
297 void setStream(Stream
*strA
) { str
= strA
; }
301 // Returns false for OOB, otherwise sets *<x> and returns true.
302 GBool
decodeInt(int *x
, JBIG2HuffmanTable
*table
);
304 Guint
readBits(Guint n
);
307 // Sort the table by prefix length and assign prefix values.
308 void buildTable(JBIG2HuffmanTable
*table
, Guint len
);
317 JBIG2HuffmanDecoder::JBIG2HuffmanDecoder() {
322 JBIG2HuffmanDecoder::~JBIG2HuffmanDecoder() {
325 void JBIG2HuffmanDecoder::reset() {
331 GBool
JBIG2HuffmanDecoder::decodeInt(int *x
, JBIG2HuffmanTable
*table
) {
332 Guint i
, len
, prefix
;
337 while (table
[i
].rangeLen
!= jbig2HuffmanEOT
) {
338 while (len
< table
[i
].prefixLen
) {
339 prefix
= (prefix
<< 1) | readBit();
342 if (prefix
== table
[i
].prefix
) {
343 if (table
[i
].rangeLen
== jbig2HuffmanOOB
) {
346 if (table
[i
].rangeLen
== jbig2HuffmanLOW
) {
347 *x
= table
[i
].val
- readBits(32);
348 } else if (table
[i
].rangeLen
> 0) {
349 *x
= table
[i
].val
+ readBits(table
[i
].rangeLen
);
360 Guint
JBIG2HuffmanDecoder::readBits(Guint n
) {
361 Guint x
, mask
, nLeft
;
363 mask
= (n
== 32) ? 0xffffffff : ((1 << n
) - 1);
365 x
= (buf
>> (bufLen
- n
)) & mask
;
368 x
= buf
& ((1 << bufLen
) - 1);
372 x
= (x
<< 8) | (str
->getChar() & 0xff);
376 buf
= str
->getChar();
378 x
= (x
<< nLeft
) | ((buf
>> bufLen
) & ((1 << nLeft
) - 1));
384 Guint
JBIG2HuffmanDecoder::readBit() {
386 buf
= str
->getChar();
390 return (buf
>> bufLen
) & 1;
393 void JBIG2HuffmanDecoder::buildTable(JBIG2HuffmanTable
*table
, Guint len
) {
394 Guint i
, j
, k
, prefix
;
395 JBIG2HuffmanTable tab
;
397 // stable selection sort:
398 // - entries with prefixLen > 0, in ascending prefixLen order
399 // - entry with prefixLen = 0, rangeLen = EOT
400 // - all other entries with prefixLen = 0
401 // (on entry, table[len] has prefixLen = 0, rangeLen = EOT)
402 for (i
= 0; i
< len
; ++i
) {
403 for (j
= i
; j
< len
&& table
[j
].prefixLen
== 0; ++j
) ;
407 for (k
= j
+ 1; k
< len
; ++k
) {
408 if (table
[k
].prefixLen
> 0 &&
409 table
[k
].prefixLen
< table
[j
].prefixLen
) {
415 for (k
= j
; k
> i
; --k
) {
416 table
[k
] = table
[k
- 1];
421 table
[i
] = table
[len
];
426 table
[i
++].prefix
= prefix
++;
427 for (; table
[i
].rangeLen
!= jbig2HuffmanEOT
; ++i
) {
428 prefix
<<= table
[i
].prefixLen
- table
[i
-1].prefixLen
;
429 table
[i
].prefix
= prefix
++;
433 //------------------------------------------------------------------------
435 //------------------------------------------------------------------------
437 class JBIG2MMRDecoder
{
442 void setStream(Stream
*strA
) { str
= strA
; }
448 void skipTo(Guint length
);
458 JBIG2MMRDecoder::JBIG2MMRDecoder() {
463 JBIG2MMRDecoder::~JBIG2MMRDecoder() {
466 void JBIG2MMRDecoder::reset() {
472 int JBIG2MMRDecoder::get2DCode() {
476 buf
= str
->getChar() & 0xff;
479 p
= &twoDimTab1
[(buf
>> 1) & 0x7f];
480 } else if (bufLen
== 8) {
481 p
= &twoDimTab1
[(buf
>> 1) & 0x7f];
483 p
= &twoDimTab1
[(buf
<< (7 - bufLen
)) & 0x7f];
484 if (p
->bits
< 0 || p
->bits
> (int)bufLen
) {
485 buf
= (buf
<< 8) | (str
->getChar() & 0xff);
488 p
= &twoDimTab1
[(buf
>> (bufLen
- 7)) & 0x7f];
492 error(str
->getPos(), "Bad two dim code in JBIG2 MMR stream");
499 int JBIG2MMRDecoder::getWhiteCode() {
504 buf
= str
->getChar() & 0xff;
509 if (bufLen
>= 7 && ((buf
>> (bufLen
- 7)) & 0x7f) == 0) {
511 code
= buf
<< (12 - bufLen
);
513 code
= buf
>> (bufLen
- 12);
515 p
= &whiteTab1
[code
& 0x1f];
518 code
= buf
<< (9 - bufLen
);
520 code
= buf
>> (bufLen
- 9);
522 p
= &whiteTab2
[code
& 0x1ff];
524 if (p
->bits
> 0 && p
->bits
<= (int)bufLen
) {
531 buf
= (buf
<< 8) | (str
->getChar() & 0xff);
535 error(str
->getPos(), "Bad white code in JBIG2 MMR stream");
536 // eat a bit and return a positive number so that the caller doesn't
537 // go into an infinite loop
542 int JBIG2MMRDecoder::getBlackCode() {
547 buf
= str
->getChar() & 0xff;
552 if (bufLen
>= 6 && ((buf
>> (bufLen
- 6)) & 0x3f) == 0) {
554 code
= buf
<< (13 - bufLen
);
556 code
= buf
>> (bufLen
- 13);
558 p
= &blackTab1
[code
& 0x7f];
559 } else if (bufLen
>= 4 && ((buf
>> (bufLen
- 4)) & 0x0f) == 0) {
561 code
= buf
<< (12 - bufLen
);
563 code
= buf
>> (bufLen
- 12);
565 p
= &blackTab2
[(code
& 0xff) - 64];
568 code
= buf
<< (6 - bufLen
);
570 code
= buf
>> (bufLen
- 6);
572 p
= &blackTab3
[code
& 0x3f];
574 if (p
->bits
> 0 && p
->bits
<= (int)bufLen
) {
581 buf
= (buf
<< 8) | (str
->getChar() & 0xff);
585 error(str
->getPos(), "Bad black code in JBIG2 MMR stream");
586 // eat a bit and return a positive number so that the caller doesn't
587 // go into an infinite loop
592 Guint
JBIG2MMRDecoder::get24Bits() {
593 while (bufLen
< 24) {
594 buf
= (buf
<< 8) | (str
->getChar() & 0xff);
598 return (buf
>> (bufLen
- 24)) & 0xffffff;
601 void JBIG2MMRDecoder::skipTo(Guint length
) {
602 while (nBytesRead
< length
) {
608 //------------------------------------------------------------------------
610 //------------------------------------------------------------------------
612 enum JBIG2SegmentType
{
622 JBIG2Segment(Guint segNumA
) { segNum
= segNumA
; }
623 virtual ~JBIG2Segment() {}
624 void setSegNum(Guint segNumA
) { segNum
= segNumA
; }
625 Guint
getSegNum() { return segNum
; }
626 virtual JBIG2SegmentType
getType() = 0;
633 //------------------------------------------------------------------------
635 //------------------------------------------------------------------------
637 struct JBIG2BitmapPtr
{
643 class JBIG2Bitmap
: public JBIG2Segment
{
646 JBIG2Bitmap(Guint segNumA
, int wA
, int hA
);
647 virtual ~JBIG2Bitmap();
648 virtual JBIG2SegmentType
getType() { return jbig2SegBitmap
; }
649 JBIG2Bitmap
*copy() { return new JBIG2Bitmap(0, this); }
650 JBIG2Bitmap
*getSlice(Guint x
, Guint y
, Guint wA
, Guint hA
);
651 void expand(int newH
, Guint pixel
);
654 int getWidth() { return w
; }
655 int getHeight() { return h
; }
656 int getPixel(int x
, int y
)
657 { return (x
< 0 || x
>= w
|| y
< 0 || y
>= h
) ? 0 :
658 (data
[y
* line
+ (x
>> 3)] >> (7 - (x
& 7))) & 1; }
659 void setPixel(int x
, int y
)
660 { data
[y
* line
+ (x
>> 3)] |= 1 << (7 - (x
& 7)); }
661 void clearPixel(int x
, int y
)
662 { data
[y
* line
+ (x
>> 3)] &= 0x7f7f >> (x
& 7); }
663 void getPixelPtr(int x
, int y
, JBIG2BitmapPtr
*ptr
);
664 int nextPixel(JBIG2BitmapPtr
*ptr
);
665 void duplicateRow(int yDest
, int ySrc
);
666 void combine(JBIG2Bitmap
*bitmap
, int x
, int y
, Guint combOp
);
667 Guchar
*getDataPtr() { return data
; }
668 int getDataSize() { return h
* line
; }
672 JBIG2Bitmap(Guint segNumA
, JBIG2Bitmap
*bitmap
);
678 JBIG2Bitmap::JBIG2Bitmap(Guint segNumA
, int wA
, int hA
):
679 JBIG2Segment(segNumA
)
683 line
= (wA
+ 7) >> 3;
684 // need to allocate one extra guard byte for use in combine()
685 data
= (Guchar
*)gmalloc(h
* line
+ 1);
689 JBIG2Bitmap::JBIG2Bitmap(Guint segNumA
, JBIG2Bitmap
*bitmap
):
690 JBIG2Segment(segNumA
)
695 // need to allocate one extra guard byte for use in combine()
696 data
= (Guchar
*)gmalloc(h
* line
+ 1);
697 memcpy(data
, bitmap
->data
, h
* line
);
701 JBIG2Bitmap::~JBIG2Bitmap() {
706 JBIG2Bitmap
*JBIG2Bitmap::getSlice(Guint x
, Guint y
, Guint wA
, Guint hA
) {
710 slice
= new JBIG2Bitmap(0, wA
, hA
);
711 slice
->clearToZero();
712 for (yy
= 0; yy
< hA
; ++yy
) {
713 for (xx
= 0; xx
< wA
; ++xx
) {
714 if (getPixel(x
+ xx
, y
+ yy
)) {
715 slice
->setPixel(xx
, yy
);
722 void JBIG2Bitmap::expand(int newH
, Guint pixel
) {
726 // need to allocate one extra guard byte for use in combine()
727 data
= (Guchar
*)grealloc(data
, newH
* line
+ 1);
729 memset(data
+ h
* line
, 0xff, (newH
- h
) * line
);
731 memset(data
+ h
* line
, 0x00, (newH
- h
) * line
);
737 void JBIG2Bitmap::clearToZero() {
738 memset(data
, 0, h
* line
);
741 void JBIG2Bitmap::clearToOne() {
742 memset(data
, 0xff, h
* line
);
745 inline void JBIG2Bitmap::getPixelPtr(int x
, int y
, JBIG2BitmapPtr
*ptr
) {
746 if (y
< 0 || y
>= h
|| x
>= w
) {
749 ptr
->p
= &data
[y
* line
];
753 ptr
->p
= &data
[y
* line
+ (x
>> 3)];
754 ptr
->shift
= 7 - (x
& 7);
759 inline int JBIG2Bitmap::nextPixel(JBIG2BitmapPtr
*ptr
) {
764 } else if (ptr
->x
< 0) {
768 pix
= (*ptr
->p
>> ptr
->shift
) & 1;
771 } else if (ptr
->shift
== 0) {
781 void JBIG2Bitmap::duplicateRow(int yDest
, int ySrc
) {
782 memcpy(data
+ yDest
* line
, data
+ ySrc
* line
, line
);
785 void JBIG2Bitmap::combine(JBIG2Bitmap
*bitmap
, int x
, int y
,
787 int x0
, x1
, y0
, y1
, xx
, yy
;
788 Guchar
*srcPtr
, *destPtr
;
789 Guint src0
, src1
, src
, dest
, s1
, s2
, m1
, m2
, m3
;
797 if (y
+ bitmap
->h
> h
) {
821 m1
= 0xff >> (x1
& 7);
822 m2
= 0xff << (((x1
& 7) == 0) ? 0 : 8 - (x1
& 7));
823 m3
= (0xff >> s1
) & m2
;
825 oneByte
= x0
== ((x1
- 1) & ~7);
827 for (yy
= y0
; yy
< y1
; ++yy
) {
829 // one byte per line -- need to mask both left and right side
832 destPtr
= data
+ (y
+ yy
) * line
+ (x
>> 3);
833 srcPtr
= bitmap
->data
+ yy
* bitmap
->line
;
838 dest
|= (src1
>> s1
) & m2
;
841 dest
&= ((0xff00 | src1
) >> s1
) | m1
;
844 dest
^= (src1
>> s1
) & m2
;
847 dest
^= ((src1
^ 0xff) >> s1
) & m2
;
850 dest
= (dest
& ~m3
) | ((src1
>> s1
) & m3
);
855 destPtr
= data
+ (y
+ yy
) * line
;
856 srcPtr
= bitmap
->data
+ yy
* bitmap
->line
+ (-x
>> 3);
870 dest
^= (src1
^ 0xff) & m2
;
873 dest
= (src1
& m2
) | (dest
& m1
);
879 // multiple bytes per line -- need to mask left side of left-most
880 // byte and right side of right-most byte
885 destPtr
= data
+ (y
+ yy
) * line
+ (x
>> 3);
886 srcPtr
= bitmap
->data
+ yy
* bitmap
->line
;
894 dest
&= (0xff00 | src1
) >> s1
;
900 dest
^= (src1
^ 0xff) >> s1
;
903 dest
= (dest
& (0xff << s2
)) | (src1
>> s1
);
909 destPtr
= data
+ (y
+ yy
) * line
;
910 srcPtr
= bitmap
->data
+ yy
* bitmap
->line
+ (-x
>> 3);
916 for (; xx
< x1
- 8; xx
+= 8) {
920 src
= (((src0
<< 8) | src1
) >> s1
) & 0xff;
942 // note: this last byte (src1) may not actually be used, depending
943 // on the values of s1, m1, and m2 - and in fact, it may be off
944 // the edge of the source bitmap, which means we need to allocate
945 // one extra guard byte at the end of each bitmap
949 src
= (((src0
<< 8) | src1
) >> s1
) & 0xff;
961 dest
^= (src
^ 0xff) & m2
;
964 dest
= (src
& m2
) | (dest
& m1
);
972 //------------------------------------------------------------------------
974 //------------------------------------------------------------------------
976 class JBIG2SymbolDict
: public JBIG2Segment
{
979 JBIG2SymbolDict(Guint segNumA
, Guint sizeA
);
980 virtual ~JBIG2SymbolDict();
981 virtual JBIG2SegmentType
getType() { return jbig2SegSymbolDict
; }
982 Guint
getSize() { return size
; }
983 void setBitmap(Guint idx
, JBIG2Bitmap
*bitmap
) { bitmaps
[idx
] = bitmap
; }
984 JBIG2Bitmap
*getBitmap(Guint idx
) { return bitmaps
[idx
]; }
985 void setGenericRegionStats(JArithmeticDecoderStats
*stats
)
986 { genericRegionStats
= stats
; }
987 void setRefinementRegionStats(JArithmeticDecoderStats
*stats
)
988 { refinementRegionStats
= stats
; }
989 JArithmeticDecoderStats
*getGenericRegionStats()
990 { return genericRegionStats
; }
991 JArithmeticDecoderStats
*getRefinementRegionStats()
992 { return refinementRegionStats
; }
997 JBIG2Bitmap
**bitmaps
;
998 JArithmeticDecoderStats
*genericRegionStats
;
999 JArithmeticDecoderStats
*refinementRegionStats
;
1002 JBIG2SymbolDict::JBIG2SymbolDict(Guint segNumA
, Guint sizeA
):
1003 JBIG2Segment(segNumA
)
1006 bitmaps
= (JBIG2Bitmap
**)gmallocn(size
, sizeof(JBIG2Bitmap
*));
1007 genericRegionStats
= NULL
;
1008 refinementRegionStats
= NULL
;
1011 JBIG2SymbolDict::~JBIG2SymbolDict() {
1014 for (i
= 0; i
< size
; ++i
) {
1018 if (genericRegionStats
) {
1019 delete genericRegionStats
;
1021 if (refinementRegionStats
) {
1022 delete refinementRegionStats
;
1026 //------------------------------------------------------------------------
1028 //------------------------------------------------------------------------
1030 class JBIG2PatternDict
: public JBIG2Segment
{
1033 JBIG2PatternDict(Guint segNumA
, Guint sizeA
);
1034 virtual ~JBIG2PatternDict();
1035 virtual JBIG2SegmentType
getType() { return jbig2SegPatternDict
; }
1036 Guint
getSize() { return size
; }
1037 void setBitmap(Guint idx
, JBIG2Bitmap
*bitmap
) { bitmaps
[idx
] = bitmap
; }
1038 JBIG2Bitmap
*getBitmap(Guint idx
) { return bitmaps
[idx
]; }
1043 JBIG2Bitmap
**bitmaps
;
1046 JBIG2PatternDict::JBIG2PatternDict(Guint segNumA
, Guint sizeA
):
1047 JBIG2Segment(segNumA
)
1050 bitmaps
= (JBIG2Bitmap
**)gmallocn(size
, sizeof(JBIG2Bitmap
*));
1053 JBIG2PatternDict::~JBIG2PatternDict() {
1056 for (i
= 0; i
< size
; ++i
) {
1062 //------------------------------------------------------------------------
1064 //------------------------------------------------------------------------
1066 class JBIG2CodeTable
: public JBIG2Segment
{
1069 JBIG2CodeTable(Guint segNumA
, JBIG2HuffmanTable
*tableA
);
1070 virtual ~JBIG2CodeTable();
1071 virtual JBIG2SegmentType
getType() { return jbig2SegCodeTable
; }
1072 JBIG2HuffmanTable
*getHuffTable() { return table
; }
1076 JBIG2HuffmanTable
*table
;
1079 JBIG2CodeTable::JBIG2CodeTable(Guint segNumA
, JBIG2HuffmanTable
*tableA
):
1080 JBIG2Segment(segNumA
)
1085 JBIG2CodeTable::~JBIG2CodeTable() {
1089 //------------------------------------------------------------------------
1091 //------------------------------------------------------------------------
1093 JBIG2Stream::JBIG2Stream(Stream
*strA
, Object
*globalsStream
):
1098 arithDecoder
= new JArithmeticDecoder();
1099 genericRegionStats
= new JArithmeticDecoderStats(1 << 1);
1100 refinementRegionStats
= new JArithmeticDecoderStats(1 << 1);
1101 iadhStats
= new JArithmeticDecoderStats(1 << 9);
1102 iadwStats
= new JArithmeticDecoderStats(1 << 9);
1103 iaexStats
= new JArithmeticDecoderStats(1 << 9);
1104 iaaiStats
= new JArithmeticDecoderStats(1 << 9);
1105 iadtStats
= new JArithmeticDecoderStats(1 << 9);
1106 iaitStats
= new JArithmeticDecoderStats(1 << 9);
1107 iafsStats
= new JArithmeticDecoderStats(1 << 9);
1108 iadsStats
= new JArithmeticDecoderStats(1 << 9);
1109 iardxStats
= new JArithmeticDecoderStats(1 << 9);
1110 iardyStats
= new JArithmeticDecoderStats(1 << 9);
1111 iardwStats
= new JArithmeticDecoderStats(1 << 9);
1112 iardhStats
= new JArithmeticDecoderStats(1 << 9);
1113 iariStats
= new JArithmeticDecoderStats(1 << 9);
1114 iaidStats
= new JArithmeticDecoderStats(1 << 1);
1115 huffDecoder
= new JBIG2HuffmanDecoder();
1116 mmrDecoder
= new JBIG2MMRDecoder();
1118 segments
= globalSegments
= new GList();
1119 if (globalsStream
->isStream()) {
1120 curStr
= globalsStream
->getStream();
1122 arithDecoder
->setStream(curStr
);
1123 huffDecoder
->setStream(curStr
);
1124 mmrDecoder
->setStream(curStr
);
1130 dataPtr
= dataEnd
= NULL
;
1133 JBIG2Stream::~JBIG2Stream() {
1134 delete arithDecoder
;
1135 delete genericRegionStats
;
1136 delete refinementRegionStats
;
1157 deleteGList(segments
, JBIG2Segment
);
1159 if (globalSegments
) {
1160 deleteGList(globalSegments
, JBIG2Segment
);
1165 void JBIG2Stream::reset() {
1171 deleteGList(segments
, JBIG2Segment
);
1173 segments
= new GList();
1177 arithDecoder
->setStream(curStr
);
1178 huffDecoder
->setStream(curStr
);
1179 mmrDecoder
->setStream(curStr
);
1183 dataPtr
= pageBitmap
->getDataPtr();
1184 dataEnd
= dataPtr
+ pageBitmap
->getDataSize();
1190 int JBIG2Stream::getChar() {
1191 if (dataPtr
&& dataPtr
< dataEnd
) {
1192 return (*dataPtr
++ ^ 0xff) & 0xff;
1197 int JBIG2Stream::lookChar() {
1198 if (dataPtr
&& dataPtr
< dataEnd
) {
1199 return (*dataPtr
^ 0xff) & 0xff;
1204 GString
*JBIG2Stream::getPSFilter(int psLevel
, char *indent
) {
1208 GBool
JBIG2Stream::isBinary(GBool last
) {
1209 return str
->isBinary(gTrue
);
1212 void JBIG2Stream::readSegments() {
1213 Guint segNum
, segFlags
, segType
, page
, segLength
;
1214 Guint refFlags
, nRefSegs
;
1219 while (readULong(&segNum
)) {
1221 // segment header flags
1222 if (!readUByte(&segFlags
)) {
1225 segType
= segFlags
& 0x3f;
1227 // referred-to segment count and retention flags
1228 if (!readUByte(&refFlags
)) {
1231 nRefSegs
= refFlags
>> 5;
1232 if (nRefSegs
== 7) {
1233 if ((c1
= curStr
->getChar()) == EOF
||
1234 (c2
= curStr
->getChar()) == EOF
||
1235 (c3
= curStr
->getChar()) == EOF
) {
1238 refFlags
= (refFlags
<< 24) | (c1
<< 16) | (c2
<< 8) | c3
;
1239 nRefSegs
= refFlags
& 0x1fffffff;
1240 for (i
= 0; i
< (nRefSegs
+ 9) >> 3; ++i
) {
1241 c1
= curStr
->getChar();
1245 // referred-to segment numbers
1246 refSegs
= (Guint
*)gmallocn(nRefSegs
, sizeof(Guint
));
1247 if (segNum
<= 256) {
1248 for (i
= 0; i
< nRefSegs
; ++i
) {
1249 if (!readUByte(&refSegs
[i
])) {
1253 } else if (segNum
<= 65536) {
1254 for (i
= 0; i
< nRefSegs
; ++i
) {
1255 if (!readUWord(&refSegs
[i
])) {
1260 for (i
= 0; i
< nRefSegs
; ++i
) {
1261 if (!readULong(&refSegs
[i
])) {
1267 // segment page association
1268 if (segFlags
& 0x40) {
1269 if (!readULong(&page
)) {
1273 if (!readUByte(&page
)) {
1278 // segment data length
1279 if (!readULong(&segLength
)) {
1283 // read the segment data
1286 if (!readSymbolDictSeg(segNum
, segLength
, refSegs
, nRefSegs
)) {
1291 readTextRegionSeg(segNum
, gFalse
, gFalse
, segLength
, refSegs
, nRefSegs
);
1294 readTextRegionSeg(segNum
, gTrue
, gFalse
, segLength
, refSegs
, nRefSegs
);
1297 readTextRegionSeg(segNum
, gTrue
, gTrue
, segLength
, refSegs
, nRefSegs
);
1300 readPatternDictSeg(segNum
, segLength
);
1303 readHalftoneRegionSeg(segNum
, gFalse
, gFalse
, segLength
,
1307 readHalftoneRegionSeg(segNum
, gTrue
, gFalse
, segLength
,
1311 readHalftoneRegionSeg(segNum
, gTrue
, gTrue
, segLength
,
1315 readGenericRegionSeg(segNum
, gFalse
, gFalse
, segLength
);
1318 readGenericRegionSeg(segNum
, gTrue
, gFalse
, segLength
);
1321 readGenericRegionSeg(segNum
, gTrue
, gTrue
, segLength
);
1324 readGenericRefinementRegionSeg(segNum
, gFalse
, gFalse
, segLength
,
1328 readGenericRefinementRegionSeg(segNum
, gTrue
, gFalse
, segLength
,
1332 readGenericRefinementRegionSeg(segNum
, gTrue
, gTrue
, segLength
,
1336 readPageInfoSeg(segLength
);
1339 readEndOfStripeSeg(segLength
);
1342 readProfilesSeg(segLength
);
1345 readCodeTableSeg(segNum
, segLength
);
1348 readExtensionSeg(segLength
);
1351 error(getPos(), "Unknown segment type in JBIG2 stream");
1352 for (i
= 0; i
< segLength
; ++i
) {
1353 if ((c1
= curStr
->getChar()) == EOF
) {
1372 error(getPos(), "Unexpected EOF in JBIG2 stream");
1375 GBool
JBIG2Stream::readSymbolDictSeg(Guint segNum
, Guint length
,
1376 Guint
*refSegs
, Guint nRefSegs
) {
1377 JBIG2SymbolDict
*symbolDict
;
1378 JBIG2HuffmanTable
*huffDHTable
, *huffDWTable
;
1379 JBIG2HuffmanTable
*huffBMSizeTable
, *huffAggInstTable
;
1382 JBIG2SymbolDict
*inputSymbolDict
;
1383 Guint flags
, sdTemplate
, sdrTemplate
, huff
, refAgg
;
1384 Guint huffDH
, huffDW
, huffBMSize
, huffAggInst
;
1385 Guint contextUsed
, contextRetained
;
1386 int sdATX
[4], sdATY
[4], sdrATX
[2], sdrATY
[2];
1387 Guint numExSyms
, numNewSyms
, numInputSyms
, symCodeLen
;
1388 JBIG2Bitmap
**bitmaps
;
1389 JBIG2Bitmap
*collBitmap
, *refBitmap
;
1391 Guint symHeight
, symWidth
, totalWidth
, x
, symID
;
1392 int dh
, dw
, refAggNum
, refDX
, refDY
, bmSize
;
1398 // symbol dictionary flags
1399 if (!readUWord(&flags
)) {
1402 sdTemplate
= (flags
>> 10) & 3;
1403 sdrTemplate
= (flags
>> 12) & 1;
1405 refAgg
= (flags
>> 1) & 1;
1406 huffDH
= (flags
>> 2) & 3;
1407 huffDW
= (flags
>> 4) & 3;
1408 huffBMSize
= (flags
>> 6) & 1;
1409 huffAggInst
= (flags
>> 7) & 1;
1410 contextUsed
= (flags
>> 8) & 1;
1411 contextRetained
= (flags
>> 9) & 1;
1413 // symbol dictionary AT flags
1415 if (sdTemplate
== 0) {
1416 if (!readByte(&sdATX
[0]) ||
1417 !readByte(&sdATY
[0]) ||
1418 !readByte(&sdATX
[1]) ||
1419 !readByte(&sdATY
[1]) ||
1420 !readByte(&sdATX
[2]) ||
1421 !readByte(&sdATY
[2]) ||
1422 !readByte(&sdATX
[3]) ||
1423 !readByte(&sdATY
[3])) {
1427 if (!readByte(&sdATX
[0]) ||
1428 !readByte(&sdATY
[0])) {
1434 // symbol dictionary refinement AT flags
1435 if (refAgg
&& !sdrTemplate
) {
1436 if (!readByte(&sdrATX
[0]) ||
1437 !readByte(&sdrATY
[0]) ||
1438 !readByte(&sdrATX
[1]) ||
1439 !readByte(&sdrATY
[1])) {
1444 // SDNUMEXSYMS and SDNUMNEWSYMS
1445 if (!readULong(&numExSyms
) || !readULong(&numNewSyms
)) {
1449 // get referenced segments: input symbol dictionaries and code tables
1450 codeTables
= new GList();
1452 for (i
= 0; i
< nRefSegs
; ++i
) {
1453 seg
= findSegment(refSegs
[i
]);
1454 if (seg
->getType() == jbig2SegSymbolDict
) {
1455 numInputSyms
+= ((JBIG2SymbolDict
*)seg
)->getSize();
1456 } else if (seg
->getType() == jbig2SegCodeTable
) {
1457 codeTables
->append(seg
);
1461 // compute symbol code length
1464 while (i
< numInputSyms
+ numNewSyms
) {
1469 // get the input symbol bitmaps
1470 bitmaps
= (JBIG2Bitmap
**)gmallocn(numInputSyms
+ numNewSyms
,
1471 sizeof(JBIG2Bitmap
*));
1472 for (i
= 0; i
< numInputSyms
+ numNewSyms
; ++i
) {
1476 inputSymbolDict
= NULL
;
1477 for (i
= 0; i
< nRefSegs
; ++i
) {
1478 seg
= findSegment(refSegs
[i
]);
1479 if (seg
->getType() == jbig2SegSymbolDict
) {
1480 inputSymbolDict
= (JBIG2SymbolDict
*)seg
;
1481 for (j
= 0; j
< inputSymbolDict
->getSize(); ++j
) {
1482 bitmaps
[k
++] = inputSymbolDict
->getBitmap(j
);
1487 // get the Huffman tables
1488 huffDHTable
= huffDWTable
= NULL
; // make gcc happy
1489 huffBMSizeTable
= huffAggInstTable
= NULL
; // make gcc happy
1493 huffDHTable
= huffTableD
;
1494 } else if (huffDH
== 1) {
1495 huffDHTable
= huffTableE
;
1497 huffDHTable
= ((JBIG2CodeTable
*)codeTables
->get(i
++))->getHuffTable();
1500 huffDWTable
= huffTableB
;
1501 } else if (huffDW
== 1) {
1502 huffDWTable
= huffTableC
;
1504 huffDWTable
= ((JBIG2CodeTable
*)codeTables
->get(i
++))->getHuffTable();
1506 if (huffBMSize
== 0) {
1507 huffBMSizeTable
= huffTableA
;
1510 ((JBIG2CodeTable
*)codeTables
->get(i
++))->getHuffTable();
1512 if (huffAggInst
== 0) {
1513 huffAggInstTable
= huffTableA
;
1516 ((JBIG2CodeTable
*)codeTables
->get(i
++))->getHuffTable();
1521 // set up the Huffman decoder
1523 huffDecoder
->reset();
1525 // set up the arithmetic decoder
1527 if (contextUsed
&& inputSymbolDict
) {
1528 resetGenericStats(sdTemplate
, inputSymbolDict
->getGenericRegionStats());
1530 resetGenericStats(sdTemplate
, NULL
);
1532 resetIntStats(symCodeLen
);
1533 arithDecoder
->start();
1536 // set up the arithmetic decoder for refinement/aggregation
1538 if (contextUsed
&& inputSymbolDict
) {
1539 resetRefinementStats(sdrTemplate
,
1540 inputSymbolDict
->getRefinementRegionStats());
1542 resetRefinementStats(sdrTemplate
, NULL
);
1546 // allocate symbol widths storage
1548 if (huff
&& !refAgg
) {
1549 symWidths
= (Guint
*)gmallocn(numNewSyms
, sizeof(Guint
));
1554 while (i
< numNewSyms
) {
1556 // read the height class delta height
1558 huffDecoder
->decodeInt(&dh
, huffDHTable
);
1560 arithDecoder
->decodeInt(&dh
, iadhStats
);
1562 if (dh
< 0 && (Guint
)-dh
>= symHeight
) {
1563 error(getPos(), "Bad delta-height value in JBIG2 symbol dictionary");
1571 // read the symbols in this height class
1574 // read the delta width
1576 if (!huffDecoder
->decodeInt(&dw
, huffDWTable
)) {
1580 if (!arithDecoder
->decodeInt(&dw
, iadwStats
)) {
1584 if (dw
< 0 && (Guint
)-dw
>= symWidth
) {
1585 error(getPos(), "Bad delta-height value in JBIG2 symbol dictionary");
1590 // using a collective bitmap, so don't read a bitmap here
1591 if (huff
&& !refAgg
) {
1592 symWidths
[i
] = symWidth
;
1593 totalWidth
+= symWidth
;
1595 // refinement/aggregate coding
1596 } else if (refAgg
) {
1598 if (!huffDecoder
->decodeInt(&refAggNum
, huffAggInstTable
)) {
1602 if (!arithDecoder
->decodeInt(&refAggNum
, iaaiStats
)) {
1606 #if 0 //~ This special case was added about a year before the final draft
1607 //~ of the JBIG2 spec was released. I have encountered some old
1608 //~ JBIG2 images that predate it.
1611 if (refAggNum
== 1) {
1614 symID
= huffDecoder
->readBits(symCodeLen
);
1615 huffDecoder
->decodeInt(&refDX
, huffTableO
);
1616 huffDecoder
->decodeInt(&refDY
, huffTableO
);
1617 huffDecoder
->decodeInt(&bmSize
, huffTableA
);
1618 huffDecoder
->reset();
1619 arithDecoder
->start();
1621 symID
= arithDecoder
->decodeIAID(symCodeLen
, iaidStats
);
1622 arithDecoder
->decodeInt(&refDX
, iardxStats
);
1623 arithDecoder
->decodeInt(&refDY
, iardyStats
);
1625 refBitmap
= bitmaps
[symID
];
1626 bitmaps
[numInputSyms
+ i
] =
1627 readGenericRefinementRegion(symWidth
, symHeight
,
1628 sdrTemplate
, gFalse
,
1629 refBitmap
, refDX
, refDY
,
1631 //~ do we need to use the bmSize value here (in Huffman mode)?
1633 bitmaps
[numInputSyms
+ i
] =
1634 readTextRegion(huff
, gTrue
, symWidth
, symHeight
,
1635 refAggNum
, 0, numInputSyms
+ i
, NULL
,
1636 symCodeLen
, bitmaps
, 0, 0, 0, 1, 0,
1637 huffTableF
, huffTableH
, huffTableK
, huffTableO
,
1638 huffTableO
, huffTableO
, huffTableO
, huffTableA
,
1639 sdrTemplate
, sdrATX
, sdrATY
);
1642 // non-ref/agg coding
1644 bitmaps
[numInputSyms
+ i
] =
1645 readGenericBitmap(gFalse
, symWidth
, symHeight
,
1646 sdTemplate
, gFalse
, gFalse
, NULL
,
1653 // read the collective bitmap
1654 if (huff
&& !refAgg
) {
1655 huffDecoder
->decodeInt(&bmSize
, huffBMSizeTable
);
1656 huffDecoder
->reset();
1658 collBitmap
= new JBIG2Bitmap(0, totalWidth
, symHeight
);
1659 bmSize
= symHeight
* ((totalWidth
+ 7) >> 3);
1660 p
= collBitmap
->getDataPtr();
1661 for (k
= 0; k
< (Guint
)bmSize
; ++k
) {
1662 *p
++ = curStr
->getChar();
1665 collBitmap
= readGenericBitmap(gTrue
, totalWidth
, symHeight
,
1666 0, gFalse
, gFalse
, NULL
, NULL
, NULL
,
1670 for (; j
< i
; ++j
) {
1671 bitmaps
[numInputSyms
+ j
] =
1672 collBitmap
->getSlice(x
, 0, symWidths
[j
], symHeight
);
1679 // create the symbol dict object
1680 symbolDict
= new JBIG2SymbolDict(segNum
, numExSyms
);
1682 // exported symbol list
1685 while (i
< numInputSyms
+ numNewSyms
) {
1687 huffDecoder
->decodeInt(&run
, huffTableA
);
1689 arithDecoder
->decodeInt(&run
, iaexStats
);
1692 for (cnt
= 0; cnt
< run
; ++cnt
) {
1693 symbolDict
->setBitmap(j
++, bitmaps
[i
++]->copy());
1701 for (i
= 0; i
< numNewSyms
; ++i
) {
1702 delete bitmaps
[numInputSyms
+ i
];
1709 // save the arithmetic decoder stats
1710 if (!huff
&& contextRetained
) {
1711 symbolDict
->setGenericRegionStats(genericRegionStats
->copy());
1713 symbolDict
->setRefinementRegionStats(refinementRegionStats
->copy());
1717 // store the new symbol dict
1718 segments
->append(symbolDict
);
1723 for (i
= 0; i
< numNewSyms
; ++i
) {
1724 if (bitmaps
[numInputSyms
+ i
]) {
1725 delete bitmaps
[numInputSyms
+ i
];
1735 error(getPos(), "Unexpected EOF in JBIG2 stream");
1739 void JBIG2Stream::readTextRegionSeg(Guint segNum
, GBool imm
,
1740 GBool lossless
, Guint length
,
1741 Guint
*refSegs
, Guint nRefSegs
) {
1742 JBIG2Bitmap
*bitmap
;
1743 JBIG2HuffmanTable runLengthTab
[36];
1744 JBIG2HuffmanTable
*symCodeTab
;
1745 JBIG2HuffmanTable
*huffFSTable
, *huffDSTable
, *huffDTTable
;
1746 JBIG2HuffmanTable
*huffRDWTable
, *huffRDHTable
;
1747 JBIG2HuffmanTable
*huffRDXTable
, *huffRDYTable
, *huffRSizeTable
;
1750 JBIG2SymbolDict
*symbolDict
;
1752 Guint w
, h
, x
, y
, segInfoFlags
, extCombOp
;
1753 Guint flags
, huff
, refine
, logStrips
, refCorner
, transposed
;
1754 Guint combOp
, defPixel
, templ
;
1756 Guint huffFlags
, huffFS
, huffDS
, huffDT
;
1757 Guint huffRDW
, huffRDH
, huffRDX
, huffRDY
, huffRSize
;
1758 Guint numInstances
, numSyms
, symCodeLen
;
1763 // region segment info field
1764 if (!readULong(&w
) || !readULong(&h
) ||
1765 !readULong(&x
) || !readULong(&y
) ||
1766 !readUByte(&segInfoFlags
)) {
1769 extCombOp
= segInfoFlags
& 7;
1771 // rest of the text region header
1772 if (!readUWord(&flags
)) {
1776 refine
= (flags
>> 1) & 1;
1777 logStrips
= (flags
>> 2) & 3;
1778 refCorner
= (flags
>> 4) & 3;
1779 transposed
= (flags
>> 6) & 1;
1780 combOp
= (flags
>> 7) & 3;
1781 defPixel
= (flags
>> 9) & 1;
1782 sOffset
= (flags
>> 10) & 0x1f;
1783 if (sOffset
& 0x10) {
1784 sOffset
|= -1 - 0x0f;
1786 templ
= (flags
>> 15) & 1;
1787 huffFS
= huffDS
= huffDT
= 0; // make gcc happy
1788 huffRDW
= huffRDH
= huffRDX
= huffRDY
= huffRSize
= 0; // make gcc happy
1790 if (!readUWord(&huffFlags
)) {
1793 huffFS
= huffFlags
& 3;
1794 huffDS
= (huffFlags
>> 2) & 3;
1795 huffDT
= (huffFlags
>> 4) & 3;
1796 huffRDW
= (huffFlags
>> 6) & 3;
1797 huffRDH
= (huffFlags
>> 8) & 3;
1798 huffRDX
= (huffFlags
>> 10) & 3;
1799 huffRDY
= (huffFlags
>> 12) & 3;
1800 huffRSize
= (huffFlags
>> 14) & 1;
1802 if (refine
&& templ
== 0) {
1803 if (!readByte(&atx
[0]) || !readByte(&aty
[0]) ||
1804 !readByte(&atx
[1]) || !readByte(&aty
[1])) {
1808 if (!readULong(&numInstances
)) {
1812 // get symbol dictionaries and tables
1813 codeTables
= new GList();
1815 for (i
= 0; i
< nRefSegs
; ++i
) {
1816 if ((seg
= findSegment(refSegs
[i
]))) {
1817 if (seg
->getType() == jbig2SegSymbolDict
) {
1818 numSyms
+= ((JBIG2SymbolDict
*)seg
)->getSize();
1819 } else if (seg
->getType() == jbig2SegCodeTable
) {
1820 codeTables
->append(seg
);
1823 error(getPos(), "Invalid segment reference in JBIG2 text region");
1828 while (i
< numSyms
) {
1833 // get the symbol bitmaps
1834 syms
= (JBIG2Bitmap
**)gmallocn(numSyms
, sizeof(JBIG2Bitmap
*));
1836 for (i
= 0; i
< nRefSegs
; ++i
) {
1837 if ((seg
= findSegment(refSegs
[i
]))) {
1838 if (seg
->getType() == jbig2SegSymbolDict
) {
1839 symbolDict
= (JBIG2SymbolDict
*)seg
;
1840 for (k
= 0; k
< symbolDict
->getSize(); ++k
) {
1841 syms
[kk
++] = symbolDict
->getBitmap(k
);
1847 // get the Huffman tables
1848 huffFSTable
= huffDSTable
= huffDTTable
= NULL
; // make gcc happy
1849 huffRDWTable
= huffRDHTable
= NULL
; // make gcc happy
1850 huffRDXTable
= huffRDYTable
= huffRSizeTable
= NULL
; // make gcc happy
1854 huffFSTable
= huffTableF
;
1855 } else if (huffFS
== 1) {
1856 huffFSTable
= huffTableG
;
1858 huffFSTable
= ((JBIG2CodeTable
*)codeTables
->get(i
++))->getHuffTable();
1861 huffDSTable
= huffTableH
;
1862 } else if (huffDS
== 1) {
1863 huffDSTable
= huffTableI
;
1864 } else if (huffDS
== 2) {
1865 huffDSTable
= huffTableJ
;
1867 huffDSTable
= ((JBIG2CodeTable
*)codeTables
->get(i
++))->getHuffTable();
1870 huffDTTable
= huffTableK
;
1871 } else if (huffDT
== 1) {
1872 huffDTTable
= huffTableL
;
1873 } else if (huffDT
== 2) {
1874 huffDTTable
= huffTableM
;
1876 huffDTTable
= ((JBIG2CodeTable
*)codeTables
->get(i
++))->getHuffTable();
1879 huffRDWTable
= huffTableN
;
1880 } else if (huffRDW
== 1) {
1881 huffRDWTable
= huffTableO
;
1883 huffRDWTable
= ((JBIG2CodeTable
*)codeTables
->get(i
++))->getHuffTable();
1886 huffRDHTable
= huffTableN
;
1887 } else if (huffRDH
== 1) {
1888 huffRDHTable
= huffTableO
;
1890 huffRDHTable
= ((JBIG2CodeTable
*)codeTables
->get(i
++))->getHuffTable();
1893 huffRDXTable
= huffTableN
;
1894 } else if (huffRDX
== 1) {
1895 huffRDXTable
= huffTableO
;
1897 huffRDXTable
= ((JBIG2CodeTable
*)codeTables
->get(i
++))->getHuffTable();
1900 huffRDYTable
= huffTableN
;
1901 } else if (huffRDY
== 1) {
1902 huffRDYTable
= huffTableO
;
1904 huffRDYTable
= ((JBIG2CodeTable
*)codeTables
->get(i
++))->getHuffTable();
1906 if (huffRSize
== 0) {
1907 huffRSizeTable
= huffTableA
;
1910 ((JBIG2CodeTable
*)codeTables
->get(i
++))->getHuffTable();
1915 // symbol ID Huffman decoding table
1917 huffDecoder
->reset();
1918 for (i
= 0; i
< 32; ++i
) {
1919 runLengthTab
[i
].val
= i
;
1920 runLengthTab
[i
].prefixLen
= huffDecoder
->readBits(4);
1921 runLengthTab
[i
].rangeLen
= 0;
1923 runLengthTab
[32].val
= 0x103;
1924 runLengthTab
[32].prefixLen
= huffDecoder
->readBits(4);
1925 runLengthTab
[32].rangeLen
= 2;
1926 runLengthTab
[33].val
= 0x203;
1927 runLengthTab
[33].prefixLen
= huffDecoder
->readBits(4);
1928 runLengthTab
[33].rangeLen
= 3;
1929 runLengthTab
[34].val
= 0x20b;
1930 runLengthTab
[34].prefixLen
= huffDecoder
->readBits(4);
1931 runLengthTab
[34].rangeLen
= 7;
1932 runLengthTab
[35].prefixLen
= 0;
1933 runLengthTab
[35].rangeLen
= jbig2HuffmanEOT
;
1934 huffDecoder
->buildTable(runLengthTab
, 35);
1935 symCodeTab
= (JBIG2HuffmanTable
*)gmallocn(numSyms
+ 1,
1936 sizeof(JBIG2HuffmanTable
));
1937 for (i
= 0; i
< numSyms
; ++i
) {
1938 symCodeTab
[i
].val
= i
;
1939 symCodeTab
[i
].rangeLen
= 0;
1942 while (i
< numSyms
) {
1943 huffDecoder
->decodeInt(&j
, runLengthTab
);
1945 for (j
-= 0x200; j
&& i
< numSyms
; --j
) {
1946 symCodeTab
[i
++].prefixLen
= 0;
1948 } else if (j
> 0x100) {
1949 for (j
-= 0x100; j
&& i
< numSyms
; --j
) {
1950 symCodeTab
[i
].prefixLen
= symCodeTab
[i
-1].prefixLen
;
1954 symCodeTab
[i
++].prefixLen
= j
;
1957 symCodeTab
[numSyms
].prefixLen
= 0;
1958 symCodeTab
[numSyms
].rangeLen
= jbig2HuffmanEOT
;
1959 huffDecoder
->buildTable(symCodeTab
, numSyms
);
1960 huffDecoder
->reset();
1962 // set up the arithmetic decoder
1965 resetIntStats(symCodeLen
);
1966 arithDecoder
->start();
1969 resetRefinementStats(templ
, NULL
);
1972 bitmap
= readTextRegion(huff
, refine
, w
, h
, numInstances
,
1973 logStrips
, numSyms
, symCodeTab
, symCodeLen
, syms
,
1974 defPixel
, combOp
, transposed
, refCorner
, sOffset
,
1975 huffFSTable
, huffDSTable
, huffDTTable
,
1976 huffRDWTable
, huffRDHTable
,
1977 huffRDXTable
, huffRDYTable
, huffRSizeTable
,
1982 // combine the region bitmap into the page bitmap
1984 if (pageH
== 0xffffffff && y
+ h
> curPageH
) {
1985 pageBitmap
->expand(y
+ h
, pageDefPixel
);
1987 pageBitmap
->combine(bitmap
, x
, y
, extCombOp
);
1990 // store the region bitmap
1992 bitmap
->setSegNum(segNum
);
1993 segments
->append(bitmap
);
1996 // clean up the Huffman decoder
2004 error(getPos(), "Unexpected EOF in JBIG2 stream");
2007 JBIG2Bitmap
*JBIG2Stream::readTextRegion(GBool huff
, GBool refine
,
2012 JBIG2HuffmanTable
*symCodeTab
,
2015 Guint defPixel
, Guint combOp
,
2016 Guint transposed
, Guint refCorner
,
2018 JBIG2HuffmanTable
*huffFSTable
,
2019 JBIG2HuffmanTable
*huffDSTable
,
2020 JBIG2HuffmanTable
*huffDTTable
,
2021 JBIG2HuffmanTable
*huffRDWTable
,
2022 JBIG2HuffmanTable
*huffRDHTable
,
2023 JBIG2HuffmanTable
*huffRDXTable
,
2024 JBIG2HuffmanTable
*huffRDYTable
,
2025 JBIG2HuffmanTable
*huffRSizeTable
,
2027 int *atx
, int *aty
) {
2028 JBIG2Bitmap
*bitmap
;
2029 JBIG2Bitmap
*symbolBitmap
;
2031 int t
, dt
, tt
, s
, ds
, sFirst
, j
;
2032 int rdw
, rdh
, rdx
, rdy
, ri
, refDX
, refDY
, bmSize
;
2033 Guint symID
, inst
, bw
, bh
;
2035 strips
= 1 << logStrips
;
2037 // allocate the bitmap
2038 bitmap
= new JBIG2Bitmap(0, w
, h
);
2040 bitmap
->clearToOne();
2042 bitmap
->clearToZero();
2045 // decode initial T value
2047 huffDecoder
->decodeInt(&t
, huffDTTable
);
2049 arithDecoder
->decodeInt(&t
, iadtStats
);
2055 while (inst
< numInstances
) {
2059 huffDecoder
->decodeInt(&dt
, huffDTTable
);
2061 arithDecoder
->decodeInt(&dt
, iadtStats
);
2067 huffDecoder
->decodeInt(&ds
, huffFSTable
);
2069 arithDecoder
->decodeInt(&ds
, iafsStats
);
2074 // read the instances
2081 dt
= huffDecoder
->readBits(logStrips
);
2083 arithDecoder
->decodeInt(&dt
, iaitStats
);
2090 huffDecoder
->decodeInt(&j
, symCodeTab
);
2093 symID
= huffDecoder
->readBits(symCodeLen
);
2096 symID
= arithDecoder
->decodeIAID(symCodeLen
, iaidStats
);
2099 if (symID
>= (Guint
)numSyms
) {
2100 error(getPos(), "Invalid symbol number in JBIG2 text region");
2103 // get the symbol bitmap
2104 symbolBitmap
= NULL
;
2107 ri
= (int)huffDecoder
->readBit();
2109 arithDecoder
->decodeInt(&ri
, iariStats
);
2116 huffDecoder
->decodeInt(&rdw
, huffRDWTable
);
2117 huffDecoder
->decodeInt(&rdh
, huffRDHTable
);
2118 huffDecoder
->decodeInt(&rdx
, huffRDXTable
);
2119 huffDecoder
->decodeInt(&rdy
, huffRDYTable
);
2120 huffDecoder
->decodeInt(&bmSize
, huffRSizeTable
);
2121 huffDecoder
->reset();
2122 arithDecoder
->start();
2124 arithDecoder
->decodeInt(&rdw
, iardwStats
);
2125 arithDecoder
->decodeInt(&rdh
, iardhStats
);
2126 arithDecoder
->decodeInt(&rdx
, iardxStats
);
2127 arithDecoder
->decodeInt(&rdy
, iardyStats
);
2129 refDX
= ((rdw
>= 0) ? rdw
: rdw
- 1) / 2 + rdx
;
2130 refDY
= ((rdh
>= 0) ? rdh
: rdh
- 1) / 2 + rdy
;
2133 readGenericRefinementRegion(rdw
+ syms
[symID
]->getWidth(),
2134 rdh
+ syms
[symID
]->getHeight(),
2135 templ
, gFalse
, syms
[symID
],
2136 refDX
, refDY
, atx
, aty
);
2137 //~ do we need to use the bmSize value here (in Huffman mode)?
2139 symbolBitmap
= syms
[symID
];
2142 // combine the symbol bitmap into the region bitmap
2143 //~ something is wrong here - refCorner shouldn't degenerate into
2145 bw
= symbolBitmap
->getWidth() - 1;
2146 bh
= symbolBitmap
->getHeight() - 1;
2148 switch (refCorner
) {
2149 case 0: // bottom left
2150 bitmap
->combine(symbolBitmap
, tt
, s
, combOp
);
2153 bitmap
->combine(symbolBitmap
, tt
, s
, combOp
);
2155 case 2: // bottom right
2156 bitmap
->combine(symbolBitmap
, tt
- bw
, s
, combOp
);
2158 case 3: // top right
2159 bitmap
->combine(symbolBitmap
, tt
- bw
, s
, combOp
);
2164 switch (refCorner
) {
2165 case 0: // bottom left
2166 bitmap
->combine(symbolBitmap
, s
, tt
- bh
, combOp
);
2169 bitmap
->combine(symbolBitmap
, s
, tt
, combOp
);
2171 case 2: // bottom right
2172 bitmap
->combine(symbolBitmap
, s
, tt
- bh
, combOp
);
2174 case 3: // top right
2175 bitmap
->combine(symbolBitmap
, s
, tt
, combOp
);
2181 delete symbolBitmap
;
2190 if (!huffDecoder
->decodeInt(&ds
, huffDSTable
)) {
2194 if (!arithDecoder
->decodeInt(&ds
, iadsStats
)) {
2205 void JBIG2Stream::readPatternDictSeg(Guint segNum
, Guint length
) {
2206 JBIG2PatternDict
*patternDict
;
2207 JBIG2Bitmap
*bitmap
;
2208 Guint flags
, patternW
, patternH
, grayMax
, templ
, mmr
;
2212 // halftone dictionary flags, pattern width and height, max gray value
2213 if (!readUByte(&flags
) ||
2214 !readUByte(&patternW
) ||
2215 !readUByte(&patternH
) ||
2216 !readULong(&grayMax
)) {
2219 templ
= (flags
>> 1) & 3;
2222 // set up the arithmetic decoder
2224 resetGenericStats(templ
, NULL
);
2225 arithDecoder
->start();
2229 atx
[0] = -(int)patternW
; aty
[0] = 0;
2230 atx
[1] = -3; aty
[1] = -1;
2231 atx
[2] = 2; aty
[2] = -2;
2232 atx
[3] = -2; aty
[3] = -2;
2233 bitmap
= readGenericBitmap(mmr
, (grayMax
+ 1) * patternW
, patternH
,
2234 templ
, gFalse
, gFalse
, NULL
,
2235 atx
, aty
, length
- 7);
2237 // create the pattern dict object
2238 patternDict
= new JBIG2PatternDict(segNum
, grayMax
+ 1);
2240 // split up the bitmap
2242 for (i
= 0; i
<= grayMax
; ++i
) {
2243 patternDict
->setBitmap(i
, bitmap
->getSlice(x
, 0, patternW
, patternH
));
2250 // store the new pattern dict
2251 segments
->append(patternDict
);
2256 error(getPos(), "Unexpected EOF in JBIG2 stream");
2259 void JBIG2Stream::readHalftoneRegionSeg(Guint segNum
, GBool imm
,
2260 GBool lossless
, Guint length
,
2261 Guint
*refSegs
, Guint nRefSegs
) {
2262 JBIG2Bitmap
*bitmap
;
2264 JBIG2PatternDict
*patternDict
;
2265 JBIG2Bitmap
*skipBitmap
;
2267 JBIG2Bitmap
*grayBitmap
;
2268 JBIG2Bitmap
*patternBitmap
;
2269 Guint w
, h
, x
, y
, segInfoFlags
, extCombOp
;
2270 Guint flags
, mmr
, templ
, enableSkip
, combOp
;
2271 Guint gridW
, gridH
, stepX
, stepY
, patW
, patH
;
2273 int gridX
, gridY
, xx
, yy
, bit
, j
;
2276 // region segment info field
2277 if (!readULong(&w
) || !readULong(&h
) ||
2278 !readULong(&x
) || !readULong(&y
) ||
2279 !readUByte(&segInfoFlags
)) {
2282 extCombOp
= segInfoFlags
& 7;
2284 // rest of the halftone region header
2285 if (!readUByte(&flags
)) {
2289 templ
= (flags
>> 1) & 3;
2290 enableSkip
= (flags
>> 3) & 1;
2291 combOp
= (flags
>> 4) & 7;
2292 if (!readULong(&gridW
) || !readULong(&gridH
) ||
2293 !readLong(&gridX
) || !readLong(&gridY
) ||
2294 !readUWord(&stepX
) || !readUWord(&stepY
)) {
2298 // get pattern dictionary
2299 if (nRefSegs
!= 1) {
2300 error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
2303 seg
= findSegment(refSegs
[0]);
2304 if (seg
->getType() != jbig2SegPatternDict
) {
2305 error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
2308 patternDict
= (JBIG2PatternDict
*)seg
;
2311 while (i
< patternDict
->getSize()) {
2315 patW
= patternDict
->getBitmap(0)->getWidth();
2316 patH
= patternDict
->getBitmap(0)->getHeight();
2318 // set up the arithmetic decoder
2320 resetGenericStats(templ
, NULL
);
2321 arithDecoder
->start();
2324 // allocate the bitmap
2325 bitmap
= new JBIG2Bitmap(segNum
, w
, h
);
2326 if (flags
& 0x80) { // HDEFPIXEL
2327 bitmap
->clearToOne();
2329 bitmap
->clearToZero();
2332 // compute the skip bitmap
2335 skipBitmap
= new JBIG2Bitmap(0, gridW
, gridH
);
2336 skipBitmap
->clearToZero();
2337 for (m
= 0; m
< gridH
; ++m
) {
2338 xx
= gridX
+ m
* stepY
;
2339 yy
= gridY
+ m
* stepX
;
2340 for (n
= 0; n
< gridW
; ++n
) {
2341 if (((xx
+ (int)patW
) >> 8) <= 0 || (xx
>> 8) >= (int)w
||
2342 ((yy
+ (int)patH
) >> 8) <= 0 || (yy
>> 8) >= (int)h
) {
2343 skipBitmap
->setPixel(n
, m
);
2349 // read the gray-scale image
2350 grayImg
= (Guint
*)gmallocn(gridW
* gridH
, sizeof(Guint
));
2351 memset(grayImg
, 0, gridW
* gridH
* sizeof(Guint
));
2352 atx
[0] = templ
<= 1 ? 3 : 2; aty
[0] = -1;
2353 atx
[1] = -3; aty
[1] = -1;
2354 atx
[2] = 2; aty
[2] = -2;
2355 atx
[3] = -2; aty
[3] = -2;
2356 for (j
= bpp
- 1; j
>= 0; --j
) {
2357 grayBitmap
= readGenericBitmap(mmr
, gridW
, gridH
, templ
, gFalse
,
2358 enableSkip
, skipBitmap
, atx
, aty
, -1);
2360 for (m
= 0; m
< gridH
; ++m
) {
2361 for (n
= 0; n
< gridW
; ++n
) {
2362 bit
= grayBitmap
->getPixel(n
, m
) ^ (grayImg
[i
] & 1);
2363 grayImg
[i
] = (grayImg
[i
] << 1) | bit
;
2372 for (m
= 0; m
< gridH
; ++m
) {
2373 xx
= gridX
+ m
* stepY
;
2374 yy
= gridY
+ m
* stepX
;
2375 for (n
= 0; n
< gridW
; ++n
) {
2376 if (!(enableSkip
&& skipBitmap
->getPixel(n
, m
))) {
2377 patternBitmap
= patternDict
->getBitmap(grayImg
[i
]);
2378 bitmap
->combine(patternBitmap
, xx
>> 8, yy
>> 8, combOp
);
2388 // combine the region bitmap into the page bitmap
2390 if (pageH
== 0xffffffff && y
+ h
> curPageH
) {
2391 pageBitmap
->expand(y
+ h
, pageDefPixel
);
2393 pageBitmap
->combine(bitmap
, x
, y
, extCombOp
);
2396 // store the region bitmap
2398 segments
->append(bitmap
);
2404 error(getPos(), "Unexpected EOF in JBIG2 stream");
2407 void JBIG2Stream::readGenericRegionSeg(Guint segNum
, GBool imm
,
2408 GBool lossless
, Guint length
) {
2409 JBIG2Bitmap
*bitmap
;
2410 Guint w
, h
, x
, y
, segInfoFlags
, extCombOp
;
2411 Guint flags
, mmr
, templ
, tpgdOn
;
2414 // region segment info field
2415 if (!readULong(&w
) || !readULong(&h
) ||
2416 !readULong(&x
) || !readULong(&y
) ||
2417 !readUByte(&segInfoFlags
)) {
2420 extCombOp
= segInfoFlags
& 7;
2422 // rest of the generic region segment header
2423 if (!readUByte(&flags
)) {
2427 templ
= (flags
>> 1) & 3;
2428 tpgdOn
= (flags
>> 3) & 1;
2433 if (!readByte(&atx
[0]) ||
2434 !readByte(&aty
[0]) ||
2435 !readByte(&atx
[1]) ||
2436 !readByte(&aty
[1]) ||
2437 !readByte(&atx
[2]) ||
2438 !readByte(&aty
[2]) ||
2439 !readByte(&atx
[3]) ||
2440 !readByte(&aty
[3])) {
2444 if (!readByte(&atx
[0]) ||
2445 !readByte(&aty
[0])) {
2451 // set up the arithmetic decoder
2453 resetGenericStats(templ
, NULL
);
2454 arithDecoder
->start();
2458 bitmap
= readGenericBitmap(mmr
, w
, h
, templ
, tpgdOn
, gFalse
,
2459 NULL
, atx
, aty
, mmr
? 0 : length
- 18);
2461 // combine the region bitmap into the page bitmap
2463 if (pageH
== 0xffffffff && y
+ h
> curPageH
) {
2464 pageBitmap
->expand(y
+ h
, pageDefPixel
);
2466 pageBitmap
->combine(bitmap
, x
, y
, extCombOp
);
2469 // store the region bitmap
2471 bitmap
->setSegNum(segNum
);
2472 segments
->append(bitmap
);
2478 error(getPos(), "Unexpected EOF in JBIG2 stream");
2481 JBIG2Bitmap
*JBIG2Stream::readGenericBitmap(GBool mmr
, int w
, int h
,
2482 int templ
, GBool tpgdOn
,
2483 GBool useSkip
, JBIG2Bitmap
*skip
,
2485 int mmrDataLength
) {
2486 JBIG2Bitmap
*bitmap
;
2488 Guint ltpCX
, cx
, cx0
, cx1
, cx2
;
2489 JBIG2BitmapPtr cxPtr0
, cxPtr1
;
2490 JBIG2BitmapPtr atPtr0
, atPtr1
, atPtr2
, atPtr3
;
2491 int *refLine
, *codingLine
;
2492 int code1
, code2
, code3
;
2493 int x
, y
, a0
, pix
, i
, refI
, codingI
;
2495 bitmap
= new JBIG2Bitmap(0, w
, h
);
2496 bitmap
->clearToZero();
2502 mmrDecoder
->reset();
2503 refLine
= (int *)gmallocn(w
+ 2, sizeof(int));
2504 codingLine
= (int *)gmallocn(w
+ 2, sizeof(int));
2505 codingLine
[0] = codingLine
[1] = w
;
2507 for (y
= 0; y
< h
; ++y
) {
2509 // copy coding line to ref line
2510 for (i
= 0; codingLine
[i
] < w
; ++i
) {
2511 refLine
[i
] = codingLine
[i
];
2513 refLine
[i
] = refLine
[i
+ 1] = w
;
2516 refI
= 0; // b1 = refLine[refI]
2517 codingI
= 0; // a1 = codingLine[codingI]
2520 code1
= mmrDecoder
->get2DCode();
2523 if (refLine
[refI
] < w
) {
2524 a0
= refLine
[refI
+ 1];
2532 code1
+= code3
= mmrDecoder
->getBlackCode();
2533 } while (code3
>= 64);
2536 code2
+= code3
= mmrDecoder
->getWhiteCode();
2537 } while (code3
>= 64);
2541 code1
+= code3
= mmrDecoder
->getWhiteCode();
2542 } while (code3
>= 64);
2545 code2
+= code3
= mmrDecoder
->getBlackCode();
2546 } while (code3
>= 64);
2548 if (code1
> 0 || code2
> 0) {
2549 a0
= codingLine
[codingI
++] = a0
+ code1
;
2550 a0
= codingLine
[codingI
++] = a0
+ code2
;
2551 while (refLine
[refI
] <= a0
&& refLine
[refI
] < w
) {
2557 a0
= codingLine
[codingI
++] = refLine
[refI
];
2558 if (refLine
[refI
] < w
) {
2563 a0
= codingLine
[codingI
++] = refLine
[refI
] + 1;
2564 if (refLine
[refI
] < w
) {
2566 while (refLine
[refI
] <= a0
&& refLine
[refI
] < w
) {
2572 a0
= codingLine
[codingI
++] = refLine
[refI
] + 2;
2573 if (refLine
[refI
] < w
) {
2575 while (refLine
[refI
] <= a0
&& refLine
[refI
] < w
) {
2581 a0
= codingLine
[codingI
++] = refLine
[refI
] + 3;
2582 if (refLine
[refI
] < w
) {
2584 while (refLine
[refI
] <= a0
&& refLine
[refI
] < w
) {
2590 a0
= codingLine
[codingI
++] = refLine
[refI
] - 1;
2596 while (refLine
[refI
] <= a0
&& refLine
[refI
] < w
) {
2601 a0
= codingLine
[codingI
++] = refLine
[refI
] - 2;
2607 while (refLine
[refI
] <= a0
&& refLine
[refI
] < w
) {
2612 a0
= codingLine
[codingI
++] = refLine
[refI
] - 3;
2618 while (refLine
[refI
] <= a0
&& refLine
[refI
] < w
) {
2623 error(getPos(), "Illegal code in JBIG2 MMR bitmap data");
2627 codingLine
[codingI
++] = w
;
2629 // convert the run lengths to a bitmap line
2631 while (codingLine
[i
] < w
) {
2632 for (x
= codingLine
[i
]; x
< codingLine
[i
+1]; ++x
) {
2633 bitmap
->setPixel(x
, y
);
2639 if (mmrDataLength
>= 0) {
2640 mmrDecoder
->skipTo(mmrDataLength
);
2642 if (mmrDecoder
->get24Bits() != 0x001001) {
2643 error(getPos(), "Missing EOFB in JBIG2 MMR bitmap data");
2650 //----- arithmetic decode
2653 // set up the typical row context
2654 ltpCX
= 0; // make gcc happy
2658 ltpCX
= 0x3953; // 001 11001 0101 0011
2661 ltpCX
= 0x079a; // 0011 11001 101 0
2664 ltpCX
= 0x0e3; // 001 1100 01 1
2667 ltpCX
= 0x18a; // 01100 0101 1
2673 cx
= cx0
= cx1
= cx2
= 0; // make gcc happy
2674 for (y
= 0; y
< h
; ++y
) {
2676 // check for a "typical" (duplicate) row
2678 if (arithDecoder
->decodeBit(ltpCX
, genericRegionStats
)) {
2682 bitmap
->duplicateRow(y
, y
-1);
2690 // set up the context
2691 bitmap
->getPixelPtr(0, y
-2, &cxPtr0
);
2692 cx0
= bitmap
->nextPixel(&cxPtr0
);
2693 cx0
= (cx0
<< 1) | bitmap
->nextPixel(&cxPtr0
);
2694 bitmap
->getPixelPtr(0, y
-1, &cxPtr1
);
2695 cx1
= bitmap
->nextPixel(&cxPtr1
);
2696 cx1
= (cx1
<< 1) | bitmap
->nextPixel(&cxPtr1
);
2697 cx1
= (cx1
<< 1) | bitmap
->nextPixel(&cxPtr1
);
2699 bitmap
->getPixelPtr(atx
[0], y
+ aty
[0], &atPtr0
);
2700 bitmap
->getPixelPtr(atx
[1], y
+ aty
[1], &atPtr1
);
2701 bitmap
->getPixelPtr(atx
[2], y
+ aty
[2], &atPtr2
);
2702 bitmap
->getPixelPtr(atx
[3], y
+ aty
[3], &atPtr3
);
2705 for (x
= 0; x
< w
; ++x
) {
2707 // build the context
2708 cx
= (cx0
<< 13) | (cx1
<< 8) | (cx2
<< 4) |
2709 (bitmap
->nextPixel(&atPtr0
) << 3) |
2710 (bitmap
->nextPixel(&atPtr1
) << 2) |
2711 (bitmap
->nextPixel(&atPtr2
) << 1) |
2712 bitmap
->nextPixel(&atPtr3
);
2714 // check for a skipped pixel
2715 if (useSkip
&& skip
->getPixel(x
, y
)) {
2719 } else if ((pix
= arithDecoder
->decodeBit(cx
, genericRegionStats
))) {
2720 bitmap
->setPixel(x
, y
);
2723 // update the context
2724 cx0
= ((cx0
<< 1) | bitmap
->nextPixel(&cxPtr0
)) & 0x07;
2725 cx1
= ((cx1
<< 1) | bitmap
->nextPixel(&cxPtr1
)) & 0x1f;
2726 cx2
= ((cx2
<< 1) | pix
) & 0x0f;
2732 // set up the context
2733 bitmap
->getPixelPtr(0, y
-2, &cxPtr0
);
2734 cx0
= bitmap
->nextPixel(&cxPtr0
);
2735 cx0
= (cx0
<< 1) | bitmap
->nextPixel(&cxPtr0
);
2736 cx0
= (cx0
<< 1) | bitmap
->nextPixel(&cxPtr0
);
2737 bitmap
->getPixelPtr(0, y
-1, &cxPtr1
);
2738 cx1
= bitmap
->nextPixel(&cxPtr1
);
2739 cx1
= (cx1
<< 1) | bitmap
->nextPixel(&cxPtr1
);
2740 cx1
= (cx1
<< 1) | bitmap
->nextPixel(&cxPtr1
);
2742 bitmap
->getPixelPtr(atx
[0], y
+ aty
[0], &atPtr0
);
2745 for (x
= 0; x
< w
; ++x
) {
2747 // build the context
2748 cx
= (cx0
<< 9) | (cx1
<< 4) | (cx2
<< 1) |
2749 bitmap
->nextPixel(&atPtr0
);
2751 // check for a skipped pixel
2752 if (useSkip
&& skip
->getPixel(x
, y
)) {
2756 } else if ((pix
= arithDecoder
->decodeBit(cx
, genericRegionStats
))) {
2757 bitmap
->setPixel(x
, y
);
2760 // update the context
2761 cx0
= ((cx0
<< 1) | bitmap
->nextPixel(&cxPtr0
)) & 0x0f;
2762 cx1
= ((cx1
<< 1) | bitmap
->nextPixel(&cxPtr1
)) & 0x1f;
2763 cx2
= ((cx2
<< 1) | pix
) & 0x07;
2769 // set up the context
2770 bitmap
->getPixelPtr(0, y
-2, &cxPtr0
);
2771 cx0
= bitmap
->nextPixel(&cxPtr0
);
2772 cx0
= (cx0
<< 1) | bitmap
->nextPixel(&cxPtr0
);
2773 bitmap
->getPixelPtr(0, y
-1, &cxPtr1
);
2774 cx1
= bitmap
->nextPixel(&cxPtr1
);
2775 cx1
= (cx1
<< 1) | bitmap
->nextPixel(&cxPtr1
);
2777 bitmap
->getPixelPtr(atx
[0], y
+ aty
[0], &atPtr0
);
2780 for (x
= 0; x
< w
; ++x
) {
2782 // build the context
2783 cx
= (cx0
<< 7) | (cx1
<< 3) | (cx2
<< 1) |
2784 bitmap
->nextPixel(&atPtr0
);
2786 // check for a skipped pixel
2787 if (useSkip
&& skip
->getPixel(x
, y
)) {
2791 } else if ((pix
= arithDecoder
->decodeBit(cx
, genericRegionStats
))) {
2792 bitmap
->setPixel(x
, y
);
2795 // update the context
2796 cx0
= ((cx0
<< 1) | bitmap
->nextPixel(&cxPtr0
)) & 0x07;
2797 cx1
= ((cx1
<< 1) | bitmap
->nextPixel(&cxPtr1
)) & 0x0f;
2798 cx2
= ((cx2
<< 1) | pix
) & 0x03;
2804 // set up the context
2805 bitmap
->getPixelPtr(0, y
-1, &cxPtr1
);
2806 cx1
= bitmap
->nextPixel(&cxPtr1
);
2807 cx1
= (cx1
<< 1) | bitmap
->nextPixel(&cxPtr1
);
2809 bitmap
->getPixelPtr(atx
[0], y
+ aty
[0], &atPtr0
);
2812 for (x
= 0; x
< w
; ++x
) {
2814 // build the context
2815 cx
= (cx1
<< 5) | (cx2
<< 1) |
2816 bitmap
->nextPixel(&atPtr0
);
2818 // check for a skipped pixel
2819 if (useSkip
&& skip
->getPixel(x
, y
)) {
2823 } else if ((pix
= arithDecoder
->decodeBit(cx
, genericRegionStats
))) {
2824 bitmap
->setPixel(x
, y
);
2827 // update the context
2828 cx1
= ((cx1
<< 1) | bitmap
->nextPixel(&cxPtr1
)) & 0x1f;
2829 cx2
= ((cx2
<< 1) | pix
) & 0x0f;
2839 void JBIG2Stream::readGenericRefinementRegionSeg(Guint segNum
, GBool imm
,
2840 GBool lossless
, Guint length
,
2843 JBIG2Bitmap
*bitmap
, *refBitmap
;
2844 Guint w
, h
, x
, y
, segInfoFlags
, extCombOp
;
2845 Guint flags
, templ
, tpgrOn
;
2849 // region segment info field
2850 if (!readULong(&w
) || !readULong(&h
) ||
2851 !readULong(&x
) || !readULong(&y
) ||
2852 !readUByte(&segInfoFlags
)) {
2855 extCombOp
= segInfoFlags
& 7;
2857 // rest of the generic refinement region segment header
2858 if (!readUByte(&flags
)) {
2862 tpgrOn
= (flags
>> 1) & 1;
2866 if (!readByte(&atx
[0]) || !readByte(&aty
[0]) ||
2867 !readByte(&atx
[1]) || !readByte(&aty
[1])) {
2872 // resize the page bitmap if needed
2873 if (nRefSegs
== 0 || imm
) {
2874 if (pageH
== 0xffffffff && y
+ h
> curPageH
) {
2875 pageBitmap
->expand(y
+ h
, pageDefPixel
);
2879 // get referenced bitmap
2881 error(getPos(), "Bad reference in JBIG2 generic refinement segment");
2884 if (nRefSegs
== 1) {
2885 seg
= findSegment(refSegs
[0]);
2886 if (seg
->getType() != jbig2SegBitmap
) {
2887 error(getPos(), "Bad bitmap reference in JBIG2 generic refinement segment");
2890 refBitmap
= (JBIG2Bitmap
*)seg
;
2892 refBitmap
= pageBitmap
->getSlice(x
, y
, w
, h
);
2895 // set up the arithmetic decoder
2896 resetRefinementStats(templ
, NULL
);
2897 arithDecoder
->start();
2900 bitmap
= readGenericRefinementRegion(w
, h
, templ
, tpgrOn
,
2901 refBitmap
, 0, 0, atx
, aty
);
2903 // combine the region bitmap into the page bitmap
2905 pageBitmap
->combine(bitmap
, x
, y
, extCombOp
);
2908 // store the region bitmap
2910 bitmap
->setSegNum(segNum
);
2911 segments
->append(bitmap
);
2914 // delete the referenced bitmap
2915 if (nRefSegs
== 1) {
2916 discardSegment(refSegs
[0]);
2924 error(getPos(), "Unexpected EOF in JBIG2 stream");
2927 JBIG2Bitmap
*JBIG2Stream::readGenericRefinementRegion(int w
, int h
,
2928 int templ
, GBool tpgrOn
,
2929 JBIG2Bitmap
*refBitmap
,
2930 int refDX
, int refDY
,
2931 int *atx
, int *aty
) {
2932 JBIG2Bitmap
*bitmap
;
2934 Guint ltpCX
, cx
, cx0
, cx2
, cx3
, cx4
, tpgrCX0
, tpgrCX1
, tpgrCX2
;
2935 JBIG2BitmapPtr cxPtr0
, cxPtr1
, cxPtr2
, cxPtr3
, cxPtr4
, cxPtr5
, cxPtr6
;
2936 JBIG2BitmapPtr tpgrCXPtr0
, tpgrCXPtr1
, tpgrCXPtr2
;
2939 bitmap
= new JBIG2Bitmap(0, w
, h
);
2940 bitmap
->clearToZero();
2942 // set up the typical row context
2950 for (y
= 0; y
< h
; ++y
) {
2954 // set up the context
2955 bitmap
->getPixelPtr(0, y
-1, &cxPtr0
);
2956 cx0
= bitmap
->nextPixel(&cxPtr0
);
2957 bitmap
->getPixelPtr(-1, y
, &cxPtr1
);
2958 refBitmap
->getPixelPtr(-refDX
, y
-1-refDY
, &cxPtr2
);
2959 refBitmap
->getPixelPtr(-1-refDX
, y
-refDY
, &cxPtr3
);
2960 cx3
= refBitmap
->nextPixel(&cxPtr3
);
2961 cx3
= (cx3
<< 1) | refBitmap
->nextPixel(&cxPtr3
);
2962 refBitmap
->getPixelPtr(-refDX
, y
+1-refDY
, &cxPtr4
);
2963 cx4
= refBitmap
->nextPixel(&cxPtr4
);
2965 // set up the typical prediction context
2966 tpgrCX0
= tpgrCX1
= tpgrCX2
= 0; // make gcc happy
2968 refBitmap
->getPixelPtr(-1-refDX
, y
-1-refDY
, &tpgrCXPtr0
);
2969 tpgrCX0
= refBitmap
->nextPixel(&tpgrCXPtr0
);
2970 tpgrCX0
= (tpgrCX0
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr0
);
2971 tpgrCX0
= (tpgrCX0
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr0
);
2972 refBitmap
->getPixelPtr(-1-refDX
, y
-refDY
, &tpgrCXPtr1
);
2973 tpgrCX1
= refBitmap
->nextPixel(&tpgrCXPtr1
);
2974 tpgrCX1
= (tpgrCX1
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr1
);
2975 tpgrCX1
= (tpgrCX1
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr1
);
2976 refBitmap
->getPixelPtr(-1-refDX
, y
+1-refDY
, &tpgrCXPtr2
);
2977 tpgrCX2
= refBitmap
->nextPixel(&tpgrCXPtr2
);
2978 tpgrCX2
= (tpgrCX2
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr2
);
2979 tpgrCX2
= (tpgrCX2
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr2
);
2982 for (x
= 0; x
< w
; ++x
) {
2984 // update the context
2985 cx0
= ((cx0
<< 1) | bitmap
->nextPixel(&cxPtr0
)) & 7;
2986 cx3
= ((cx3
<< 1) | refBitmap
->nextPixel(&cxPtr3
)) & 7;
2987 cx4
= ((cx4
<< 1) | refBitmap
->nextPixel(&cxPtr4
)) & 3;
2990 // update the typical predictor context
2991 tpgrCX0
= ((tpgrCX0
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr0
)) & 7;
2992 tpgrCX1
= ((tpgrCX1
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr1
)) & 7;
2993 tpgrCX2
= ((tpgrCX2
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr2
)) & 7;
2995 // check for a "typical" pixel
2996 if (arithDecoder
->decodeBit(ltpCX
, refinementRegionStats
)) {
2999 if (tpgrCX0
== 0 && tpgrCX1
== 0 && tpgrCX2
== 0) {
3000 bitmap
->clearPixel(x
, y
);
3002 } else if (tpgrCX0
== 7 && tpgrCX1
== 7 && tpgrCX2
== 7) {
3003 bitmap
->setPixel(x
, y
);
3008 // build the context
3009 cx
= (cx0
<< 7) | (bitmap
->nextPixel(&cxPtr1
) << 6) |
3010 (refBitmap
->nextPixel(&cxPtr2
) << 5) |
3014 if ((pix
= arithDecoder
->decodeBit(cx
, refinementRegionStats
))) {
3015 bitmap
->setPixel(x
, y
);
3021 // set up the context
3022 bitmap
->getPixelPtr(0, y
-1, &cxPtr0
);
3023 cx0
= bitmap
->nextPixel(&cxPtr0
);
3024 bitmap
->getPixelPtr(-1, y
, &cxPtr1
);
3025 refBitmap
->getPixelPtr(-refDX
, y
-1-refDY
, &cxPtr2
);
3026 cx2
= refBitmap
->nextPixel(&cxPtr2
);
3027 refBitmap
->getPixelPtr(-1-refDX
, y
-refDY
, &cxPtr3
);
3028 cx3
= refBitmap
->nextPixel(&cxPtr3
);
3029 cx3
= (cx3
<< 1) | refBitmap
->nextPixel(&cxPtr3
);
3030 refBitmap
->getPixelPtr(-1-refDX
, y
+1-refDY
, &cxPtr4
);
3031 cx4
= refBitmap
->nextPixel(&cxPtr4
);
3032 cx4
= (cx4
<< 1) | refBitmap
->nextPixel(&cxPtr4
);
3033 bitmap
->getPixelPtr(atx
[0], y
+aty
[0], &cxPtr5
);
3034 refBitmap
->getPixelPtr(atx
[1]-refDX
, y
+aty
[1]-refDY
, &cxPtr6
);
3036 // set up the typical prediction context
3037 tpgrCX0
= tpgrCX1
= tpgrCX2
= 0; // make gcc happy
3039 refBitmap
->getPixelPtr(-1-refDX
, y
-1-refDY
, &tpgrCXPtr0
);
3040 tpgrCX0
= refBitmap
->nextPixel(&tpgrCXPtr0
);
3041 tpgrCX0
= (tpgrCX0
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr0
);
3042 tpgrCX0
= (tpgrCX0
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr0
);
3043 refBitmap
->getPixelPtr(-1-refDX
, y
-refDY
, &tpgrCXPtr1
);
3044 tpgrCX1
= refBitmap
->nextPixel(&tpgrCXPtr1
);
3045 tpgrCX1
= (tpgrCX1
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr1
);
3046 tpgrCX1
= (tpgrCX1
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr1
);
3047 refBitmap
->getPixelPtr(-1-refDX
, y
+1-refDY
, &tpgrCXPtr2
);
3048 tpgrCX2
= refBitmap
->nextPixel(&tpgrCXPtr2
);
3049 tpgrCX2
= (tpgrCX2
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr2
);
3050 tpgrCX2
= (tpgrCX2
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr2
);
3053 for (x
= 0; x
< w
; ++x
) {
3055 // update the context
3056 cx0
= ((cx0
<< 1) | bitmap
->nextPixel(&cxPtr0
)) & 3;
3057 cx2
= ((cx2
<< 1) | refBitmap
->nextPixel(&cxPtr2
)) & 3;
3058 cx3
= ((cx3
<< 1) | refBitmap
->nextPixel(&cxPtr3
)) & 7;
3059 cx4
= ((cx4
<< 1) | refBitmap
->nextPixel(&cxPtr4
)) & 7;
3062 // update the typical predictor context
3063 tpgrCX0
= ((tpgrCX0
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr0
)) & 7;
3064 tpgrCX1
= ((tpgrCX1
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr1
)) & 7;
3065 tpgrCX2
= ((tpgrCX2
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr2
)) & 7;
3067 // check for a "typical" pixel
3068 if (arithDecoder
->decodeBit(ltpCX
, refinementRegionStats
)) {
3071 if (tpgrCX0
== 0 && tpgrCX1
== 0 && tpgrCX2
== 0) {
3072 bitmap
->clearPixel(x
, y
);
3074 } else if (tpgrCX0
== 7 && tpgrCX1
== 7 && tpgrCX2
== 7) {
3075 bitmap
->setPixel(x
, y
);
3080 // build the context
3081 cx
= (cx0
<< 11) | (bitmap
->nextPixel(&cxPtr1
) << 10) |
3082 (cx2
<< 8) | (cx3
<< 5) | (cx4
<< 2) |
3083 (bitmap
->nextPixel(&cxPtr5
) << 1) |
3084 refBitmap
->nextPixel(&cxPtr6
);
3087 if ((pix
= arithDecoder
->decodeBit(cx
, refinementRegionStats
))) {
3088 bitmap
->setPixel(x
, y
);
3097 void JBIG2Stream::readPageInfoSeg(Guint length
) {
3098 Guint xRes
, yRes
, flags
, striping
;
3100 if (!readULong(&pageW
) || !readULong(&pageH
) ||
3101 !readULong(&xRes
) || !readULong(&yRes
) ||
3102 !readUByte(&flags
) || !readUWord(&striping
)) {
3105 pageDefPixel
= (flags
>> 2) & 1;
3106 defCombOp
= (flags
>> 3) & 3;
3108 // allocate the page bitmap
3109 if (pageH
== 0xffffffff) {
3110 curPageH
= striping
& 0x7fff;
3114 pageBitmap
= new JBIG2Bitmap(0, pageW
, curPageH
);
3116 // default pixel value
3118 pageBitmap
->clearToOne();
3120 pageBitmap
->clearToZero();
3126 error(getPos(), "Unexpected EOF in JBIG2 stream");
3129 void JBIG2Stream::readEndOfStripeSeg(Guint length
) {
3133 for (i
= 0; i
< length
; ++i
) {
3138 void JBIG2Stream::readProfilesSeg(Guint length
) {
3142 for (i
= 0; i
< length
; ++i
) {
3147 void JBIG2Stream::readCodeTableSeg(Guint segNum
, Guint length
) {
3148 JBIG2HuffmanTable
*huffTab
;
3149 Guint flags
, oob
, prefixBits
, rangeBits
;
3150 int lowVal
, highVal
, val
;
3151 Guint huffTabSize
, i
;
3153 if (!readUByte(&flags
) || !readLong(&lowVal
) || !readLong(&highVal
)) {
3157 prefixBits
= ((flags
>> 1) & 7) + 1;
3158 rangeBits
= ((flags
>> 4) & 7) + 1;
3160 huffDecoder
->reset();
3162 huffTab
= (JBIG2HuffmanTable
*)
3163 gmallocn(huffTabSize
, sizeof(JBIG2HuffmanTable
));
3166 while (val
< highVal
) {
3167 if (i
== huffTabSize
) {
3169 huffTab
= (JBIG2HuffmanTable
*)
3170 greallocn(huffTab
, huffTabSize
, sizeof(JBIG2HuffmanTable
));
3172 huffTab
[i
].val
= val
;
3173 huffTab
[i
].prefixLen
= huffDecoder
->readBits(prefixBits
);
3174 huffTab
[i
].rangeLen
= huffDecoder
->readBits(rangeBits
);
3175 val
+= 1 << huffTab
[i
].rangeLen
;
3178 if (i
+ oob
+ 3 > huffTabSize
) {
3179 huffTabSize
= i
+ oob
+ 3;
3180 huffTab
= (JBIG2HuffmanTable
*)
3181 greallocn(huffTab
, huffTabSize
, sizeof(JBIG2HuffmanTable
));
3183 huffTab
[i
].val
= lowVal
- 1;
3184 huffTab
[i
].prefixLen
= huffDecoder
->readBits(prefixBits
);
3185 huffTab
[i
].rangeLen
= jbig2HuffmanLOW
;
3187 huffTab
[i
].val
= highVal
;
3188 huffTab
[i
].prefixLen
= huffDecoder
->readBits(prefixBits
);
3189 huffTab
[i
].rangeLen
= 32;
3193 huffTab
[i
].prefixLen
= huffDecoder
->readBits(prefixBits
);
3194 huffTab
[i
].rangeLen
= jbig2HuffmanOOB
;
3198 huffTab
[i
].prefixLen
= 0;
3199 huffTab
[i
].rangeLen
= jbig2HuffmanEOT
;
3200 huffDecoder
->buildTable(huffTab
, i
);
3202 // create and store the new table segment
3203 segments
->append(new JBIG2CodeTable(segNum
, huffTab
));
3208 error(getPos(), "Unexpected EOF in JBIG2 stream");
3211 void JBIG2Stream::readExtensionSeg(Guint length
) {
3215 for (i
= 0; i
< length
; ++i
) {
3220 JBIG2Segment
*JBIG2Stream::findSegment(Guint segNum
) {
3224 for (i
= 0; i
< globalSegments
->getLength(); ++i
) {
3225 seg
= (JBIG2Segment
*)globalSegments
->get(i
);
3226 if (seg
->getSegNum() == segNum
) {
3230 for (i
= 0; i
< segments
->getLength(); ++i
) {
3231 seg
= (JBIG2Segment
*)segments
->get(i
);
3232 if (seg
->getSegNum() == segNum
) {
3239 void JBIG2Stream::discardSegment(Guint segNum
) {
3243 for (i
= 0; i
< globalSegments
->getLength(); ++i
) {
3244 seg
= (JBIG2Segment
*)globalSegments
->get(i
);
3245 if (seg
->getSegNum() == segNum
) {
3246 globalSegments
->del(i
);
3250 for (i
= 0; i
< segments
->getLength(); ++i
) {
3251 seg
= (JBIG2Segment
*)segments
->get(i
);
3252 if (seg
->getSegNum() == segNum
) {
3259 void JBIG2Stream::resetGenericStats(Guint templ
,
3260 JArithmeticDecoderStats
*prevStats
) {
3263 size
= contextSize
[templ
];
3264 if (prevStats
&& prevStats
->getContextSize() == size
) {
3265 if (genericRegionStats
->getContextSize() == size
) {
3266 genericRegionStats
->copyFrom(prevStats
);
3268 delete genericRegionStats
;
3269 genericRegionStats
= prevStats
->copy();
3272 if (genericRegionStats
->getContextSize() == size
) {
3273 genericRegionStats
->reset();
3275 delete genericRegionStats
;
3276 genericRegionStats
= new JArithmeticDecoderStats(1 << size
);
3281 void JBIG2Stream::resetRefinementStats(Guint templ
,
3282 JArithmeticDecoderStats
*prevStats
) {
3285 size
= refContextSize
[templ
];
3286 if (prevStats
&& prevStats
->getContextSize() == size
) {
3287 if (refinementRegionStats
->getContextSize() == size
) {
3288 refinementRegionStats
->copyFrom(prevStats
);
3290 delete refinementRegionStats
;
3291 refinementRegionStats
= prevStats
->copy();
3294 if (refinementRegionStats
->getContextSize() == size
) {
3295 refinementRegionStats
->reset();
3297 delete refinementRegionStats
;
3298 refinementRegionStats
= new JArithmeticDecoderStats(1 << size
);
3303 void JBIG2Stream::resetIntStats(int symCodeLen
) {
3312 iardxStats
->reset();
3313 iardyStats
->reset();
3314 iardwStats
->reset();
3315 iardhStats
->reset();
3317 if (iaidStats
->getContextSize() == symCodeLen
+ 1) {
3321 iaidStats
= new JArithmeticDecoderStats(1 << (symCodeLen
+ 1));
3325 GBool
JBIG2Stream::readUByte(Guint
*x
) {
3328 if ((c0
= curStr
->getChar()) == EOF
) {
3335 GBool
JBIG2Stream::readByte(int *x
) {
3338 if ((c0
= curStr
->getChar()) == EOF
) {
3348 GBool
JBIG2Stream::readUWord(Guint
*x
) {
3351 if ((c0
= curStr
->getChar()) == EOF
||
3352 (c1
= curStr
->getChar()) == EOF
) {
3355 *x
= (Guint
)((c0
<< 8) | c1
);
3359 GBool
JBIG2Stream::readULong(Guint
*x
) {
3362 if ((c0
= curStr
->getChar()) == EOF
||
3363 (c1
= curStr
->getChar()) == EOF
||
3364 (c2
= curStr
->getChar()) == EOF
||
3365 (c3
= curStr
->getChar()) == EOF
) {
3368 *x
= (Guint
)((c0
<< 24) | (c1
<< 16) | (c2
<< 8) | c3
);
3372 GBool
JBIG2Stream::readLong(int *x
) {
3375 if ((c0
= curStr
->getChar()) == EOF
||
3376 (c1
= curStr
->getChar()) == EOF
||
3377 (c2
= curStr
->getChar()) == EOF
||
3378 (c3
= curStr
->getChar()) == EOF
) {
3381 *x
= ((c0
<< 24) | (c1
<< 16) | (c2
<< 8) | c3
);
3383 *x
|= -1 - (int)0xffffffff;