1 //========================================================================
5 // Copyright 2002-2003 Glyph & Cog, LLC
7 //========================================================================
9 //========================================================================
11 // Modified under the Poppler project - http://poppler.freedesktop.org
13 // All changes made under the Poppler project to this file are licensed
14 // under GPL version 2 or later
16 // Copyright (C) 2006 Raj Kumar <rkumar@archive.org>
17 // Copyright (C) 2006 Paul Walmsley <paul@booyaka.com>
18 // Copyright (C) 2006-2010, 2012, 2014, 2015 Albert Astals Cid <aacid@kde.org>
19 // Copyright (C) 2009 David Benjamin <davidben@mit.edu>
20 // Copyright (C) 2011 Edward Jiang <ejiang@google.com>
21 // Copyright (C) 2012 William Bader <williambader@hotmail.com>
22 // Copyright (C) 2012 Thomas Freitag <Thomas.Freitag@alfa.de>
23 // Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
24 // Copyright (C) 2013, 2014 Fabio D'Urso <fabiodurso@hotmail.it>
25 // Copyright (C) 2015 Suzuki Toshiya <mpsuzuki@hiroshima-u.ac.jp>
27 // To see a description of the changes please see the Changelog file that
28 // came with your tarball or type make ChangeLog if you are building from git
30 //========================================================================
34 #ifdef USE_GCC_PRAGMAS
35 #pragma implementation
40 #include "goo/GooList.h"
42 #include "JArithmeticDecoder.h"
43 #include "JBIG2Stream.h"
45 //~ share these tables
46 #include "Stream-CCITT.h"
48 //------------------------------------------------------------------------
50 static const int contextSize
[4] = { 16, 13, 10, 10 };
51 static const int refContextSize
[2] = { 13, 10 };
53 //------------------------------------------------------------------------
55 //------------------------------------------------------------------------
57 #define jbig2HuffmanLOW 0xfffffffd
58 #define jbig2HuffmanOOB 0xfffffffe
59 #define jbig2HuffmanEOT 0xffffffff
61 struct JBIG2HuffmanTable
{
64 Guint rangeLen
; // can also be LOW, OOB, or EOT
68 static JBIG2HuffmanTable huffTableA
[] = {
71 { 272, 3, 16, 0x006 },
72 { 65808, 3, 32, 0x007 },
73 { 0, 0, jbig2HuffmanEOT
, 0 }
76 static JBIG2HuffmanTable huffTableB
[] = {
83 { 0, 6, jbig2HuffmanOOB
, 0x03f },
84 { 0, 0, jbig2HuffmanEOT
, 0 }
87 static JBIG2HuffmanTable huffTableC
[] = {
93 { 0, 6, jbig2HuffmanOOB
, 0x03e },
95 { -256, 8, 8, 0x0fe },
96 { -257, 8, jbig2HuffmanLOW
, 0x0ff },
97 { 0, 0, jbig2HuffmanEOT
, 0 }
100 static JBIG2HuffmanTable huffTableD
[] = {
106 { 76, 5, 32, 0x01f },
107 { 0, 0, jbig2HuffmanEOT
, 0 }
110 static JBIG2HuffmanTable huffTableE
[] = {
116 { 76, 6, 32, 0x03e },
117 { -255, 7, 8, 0x07e },
118 { -256, 7, jbig2HuffmanLOW
, 0x07f },
119 { 0, 0, jbig2HuffmanEOT
, 0 }
122 static JBIG2HuffmanTable huffTableF
[] = {
124 { 128, 3, 7, 0x002 },
125 { 256, 3, 8, 0x003 },
126 { -1024, 4, 9, 0x008 },
127 { -512, 4, 8, 0x009 },
128 { -256, 4, 7, 0x00a },
129 { -32, 4, 5, 0x00b },
130 { 512, 4, 9, 0x00c },
131 { 1024, 4, 10, 0x00d },
132 { -2048, 5, 10, 0x01c },
133 { -128, 5, 6, 0x01d },
134 { -64, 5, 5, 0x01e },
135 { -2049, 6, jbig2HuffmanLOW
, 0x03e },
136 { 2048, 6, 32, 0x03f },
137 { 0, 0, jbig2HuffmanEOT
, 0 }
140 static JBIG2HuffmanTable huffTableG
[] = {
141 { -512, 3, 8, 0x000 },
142 { 256, 3, 8, 0x001 },
143 { 512, 3, 9, 0x002 },
144 { 1024, 3, 10, 0x003 },
145 { -1024, 4, 9, 0x008 },
146 { -256, 4, 7, 0x009 },
147 { -32, 4, 5, 0x00a },
149 { 128, 4, 7, 0x00c },
150 { -128, 5, 6, 0x01a },
151 { -64, 5, 5, 0x01b },
154 { -1025, 5, jbig2HuffmanLOW
, 0x01e },
155 { 2048, 5, 32, 0x01f },
156 { 0, 0, jbig2HuffmanEOT
, 0 }
159 static JBIG2HuffmanTable huffTableH
[] = {
161 { 0, 2, jbig2HuffmanOOB
, 0x001 },
168 { 134, 5, 7, 0x01c },
171 { 262, 6, 7, 0x03c },
172 { 646, 6, 10, 0x03d },
174 { 390, 7, 8, 0x07d },
175 { -15, 8, 3, 0x0fc },
179 { -16, 9, jbig2HuffmanLOW
, 0x1fe },
180 { 1670, 9, 32, 0x1ff },
181 { 0, 0, jbig2HuffmanEOT
, 0 }
184 static JBIG2HuffmanTable huffTableI
[] = {
185 { 0, 2, jbig2HuffmanOOB
, 0x000 },
193 { 139, 5, 7, 0x01b },
194 { 267, 5, 8, 0x01c },
197 { 523, 6, 8, 0x03c },
198 { 1291, 6, 11, 0x03d },
200 { 779, 7, 9, 0x07d },
201 { -31, 8, 4, 0x0fc },
202 { -11, 8, 2, 0x0fd },
203 { -15, 9, 2, 0x1fc },
205 { -32, 9, jbig2HuffmanLOW
, 0x1fe },
206 { 3339, 9, 32, 0x1ff },
207 { 0, 0, jbig2HuffmanEOT
, 0 }
210 static JBIG2HuffmanTable huffTableJ
[] = {
213 { 0, 2, jbig2HuffmanOOB
, 0x002 },
218 { 102, 6, 5, 0x037 },
219 { 134, 6, 6, 0x038 },
220 { 198, 6, 7, 0x039 },
221 { 326, 6, 8, 0x03a },
222 { 582, 6, 9, 0x03b },
223 { 1094, 6, 10, 0x03c },
224 { -21, 7, 4, 0x07a },
227 { 2118, 7, 11, 0x07d },
230 { -22, 8, jbig2HuffmanLOW
, 0x0fe },
231 { 4166, 8, 32, 0x0ff },
232 { 0, 0, jbig2HuffmanEOT
, 0 }
235 static JBIG2HuffmanTable huffTableK
[] = {
248 { 141, 7, 32, 0x07f },
249 { 0, 0, jbig2HuffmanEOT
, 0 }
252 static JBIG2HuffmanTable huffTableL
[] = {
265 { 73, 8, 32, 0x0ff },
266 { 0, 0, jbig2HuffmanEOT
, 0 }
269 static JBIG2HuffmanTable huffTableM
[] = {
282 { 141, 7, 32, 0x07f },
283 { 0, 0, jbig2HuffmanEOT
, 0 }
286 static JBIG2HuffmanTable huffTableN
[] = {
292 { 0, 0, jbig2HuffmanEOT
, 0 }
295 static JBIG2HuffmanTable huffTableO
[] = {
305 { -24, 7, 4, 0x07c },
307 { -25, 7, jbig2HuffmanLOW
, 0x07e },
308 { 25, 7, 32, 0x07f },
309 { 0, 0, jbig2HuffmanEOT
, 0 }
312 //------------------------------------------------------------------------
313 // JBIG2HuffmanDecoder
314 //------------------------------------------------------------------------
316 class JBIG2HuffmanDecoder
{
319 JBIG2HuffmanDecoder();
320 ~JBIG2HuffmanDecoder();
321 void setStream(Stream
*strA
) { str
= strA
; }
325 // Returns false for OOB, otherwise sets *<x> and returns true.
326 GBool
decodeInt(int *x
, JBIG2HuffmanTable
*table
);
328 Guint
readBits(Guint n
);
331 // Sort the table by prefix length and assign prefix values.
332 void buildTable(JBIG2HuffmanTable
*table
, Guint len
);
341 JBIG2HuffmanDecoder::JBIG2HuffmanDecoder() {
346 JBIG2HuffmanDecoder::~JBIG2HuffmanDecoder() {
349 void JBIG2HuffmanDecoder::reset() {
355 GBool
JBIG2HuffmanDecoder::decodeInt(int *x
, JBIG2HuffmanTable
*table
) {
356 Guint i
, len
, prefix
;
361 while (table
[i
].rangeLen
!= jbig2HuffmanEOT
) {
362 while (len
< table
[i
].prefixLen
) {
363 prefix
= (prefix
<< 1) | readBit();
366 if (prefix
== table
[i
].prefix
) {
367 if (table
[i
].rangeLen
== jbig2HuffmanOOB
) {
370 if (table
[i
].rangeLen
== jbig2HuffmanLOW
) {
371 *x
= table
[i
].val
- readBits(32);
372 } else if (table
[i
].rangeLen
> 0) {
373 *x
= table
[i
].val
+ readBits(table
[i
].rangeLen
);
384 Guint
JBIG2HuffmanDecoder::readBits(Guint n
) {
385 Guint x
, mask
, nLeft
;
387 mask
= (n
== 32) ? 0xffffffff : ((1 << n
) - 1);
389 x
= (buf
>> (bufLen
- n
)) & mask
;
392 x
= buf
& ((1 << bufLen
) - 1);
396 x
= (x
<< 8) | (str
->getChar() & 0xff);
400 buf
= str
->getChar();
402 x
= (x
<< nLeft
) | ((buf
>> bufLen
) & ((1 << nLeft
) - 1));
408 Guint
JBIG2HuffmanDecoder::readBit() {
410 buf
= str
->getChar();
414 return (buf
>> bufLen
) & 1;
417 void JBIG2HuffmanDecoder::buildTable(JBIG2HuffmanTable
*table
, Guint len
) {
418 Guint i
, j
, k
, prefix
;
419 JBIG2HuffmanTable tab
;
421 // stable selection sort:
422 // - entries with prefixLen > 0, in ascending prefixLen order
423 // - entry with prefixLen = 0, rangeLen = EOT
424 // - all other entries with prefixLen = 0
425 // (on entry, table[len] has prefixLen = 0, rangeLen = EOT)
426 for (i
= 0; i
< len
; ++i
) {
427 for (j
= i
; j
< len
&& table
[j
].prefixLen
== 0; ++j
) ;
431 for (k
= j
+ 1; k
< len
; ++k
) {
432 if (table
[k
].prefixLen
> 0 &&
433 table
[k
].prefixLen
< table
[j
].prefixLen
) {
439 for (k
= j
; k
> i
; --k
) {
440 table
[k
] = table
[k
- 1];
445 table
[i
] = table
[len
];
448 if (table
[0].rangeLen
!= jbig2HuffmanEOT
) {
451 table
[i
++].prefix
= prefix
++;
452 for (; table
[i
].rangeLen
!= jbig2HuffmanEOT
; ++i
) {
453 prefix
<<= table
[i
].prefixLen
- table
[i
-1].prefixLen
;
454 table
[i
].prefix
= prefix
++;
459 //------------------------------------------------------------------------
461 //------------------------------------------------------------------------
463 class JBIG2MMRDecoder
{
468 void setStream(Stream
*strA
) { str
= strA
; }
474 void skipTo(Guint length
);
484 JBIG2MMRDecoder::JBIG2MMRDecoder() {
489 JBIG2MMRDecoder::~JBIG2MMRDecoder() {
492 void JBIG2MMRDecoder::reset() {
498 int JBIG2MMRDecoder::get2DCode() {
502 buf
= str
->getChar() & 0xff;
505 p
= &twoDimTab1
[(buf
>> 1) & 0x7f];
506 } else if (bufLen
== 8) {
507 p
= &twoDimTab1
[(buf
>> 1) & 0x7f];
509 p
= &twoDimTab1
[(buf
<< (7 - bufLen
)) & 0x7f];
510 if (p
->bits
< 0 || p
->bits
> (int)bufLen
) {
511 buf
= (buf
<< 8) | (str
->getChar() & 0xff);
514 p
= &twoDimTab1
[(buf
>> (bufLen
- 7)) & 0x7f];
518 error(errSyntaxError
, str
->getPos(), "Bad two dim code in JBIG2 MMR stream");
525 int JBIG2MMRDecoder::getWhiteCode() {
530 buf
= str
->getChar() & 0xff;
535 if (bufLen
>= 11 && ((buf
>> (bufLen
- 7)) & 0x7f) == 0) {
537 code
= buf
<< (12 - bufLen
);
539 code
= buf
>> (bufLen
- 12);
541 p
= &whiteTab1
[code
& 0x1f];
544 code
= buf
<< (9 - bufLen
);
546 code
= buf
>> (bufLen
- 9);
548 p
= &whiteTab2
[code
& 0x1ff];
550 if (p
->bits
> 0 && p
->bits
<= (int)bufLen
) {
557 buf
= (buf
<< 8) | (str
->getChar() & 0xff);
561 error(errSyntaxError
, str
->getPos(), "Bad white code in JBIG2 MMR stream");
562 // eat a bit and return a positive number so that the caller doesn't
563 // go into an infinite loop
568 int JBIG2MMRDecoder::getBlackCode() {
573 buf
= str
->getChar() & 0xff;
578 if (bufLen
>= 10 && ((buf
>> (bufLen
- 6)) & 0x3f) == 0) {
580 code
= buf
<< (13 - bufLen
);
582 code
= buf
>> (bufLen
- 13);
584 p
= &blackTab1
[code
& 0x7f];
585 } else if (bufLen
>= 7 && ((buf
>> (bufLen
- 4)) & 0x0f) == 0 &&
586 ((buf
>> (bufLen
- 6)) & 0x03) != 0) {
588 code
= buf
<< (12 - bufLen
);
590 code
= buf
>> (bufLen
- 12);
592 if (unlikely((code
& 0xff) < 64)) {
595 p
= &blackTab2
[(code
& 0xff) - 64];
598 code
= buf
<< (6 - bufLen
);
600 code
= buf
>> (bufLen
- 6);
602 p
= &blackTab3
[code
& 0x3f];
604 if (p
->bits
> 0 && p
->bits
<= (int)bufLen
) {
611 buf
= (buf
<< 8) | (str
->getChar() & 0xff);
615 error(errSyntaxError
, str
->getPos(), "Bad black code in JBIG2 MMR stream");
616 // eat a bit and return a positive number so that the caller doesn't
617 // go into an infinite loop
622 Guint
JBIG2MMRDecoder::get24Bits() {
623 while (bufLen
< 24) {
624 buf
= (buf
<< 8) | (str
->getChar() & 0xff);
628 return (buf
>> (bufLen
- 24)) & 0xffffff;
631 void JBIG2MMRDecoder::skipTo(Guint length
) {
632 while (nBytesRead
< length
) {
638 //------------------------------------------------------------------------
640 //------------------------------------------------------------------------
642 enum JBIG2SegmentType
{
652 JBIG2Segment(Guint segNumA
) { segNum
= segNumA
; }
653 virtual ~JBIG2Segment() {}
654 void setSegNum(Guint segNumA
) { segNum
= segNumA
; }
655 Guint
getSegNum() { return segNum
; }
656 virtual JBIG2SegmentType
getType() = 0;
663 //------------------------------------------------------------------------
665 //------------------------------------------------------------------------
667 struct JBIG2BitmapPtr
{
673 class JBIG2Bitmap
: public JBIG2Segment
{
676 JBIG2Bitmap(Guint segNumA
, int wA
, int hA
);
677 virtual ~JBIG2Bitmap();
678 virtual JBIG2SegmentType
getType() { return jbig2SegBitmap
; }
679 JBIG2Bitmap
*copy() { return new JBIG2Bitmap(0, this); }
680 JBIG2Bitmap
*getSlice(Guint x
, Guint y
, Guint wA
, Guint hA
);
681 void expand(int newH
, Guint pixel
);
684 int getWidth() { return w
; }
685 int getHeight() { return h
; }
686 int getLineSize() { return line
; }
687 int getPixel(int x
, int y
)
688 { return (x
< 0 || x
>= w
|| y
< 0 || y
>= h
) ? 0 :
689 (data
[y
* line
+ (x
>> 3)] >> (7 - (x
& 7))) & 1; }
690 void setPixel(int x
, int y
)
691 { data
[y
* line
+ (x
>> 3)] |= 1 << (7 - (x
& 7)); }
692 void clearPixel(int x
, int y
)
693 { data
[y
* line
+ (x
>> 3)] &= 0x7f7f >> (x
& 7); }
694 void getPixelPtr(int x
, int y
, JBIG2BitmapPtr
*ptr
);
695 int nextPixel(JBIG2BitmapPtr
*ptr
);
696 void duplicateRow(int yDest
, int ySrc
);
697 void combine(JBIG2Bitmap
*bitmap
, int x
, int y
, Guint combOp
);
698 Guchar
*getDataPtr() { return data
; }
699 int getDataSize() { return h
* line
; }
700 GBool
isOk() { return data
!= NULL
; }
704 JBIG2Bitmap(Guint segNumA
, JBIG2Bitmap
*bitmap
);
710 JBIG2Bitmap::JBIG2Bitmap(Guint segNumA
, int wA
, int hA
):
711 JBIG2Segment(segNumA
)
715 line
= (wA
+ 7) >> 3;
717 if (w
<= 0 || h
<= 0 || line
<= 0 || h
>= (INT_MAX
- 1) / line
) {
718 error(errSyntaxError
, -1, "invalid width/height");
722 // need to allocate one extra guard byte for use in combine()
723 data
= (Guchar
*)gmalloc_checkoverflow(h
* line
+ 1);
729 JBIG2Bitmap::JBIG2Bitmap(Guint segNumA
, JBIG2Bitmap
*bitmap
):
730 JBIG2Segment(segNumA
)
732 if (unlikely(bitmap
== NULL
)) {
733 error(errSyntaxError
, -1, "NULL bitmap in JBIG2Bitmap");
743 if (w
<= 0 || h
<= 0 || line
<= 0 || h
>= (INT_MAX
- 1) / line
) {
744 error(errSyntaxError
, -1, "invalid width/height");
748 // need to allocate one extra guard byte for use in combine()
749 data
= (Guchar
*)gmalloc(h
* line
+ 1);
750 memcpy(data
, bitmap
->data
, h
* line
);
754 JBIG2Bitmap::~JBIG2Bitmap() {
759 JBIG2Bitmap
*JBIG2Bitmap::getSlice(Guint x
, Guint y
, Guint wA
, Guint hA
) {
763 slice
= new JBIG2Bitmap(0, wA
, hA
);
765 slice
->clearToZero();
766 for (yy
= 0; yy
< hA
; ++yy
) {
767 for (xx
= 0; xx
< wA
; ++xx
) {
768 if (getPixel(x
+ xx
, y
+ yy
)) {
769 slice
->setPixel(xx
, yy
);
780 void JBIG2Bitmap::expand(int newH
, Guint pixel
) {
781 if (newH
<= h
|| line
<= 0 || newH
>= (INT_MAX
- 1) / line
) {
782 error(errSyntaxError
, -1, "invalid width/height");
787 // need to allocate one extra guard byte for use in combine()
788 data
= (Guchar
*)grealloc(data
, newH
* line
+ 1);
790 memset(data
+ h
* line
, 0xff, (newH
- h
) * line
);
792 memset(data
+ h
* line
, 0x00, (newH
- h
) * line
);
798 void JBIG2Bitmap::clearToZero() {
799 memset(data
, 0, h
* line
);
802 void JBIG2Bitmap::clearToOne() {
803 memset(data
, 0xff, h
* line
);
806 inline void JBIG2Bitmap::getPixelPtr(int x
, int y
, JBIG2BitmapPtr
*ptr
) {
807 if (y
< 0 || y
>= h
|| x
>= w
) {
809 ptr
->shift
= 0; // make gcc happy
810 ptr
->x
= 0; // make gcc happy
812 ptr
->p
= &data
[y
* line
];
816 ptr
->p
= &data
[y
* line
+ (x
>> 3)];
817 ptr
->shift
= 7 - (x
& 7);
822 inline int JBIG2Bitmap::nextPixel(JBIG2BitmapPtr
*ptr
) {
827 } else if (ptr
->x
< 0) {
831 pix
= (*ptr
->p
>> ptr
->shift
) & 1;
834 } else if (ptr
->shift
== 0) {
844 void JBIG2Bitmap::duplicateRow(int yDest
, int ySrc
) {
845 memcpy(data
+ yDest
* line
, data
+ ySrc
* line
, line
);
848 void JBIG2Bitmap::combine(JBIG2Bitmap
*bitmap
, int x
, int y
,
850 int x0
, x1
, y0
, y1
, xx
, yy
;
851 Guchar
*srcPtr
, *destPtr
;
852 Guint src0
, src1
, src
, dest
, s1
, s2
, m1
, m2
, m3
;
855 // check for the pathological case where y = -2^31
856 if (y
< -0x7fffffff) {
864 if (y
+ bitmap
->h
> h
) {
888 m1
= 0xff >> (x1
& 7);
889 m2
= 0xff << (((x1
& 7) == 0) ? 0 : 8 - (x1
& 7));
890 m3
= (0xff >> s1
) & m2
;
892 oneByte
= x0
== ((x1
- 1) & ~7);
894 for (yy
= y0
; yy
< y1
; ++yy
) {
896 // one byte per line -- need to mask both left and right side
899 destPtr
= data
+ (y
+ yy
) * line
+ (x
>> 3);
900 srcPtr
= bitmap
->data
+ yy
* bitmap
->line
;
905 dest
|= (src1
>> s1
) & m2
;
908 dest
&= ((0xff00 | src1
) >> s1
) | m1
;
911 dest
^= (src1
>> s1
) & m2
;
914 dest
^= ((src1
^ 0xff) >> s1
) & m2
;
917 dest
= (dest
& ~m3
) | ((src1
>> s1
) & m3
);
922 destPtr
= data
+ (y
+ yy
) * line
;
923 srcPtr
= bitmap
->data
+ yy
* bitmap
->line
+ (-x
>> 3);
937 dest
^= (src1
^ 0xff) & m2
;
940 dest
= (src1
& m2
) | (dest
& m1
);
946 // multiple bytes per line -- need to mask left side of left-most
947 // byte and right side of right-most byte
952 destPtr
= data
+ (y
+ yy
) * line
+ (x
>> 3);
953 srcPtr
= bitmap
->data
+ yy
* bitmap
->line
;
961 dest
&= (0xff00 | src1
) >> s1
;
967 dest
^= (src1
^ 0xff) >> s1
;
970 dest
= (dest
& (0xff << s2
)) | (src1
>> s1
);
976 destPtr
= data
+ (y
+ yy
) * line
;
977 srcPtr
= bitmap
->data
+ yy
* bitmap
->line
+ (-x
>> 3);
983 for (; xx
< x1
- 8; xx
+= 8) {
987 src
= (((src0
<< 8) | src1
) >> s1
) & 0xff;
1009 // note: this last byte (src1) may not actually be used, depending
1010 // on the values of s1, m1, and m2 - and in fact, it may be off
1011 // the edge of the source bitmap, which means we need to allocate
1012 // one extra guard byte at the end of each bitmap
1016 src
= (((src0
<< 8) | src1
) >> s1
) & 0xff;
1028 dest
^= (src
^ 0xff) & m2
;
1031 dest
= (src
& m2
) | (dest
& m1
);
1039 //------------------------------------------------------------------------
1041 //------------------------------------------------------------------------
1043 class JBIG2SymbolDict
: public JBIG2Segment
{
1046 JBIG2SymbolDict(Guint segNumA
, Guint sizeA
);
1047 virtual ~JBIG2SymbolDict();
1048 virtual JBIG2SegmentType
getType() { return jbig2SegSymbolDict
; }
1049 Guint
getSize() { return size
; }
1050 void setBitmap(Guint idx
, JBIG2Bitmap
*bitmap
) { bitmaps
[idx
] = bitmap
; }
1051 JBIG2Bitmap
*getBitmap(Guint idx
) { return bitmaps
[idx
]; }
1052 GBool
isOk() { return bitmaps
!= NULL
; }
1053 void setGenericRegionStats(JArithmeticDecoderStats
*stats
)
1054 { genericRegionStats
= stats
; }
1055 void setRefinementRegionStats(JArithmeticDecoderStats
*stats
)
1056 { refinementRegionStats
= stats
; }
1057 JArithmeticDecoderStats
*getGenericRegionStats()
1058 { return genericRegionStats
; }
1059 JArithmeticDecoderStats
*getRefinementRegionStats()
1060 { return refinementRegionStats
; }
1065 JBIG2Bitmap
**bitmaps
;
1066 JArithmeticDecoderStats
*genericRegionStats
;
1067 JArithmeticDecoderStats
*refinementRegionStats
;
1070 JBIG2SymbolDict::JBIG2SymbolDict(Guint segNumA
, Guint sizeA
):
1071 JBIG2Segment(segNumA
)
1076 bitmaps
= (JBIG2Bitmap
**)gmallocn_checkoverflow(size
, sizeof(JBIG2Bitmap
*));
1077 if (!bitmaps
) size
= 0;
1078 for (i
= 0; i
< size
; ++i
) {
1081 genericRegionStats
= NULL
;
1082 refinementRegionStats
= NULL
;
1085 JBIG2SymbolDict::~JBIG2SymbolDict() {
1088 for (i
= 0; i
< size
; ++i
) {
1092 if (genericRegionStats
) {
1093 delete genericRegionStats
;
1095 if (refinementRegionStats
) {
1096 delete refinementRegionStats
;
1100 //------------------------------------------------------------------------
1102 //------------------------------------------------------------------------
1104 class JBIG2PatternDict
: public JBIG2Segment
{
1107 JBIG2PatternDict(Guint segNumA
, Guint sizeA
);
1108 virtual ~JBIG2PatternDict();
1109 virtual JBIG2SegmentType
getType() { return jbig2SegPatternDict
; }
1110 Guint
getSize() { return size
; }
1111 void setBitmap(Guint idx
, JBIG2Bitmap
*bitmap
) { if (likely(idx
< size
)) bitmaps
[idx
] = bitmap
; }
1112 JBIG2Bitmap
*getBitmap(Guint idx
) { return (idx
< size
) ? bitmaps
[idx
] : NULL
; }
1117 JBIG2Bitmap
**bitmaps
;
1120 JBIG2PatternDict::JBIG2PatternDict(Guint segNumA
, Guint sizeA
):
1121 JBIG2Segment(segNumA
)
1123 bitmaps
= (JBIG2Bitmap
**)gmallocn_checkoverflow(sizeA
, sizeof(JBIG2Bitmap
*));
1128 error(errSyntaxError
, -1, "JBIG2PatternDict: can't allocate bitmaps");
1132 JBIG2PatternDict::~JBIG2PatternDict() {
1135 for (i
= 0; i
< size
; ++i
) {
1141 //------------------------------------------------------------------------
1143 //------------------------------------------------------------------------
1145 class JBIG2CodeTable
: public JBIG2Segment
{
1148 JBIG2CodeTable(Guint segNumA
, JBIG2HuffmanTable
*tableA
);
1149 virtual ~JBIG2CodeTable();
1150 virtual JBIG2SegmentType
getType() { return jbig2SegCodeTable
; }
1151 JBIG2HuffmanTable
*getHuffTable() { return table
; }
1155 JBIG2HuffmanTable
*table
;
1158 JBIG2CodeTable::JBIG2CodeTable(Guint segNumA
, JBIG2HuffmanTable
*tableA
):
1159 JBIG2Segment(segNumA
)
1164 JBIG2CodeTable::~JBIG2CodeTable() {
1168 //------------------------------------------------------------------------
1170 //------------------------------------------------------------------------
1172 JBIG2Stream::JBIG2Stream(Stream
*strA
, Object
*globalsStreamA
, Object
*globalsStreamRefA
):
1177 arithDecoder
= new JArithmeticDecoder();
1178 genericRegionStats
= new JArithmeticDecoderStats(1 << 1);
1179 refinementRegionStats
= new JArithmeticDecoderStats(1 << 1);
1180 iadhStats
= new JArithmeticDecoderStats(1 << 9);
1181 iadwStats
= new JArithmeticDecoderStats(1 << 9);
1182 iaexStats
= new JArithmeticDecoderStats(1 << 9);
1183 iaaiStats
= new JArithmeticDecoderStats(1 << 9);
1184 iadtStats
= new JArithmeticDecoderStats(1 << 9);
1185 iaitStats
= new JArithmeticDecoderStats(1 << 9);
1186 iafsStats
= new JArithmeticDecoderStats(1 << 9);
1187 iadsStats
= new JArithmeticDecoderStats(1 << 9);
1188 iardxStats
= new JArithmeticDecoderStats(1 << 9);
1189 iardyStats
= new JArithmeticDecoderStats(1 << 9);
1190 iardwStats
= new JArithmeticDecoderStats(1 << 9);
1191 iardhStats
= new JArithmeticDecoderStats(1 << 9);
1192 iariStats
= new JArithmeticDecoderStats(1 << 9);
1193 iaidStats
= new JArithmeticDecoderStats(1 << 1);
1194 huffDecoder
= new JBIG2HuffmanDecoder();
1195 mmrDecoder
= new JBIG2MMRDecoder();
1197 if (globalsStreamA
->isStream()) {
1198 globalsStreamA
->copy(&globalsStream
);
1199 if (globalsStreamRefA
->isRef())
1200 globalsStreamRef
= globalsStreamRefA
->getRef();
1203 segments
= globalSegments
= NULL
;
1205 dataPtr
= dataEnd
= NULL
;
1208 JBIG2Stream::~JBIG2Stream() {
1210 globalsStream
.free();
1211 delete arithDecoder
;
1212 delete genericRegionStats
;
1213 delete refinementRegionStats
;
1233 void JBIG2Stream::reset() {
1234 // read the globals stream
1235 globalSegments
= new GooList();
1236 if (globalsStream
.isStream()) {
1237 segments
= globalSegments
;
1238 curStr
= globalsStream
.getStream();
1240 arithDecoder
->setStream(curStr
);
1241 huffDecoder
->setStream(curStr
);
1242 mmrDecoder
->setStream(curStr
);
1247 // read the main stream
1248 segments
= new GooList();
1251 arithDecoder
->setStream(curStr
);
1252 huffDecoder
->setStream(curStr
);
1253 mmrDecoder
->setStream(curStr
);
1257 dataPtr
= pageBitmap
->getDataPtr();
1258 dataEnd
= dataPtr
+ pageBitmap
->getDataSize();
1260 dataPtr
= dataEnd
= NULL
;
1264 void JBIG2Stream::close() {
1270 deleteGooList(segments
, JBIG2Segment
);
1273 if (globalSegments
) {
1274 deleteGooList(globalSegments
, JBIG2Segment
);
1275 globalSegments
= NULL
;
1277 dataPtr
= dataEnd
= NULL
;
1278 FilterStream::close();
1281 int JBIG2Stream::getChar() {
1282 if (dataPtr
&& dataPtr
< dataEnd
) {
1283 return (*dataPtr
++ ^ 0xff) & 0xff;
1288 int JBIG2Stream::lookChar() {
1289 if (dataPtr
&& dataPtr
< dataEnd
) {
1290 return (*dataPtr
^ 0xff) & 0xff;
1295 Goffset
JBIG2Stream::getPos() {
1296 if (pageBitmap
== NULL
) {
1299 return dataPtr
- pageBitmap
->getDataPtr();
1302 int JBIG2Stream::getChars(int nChars
, Guchar
*buffer
) {
1308 if (dataEnd
- dataPtr
< nChars
) {
1309 n
= (int)(dataEnd
- dataPtr
);
1313 for (i
= 0; i
< n
; ++i
) {
1314 buffer
[i
] = *dataPtr
++ ^ 0xff;
1319 GooString
*JBIG2Stream::getPSFilter(int psLevel
, const char *indent
) {
1323 GBool
JBIG2Stream::isBinary(GBool last
) {
1324 return str
->isBinary(gTrue
);
1327 void JBIG2Stream::readSegments() {
1328 Guint segNum
, segFlags
, segType
, page
, segLength
;
1329 Guint refFlags
, nRefSegs
;
1335 while (readULong(&segNum
)) {
1337 // segment header flags
1338 if (!readUByte(&segFlags
)) {
1341 segType
= segFlags
& 0x3f;
1343 // referred-to segment count and retention flags
1344 if (!readUByte(&refFlags
)) {
1347 nRefSegs
= refFlags
>> 5;
1348 if (nRefSegs
== 7) {
1349 if ((c1
= curStr
->getChar()) == EOF
||
1350 (c2
= curStr
->getChar()) == EOF
||
1351 (c3
= curStr
->getChar()) == EOF
) {
1354 refFlags
= (refFlags
<< 24) | (c1
<< 16) | (c2
<< 8) | c3
;
1355 nRefSegs
= refFlags
& 0x1fffffff;
1356 for (i
= 0; i
< (nRefSegs
+ 9) >> 3; ++i
) {
1357 if ((c1
= curStr
->getChar()) == EOF
) {
1363 // referred-to segment numbers
1364 refSegs
= (Guint
*)gmallocn(nRefSegs
, sizeof(Guint
));
1365 if (segNum
<= 256) {
1366 for (i
= 0; i
< nRefSegs
; ++i
) {
1367 if (!readUByte(&refSegs
[i
])) {
1371 } else if (segNum
<= 65536) {
1372 for (i
= 0; i
< nRefSegs
; ++i
) {
1373 if (!readUWord(&refSegs
[i
])) {
1378 for (i
= 0; i
< nRefSegs
; ++i
) {
1379 if (!readULong(&refSegs
[i
])) {
1385 // segment page association
1386 if (segFlags
& 0x40) {
1387 if (!readULong(&page
)) {
1391 if (!readUByte(&page
)) {
1396 // segment data length
1397 if (!readULong(&segLength
)) {
1401 // keep track of the start of the segment data
1402 segDataPos
= curStr
->getPos();
1404 // check for missing page information segment
1405 if (!pageBitmap
&& ((segType
>= 4 && segType
<= 7) ||
1406 (segType
>= 20 && segType
<= 43))) {
1407 error(errSyntaxError
, curStr
->getPos(), "First JBIG2 segment associated with a page must be a page information segment");
1411 // read the segment data
1414 if (!readSymbolDictSeg(segNum
, segLength
, refSegs
, nRefSegs
)) {
1419 readTextRegionSeg(segNum
, gFalse
, gFalse
, segLength
, refSegs
, nRefSegs
);
1422 readTextRegionSeg(segNum
, gTrue
, gFalse
, segLength
, refSegs
, nRefSegs
);
1425 readTextRegionSeg(segNum
, gTrue
, gTrue
, segLength
, refSegs
, nRefSegs
);
1428 readPatternDictSeg(segNum
, segLength
);
1431 readHalftoneRegionSeg(segNum
, gFalse
, gFalse
, segLength
,
1435 readHalftoneRegionSeg(segNum
, gTrue
, gFalse
, segLength
,
1439 readHalftoneRegionSeg(segNum
, gTrue
, gTrue
, segLength
,
1443 readGenericRegionSeg(segNum
, gFalse
, gFalse
, segLength
);
1446 readGenericRegionSeg(segNum
, gTrue
, gFalse
, segLength
);
1449 readGenericRegionSeg(segNum
, gTrue
, gTrue
, segLength
);
1452 readGenericRefinementRegionSeg(segNum
, gFalse
, gFalse
, segLength
,
1456 readGenericRefinementRegionSeg(segNum
, gTrue
, gFalse
, segLength
,
1460 readGenericRefinementRegionSeg(segNum
, gTrue
, gTrue
, segLength
,
1464 readPageInfoSeg(segLength
);
1467 readEndOfStripeSeg(segLength
);
1470 readProfilesSeg(segLength
);
1473 readCodeTableSeg(segNum
, segLength
);
1476 readExtensionSeg(segLength
);
1479 error(errSyntaxError
, curStr
->getPos(), "Unknown segment type in JBIG2 stream");
1480 for (i
= 0; i
< segLength
; ++i
) {
1481 if ((c1
= curStr
->getChar()) == EOF
) {
1488 // Make sure the segment handler read all of the bytes in the
1489 // segment data, unless this segment is marked as having an
1490 // unknown length (section 7.2.7 of the JBIG2 Final Committee Draft)
1492 if (segLength
!= 0xffffffff) {
1494 Goffset segExtraBytes
= segDataPos
+ segLength
- curStr
->getPos();
1495 if (segExtraBytes
> 0) {
1497 // If we didn't read all of the bytes in the segment data,
1498 // indicate an error, and throw away the rest of the data.
1500 // v.3.1.01.13 of the LuraTech PDF Compressor Server will
1501 // sometimes generate an extraneous NULL byte at the end of
1502 // arithmetic-coded symbol dictionary segments when numNewSyms
1503 // == 0. Segments like this often occur for blank pages.
1505 error(errSyntaxError
, curStr
->getPos(), "{0:lld} extraneous byte{1:s} after segment",
1506 segExtraBytes
, (segExtraBytes
> 1) ? "s" : "");
1508 // Burn through the remaining bytes -- inefficient, but
1509 // hopefully we're not doing this much
1512 for (Goffset i
= segExtraBytes
; i
> 0; i
--) {
1516 } else if (segExtraBytes
< 0) {
1518 // If we read more bytes than we should have, according to the
1519 // segment length field, note an error.
1521 error(errSyntaxError
, curStr
->getPos(), "Previous segment handler read too many bytes");
1539 error(errSyntaxError
, curStr
->getPos(), "Unexpected EOF in JBIG2 stream");
1542 GBool
JBIG2Stream::readSymbolDictSeg(Guint segNum
, Guint length
,
1543 Guint
*refSegs
, Guint nRefSegs
) {
1544 JBIG2SymbolDict
*symbolDict
;
1545 JBIG2HuffmanTable
*huffDHTable
, *huffDWTable
;
1546 JBIG2HuffmanTable
*huffBMSizeTable
, *huffAggInstTable
;
1548 GooList
*codeTables
;
1549 JBIG2SymbolDict
*inputSymbolDict
;
1550 Guint flags
, sdTemplate
, sdrTemplate
, huff
, refAgg
;
1551 Guint huffDH
, huffDW
, huffBMSize
, huffAggInst
;
1552 Guint contextUsed
, contextRetained
;
1553 int sdATX
[4], sdATY
[4], sdrATX
[2], sdrATY
[2];
1554 Guint numExSyms
, numNewSyms
, numInputSyms
, symCodeLen
;
1555 JBIG2Bitmap
**bitmaps
;
1556 JBIG2Bitmap
*collBitmap
, *refBitmap
;
1558 Guint symHeight
, symWidth
, totalWidth
, x
, symID
;
1559 int dh
, dw
, refAggNum
, refDX
, refDY
, bmSize
;
1567 // symbol dictionary flags
1568 if (!readUWord(&flags
)) {
1571 sdTemplate
= (flags
>> 10) & 3;
1572 sdrTemplate
= (flags
>> 12) & 1;
1574 refAgg
= (flags
>> 1) & 1;
1575 huffDH
= (flags
>> 2) & 3;
1576 huffDW
= (flags
>> 4) & 3;
1577 huffBMSize
= (flags
>> 6) & 1;
1578 huffAggInst
= (flags
>> 7) & 1;
1579 contextUsed
= (flags
>> 8) & 1;
1580 contextRetained
= (flags
>> 9) & 1;
1582 // symbol dictionary AT flags
1584 if (sdTemplate
== 0) {
1585 if (!readByte(&sdATX
[0]) ||
1586 !readByte(&sdATY
[0]) ||
1587 !readByte(&sdATX
[1]) ||
1588 !readByte(&sdATY
[1]) ||
1589 !readByte(&sdATX
[2]) ||
1590 !readByte(&sdATY
[2]) ||
1591 !readByte(&sdATX
[3]) ||
1592 !readByte(&sdATY
[3])) {
1596 if (!readByte(&sdATX
[0]) ||
1597 !readByte(&sdATY
[0])) {
1603 // symbol dictionary refinement AT flags
1604 if (refAgg
&& !sdrTemplate
) {
1605 if (!readByte(&sdrATX
[0]) ||
1606 !readByte(&sdrATY
[0]) ||
1607 !readByte(&sdrATX
[1]) ||
1608 !readByte(&sdrATY
[1])) {
1613 // SDNUMEXSYMS and SDNUMNEWSYMS
1614 if (!readULong(&numExSyms
) || !readULong(&numNewSyms
)) {
1618 // get referenced segments: input symbol dictionaries and code tables
1619 codeTables
= new GooList();
1621 for (i
= 0; i
< nRefSegs
; ++i
) {
1622 // This is need by bug 12014, returning gFalse makes it not crash
1623 // but we end up with a empty page while acroread is able to render
1625 if ((seg
= findSegment(refSegs
[i
]))) {
1626 if (seg
->getType() == jbig2SegSymbolDict
) {
1627 j
= ((JBIG2SymbolDict
*)seg
)->getSize();
1628 if (numInputSyms
> UINT_MAX
- j
) {
1629 error(errSyntaxError
, curStr
->getPos(), "Too many input symbols in JBIG2 symbol dictionary");
1634 } else if (seg
->getType() == jbig2SegCodeTable
) {
1635 codeTables
->append(seg
);
1642 if (numInputSyms
> UINT_MAX
- numNewSyms
) {
1643 error(errSyntaxError
, curStr
->getPos(), "Too many input symbols in JBIG2 symbol dictionary");
1648 // compute symbol code length, per 6.5.8.2.3
1649 // symCodeLen = ceil( log2( numInputSyms + numNewSyms ) )
1650 i
= numInputSyms
+ numNewSyms
;
1652 symCodeLen
= huff
? 1 : 0;
1656 // i = floor((numSyms-1) / 2^symCodeLen)
1663 // get the input symbol bitmaps
1664 bitmaps
= (JBIG2Bitmap
**)gmallocn_checkoverflow(numInputSyms
+ numNewSyms
,
1665 sizeof(JBIG2Bitmap
*));
1666 if (!bitmaps
&& (numInputSyms
+ numNewSyms
> 0)) {
1667 error(errSyntaxError
, curStr
->getPos(), "Too many input symbols in JBIG2 symbol dictionary");
1671 for (i
= 0; i
< numInputSyms
+ numNewSyms
; ++i
) {
1675 inputSymbolDict
= NULL
;
1676 for (i
= 0; i
< nRefSegs
; ++i
) {
1677 seg
= findSegment(refSegs
[i
]);
1678 if (seg
!= NULL
&& seg
->getType() == jbig2SegSymbolDict
) {
1679 inputSymbolDict
= (JBIG2SymbolDict
*)seg
;
1680 for (j
= 0; j
< inputSymbolDict
->getSize(); ++j
) {
1681 bitmaps
[k
++] = inputSymbolDict
->getBitmap(j
);
1686 // get the Huffman tables
1687 huffDHTable
= huffDWTable
= NULL
; // make gcc happy
1688 huffBMSizeTable
= huffAggInstTable
= NULL
; // make gcc happy
1692 huffDHTable
= huffTableD
;
1693 } else if (huffDH
== 1) {
1694 huffDHTable
= huffTableE
;
1696 if (i
>= (Guint
)codeTables
->getLength()) {
1697 goto codeTableError
;
1699 huffDHTable
= ((JBIG2CodeTable
*)codeTables
->get(i
++))->getHuffTable();
1702 huffDWTable
= huffTableB
;
1703 } else if (huffDW
== 1) {
1704 huffDWTable
= huffTableC
;
1706 if (i
>= (Guint
)codeTables
->getLength()) {
1707 goto codeTableError
;
1709 huffDWTable
= ((JBIG2CodeTable
*)codeTables
->get(i
++))->getHuffTable();
1711 if (huffBMSize
== 0) {
1712 huffBMSizeTable
= huffTableA
;
1714 if (i
>= (Guint
)codeTables
->getLength()) {
1715 goto codeTableError
;
1718 ((JBIG2CodeTable
*)codeTables
->get(i
++))->getHuffTable();
1720 if (huffAggInst
== 0) {
1721 huffAggInstTable
= huffTableA
;
1723 if (i
>= (Guint
)codeTables
->getLength()) {
1724 goto codeTableError
;
1727 ((JBIG2CodeTable
*)codeTables
->get(i
++))->getHuffTable();
1732 // set up the Huffman decoder
1734 huffDecoder
->reset();
1736 // set up the arithmetic decoder
1738 if (contextUsed
&& inputSymbolDict
) {
1739 resetGenericStats(sdTemplate
, inputSymbolDict
->getGenericRegionStats());
1741 resetGenericStats(sdTemplate
, NULL
);
1743 resetIntStats(symCodeLen
);
1744 arithDecoder
->start();
1747 // set up the arithmetic decoder for refinement/aggregation
1749 if (contextUsed
&& inputSymbolDict
) {
1750 resetRefinementStats(sdrTemplate
,
1751 inputSymbolDict
->getRefinementRegionStats());
1753 resetRefinementStats(sdrTemplate
, NULL
);
1757 // allocate symbol widths storage
1758 if (huff
&& !refAgg
) {
1759 symWidths
= (Guint
*)gmallocn(numNewSyms
, sizeof(Guint
));
1764 while (i
< numNewSyms
) {
1766 // read the height class delta height
1768 huffDecoder
->decodeInt(&dh
, huffDHTable
);
1770 arithDecoder
->decodeInt(&dh
, iadhStats
);
1772 if (dh
< 0 && (Guint
)-dh
>= symHeight
) {
1773 error(errSyntaxError
, curStr
->getPos(), "Bad delta-height value in JBIG2 symbol dictionary");
1777 if (unlikely(symHeight
> 0x40000000)) {
1778 error(errSyntaxError
, curStr
->getPos(), "Bad height value in JBIG2 symbol dictionary");
1785 // read the symbols in this height class
1788 // read the delta width
1790 if (!huffDecoder
->decodeInt(&dw
, huffDWTable
)) {
1794 if (!arithDecoder
->decodeInt(&dw
, iadwStats
)) {
1798 if (dw
< 0 && (Guint
)-dw
>= symWidth
) {
1799 error(errSyntaxError
, curStr
->getPos(), "Bad delta-height value in JBIG2 symbol dictionary");
1803 if (i
>= numNewSyms
) {
1804 error(errSyntaxError
, curStr
->getPos(), "Too many symbols in JBIG2 symbol dictionary");
1808 // using a collective bitmap, so don't read a bitmap here
1809 if (huff
&& !refAgg
) {
1810 symWidths
[i
] = symWidth
;
1811 totalWidth
+= symWidth
;
1813 // refinement/aggregate coding
1814 } else if (refAgg
) {
1816 if (!huffDecoder
->decodeInt(&refAggNum
, huffAggInstTable
)) {
1820 if (!arithDecoder
->decodeInt(&refAggNum
, iaaiStats
)) {
1824 #if 0 //~ This special case was added about a year before the final draft
1825 //~ of the JBIG2 spec was released. I have encountered some old
1826 //~ JBIG2 images that predate it.
1829 if (refAggNum
== 1) {
1832 symID
= huffDecoder
->readBits(symCodeLen
);
1833 huffDecoder
->decodeInt(&refDX
, huffTableO
);
1834 huffDecoder
->decodeInt(&refDY
, huffTableO
);
1835 huffDecoder
->decodeInt(&bmSize
, huffTableA
);
1836 huffDecoder
->reset();
1837 arithDecoder
->start();
1839 symID
= arithDecoder
->decodeIAID(symCodeLen
, iaidStats
);
1840 arithDecoder
->decodeInt(&refDX
, iardxStats
);
1841 arithDecoder
->decodeInt(&refDY
, iardyStats
);
1843 if (symID
>= numInputSyms
+ i
) {
1844 error(errSyntaxError
, curStr
->getPos(), "Invalid symbol ID in JBIG2 symbol dictionary");
1847 refBitmap
= bitmaps
[symID
];
1848 if (unlikely(refBitmap
== NULL
)) {
1849 error(errSyntaxError
, curStr
->getPos(), "Invalid ref bitmap for symbol ID {0:ud} in JBIG2 symbol dictionary", symID
);
1852 bitmaps
[numInputSyms
+ i
] =
1853 readGenericRefinementRegion(symWidth
, symHeight
,
1854 sdrTemplate
, gFalse
,
1855 refBitmap
, refDX
, refDY
,
1857 //~ do we need to use the bmSize value here (in Huffman mode)?
1859 bitmaps
[numInputSyms
+ i
] =
1860 readTextRegion(huff
, gTrue
, symWidth
, symHeight
,
1861 refAggNum
, 0, numInputSyms
+ i
, NULL
,
1862 symCodeLen
, bitmaps
, 0, 0, 0, 1, 0,
1863 huffTableF
, huffTableH
, huffTableK
, huffTableO
,
1864 huffTableO
, huffTableO
, huffTableO
, huffTableA
,
1865 sdrTemplate
, sdrATX
, sdrATY
);
1868 // non-ref/agg coding
1870 bitmaps
[numInputSyms
+ i
] =
1871 readGenericBitmap(gFalse
, symWidth
, symHeight
,
1872 sdTemplate
, gFalse
, gFalse
, NULL
,
1879 // read the collective bitmap
1880 if (huff
&& !refAgg
) {
1881 huffDecoder
->decodeInt(&bmSize
, huffBMSizeTable
);
1882 huffDecoder
->reset();
1884 collBitmap
= new JBIG2Bitmap(0, totalWidth
, symHeight
);
1885 bmSize
= symHeight
* ((totalWidth
+ 7) >> 3);
1886 p
= collBitmap
->getDataPtr();
1887 if (unlikely(p
== NULL
)) {
1891 for (k
= 0; k
< (Guint
)bmSize
; ++k
) {
1892 if ((c
= curStr
->getChar()) == EOF
) {
1898 collBitmap
= readGenericBitmap(gTrue
, totalWidth
, symHeight
,
1899 0, gFalse
, gFalse
, NULL
, NULL
, NULL
,
1902 if (likely(collBitmap
!= NULL
)) {
1904 for (; j
< i
; ++j
) {
1905 bitmaps
[numInputSyms
+ j
] =
1906 collBitmap
->getSlice(x
, 0, symWidths
[j
], symHeight
);
1911 error(errSyntaxError
, curStr
->getPos(), "collBitmap was null");
1917 // create the symbol dict object
1918 symbolDict
= new JBIG2SymbolDict(segNum
, numExSyms
);
1919 if (!symbolDict
->isOk()) {
1924 // exported symbol list
1927 while (i
< numInputSyms
+ numNewSyms
) {
1929 huffDecoder
->decodeInt(&run
, huffTableA
);
1931 arithDecoder
->decodeInt(&run
, iaexStats
);
1933 if (i
+ run
> numInputSyms
+ numNewSyms
||
1934 (ex
&& j
+ run
> numExSyms
)) {
1935 error(errSyntaxError
, curStr
->getPos(), "Too many exported symbols in JBIG2 symbol dictionary");
1936 for ( ; j
< numExSyms
; ++j
) symbolDict
->setBitmap(j
, NULL
);
1941 for (cnt
= 0; cnt
< run
; ++cnt
) {
1942 symbolDict
->setBitmap(j
++, bitmaps
[i
++]->copy());
1949 if (j
!= numExSyms
) {
1950 error(errSyntaxError
, curStr
->getPos(), "Too few symbols in JBIG2 symbol dictionary");
1951 for ( ; j
< numExSyms
; ++j
) symbolDict
->setBitmap(j
, NULL
);
1956 for (i
= 0; i
< numNewSyms
; ++i
) {
1957 delete bitmaps
[numInputSyms
+ i
];
1964 // save the arithmetic decoder stats
1965 if (!huff
&& contextRetained
) {
1966 symbolDict
->setGenericRegionStats(genericRegionStats
->copy());
1968 symbolDict
->setRefinementRegionStats(refinementRegionStats
->copy());
1972 // store the new symbol dict
1973 segments
->append(symbolDict
);
1978 error(errSyntaxError
, curStr
->getPos(), "Missing code table in JBIG2 symbol dictionary");
1982 for (i
= 0; i
< numNewSyms
; ++i
) {
1983 if (bitmaps
[numInputSyms
+ i
]) {
1984 delete bitmaps
[numInputSyms
+ i
];
1994 error(errSyntaxError
, curStr
->getPos(), "Unexpected EOF in JBIG2 stream");
1998 void JBIG2Stream::readTextRegionSeg(Guint segNum
, GBool imm
,
1999 GBool lossless
, Guint length
,
2000 Guint
*refSegs
, Guint nRefSegs
) {
2001 JBIG2Bitmap
*bitmap
;
2002 JBIG2HuffmanTable runLengthTab
[36];
2003 JBIG2HuffmanTable
*symCodeTab
;
2004 JBIG2HuffmanTable
*huffFSTable
, *huffDSTable
, *huffDTTable
;
2005 JBIG2HuffmanTable
*huffRDWTable
, *huffRDHTable
;
2006 JBIG2HuffmanTable
*huffRDXTable
, *huffRDYTable
, *huffRSizeTable
;
2008 GooList
*codeTables
;
2009 JBIG2SymbolDict
*symbolDict
;
2011 Guint w
, h
, x
, y
, segInfoFlags
, extCombOp
;
2012 Guint flags
, huff
, refine
, logStrips
, refCorner
, transposed
;
2013 Guint combOp
, defPixel
, templ
;
2015 Guint huffFlags
, huffFS
, huffDS
, huffDT
;
2016 Guint huffRDW
, huffRDH
, huffRDX
, huffRDY
, huffRSize
;
2017 Guint numInstances
, numSyms
, symCodeLen
;
2022 // region segment info field
2023 if (!readULong(&w
) || !readULong(&h
) ||
2024 !readULong(&x
) || !readULong(&y
) ||
2025 !readUByte(&segInfoFlags
)) {
2028 extCombOp
= segInfoFlags
& 7;
2030 // rest of the text region header
2031 if (!readUWord(&flags
)) {
2035 refine
= (flags
>> 1) & 1;
2036 logStrips
= (flags
>> 2) & 3;
2037 refCorner
= (flags
>> 4) & 3;
2038 transposed
= (flags
>> 6) & 1;
2039 combOp
= (flags
>> 7) & 3;
2040 defPixel
= (flags
>> 9) & 1;
2041 sOffset
= (flags
>> 10) & 0x1f;
2042 if (sOffset
& 0x10) {
2043 sOffset
|= -1 - 0x0f;
2045 templ
= (flags
>> 15) & 1;
2046 huffFS
= huffDS
= huffDT
= 0; // make gcc happy
2047 huffRDW
= huffRDH
= huffRDX
= huffRDY
= huffRSize
= 0; // make gcc happy
2049 if (!readUWord(&huffFlags
)) {
2052 huffFS
= huffFlags
& 3;
2053 huffDS
= (huffFlags
>> 2) & 3;
2054 huffDT
= (huffFlags
>> 4) & 3;
2055 huffRDW
= (huffFlags
>> 6) & 3;
2056 huffRDH
= (huffFlags
>> 8) & 3;
2057 huffRDX
= (huffFlags
>> 10) & 3;
2058 huffRDY
= (huffFlags
>> 12) & 3;
2059 huffRSize
= (huffFlags
>> 14) & 1;
2061 if (refine
&& templ
== 0) {
2062 if (!readByte(&atx
[0]) || !readByte(&aty
[0]) ||
2063 !readByte(&atx
[1]) || !readByte(&aty
[1])) {
2067 if (!readULong(&numInstances
)) {
2071 // get symbol dictionaries and tables
2072 codeTables
= new GooList();
2074 for (i
= 0; i
< nRefSegs
; ++i
) {
2075 if ((seg
= findSegment(refSegs
[i
]))) {
2076 if (seg
->getType() == jbig2SegSymbolDict
) {
2077 numSyms
+= ((JBIG2SymbolDict
*)seg
)->getSize();
2078 } else if (seg
->getType() == jbig2SegCodeTable
) {
2079 codeTables
->append(seg
);
2082 error(errSyntaxError
, curStr
->getPos(), "Invalid segment reference in JBIG2 text region");
2089 symCodeLen
= huff
? 1 : 0;
2093 // i = floor((numSyms-1) / 2^symCodeLen)
2100 // get the symbol bitmaps
2101 syms
= (JBIG2Bitmap
**)gmallocn(numSyms
, sizeof(JBIG2Bitmap
*));
2103 for (i
= 0; i
< nRefSegs
; ++i
) {
2104 if ((seg
= findSegment(refSegs
[i
]))) {
2105 if (seg
->getType() == jbig2SegSymbolDict
) {
2106 symbolDict
= (JBIG2SymbolDict
*)seg
;
2107 for (k
= 0; k
< symbolDict
->getSize(); ++k
) {
2108 syms
[kk
++] = symbolDict
->getBitmap(k
);
2114 // get the Huffman tables
2115 huffFSTable
= huffDSTable
= huffDTTable
= NULL
; // make gcc happy
2116 huffRDWTable
= huffRDHTable
= NULL
; // make gcc happy
2117 huffRDXTable
= huffRDYTable
= huffRSizeTable
= NULL
; // make gcc happy
2121 huffFSTable
= huffTableF
;
2122 } else if (huffFS
== 1) {
2123 huffFSTable
= huffTableG
;
2125 if (i
>= (Guint
)codeTables
->getLength()) {
2126 goto codeTableError
;
2128 huffFSTable
= ((JBIG2CodeTable
*)codeTables
->get(i
++))->getHuffTable();
2131 huffDSTable
= huffTableH
;
2132 } else if (huffDS
== 1) {
2133 huffDSTable
= huffTableI
;
2134 } else if (huffDS
== 2) {
2135 huffDSTable
= huffTableJ
;
2137 if (i
>= (Guint
)codeTables
->getLength()) {
2138 goto codeTableError
;
2140 huffDSTable
= ((JBIG2CodeTable
*)codeTables
->get(i
++))->getHuffTable();
2143 huffDTTable
= huffTableK
;
2144 } else if (huffDT
== 1) {
2145 huffDTTable
= huffTableL
;
2146 } else if (huffDT
== 2) {
2147 huffDTTable
= huffTableM
;
2149 if (i
>= (Guint
)codeTables
->getLength()) {
2150 goto codeTableError
;
2152 huffDTTable
= ((JBIG2CodeTable
*)codeTables
->get(i
++))->getHuffTable();
2155 huffRDWTable
= huffTableN
;
2156 } else if (huffRDW
== 1) {
2157 huffRDWTable
= huffTableO
;
2159 if (i
>= (Guint
)codeTables
->getLength()) {
2160 goto codeTableError
;
2162 huffRDWTable
= ((JBIG2CodeTable
*)codeTables
->get(i
++))->getHuffTable();
2165 huffRDHTable
= huffTableN
;
2166 } else if (huffRDH
== 1) {
2167 huffRDHTable
= huffTableO
;
2169 if (i
>= (Guint
)codeTables
->getLength()) {
2170 goto codeTableError
;
2172 huffRDHTable
= ((JBIG2CodeTable
*)codeTables
->get(i
++))->getHuffTable();
2175 huffRDXTable
= huffTableN
;
2176 } else if (huffRDX
== 1) {
2177 huffRDXTable
= huffTableO
;
2179 if (i
>= (Guint
)codeTables
->getLength()) {
2180 goto codeTableError
;
2182 huffRDXTable
= ((JBIG2CodeTable
*)codeTables
->get(i
++))->getHuffTable();
2185 huffRDYTable
= huffTableN
;
2186 } else if (huffRDY
== 1) {
2187 huffRDYTable
= huffTableO
;
2189 if (i
>= (Guint
)codeTables
->getLength()) {
2190 goto codeTableError
;
2192 huffRDYTable
= ((JBIG2CodeTable
*)codeTables
->get(i
++))->getHuffTable();
2194 if (huffRSize
== 0) {
2195 huffRSizeTable
= huffTableA
;
2197 if (i
>= (Guint
)codeTables
->getLength()) {
2198 goto codeTableError
;
2201 ((JBIG2CodeTable
*)codeTables
->get(i
++))->getHuffTable();
2206 // symbol ID Huffman decoding table
2208 huffDecoder
->reset();
2209 for (i
= 0; i
< 32; ++i
) {
2210 runLengthTab
[i
].val
= i
;
2211 runLengthTab
[i
].prefixLen
= huffDecoder
->readBits(4);
2212 runLengthTab
[i
].rangeLen
= 0;
2214 runLengthTab
[32].val
= 0x103;
2215 runLengthTab
[32].prefixLen
= huffDecoder
->readBits(4);
2216 runLengthTab
[32].rangeLen
= 2;
2217 runLengthTab
[33].val
= 0x203;
2218 runLengthTab
[33].prefixLen
= huffDecoder
->readBits(4);
2219 runLengthTab
[33].rangeLen
= 3;
2220 runLengthTab
[34].val
= 0x20b;
2221 runLengthTab
[34].prefixLen
= huffDecoder
->readBits(4);
2222 runLengthTab
[34].rangeLen
= 7;
2223 runLengthTab
[35].prefixLen
= 0;
2224 runLengthTab
[35].rangeLen
= jbig2HuffmanEOT
;
2225 huffDecoder
->buildTable(runLengthTab
, 35);
2226 symCodeTab
= (JBIG2HuffmanTable
*)gmallocn(numSyms
+ 1,
2227 sizeof(JBIG2HuffmanTable
));
2228 for (i
= 0; i
< numSyms
; ++i
) {
2229 symCodeTab
[i
].val
= i
;
2230 symCodeTab
[i
].rangeLen
= 0;
2233 while (i
< numSyms
) {
2234 huffDecoder
->decodeInt(&j
, runLengthTab
);
2236 for (j
-= 0x200; j
&& i
< numSyms
; --j
) {
2237 symCodeTab
[i
++].prefixLen
= 0;
2239 } else if (j
> 0x100) {
2240 if (unlikely(i
== 0)) ++i
;
2241 for (j
-= 0x100; j
&& i
< numSyms
; --j
) {
2242 symCodeTab
[i
].prefixLen
= symCodeTab
[i
-1].prefixLen
;
2246 symCodeTab
[i
++].prefixLen
= j
;
2249 symCodeTab
[numSyms
].prefixLen
= 0;
2250 symCodeTab
[numSyms
].rangeLen
= jbig2HuffmanEOT
;
2251 huffDecoder
->buildTable(symCodeTab
, numSyms
);
2252 huffDecoder
->reset();
2254 // set up the arithmetic decoder
2257 resetIntStats(symCodeLen
);
2258 arithDecoder
->start();
2261 resetRefinementStats(templ
, NULL
);
2264 bitmap
= readTextRegion(huff
, refine
, w
, h
, numInstances
,
2265 logStrips
, numSyms
, symCodeTab
, symCodeLen
, syms
,
2266 defPixel
, combOp
, transposed
, refCorner
, sOffset
,
2267 huffFSTable
, huffDSTable
, huffDTTable
,
2268 huffRDWTable
, huffRDHTable
,
2269 huffRDXTable
, huffRDYTable
, huffRSizeTable
,
2275 // combine the region bitmap into the page bitmap
2277 if (pageH
== 0xffffffff && y
+ h
> curPageH
) {
2278 pageBitmap
->expand(y
+ h
, pageDefPixel
);
2280 pageBitmap
->combine(bitmap
, x
, y
, extCombOp
);
2283 // store the region bitmap
2285 bitmap
->setSegNum(segNum
);
2286 segments
->append(bitmap
);
2290 // clean up the Huffman decoder
2298 error(errSyntaxError
, curStr
->getPos(), "Missing code table in JBIG2 text region");
2304 error(errSyntaxError
, curStr
->getPos(), "Unexpected EOF in JBIG2 stream");
2308 JBIG2Bitmap
*JBIG2Stream::readTextRegion(GBool huff
, GBool refine
,
2313 JBIG2HuffmanTable
*symCodeTab
,
2316 Guint defPixel
, Guint combOp
,
2317 Guint transposed
, Guint refCorner
,
2319 JBIG2HuffmanTable
*huffFSTable
,
2320 JBIG2HuffmanTable
*huffDSTable
,
2321 JBIG2HuffmanTable
*huffDTTable
,
2322 JBIG2HuffmanTable
*huffRDWTable
,
2323 JBIG2HuffmanTable
*huffRDHTable
,
2324 JBIG2HuffmanTable
*huffRDXTable
,
2325 JBIG2HuffmanTable
*huffRDYTable
,
2326 JBIG2HuffmanTable
*huffRSizeTable
,
2328 int *atx
, int *aty
) {
2329 JBIG2Bitmap
*bitmap
;
2330 JBIG2Bitmap
*symbolBitmap
;
2332 int t
, dt
, tt
, s
, ds
, sFirst
, j
;
2333 int rdw
, rdh
, rdx
, rdy
, ri
, refDX
, refDY
, bmSize
;
2334 Guint symID
, inst
, bw
, bh
;
2336 strips
= 1 << logStrips
;
2338 // allocate the bitmap
2339 bitmap
= new JBIG2Bitmap(0, w
, h
);
2340 if (!bitmap
->isOk()) {
2345 bitmap
->clearToOne();
2347 bitmap
->clearToZero();
2350 // decode initial T value
2352 huffDecoder
->decodeInt(&t
, huffDTTable
);
2354 arithDecoder
->decodeInt(&t
, iadtStats
);
2360 while (inst
< numInstances
) {
2364 huffDecoder
->decodeInt(&dt
, huffDTTable
);
2366 arithDecoder
->decodeInt(&dt
, iadtStats
);
2372 huffDecoder
->decodeInt(&ds
, huffFSTable
);
2374 arithDecoder
->decodeInt(&ds
, iafsStats
);
2379 // read the instances
2380 // (this loop test is here to avoid an infinite loop with damaged
2381 // JBIG2 streams where the normal loop exit doesn't get triggered)
2382 while (inst
< numInstances
) {
2388 dt
= huffDecoder
->readBits(logStrips
);
2390 arithDecoder
->decodeInt(&dt
, iaitStats
);
2397 huffDecoder
->decodeInt(&j
, symCodeTab
);
2400 symID
= huffDecoder
->readBits(symCodeLen
);
2403 symID
= arithDecoder
->decodeIAID(symCodeLen
, iaidStats
);
2406 if (symID
>= (Guint
)numSyms
) {
2407 error(errSyntaxError
, curStr
->getPos(), "Invalid symbol number in JBIG2 text region");
2408 if (unlikely(numInstances
- inst
> 0x800)) {
2409 // don't loop too often with damaged JBIg2 streams
2415 // get the symbol bitmap
2416 symbolBitmap
= NULL
;
2419 ri
= (int)huffDecoder
->readBit();
2421 arithDecoder
->decodeInt(&ri
, iariStats
);
2427 GBool decodeSuccess
;
2429 decodeSuccess
= huffDecoder
->decodeInt(&rdw
, huffRDWTable
);
2430 decodeSuccess
= decodeSuccess
&& huffDecoder
->decodeInt(&rdh
, huffRDHTable
);
2431 decodeSuccess
= decodeSuccess
&& huffDecoder
->decodeInt(&rdx
, huffRDXTable
);
2432 decodeSuccess
= decodeSuccess
&& huffDecoder
->decodeInt(&rdy
, huffRDYTable
);
2433 decodeSuccess
= decodeSuccess
&& huffDecoder
->decodeInt(&bmSize
, huffRSizeTable
);
2434 huffDecoder
->reset();
2435 arithDecoder
->start();
2437 decodeSuccess
= arithDecoder
->decodeInt(&rdw
, iardwStats
);
2438 decodeSuccess
= decodeSuccess
&& arithDecoder
->decodeInt(&rdh
, iardhStats
);
2439 decodeSuccess
= decodeSuccess
&& arithDecoder
->decodeInt(&rdx
, iardxStats
);
2440 decodeSuccess
= decodeSuccess
&& arithDecoder
->decodeInt(&rdy
, iardyStats
);
2443 if (decodeSuccess
&& syms
[symID
])
2445 refDX
= ((rdw
>= 0) ? rdw
: rdw
- 1) / 2 + rdx
;
2446 refDY
= ((rdh
>= 0) ? rdh
: rdh
- 1) / 2 + rdy
;
2449 readGenericRefinementRegion(rdw
+ syms
[symID
]->getWidth(),
2450 rdh
+ syms
[symID
]->getHeight(),
2451 templ
, gFalse
, syms
[symID
],
2452 refDX
, refDY
, atx
, aty
);
2454 //~ do we need to use the bmSize value here (in Huffman mode)?
2456 symbolBitmap
= syms
[symID
];
2460 // combine the symbol bitmap into the region bitmap
2461 //~ something is wrong here - refCorner shouldn't degenerate into
2463 bw
= symbolBitmap
->getWidth() - 1;
2464 if (unlikely(symbolBitmap
->getHeight() == 0)) {
2465 error(errSyntaxError
, curStr
->getPos(), "Invalid symbol bitmap height");
2467 delete symbolBitmap
;
2472 bh
= symbolBitmap
->getHeight() - 1;
2474 if (unlikely(s
> 2 * bitmap
->getHeight())) {
2475 error(errSyntaxError
, curStr
->getPos(), "Invalid JBIG2 combine");
2477 delete symbolBitmap
;
2482 switch (refCorner
) {
2483 case 0: // bottom left
2484 bitmap
->combine(symbolBitmap
, tt
, s
, combOp
);
2487 bitmap
->combine(symbolBitmap
, tt
, s
, combOp
);
2489 case 2: // bottom right
2490 bitmap
->combine(symbolBitmap
, tt
- bw
, s
, combOp
);
2492 case 3: // top right
2493 bitmap
->combine(symbolBitmap
, tt
- bw
, s
, combOp
);
2498 switch (refCorner
) {
2499 case 0: // bottom left
2500 if (unlikely(tt
- (int) bh
> 2 * bitmap
->getHeight())) {
2501 error(errSyntaxError
, curStr
->getPos(), "Invalid JBIG2 combine");
2503 delete symbolBitmap
;
2508 bitmap
->combine(symbolBitmap
, s
, tt
- bh
, combOp
);
2511 if (unlikely(tt
> 2 * bitmap
->getHeight())) {
2512 error(errSyntaxError
, curStr
->getPos(), "Invalid JBIG2 combine");
2514 delete symbolBitmap
;
2519 bitmap
->combine(symbolBitmap
, s
, tt
, combOp
);
2521 case 2: // bottom right
2522 if (unlikely(tt
- (int) bh
> 2 * bitmap
->getHeight())) {
2523 error(errSyntaxError
, curStr
->getPos(), "Invalid JBIG2 combine");
2525 delete symbolBitmap
;
2530 bitmap
->combine(symbolBitmap
, s
, tt
- bh
, combOp
);
2532 case 3: // top right
2533 if (unlikely(tt
> 2 * bitmap
->getHeight())) {
2534 error(errSyntaxError
, curStr
->getPos(), "Invalid JBIG2 combine");
2536 delete symbolBitmap
;
2541 bitmap
->combine(symbolBitmap
, s
, tt
, combOp
);
2547 delete symbolBitmap
;
2550 // NULL symbolBitmap only happens on error
2561 if (!huffDecoder
->decodeInt(&ds
, huffDSTable
)) {
2565 if (!arithDecoder
->decodeInt(&ds
, iadsStats
)) {
2576 void JBIG2Stream::readPatternDictSeg(Guint segNum
, Guint length
) {
2577 JBIG2PatternDict
*patternDict
;
2578 JBIG2Bitmap
*bitmap
;
2579 Guint flags
, patternW
, patternH
, grayMax
, templ
, mmr
;
2583 // halftone dictionary flags, pattern width and height, max gray value
2584 if (!readUByte(&flags
) ||
2585 !readUByte(&patternW
) ||
2586 !readUByte(&patternH
) ||
2587 !readULong(&grayMax
)) {
2590 templ
= (flags
>> 1) & 3;
2593 // set up the arithmetic decoder
2595 resetGenericStats(templ
, NULL
);
2596 arithDecoder
->start();
2600 atx
[0] = -(int)patternW
; aty
[0] = 0;
2601 atx
[1] = -3; aty
[1] = -1;
2602 atx
[2] = 2; aty
[2] = -2;
2603 atx
[3] = -2; aty
[3] = -2;
2604 bitmap
= readGenericBitmap(mmr
, (grayMax
+ 1) * patternW
, patternH
,
2605 templ
, gFalse
, gFalse
, NULL
,
2606 atx
, aty
, length
- 7);
2611 // create the pattern dict object
2612 patternDict
= new JBIG2PatternDict(segNum
, grayMax
+ 1);
2614 // split up the bitmap
2616 for (i
= 0; i
<= grayMax
&& i
< patternDict
->getSize(); ++i
) {
2617 patternDict
->setBitmap(i
, bitmap
->getSlice(x
, 0, patternW
, patternH
));
2624 // store the new pattern dict
2625 segments
->append(patternDict
);
2630 error(errSyntaxError
, curStr
->getPos(), "Unexpected EOF in JBIG2 stream");
2633 void JBIG2Stream::readHalftoneRegionSeg(Guint segNum
, GBool imm
,
2634 GBool lossless
, Guint length
,
2635 Guint
*refSegs
, Guint nRefSegs
) {
2636 JBIG2Bitmap
*bitmap
;
2638 JBIG2PatternDict
*patternDict
;
2639 JBIG2Bitmap
*skipBitmap
;
2641 JBIG2Bitmap
*grayBitmap
;
2642 JBIG2Bitmap
*patternBitmap
;
2643 Guint w
, h
, x
, y
, segInfoFlags
, extCombOp
;
2644 Guint flags
, mmr
, templ
, enableSkip
, combOp
;
2645 Guint gridW
, gridH
, stepX
, stepY
, patW
, patH
;
2647 int gridX
, gridY
, xx
, yy
, bit
, j
;
2650 // region segment info field
2651 if (!readULong(&w
) || !readULong(&h
) ||
2652 !readULong(&x
) || !readULong(&y
) ||
2653 !readUByte(&segInfoFlags
)) {
2656 extCombOp
= segInfoFlags
& 7;
2658 // rest of the halftone region header
2659 if (!readUByte(&flags
)) {
2663 templ
= (flags
>> 1) & 3;
2664 enableSkip
= (flags
>> 3) & 1;
2665 combOp
= (flags
>> 4) & 7;
2666 if (!readULong(&gridW
) || !readULong(&gridH
) ||
2667 !readLong(&gridX
) || !readLong(&gridY
) ||
2668 !readUWord(&stepX
) || !readUWord(&stepY
)) {
2671 if (w
== 0 || h
== 0 || w
>= INT_MAX
/ h
) {
2672 error(errSyntaxError
, curStr
->getPos(), "Bad bitmap size in JBIG2 halftone segment");
2675 if (gridH
== 0 || gridW
>= INT_MAX
/ gridH
) {
2676 error(errSyntaxError
, curStr
->getPos(), "Bad grid size in JBIG2 halftone segment");
2680 // get pattern dictionary
2681 if (nRefSegs
!= 1) {
2682 error(errSyntaxError
, curStr
->getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
2685 seg
= findSegment(refSegs
[0]);
2686 if (seg
== NULL
|| seg
->getType() != jbig2SegPatternDict
) {
2687 error(errSyntaxError
, curStr
->getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
2691 patternDict
= (JBIG2PatternDict
*)seg
;
2692 i
= patternDict
->getSize();
2698 // i = floor((size-1) / 2^bpp)
2704 patternBitmap
= patternDict
->getBitmap(0);
2705 if (unlikely(patternBitmap
== NULL
)) {
2706 error(errSyntaxError
, curStr
->getPos(), "Bad pattern bitmap");
2709 patW
= patternBitmap
->getWidth();
2710 patH
= patternBitmap
->getHeight();
2712 // set up the arithmetic decoder
2714 resetGenericStats(templ
, NULL
);
2715 arithDecoder
->start();
2718 // allocate the bitmap
2719 bitmap
= new JBIG2Bitmap(segNum
, w
, h
);
2720 if (flags
& 0x80) { // HDEFPIXEL
2721 bitmap
->clearToOne();
2723 bitmap
->clearToZero();
2726 // compute the skip bitmap
2729 skipBitmap
= new JBIG2Bitmap(0, gridW
, gridH
);
2730 skipBitmap
->clearToZero();
2731 for (m
= 0; m
< gridH
; ++m
) {
2732 for (n
= 0; n
< gridW
; ++n
) {
2733 xx
= gridX
+ m
* stepY
+ n
* stepX
;
2734 yy
= gridY
+ m
* stepX
- n
* stepY
;
2735 if (((xx
+ (int)patW
) >> 8) <= 0 || (xx
>> 8) >= (int)w
||
2736 ((yy
+ (int)patH
) >> 8) <= 0 || (yy
>> 8) >= (int)h
) {
2737 skipBitmap
->setPixel(n
, m
);
2743 // read the gray-scale image
2744 grayImg
= (Guint
*)gmallocn(gridW
* gridH
, sizeof(Guint
));
2745 memset(grayImg
, 0, gridW
* gridH
* sizeof(Guint
));
2746 atx
[0] = templ
<= 1 ? 3 : 2; aty
[0] = -1;
2747 atx
[1] = -3; aty
[1] = -1;
2748 atx
[2] = 2; aty
[2] = -2;
2749 atx
[3] = -2; aty
[3] = -2;
2750 for (j
= bpp
- 1; j
>= 0; --j
) {
2751 grayBitmap
= readGenericBitmap(mmr
, gridW
, gridH
, templ
, gFalse
,
2752 enableSkip
, skipBitmap
, atx
, aty
, -1);
2754 for (m
= 0; m
< gridH
; ++m
) {
2755 for (n
= 0; n
< gridW
; ++n
) {
2756 bit
= grayBitmap
->getPixel(n
, m
) ^ (grayImg
[i
] & 1);
2757 grayImg
[i
] = (grayImg
[i
] << 1) | bit
;
2766 for (m
= 0; m
< gridH
; ++m
) {
2767 xx
= gridX
+ m
* stepY
;
2768 yy
= gridY
+ m
* stepX
;
2769 for (n
= 0; n
< gridW
; ++n
) {
2770 if (!(enableSkip
&& skipBitmap
->getPixel(n
, m
))) {
2771 patternBitmap
= patternDict
->getBitmap(grayImg
[i
]);
2772 if (unlikely(patternBitmap
== NULL
)) {
2773 error(errSyntaxError
, curStr
->getPos(), "Bad pattern bitmap");
2776 bitmap
->combine(patternBitmap
, xx
>> 8, yy
>> 8, combOp
);
2789 // combine the region bitmap into the page bitmap
2791 if (pageH
== 0xffffffff && y
+ h
> curPageH
) {
2792 pageBitmap
->expand(y
+ h
, pageDefPixel
);
2794 pageBitmap
->combine(bitmap
, x
, y
, extCombOp
);
2797 // store the region bitmap
2799 segments
->append(bitmap
);
2805 error(errSyntaxError
, curStr
->getPos(), "Unexpected EOF in JBIG2 stream");
2808 void JBIG2Stream::readGenericRegionSeg(Guint segNum
, GBool imm
,
2809 GBool lossless
, Guint length
) {
2810 JBIG2Bitmap
*bitmap
;
2811 Guint w
, h
, x
, y
, segInfoFlags
, extCombOp
, rowCount
;
2812 Guint flags
, mmr
, templ
, tpgdOn
;
2815 // region segment info field
2816 if (!readULong(&w
) || !readULong(&h
) ||
2817 !readULong(&x
) || !readULong(&y
) ||
2818 !readUByte(&segInfoFlags
)) {
2821 extCombOp
= segInfoFlags
& 7;
2823 // rest of the generic region segment header
2824 if (!readUByte(&flags
)) {
2828 templ
= (flags
>> 1) & 3;
2829 tpgdOn
= (flags
>> 3) & 1;
2834 if (!readByte(&atx
[0]) ||
2835 !readByte(&aty
[0]) ||
2836 !readByte(&atx
[1]) ||
2837 !readByte(&aty
[1]) ||
2838 !readByte(&atx
[2]) ||
2839 !readByte(&aty
[2]) ||
2840 !readByte(&atx
[3]) ||
2841 !readByte(&aty
[3])) {
2845 if (!readByte(&atx
[0]) ||
2846 !readByte(&aty
[0])) {
2852 // set up the arithmetic decoder
2854 resetGenericStats(templ
, NULL
);
2855 arithDecoder
->start();
2859 bitmap
= readGenericBitmap(mmr
, w
, h
, templ
, tpgdOn
, gFalse
,
2860 NULL
, atx
, aty
, mmr
? length
- 18 : 0);
2864 // combine the region bitmap into the page bitmap
2866 if (pageH
== 0xffffffff && y
+ h
> curPageH
) {
2867 pageBitmap
->expand(y
+ h
, pageDefPixel
);
2869 pageBitmap
->combine(bitmap
, x
, y
, extCombOp
);
2872 // store the region bitmap
2874 bitmap
->setSegNum(segNum
);
2875 segments
->append(bitmap
);
2878 // immediate generic segments can have an unspecified length, in
2879 // which case, a row count is stored at the end of the segment
2880 if (imm
&& length
== 0xffffffff) {
2881 readULong(&rowCount
);
2887 error(errSyntaxError
, curStr
->getPos(), "Unexpected EOF in JBIG2 stream");
2890 inline void JBIG2Stream::mmrAddPixels(int a1
, int blackPixels
,
2891 int *codingLine
, int *a0i
, int w
) {
2892 if (a1
> codingLine
[*a0i
]) {
2894 error(errSyntaxError
, curStr
->getPos(), "JBIG2 MMR row is wrong length ({0:d})", a1
);
2897 if ((*a0i
& 1) ^ blackPixels
) {
2900 codingLine
[*a0i
] = a1
;
2904 inline void JBIG2Stream::mmrAddPixelsNeg(int a1
, int blackPixels
,
2905 int *codingLine
, int *a0i
, int w
) {
2906 if (a1
> codingLine
[*a0i
]) {
2908 error(errSyntaxError
, curStr
->getPos(), "JBIG2 MMR row is wrong length ({0:d})", a1
);
2911 if ((*a0i
& 1) ^ blackPixels
) {
2914 codingLine
[*a0i
] = a1
;
2915 } else if (a1
< codingLine
[*a0i
]) {
2917 error(errSyntaxError
, curStr
->getPos(), "Invalid JBIG2 MMR code");
2920 while (*a0i
> 0 && a1
<= codingLine
[*a0i
- 1]) {
2923 codingLine
[*a0i
] = a1
;
2927 JBIG2Bitmap
*JBIG2Stream::readGenericBitmap(GBool mmr
, int w
, int h
,
2928 int templ
, GBool tpgdOn
,
2929 GBool useSkip
, JBIG2Bitmap
*skip
,
2931 int mmrDataLength
) {
2932 JBIG2Bitmap
*bitmap
;
2934 Guint ltpCX
, cx
, cx0
, cx1
, cx2
;
2935 int *refLine
, *codingLine
;
2936 int code1
, code2
, code3
;
2937 Guchar
*p0
, *p1
, *p2
, *pp
;
2938 Guchar
*atP0
, *atP1
, *atP2
, *atP3
;
2939 Guint buf0
, buf1
, buf2
;
2940 Guint atBuf0
, atBuf1
, atBuf2
, atBuf3
;
2941 int atShift0
, atShift1
, atShift2
, atShift3
;
2943 int x
, y
, x0
, x1
, a0i
, b1i
, blackPixels
, pix
, i
;
2945 bitmap
= new JBIG2Bitmap(0, w
, h
);
2946 if (!bitmap
->isOk()) {
2950 bitmap
->clearToZero();
2956 mmrDecoder
->reset();
2957 if (w
> INT_MAX
- 2) {
2958 error(errSyntaxError
, curStr
->getPos(), "Bad width in JBIG2 generic bitmap");
2959 // force a call to gmalloc(-1), which will throw an exception
2962 // 0 <= codingLine[0] < codingLine[1] < ... < codingLine[n] = w
2963 // ---> max codingLine size = w + 1
2964 // refLine has one extra guard entry at the end
2965 // ---> max refLine size = w + 2
2966 codingLine
= (int *)gmallocn(w
+ 1, sizeof(int));
2967 refLine
= (int *)gmallocn(w
+ 2, sizeof(int));
2968 memset(refLine
, 0, (w
+ 2) * sizeof(int));
2969 for (i
= 0; i
< w
+ 1; ++i
) codingLine
[i
] = w
;
2971 for (y
= 0; y
< h
; ++y
) {
2973 // copy coding line to ref line
2974 for (i
= 0; codingLine
[i
] < w
; ++i
) {
2975 refLine
[i
] = codingLine
[i
];
2986 // refLine[b1i-1] <= codingLine[a0i] < refLine[b1i] < refLine[b1i+1] <= w
2987 // exception at left edge:
2988 // codingLine[a0i = 0] = refLine[b1i = 0] = 0 is possible
2989 // exception at right edge:
2990 // refLine[b1i] = refLine[b1i+1] = w is possible
2991 while (codingLine
[a0i
] < w
) {
2992 code1
= mmrDecoder
->get2DCode();
2995 if (unlikely(b1i
+ 1 >= w
+ 2)) {
2998 mmrAddPixels(refLine
[b1i
+ 1], blackPixels
, codingLine
, &a0i
, w
);
2999 if (refLine
[b1i
+ 1] < w
) {
3007 code1
+= code3
= mmrDecoder
->getBlackCode();
3008 } while (code3
>= 64);
3010 code2
+= code3
= mmrDecoder
->getWhiteCode();
3011 } while (code3
>= 64);
3014 code1
+= code3
= mmrDecoder
->getWhiteCode();
3015 } while (code3
>= 64);
3017 code2
+= code3
= mmrDecoder
->getBlackCode();
3018 } while (code3
>= 64);
3020 mmrAddPixels(codingLine
[a0i
] + code1
, blackPixels
,
3021 codingLine
, &a0i
, w
);
3022 if (codingLine
[a0i
] < w
) {
3023 mmrAddPixels(codingLine
[a0i
] + code2
, blackPixels
^ 1,
3024 codingLine
, &a0i
, w
);
3026 while (likely(b1i
< w
+ 2) && refLine
[b1i
] <= codingLine
[a0i
] && refLine
[b1i
] < w
) {
3031 if (unlikely(b1i
>= w
+ 2)) {
3034 mmrAddPixels(refLine
[b1i
] + 3, blackPixels
, codingLine
, &a0i
, w
);
3036 if (codingLine
[a0i
] < w
) {
3038 while (likely(b1i
< w
+ 2) && refLine
[b1i
] <= codingLine
[a0i
] && refLine
[b1i
] < w
) {
3044 if (unlikely(b1i
>= w
+ 2)) {
3047 mmrAddPixels(refLine
[b1i
] + 2, blackPixels
, codingLine
, &a0i
, w
);
3049 if (codingLine
[a0i
] < w
) {
3051 while (likely(b1i
< w
+ 2) && refLine
[b1i
] <= codingLine
[a0i
] && refLine
[b1i
] < w
) {
3057 if (unlikely(b1i
>= w
+ 2)) {
3060 mmrAddPixels(refLine
[b1i
] + 1, blackPixels
, codingLine
, &a0i
, w
);
3062 if (codingLine
[a0i
] < w
) {
3064 while (likely(b1i
< w
+ 2) && refLine
[b1i
] <= codingLine
[a0i
] && refLine
[b1i
] < w
) {
3070 if (unlikely(b1i
>= w
+ 2)) {
3073 mmrAddPixels(refLine
[b1i
], blackPixels
, codingLine
, &a0i
, w
);
3075 if (codingLine
[a0i
] < w
) {
3077 while (likely(b1i
< w
+ 2) && refLine
[b1i
] <= codingLine
[a0i
] && refLine
[b1i
] < w
) {
3083 if (unlikely(b1i
>= w
+ 2)) {
3086 mmrAddPixelsNeg(refLine
[b1i
] - 3, blackPixels
, codingLine
, &a0i
, w
);
3088 if (codingLine
[a0i
] < w
) {
3094 while (likely(b1i
< w
+ 2) && refLine
[b1i
] <= codingLine
[a0i
] && refLine
[b1i
] < w
) {
3100 if (unlikely(b1i
>= w
+ 2)) {
3103 mmrAddPixelsNeg(refLine
[b1i
] - 2, blackPixels
, codingLine
, &a0i
, w
);
3105 if (codingLine
[a0i
] < w
) {
3111 while (likely(b1i
< w
+ 2) && refLine
[b1i
] <= codingLine
[a0i
] && refLine
[b1i
] < w
) {
3117 if (unlikely(b1i
>= w
+ 2)) {
3120 mmrAddPixelsNeg(refLine
[b1i
] - 1, blackPixels
, codingLine
, &a0i
, w
);
3122 if (codingLine
[a0i
] < w
) {
3128 while (likely(b1i
< w
+ 2) && refLine
[b1i
] <= codingLine
[a0i
] && refLine
[b1i
] < w
) {
3134 mmrAddPixels(w
, 0, codingLine
, &a0i
, w
);
3137 error(errSyntaxError
, curStr
->getPos(), "Illegal code in JBIG2 MMR bitmap data");
3138 mmrAddPixels(w
, 0, codingLine
, &a0i
, w
);
3143 // convert the run lengths to a bitmap line
3146 for (x
= codingLine
[i
]; x
< codingLine
[i
+1]; ++x
) {
3147 bitmap
->setPixel(x
, y
);
3149 if (codingLine
[i
+1] >= w
|| codingLine
[i
+2] >= w
) {
3156 if (mmrDataLength
>= 0) {
3157 mmrDecoder
->skipTo(mmrDataLength
);
3159 if (mmrDecoder
->get24Bits() != 0x001001) {
3160 error(errSyntaxError
, curStr
->getPos(), "Missing EOFB in JBIG2 MMR bitmap data");
3167 //----- arithmetic decode
3170 // set up the typical row context
3171 ltpCX
= 0; // make gcc happy
3175 ltpCX
= 0x3953; // 001 11001 0101 0011
3178 ltpCX
= 0x079a; // 0011 11001 101 0
3181 ltpCX
= 0x0e3; // 001 1100 01 1
3184 ltpCX
= 0x18a; // 01100 0101 1
3190 cx
= cx0
= cx1
= cx2
= 0; // make gcc happy
3191 for (y
= 0; y
< h
; ++y
) {
3193 // check for a "typical" (duplicate) row
3195 if (arithDecoder
->decodeBit(ltpCX
, genericRegionStats
)) {
3200 bitmap
->duplicateRow(y
, y
-1);
3209 // set up the context
3210 p2
= pp
= bitmap
->getDataPtr() + y
* bitmap
->getLineSize();
3213 p1
= bitmap
->getDataPtr() + (y
- 1) * bitmap
->getLineSize();
3216 p0
= bitmap
->getDataPtr() + (y
- 2) * bitmap
->getLineSize();
3227 if (atx
[0] >= -8 && atx
[0] <= 8 &&
3228 atx
[1] >= -8 && atx
[1] <= 8 &&
3229 atx
[2] >= -8 && atx
[2] <= 8 &&
3230 atx
[3] >= -8 && atx
[3] <= 8) {
3231 // set up the adaptive context
3232 if (y
+ aty
[0] >= 0 && y
+ aty
[0] < bitmap
->getHeight()) {
3233 atP0
= bitmap
->getDataPtr() + (y
+ aty
[0]) * bitmap
->getLineSize();
3234 atBuf0
= *atP0
++ << 8;
3239 atShift0
= 15 - atx
[0];
3240 if (y
+ aty
[1] >= 0 && y
+ aty
[1] < bitmap
->getHeight()) {
3241 atP1
= bitmap
->getDataPtr() + (y
+ aty
[1]) * bitmap
->getLineSize();
3242 atBuf1
= *atP1
++ << 8;
3247 atShift1
= 15 - atx
[1];
3248 if (y
+ aty
[2] >= 0 && y
+ aty
[2] < bitmap
->getHeight()) {
3249 atP2
= bitmap
->getDataPtr() + (y
+ aty
[2]) * bitmap
->getLineSize();
3250 atBuf2
= *atP2
++ << 8;
3255 atShift2
= 15 - atx
[2];
3256 if (y
+ aty
[3] >= 0 && y
+ aty
[3] < bitmap
->getHeight()) {
3257 atP3
= bitmap
->getDataPtr() + (y
+ aty
[3]) * bitmap
->getLineSize();
3258 atBuf3
= *atP3
++ << 8;
3263 atShift3
= 15 - atx
[3];
3266 for (x0
= 0, x
= 0; x0
< w
; x0
+= 8, ++pp
) {
3288 for (x1
= 0, mask
= 0x80; x1
< 8 && x
< w
; ++x1
, ++x
, mask
>>= 1) {
3290 // build the context
3291 cx0
= (buf0
>> 14) & 0x07;
3292 cx1
= (buf1
>> 13) & 0x1f;
3293 cx2
= (buf2
>> 16) & 0x0f;
3294 cx
= (cx0
<< 13) | (cx1
<< 8) | (cx2
<< 4) |
3295 (((atBuf0
>> atShift0
) & 1) << 3) |
3296 (((atBuf1
>> atShift1
) & 1) << 2) |
3297 (((atBuf2
>> atShift2
) & 1) << 1) |
3298 ((atBuf3
>> atShift3
) & 1);
3300 // check for a skipped pixel
3301 if (!(useSkip
&& skip
->getPixel(x
, y
))) {
3304 if ((pix
= arithDecoder
->decodeBit(cx
, genericRegionStats
))) {
3322 // update the context
3335 for (x0
= 0, x
= 0; x0
< w
; x0
+= 8, ++pp
) {
3345 for (x1
= 0, mask
= 0x80; x1
< 8 && x
< w
; ++x1
, ++x
, mask
>>= 1) {
3347 // build the context
3348 cx0
= (buf0
>> 14) & 0x07;
3349 cx1
= (buf1
>> 13) & 0x1f;
3350 cx2
= (buf2
>> 16) & 0x0f;
3351 cx
= (cx0
<< 13) | (cx1
<< 8) | (cx2
<< 4) |
3352 (bitmap
->getPixel(x
+ atx
[0], y
+ aty
[0]) << 3) |
3353 (bitmap
->getPixel(x
+ atx
[1], y
+ aty
[1]) << 2) |
3354 (bitmap
->getPixel(x
+ atx
[2], y
+ aty
[2]) << 1) |
3355 bitmap
->getPixel(x
+ atx
[3], y
+ aty
[3]);
3357 // check for a skipped pixel
3358 if (!(useSkip
&& skip
->getPixel(x
, y
))) {
3361 if ((pix
= arithDecoder
->decodeBit(cx
, genericRegionStats
))) {
3367 // update the context
3378 // set up the context
3379 p2
= pp
= bitmap
->getDataPtr() + y
* bitmap
->getLineSize();
3382 p1
= bitmap
->getDataPtr() + (y
- 1) * bitmap
->getLineSize();
3385 p0
= bitmap
->getDataPtr() + (y
- 2) * bitmap
->getLineSize();
3396 if (atx
[0] >= -8 && atx
[0] <= 8) {
3397 // set up the adaptive context
3398 const int atY
= y
+ aty
[0];
3399 if ((atY
>= 0) && (atY
< bitmap
->getHeight())) {
3400 atP0
= bitmap
->getDataPtr() + atY
* bitmap
->getLineSize();
3401 atBuf0
= *atP0
++ << 8;
3406 atShift0
= 15 - atx
[0];
3409 for (x0
= 0, x
= 0; x0
< w
; x0
+= 8, ++pp
) {
3422 for (x1
= 0, mask
= 0x80; x1
< 8 && x
< w
; ++x1
, ++x
, mask
>>= 1) {
3424 // build the context
3425 cx0
= (buf0
>> 13) & 0x0f;
3426 cx1
= (buf1
>> 13) & 0x1f;
3427 cx2
= (buf2
>> 16) & 0x07;
3428 cx
= (cx0
<< 9) | (cx1
<< 4) | (cx2
<< 1) |
3429 ((atBuf0
>> atShift0
) & 1);
3431 // check for a skipped pixel
3432 if (!(useSkip
&& skip
->getPixel(x
, y
))) {
3435 if ((pix
= arithDecoder
->decodeBit(cx
, genericRegionStats
))) {
3444 // update the context
3454 for (x0
= 0, x
= 0; x0
< w
; x0
+= 8, ++pp
) {
3464 for (x1
= 0, mask
= 0x80; x1
< 8 && x
< w
; ++x1
, ++x
, mask
>>= 1) {
3466 // build the context
3467 cx0
= (buf0
>> 13) & 0x0f;
3468 cx1
= (buf1
>> 13) & 0x1f;
3469 cx2
= (buf2
>> 16) & 0x07;
3470 cx
= (cx0
<< 9) | (cx1
<< 4) | (cx2
<< 1) |
3471 bitmap
->getPixel(x
+ atx
[0], y
+ aty
[0]);
3473 // check for a skipped pixel
3474 if (!(useSkip
&& skip
->getPixel(x
, y
))) {
3477 if ((pix
= arithDecoder
->decodeBit(cx
, genericRegionStats
))) {
3483 // update the context
3494 // set up the context
3495 p2
= pp
= bitmap
->getDataPtr() + y
* bitmap
->getLineSize();
3498 p1
= bitmap
->getDataPtr() + (y
- 1) * bitmap
->getLineSize();
3501 p0
= bitmap
->getDataPtr() + (y
- 2) * bitmap
->getLineSize();
3512 if (atx
[0] >= -8 && atx
[0] <= 8) {
3513 // set up the adaptive context
3514 const int atY
= y
+ aty
[0];
3515 if ((atY
>= 0) && (atY
< bitmap
->getHeight())) {
3516 atP0
= bitmap
->getDataPtr() + atY
* bitmap
->getLineSize();
3517 atBuf0
= *atP0
++ << 8;
3522 atShift0
= 15 - atx
[0];
3525 for (x0
= 0, x
= 0; x0
< w
; x0
+= 8, ++pp
) {
3538 for (x1
= 0, mask
= 0x80; x1
< 8 && x
< w
; ++x1
, ++x
, mask
>>= 1) {
3540 // build the context
3541 cx0
= (buf0
>> 14) & 0x07;
3542 cx1
= (buf1
>> 14) & 0x0f;
3543 cx2
= (buf2
>> 16) & 0x03;
3544 cx
= (cx0
<< 7) | (cx1
<< 3) | (cx2
<< 1) |
3545 ((atBuf0
>> atShift0
) & 1);
3547 // check for a skipped pixel
3548 if (!(useSkip
&& skip
->getPixel(x
, y
))) {
3551 if ((pix
= arithDecoder
->decodeBit(cx
, genericRegionStats
))) {
3560 // update the context
3570 for (x0
= 0, x
= 0; x0
< w
; x0
+= 8, ++pp
) {
3580 for (x1
= 0, mask
= 0x80; x1
< 8 && x
< w
; ++x1
, ++x
, mask
>>= 1) {
3582 // build the context
3583 cx0
= (buf0
>> 14) & 0x07;
3584 cx1
= (buf1
>> 14) & 0x0f;
3585 cx2
= (buf2
>> 16) & 0x03;
3586 cx
= (cx0
<< 7) | (cx1
<< 3) | (cx2
<< 1) |
3587 bitmap
->getPixel(x
+ atx
[0], y
+ aty
[0]);
3589 // check for a skipped pixel
3590 if (!(useSkip
&& skip
->getPixel(x
, y
))) {
3593 if ((pix
= arithDecoder
->decodeBit(cx
, genericRegionStats
))) {
3599 // update the context
3610 // set up the context
3611 p2
= pp
= bitmap
->getDataPtr() + y
* bitmap
->getLineSize();
3614 p1
= bitmap
->getDataPtr() + (y
- 1) * bitmap
->getLineSize();
3621 if (atx
[0] >= -8 && atx
[0] <= 8) {
3622 // set up the adaptive context
3623 const int atY
= y
+ aty
[0];
3624 if ((atY
>= 0) && (atY
< bitmap
->getHeight())) {
3625 atP0
= bitmap
->getDataPtr() + atY
* bitmap
->getLineSize();
3626 atBuf0
= *atP0
++ << 8;
3631 atShift0
= 15 - atx
[0];
3634 for (x0
= 0, x
= 0; x0
< w
; x0
+= 8, ++pp
) {
3644 for (x1
= 0, mask
= 0x80; x1
< 8 && x
< w
; ++x1
, ++x
, mask
>>= 1) {
3646 // build the context
3647 cx1
= (buf1
>> 14) & 0x1f;
3648 cx2
= (buf2
>> 16) & 0x0f;
3649 cx
= (cx1
<< 5) | (cx2
<< 1) |
3650 ((atBuf0
>> atShift0
) & 1);
3652 // check for a skipped pixel
3653 if (!(useSkip
&& skip
->getPixel(x
, y
))) {
3656 if ((pix
= arithDecoder
->decodeBit(cx
, genericRegionStats
))) {
3665 // update the context
3674 for (x0
= 0, x
= 0; x0
< w
; x0
+= 8, ++pp
) {
3681 for (x1
= 0, mask
= 0x80; x1
< 8 && x
< w
; ++x1
, ++x
, mask
>>= 1) {
3683 // build the context
3684 cx1
= (buf1
>> 14) & 0x1f;
3685 cx2
= (buf2
>> 16) & 0x0f;
3686 cx
= (cx1
<< 5) | (cx2
<< 1) |
3687 bitmap
->getPixel(x
+ atx
[0], y
+ aty
[0]);
3689 // check for a skipped pixel
3690 if (!(useSkip
&& skip
->getPixel(x
, y
))) {
3693 if ((pix
= arithDecoder
->decodeBit(cx
, genericRegionStats
))) {
3699 // update the context
3713 void JBIG2Stream::readGenericRefinementRegionSeg(Guint segNum
, GBool imm
,
3714 GBool lossless
, Guint length
,
3717 JBIG2Bitmap
*bitmap
, *refBitmap
;
3718 Guint w
, h
, x
, y
, segInfoFlags
, extCombOp
;
3719 Guint flags
, templ
, tpgrOn
;
3723 // region segment info field
3724 if (!readULong(&w
) || !readULong(&h
) ||
3725 !readULong(&x
) || !readULong(&y
) ||
3726 !readUByte(&segInfoFlags
)) {
3729 extCombOp
= segInfoFlags
& 7;
3731 // rest of the generic refinement region segment header
3732 if (!readUByte(&flags
)) {
3736 tpgrOn
= (flags
>> 1) & 1;
3740 if (!readByte(&atx
[0]) || !readByte(&aty
[0]) ||
3741 !readByte(&atx
[1]) || !readByte(&aty
[1])) {
3746 // resize the page bitmap if needed
3747 if (nRefSegs
== 0 || imm
) {
3748 if (pageH
== 0xffffffff && y
+ h
> curPageH
) {
3749 pageBitmap
->expand(y
+ h
, pageDefPixel
);
3753 // get referenced bitmap
3755 error(errSyntaxError
, curStr
->getPos(), "Bad reference in JBIG2 generic refinement segment");
3758 if (nRefSegs
== 1) {
3759 seg
= findSegment(refSegs
[0]);
3760 if (seg
== NULL
|| seg
->getType() != jbig2SegBitmap
) {
3761 error(errSyntaxError
, curStr
->getPos(), "Bad bitmap reference in JBIG2 generic refinement segment");
3764 refBitmap
= (JBIG2Bitmap
*)seg
;
3766 refBitmap
= pageBitmap
->getSlice(x
, y
, w
, h
);
3769 // set up the arithmetic decoder
3770 resetRefinementStats(templ
, NULL
);
3771 arithDecoder
->start();
3774 bitmap
= readGenericRefinementRegion(w
, h
, templ
, tpgrOn
,
3775 refBitmap
, 0, 0, atx
, aty
);
3777 // combine the region bitmap into the page bitmap
3778 if (imm
&& bitmap
) {
3779 pageBitmap
->combine(bitmap
, x
, y
, extCombOp
);
3782 // store the region bitmap
3785 bitmap
->setSegNum(segNum
);
3786 segments
->append(bitmap
);
3788 error(errSyntaxError
, curStr
->getPos(), "readGenericRefinementRegionSeg with null bitmap");
3792 // delete the referenced bitmap
3793 if (nRefSegs
== 1) {
3794 discardSegment(refSegs
[0]);
3802 error(errSyntaxError
, curStr
->getPos(), "Unexpected EOF in JBIG2 stream");
3805 JBIG2Bitmap
*JBIG2Stream::readGenericRefinementRegion(int w
, int h
,
3806 int templ
, GBool tpgrOn
,
3807 JBIG2Bitmap
*refBitmap
,
3808 int refDX
, int refDY
,
3809 int *atx
, int *aty
) {
3810 JBIG2Bitmap
*bitmap
;
3812 Guint ltpCX
, cx
, cx0
, cx2
, cx3
, cx4
, tpgrCX0
, tpgrCX1
, tpgrCX2
;
3813 JBIG2BitmapPtr cxPtr0
= {0};
3814 JBIG2BitmapPtr cxPtr1
= {0};
3815 JBIG2BitmapPtr cxPtr2
= {0};
3816 JBIG2BitmapPtr cxPtr3
= {0};
3817 JBIG2BitmapPtr cxPtr4
= {0};
3818 JBIG2BitmapPtr cxPtr5
= {0};
3819 JBIG2BitmapPtr cxPtr6
= {0};
3820 JBIG2BitmapPtr tpgrCXPtr0
= {0};
3821 JBIG2BitmapPtr tpgrCXPtr1
= {0};
3822 JBIG2BitmapPtr tpgrCXPtr2
= {0};
3825 bitmap
= new JBIG2Bitmap(0, w
, h
);
3826 if (!bitmap
->isOk())
3831 bitmap
->clearToZero();
3833 // set up the typical row context
3841 for (y
= 0; y
< h
; ++y
) {
3845 // set up the context
3846 bitmap
->getPixelPtr(0, y
-1, &cxPtr0
);
3847 cx0
= bitmap
->nextPixel(&cxPtr0
);
3848 bitmap
->getPixelPtr(-1, y
, &cxPtr1
);
3849 refBitmap
->getPixelPtr(-refDX
, y
-1-refDY
, &cxPtr2
);
3850 refBitmap
->getPixelPtr(-1-refDX
, y
-refDY
, &cxPtr3
);
3851 cx3
= refBitmap
->nextPixel(&cxPtr3
);
3852 cx3
= (cx3
<< 1) | refBitmap
->nextPixel(&cxPtr3
);
3853 refBitmap
->getPixelPtr(-refDX
, y
+1-refDY
, &cxPtr4
);
3854 cx4
= refBitmap
->nextPixel(&cxPtr4
);
3856 // set up the typical prediction context
3857 tpgrCX0
= tpgrCX1
= tpgrCX2
= 0; // make gcc happy
3859 refBitmap
->getPixelPtr(-1-refDX
, y
-1-refDY
, &tpgrCXPtr0
);
3860 tpgrCX0
= refBitmap
->nextPixel(&tpgrCXPtr0
);
3861 tpgrCX0
= (tpgrCX0
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr0
);
3862 tpgrCX0
= (tpgrCX0
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr0
);
3863 refBitmap
->getPixelPtr(-1-refDX
, y
-refDY
, &tpgrCXPtr1
);
3864 tpgrCX1
= refBitmap
->nextPixel(&tpgrCXPtr1
);
3865 tpgrCX1
= (tpgrCX1
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr1
);
3866 tpgrCX1
= (tpgrCX1
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr1
);
3867 refBitmap
->getPixelPtr(-1-refDX
, y
+1-refDY
, &tpgrCXPtr2
);
3868 tpgrCX2
= refBitmap
->nextPixel(&tpgrCXPtr2
);
3869 tpgrCX2
= (tpgrCX2
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr2
);
3870 tpgrCX2
= (tpgrCX2
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr2
);
3872 tpgrCXPtr0
.p
= tpgrCXPtr1
.p
= tpgrCXPtr2
.p
= NULL
; // make gcc happy
3873 tpgrCXPtr0
.shift
= tpgrCXPtr1
.shift
= tpgrCXPtr2
.shift
= 0;
3874 tpgrCXPtr0
.x
= tpgrCXPtr1
.x
= tpgrCXPtr2
.x
= 0;
3877 for (x
= 0; x
< w
; ++x
) {
3879 // update the context
3880 cx0
= ((cx0
<< 1) | bitmap
->nextPixel(&cxPtr0
)) & 7;
3881 cx3
= ((cx3
<< 1) | refBitmap
->nextPixel(&cxPtr3
)) & 7;
3882 cx4
= ((cx4
<< 1) | refBitmap
->nextPixel(&cxPtr4
)) & 3;
3885 // update the typical predictor context
3886 tpgrCX0
= ((tpgrCX0
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr0
)) & 7;
3887 tpgrCX1
= ((tpgrCX1
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr1
)) & 7;
3888 tpgrCX2
= ((tpgrCX2
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr2
)) & 7;
3890 // check for a "typical" pixel
3891 if (arithDecoder
->decodeBit(ltpCX
, refinementRegionStats
)) {
3894 if (tpgrCX0
== 0 && tpgrCX1
== 0 && tpgrCX2
== 0) {
3895 bitmap
->clearPixel(x
, y
);
3897 } else if (tpgrCX0
== 7 && tpgrCX1
== 7 && tpgrCX2
== 7) {
3898 bitmap
->setPixel(x
, y
);
3903 // build the context
3904 cx
= (cx0
<< 7) | (bitmap
->nextPixel(&cxPtr1
) << 6) |
3905 (refBitmap
->nextPixel(&cxPtr2
) << 5) |
3909 if ((pix
= arithDecoder
->decodeBit(cx
, refinementRegionStats
))) {
3910 bitmap
->setPixel(x
, y
);
3916 // set up the context
3917 bitmap
->getPixelPtr(0, y
-1, &cxPtr0
);
3918 cx0
= bitmap
->nextPixel(&cxPtr0
);
3919 bitmap
->getPixelPtr(-1, y
, &cxPtr1
);
3920 refBitmap
->getPixelPtr(-refDX
, y
-1-refDY
, &cxPtr2
);
3921 cx2
= refBitmap
->nextPixel(&cxPtr2
);
3922 refBitmap
->getPixelPtr(-1-refDX
, y
-refDY
, &cxPtr3
);
3923 cx3
= refBitmap
->nextPixel(&cxPtr3
);
3924 cx3
= (cx3
<< 1) | refBitmap
->nextPixel(&cxPtr3
);
3925 refBitmap
->getPixelPtr(-1-refDX
, y
+1-refDY
, &cxPtr4
);
3926 cx4
= refBitmap
->nextPixel(&cxPtr4
);
3927 cx4
= (cx4
<< 1) | refBitmap
->nextPixel(&cxPtr4
);
3928 bitmap
->getPixelPtr(atx
[0], y
+aty
[0], &cxPtr5
);
3929 refBitmap
->getPixelPtr(atx
[1]-refDX
, y
+aty
[1]-refDY
, &cxPtr6
);
3931 // set up the typical prediction context
3932 tpgrCX0
= tpgrCX1
= tpgrCX2
= 0; // make gcc happy
3934 refBitmap
->getPixelPtr(-1-refDX
, y
-1-refDY
, &tpgrCXPtr0
);
3935 tpgrCX0
= refBitmap
->nextPixel(&tpgrCXPtr0
);
3936 tpgrCX0
= (tpgrCX0
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr0
);
3937 tpgrCX0
= (tpgrCX0
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr0
);
3938 refBitmap
->getPixelPtr(-1-refDX
, y
-refDY
, &tpgrCXPtr1
);
3939 tpgrCX1
= refBitmap
->nextPixel(&tpgrCXPtr1
);
3940 tpgrCX1
= (tpgrCX1
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr1
);
3941 tpgrCX1
= (tpgrCX1
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr1
);
3942 refBitmap
->getPixelPtr(-1-refDX
, y
+1-refDY
, &tpgrCXPtr2
);
3943 tpgrCX2
= refBitmap
->nextPixel(&tpgrCXPtr2
);
3944 tpgrCX2
= (tpgrCX2
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr2
);
3945 tpgrCX2
= (tpgrCX2
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr2
);
3947 tpgrCXPtr0
.p
= tpgrCXPtr1
.p
= tpgrCXPtr2
.p
= NULL
; // make gcc happy
3948 tpgrCXPtr0
.shift
= tpgrCXPtr1
.shift
= tpgrCXPtr2
.shift
= 0;
3949 tpgrCXPtr0
.x
= tpgrCXPtr1
.x
= tpgrCXPtr2
.x
= 0;
3952 for (x
= 0; x
< w
; ++x
) {
3954 // update the context
3955 cx0
= ((cx0
<< 1) | bitmap
->nextPixel(&cxPtr0
)) & 3;
3956 cx2
= ((cx2
<< 1) | refBitmap
->nextPixel(&cxPtr2
)) & 3;
3957 cx3
= ((cx3
<< 1) | refBitmap
->nextPixel(&cxPtr3
)) & 7;
3958 cx4
= ((cx4
<< 1) | refBitmap
->nextPixel(&cxPtr4
)) & 7;
3961 // update the typical predictor context
3962 tpgrCX0
= ((tpgrCX0
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr0
)) & 7;
3963 tpgrCX1
= ((tpgrCX1
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr1
)) & 7;
3964 tpgrCX2
= ((tpgrCX2
<< 1) | refBitmap
->nextPixel(&tpgrCXPtr2
)) & 7;
3966 // check for a "typical" pixel
3967 if (arithDecoder
->decodeBit(ltpCX
, refinementRegionStats
)) {
3970 if (tpgrCX0
== 0 && tpgrCX1
== 0 && tpgrCX2
== 0) {
3971 bitmap
->clearPixel(x
, y
);
3973 } else if (tpgrCX0
== 7 && tpgrCX1
== 7 && tpgrCX2
== 7) {
3974 bitmap
->setPixel(x
, y
);
3979 // build the context
3980 cx
= (cx0
<< 11) | (bitmap
->nextPixel(&cxPtr1
) << 10) |
3981 (cx2
<< 8) | (cx3
<< 5) | (cx4
<< 2) |
3982 (bitmap
->nextPixel(&cxPtr5
) << 1) |
3983 refBitmap
->nextPixel(&cxPtr6
);
3986 if ((pix
= arithDecoder
->decodeBit(cx
, refinementRegionStats
))) {
3987 bitmap
->setPixel(x
, y
);
3996 void JBIG2Stream::readPageInfoSeg(Guint length
) {
3997 Guint xRes
, yRes
, flags
, striping
;
3999 if (!readULong(&pageW
) || !readULong(&pageH
) ||
4000 !readULong(&xRes
) || !readULong(&yRes
) ||
4001 !readUByte(&flags
) || !readUWord(&striping
)) {
4004 pageDefPixel
= (flags
>> 2) & 1;
4005 defCombOp
= (flags
>> 3) & 3;
4007 // allocate the page bitmap
4008 if (pageH
== 0xffffffff) {
4009 curPageH
= striping
& 0x7fff;
4013 pageBitmap
= new JBIG2Bitmap(0, pageW
, curPageH
);
4015 if (!pageBitmap
->isOk()) {
4021 // default pixel value
4023 pageBitmap
->clearToOne();
4025 pageBitmap
->clearToZero();
4031 error(errSyntaxError
, curStr
->getPos(), "Unexpected EOF in JBIG2 stream");
4034 void JBIG2Stream::readEndOfStripeSeg(Guint length
) {
4038 for (i
= 0; i
< length
; ++i
) {
4039 if (curStr
->getChar() == EOF
) {
4045 void JBIG2Stream::readProfilesSeg(Guint length
) {
4049 for (i
= 0; i
< length
; ++i
) {
4050 if (curStr
->getChar() == EOF
) {
4056 void JBIG2Stream::readCodeTableSeg(Guint segNum
, Guint length
) {
4057 JBIG2HuffmanTable
*huffTab
;
4058 Guint flags
, oob
, prefixBits
, rangeBits
;
4059 int lowVal
, highVal
, val
;
4060 Guint huffTabSize
, i
;
4062 if (!readUByte(&flags
) || !readLong(&lowVal
) || !readLong(&highVal
)) {
4066 prefixBits
= ((flags
>> 1) & 7) + 1;
4067 rangeBits
= ((flags
>> 4) & 7) + 1;
4069 huffDecoder
->reset();
4071 huffTab
= (JBIG2HuffmanTable
*)
4072 gmallocn(huffTabSize
, sizeof(JBIG2HuffmanTable
));
4075 while (val
< highVal
) {
4076 if (i
== huffTabSize
) {
4078 huffTab
= (JBIG2HuffmanTable
*)
4079 greallocn(huffTab
, huffTabSize
, sizeof(JBIG2HuffmanTable
));
4081 huffTab
[i
].val
= val
;
4082 huffTab
[i
].prefixLen
= huffDecoder
->readBits(prefixBits
);
4083 huffTab
[i
].rangeLen
= huffDecoder
->readBits(rangeBits
);
4084 val
+= 1 << huffTab
[i
].rangeLen
;
4087 if (i
+ oob
+ 3 > huffTabSize
) {
4088 huffTabSize
= i
+ oob
+ 3;
4089 huffTab
= (JBIG2HuffmanTable
*)
4090 greallocn(huffTab
, huffTabSize
, sizeof(JBIG2HuffmanTable
));
4092 huffTab
[i
].val
= lowVal
- 1;
4093 huffTab
[i
].prefixLen
= huffDecoder
->readBits(prefixBits
);
4094 huffTab
[i
].rangeLen
= jbig2HuffmanLOW
;
4096 huffTab
[i
].val
= highVal
;
4097 huffTab
[i
].prefixLen
= huffDecoder
->readBits(prefixBits
);
4098 huffTab
[i
].rangeLen
= 32;
4102 huffTab
[i
].prefixLen
= huffDecoder
->readBits(prefixBits
);
4103 huffTab
[i
].rangeLen
= jbig2HuffmanOOB
;
4107 huffTab
[i
].prefixLen
= 0;
4108 huffTab
[i
].rangeLen
= jbig2HuffmanEOT
;
4109 huffDecoder
->buildTable(huffTab
, i
);
4111 // create and store the new table segment
4112 segments
->append(new JBIG2CodeTable(segNum
, huffTab
));
4117 error(errSyntaxError
, curStr
->getPos(), "Unexpected EOF in JBIG2 stream");
4120 void JBIG2Stream::readExtensionSeg(Guint length
) {
4124 for (i
= 0; i
< length
; ++i
) {
4125 if (curStr
->getChar() == EOF
) {
4131 JBIG2Segment
*JBIG2Stream::findSegment(Guint segNum
) {
4135 for (i
= 0; i
< globalSegments
->getLength(); ++i
) {
4136 seg
= (JBIG2Segment
*)globalSegments
->get(i
);
4137 if (seg
->getSegNum() == segNum
) {
4141 for (i
= 0; i
< segments
->getLength(); ++i
) {
4142 seg
= (JBIG2Segment
*)segments
->get(i
);
4143 if (seg
->getSegNum() == segNum
) {
4150 void JBIG2Stream::discardSegment(Guint segNum
) {
4154 for (i
= 0; i
< globalSegments
->getLength(); ++i
) {
4155 seg
= (JBIG2Segment
*)globalSegments
->get(i
);
4156 if (seg
->getSegNum() == segNum
) {
4157 globalSegments
->del(i
);
4161 for (i
= 0; i
< segments
->getLength(); ++i
) {
4162 seg
= (JBIG2Segment
*)segments
->get(i
);
4163 if (seg
->getSegNum() == segNum
) {
4170 void JBIG2Stream::resetGenericStats(Guint templ
,
4171 JArithmeticDecoderStats
*prevStats
) {
4174 size
= contextSize
[templ
];
4175 if (prevStats
&& prevStats
->getContextSize() == size
) {
4176 if (genericRegionStats
->getContextSize() == size
) {
4177 genericRegionStats
->copyFrom(prevStats
);
4179 delete genericRegionStats
;
4180 genericRegionStats
= prevStats
->copy();
4183 if (genericRegionStats
->getContextSize() == size
) {
4184 genericRegionStats
->reset();
4186 delete genericRegionStats
;
4187 genericRegionStats
= new JArithmeticDecoderStats(1 << size
);
4192 void JBIG2Stream::resetRefinementStats(Guint templ
,
4193 JArithmeticDecoderStats
*prevStats
) {
4196 size
= refContextSize
[templ
];
4197 if (prevStats
&& prevStats
->getContextSize() == size
) {
4198 if (refinementRegionStats
->getContextSize() == size
) {
4199 refinementRegionStats
->copyFrom(prevStats
);
4201 delete refinementRegionStats
;
4202 refinementRegionStats
= prevStats
->copy();
4205 if (refinementRegionStats
->getContextSize() == size
) {
4206 refinementRegionStats
->reset();
4208 delete refinementRegionStats
;
4209 refinementRegionStats
= new JArithmeticDecoderStats(1 << size
);
4214 void JBIG2Stream::resetIntStats(int symCodeLen
) {
4223 iardxStats
->reset();
4224 iardyStats
->reset();
4225 iardwStats
->reset();
4226 iardhStats
->reset();
4228 if (iaidStats
->getContextSize() == 1 << (symCodeLen
+ 1)) {
4232 iaidStats
= new JArithmeticDecoderStats(1 << (symCodeLen
+ 1));
4236 GBool
JBIG2Stream::readUByte(Guint
*x
) {
4239 if ((c0
= curStr
->getChar()) == EOF
) {
4246 GBool
JBIG2Stream::readByte(int *x
) {
4249 if ((c0
= curStr
->getChar()) == EOF
) {
4259 GBool
JBIG2Stream::readUWord(Guint
*x
) {
4262 if ((c0
= curStr
->getChar()) == EOF
||
4263 (c1
= curStr
->getChar()) == EOF
) {
4266 *x
= (Guint
)((c0
<< 8) | c1
);
4270 GBool
JBIG2Stream::readULong(Guint
*x
) {
4273 if ((c0
= curStr
->getChar()) == EOF
||
4274 (c1
= curStr
->getChar()) == EOF
||
4275 (c2
= curStr
->getChar()) == EOF
||
4276 (c3
= curStr
->getChar()) == EOF
) {
4279 *x
= (Guint
)((c0
<< 24) | (c1
<< 16) | (c2
<< 8) | c3
);
4283 GBool
JBIG2Stream::readLong(int *x
) {
4286 if ((c0
= curStr
->getChar()) == EOF
||
4287 (c1
= curStr
->getChar()) == EOF
||
4288 (c2
= curStr
->getChar()) == EOF
||
4289 (c3
= curStr
->getChar()) == EOF
) {
4292 *x
= ((c0
<< 24) | (c1
<< 16) | (c2
<< 8) | c3
);
4294 *x
|= -1 - (int)0xffffffff;