beta-0.89.2
[luatex.git] / source / libs / poppler / poppler-src / poppler / JBIG2Stream.cc
bloba20c220811550b2266e4ec56f2da8a412164abd4
1 //========================================================================
2 //
3 // JBIG2Stream.cc
4 //
5 // Copyright 2002-2003 Glyph & Cog, LLC
6 //
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 //========================================================================
32 #include <config.h>
34 #ifdef USE_GCC_PRAGMAS
35 #pragma implementation
36 #endif
38 #include <stdlib.h>
39 #include <limits.h>
40 #include "goo/GooList.h"
41 #include "Error.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 //------------------------------------------------------------------------
54 // JBIG2HuffmanTable
55 //------------------------------------------------------------------------
57 #define jbig2HuffmanLOW 0xfffffffd
58 #define jbig2HuffmanOOB 0xfffffffe
59 #define jbig2HuffmanEOT 0xffffffff
61 struct JBIG2HuffmanTable {
62 int val;
63 Guint prefixLen;
64 Guint rangeLen; // can also be LOW, OOB, or EOT
65 Guint prefix;
68 static JBIG2HuffmanTable huffTableA[] = {
69 { 0, 1, 4, 0x000 },
70 { 16, 2, 8, 0x002 },
71 { 272, 3, 16, 0x006 },
72 { 65808, 3, 32, 0x007 },
73 { 0, 0, jbig2HuffmanEOT, 0 }
76 static JBIG2HuffmanTable huffTableB[] = {
77 { 0, 1, 0, 0x000 },
78 { 1, 2, 0, 0x002 },
79 { 2, 3, 0, 0x006 },
80 { 3, 4, 3, 0x00e },
81 { 11, 5, 6, 0x01e },
82 { 75, 6, 32, 0x03e },
83 { 0, 6, jbig2HuffmanOOB, 0x03f },
84 { 0, 0, jbig2HuffmanEOT, 0 }
87 static JBIG2HuffmanTable huffTableC[] = {
88 { 0, 1, 0, 0x000 },
89 { 1, 2, 0, 0x002 },
90 { 2, 3, 0, 0x006 },
91 { 3, 4, 3, 0x00e },
92 { 11, 5, 6, 0x01e },
93 { 0, 6, jbig2HuffmanOOB, 0x03e },
94 { 75, 7, 32, 0x0fe },
95 { -256, 8, 8, 0x0fe },
96 { -257, 8, jbig2HuffmanLOW, 0x0ff },
97 { 0, 0, jbig2HuffmanEOT, 0 }
100 static JBIG2HuffmanTable huffTableD[] = {
101 { 1, 1, 0, 0x000 },
102 { 2, 2, 0, 0x002 },
103 { 3, 3, 0, 0x006 },
104 { 4, 4, 3, 0x00e },
105 { 12, 5, 6, 0x01e },
106 { 76, 5, 32, 0x01f },
107 { 0, 0, jbig2HuffmanEOT, 0 }
110 static JBIG2HuffmanTable huffTableE[] = {
111 { 1, 1, 0, 0x000 },
112 { 2, 2, 0, 0x002 },
113 { 3, 3, 0, 0x006 },
114 { 4, 4, 3, 0x00e },
115 { 12, 5, 6, 0x01e },
116 { 76, 6, 32, 0x03e },
117 { -255, 7, 8, 0x07e },
118 { -256, 7, jbig2HuffmanLOW, 0x07f },
119 { 0, 0, jbig2HuffmanEOT, 0 }
122 static JBIG2HuffmanTable huffTableF[] = {
123 { 0, 2, 7, 0x000 },
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 },
148 { 0, 4, 5, 0x00b },
149 { 128, 4, 7, 0x00c },
150 { -128, 5, 6, 0x01a },
151 { -64, 5, 5, 0x01b },
152 { 32, 5, 5, 0x01c },
153 { 64, 5, 6, 0x01d },
154 { -1025, 5, jbig2HuffmanLOW, 0x01e },
155 { 2048, 5, 32, 0x01f },
156 { 0, 0, jbig2HuffmanEOT, 0 }
159 static JBIG2HuffmanTable huffTableH[] = {
160 { 0, 2, 1, 0x000 },
161 { 0, 2, jbig2HuffmanOOB, 0x001 },
162 { 4, 3, 4, 0x004 },
163 { -1, 4, 0, 0x00a },
164 { 22, 4, 4, 0x00b },
165 { 38, 4, 5, 0x00c },
166 { 2, 5, 0, 0x01a },
167 { 70, 5, 6, 0x01b },
168 { 134, 5, 7, 0x01c },
169 { 3, 6, 0, 0x03a },
170 { 20, 6, 1, 0x03b },
171 { 262, 6, 7, 0x03c },
172 { 646, 6, 10, 0x03d },
173 { -2, 7, 0, 0x07c },
174 { 390, 7, 8, 0x07d },
175 { -15, 8, 3, 0x0fc },
176 { -5, 8, 1, 0x0fd },
177 { -7, 9, 1, 0x1fc },
178 { -3, 9, 0, 0x1fd },
179 { -16, 9, jbig2HuffmanLOW, 0x1fe },
180 { 1670, 9, 32, 0x1ff },
181 { 0, 0, jbig2HuffmanEOT, 0 }
184 static JBIG2HuffmanTable huffTableI[] = {
185 { 0, 2, jbig2HuffmanOOB, 0x000 },
186 { -1, 3, 1, 0x002 },
187 { 1, 3, 1, 0x003 },
188 { 7, 3, 5, 0x004 },
189 { -3, 4, 1, 0x00a },
190 { 43, 4, 5, 0x00b },
191 { 75, 4, 6, 0x00c },
192 { 3, 5, 1, 0x01a },
193 { 139, 5, 7, 0x01b },
194 { 267, 5, 8, 0x01c },
195 { 5, 6, 1, 0x03a },
196 { 39, 6, 2, 0x03b },
197 { 523, 6, 8, 0x03c },
198 { 1291, 6, 11, 0x03d },
199 { -5, 7, 1, 0x07c },
200 { 779, 7, 9, 0x07d },
201 { -31, 8, 4, 0x0fc },
202 { -11, 8, 2, 0x0fd },
203 { -15, 9, 2, 0x1fc },
204 { -7, 9, 1, 0x1fd },
205 { -32, 9, jbig2HuffmanLOW, 0x1fe },
206 { 3339, 9, 32, 0x1ff },
207 { 0, 0, jbig2HuffmanEOT, 0 }
210 static JBIG2HuffmanTable huffTableJ[] = {
211 { -2, 2, 2, 0x000 },
212 { 6, 2, 6, 0x001 },
213 { 0, 2, jbig2HuffmanOOB, 0x002 },
214 { -3, 5, 0, 0x018 },
215 { 2, 5, 0, 0x019 },
216 { 70, 5, 5, 0x01a },
217 { 3, 6, 0, 0x036 },
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 },
225 { -4, 7, 0, 0x07b },
226 { 4, 7, 0, 0x07c },
227 { 2118, 7, 11, 0x07d },
228 { -5, 8, 0, 0x0fc },
229 { 5, 8, 0, 0x0fd },
230 { -22, 8, jbig2HuffmanLOW, 0x0fe },
231 { 4166, 8, 32, 0x0ff },
232 { 0, 0, jbig2HuffmanEOT, 0 }
235 static JBIG2HuffmanTable huffTableK[] = {
236 { 1, 1, 0, 0x000 },
237 { 2, 2, 1, 0x002 },
238 { 4, 4, 0, 0x00c },
239 { 5, 4, 1, 0x00d },
240 { 7, 5, 1, 0x01c },
241 { 9, 5, 2, 0x01d },
242 { 13, 6, 2, 0x03c },
243 { 17, 7, 2, 0x07a },
244 { 21, 7, 3, 0x07b },
245 { 29, 7, 4, 0x07c },
246 { 45, 7, 5, 0x07d },
247 { 77, 7, 6, 0x07e },
248 { 141, 7, 32, 0x07f },
249 { 0, 0, jbig2HuffmanEOT, 0 }
252 static JBIG2HuffmanTable huffTableL[] = {
253 { 1, 1, 0, 0x000 },
254 { 2, 2, 0, 0x002 },
255 { 3, 3, 1, 0x006 },
256 { 5, 5, 0, 0x01c },
257 { 6, 5, 1, 0x01d },
258 { 8, 6, 1, 0x03c },
259 { 10, 7, 0, 0x07a },
260 { 11, 7, 1, 0x07b },
261 { 13, 7, 2, 0x07c },
262 { 17, 7, 3, 0x07d },
263 { 25, 7, 4, 0x07e },
264 { 41, 8, 5, 0x0fe },
265 { 73, 8, 32, 0x0ff },
266 { 0, 0, jbig2HuffmanEOT, 0 }
269 static JBIG2HuffmanTable huffTableM[] = {
270 { 1, 1, 0, 0x000 },
271 { 2, 3, 0, 0x004 },
272 { 7, 3, 3, 0x005 },
273 { 3, 4, 0, 0x00c },
274 { 5, 4, 1, 0x00d },
275 { 4, 5, 0, 0x01c },
276 { 15, 6, 1, 0x03a },
277 { 17, 6, 2, 0x03b },
278 { 21, 6, 3, 0x03c },
279 { 29, 6, 4, 0x03d },
280 { 45, 6, 5, 0x03e },
281 { 77, 7, 6, 0x07e },
282 { 141, 7, 32, 0x07f },
283 { 0, 0, jbig2HuffmanEOT, 0 }
286 static JBIG2HuffmanTable huffTableN[] = {
287 { 0, 1, 0, 0x000 },
288 { -2, 3, 0, 0x004 },
289 { -1, 3, 0, 0x005 },
290 { 1, 3, 0, 0x006 },
291 { 2, 3, 0, 0x007 },
292 { 0, 0, jbig2HuffmanEOT, 0 }
295 static JBIG2HuffmanTable huffTableO[] = {
296 { 0, 1, 0, 0x000 },
297 { -1, 3, 0, 0x004 },
298 { 1, 3, 0, 0x005 },
299 { -2, 4, 0, 0x00c },
300 { 2, 4, 0, 0x00d },
301 { -4, 5, 1, 0x01c },
302 { 3, 5, 1, 0x01d },
303 { -8, 6, 2, 0x03c },
304 { 5, 6, 2, 0x03d },
305 { -24, 7, 4, 0x07c },
306 { 9, 7, 4, 0x07d },
307 { -25, 7, jbig2HuffmanLOW, 0x07e },
308 { 25, 7, 32, 0x07f },
309 { 0, 0, jbig2HuffmanEOT, 0 }
312 //------------------------------------------------------------------------
313 // JBIG2HuffmanDecoder
314 //------------------------------------------------------------------------
316 class JBIG2HuffmanDecoder {
317 public:
319 JBIG2HuffmanDecoder();
320 ~JBIG2HuffmanDecoder();
321 void setStream(Stream *strA) { str = strA; }
323 void reset();
325 // Returns false for OOB, otherwise sets *<x> and returns true.
326 GBool decodeInt(int *x, JBIG2HuffmanTable *table);
328 Guint readBits(Guint n);
329 Guint readBit();
331 // Sort the table by prefix length and assign prefix values.
332 void buildTable(JBIG2HuffmanTable *table, Guint len);
334 private:
336 Stream *str;
337 Guint buf;
338 Guint bufLen;
341 JBIG2HuffmanDecoder::JBIG2HuffmanDecoder() {
342 str = NULL;
343 reset();
346 JBIG2HuffmanDecoder::~JBIG2HuffmanDecoder() {
349 void JBIG2HuffmanDecoder::reset() {
350 buf = 0;
351 bufLen = 0;
354 //~ optimize this
355 GBool JBIG2HuffmanDecoder::decodeInt(int *x, JBIG2HuffmanTable *table) {
356 Guint i, len, prefix;
358 i = 0;
359 len = 0;
360 prefix = 0;
361 while (table[i].rangeLen != jbig2HuffmanEOT) {
362 while (len < table[i].prefixLen) {
363 prefix = (prefix << 1) | readBit();
364 ++len;
366 if (prefix == table[i].prefix) {
367 if (table[i].rangeLen == jbig2HuffmanOOB) {
368 return gFalse;
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);
374 } else {
375 *x = table[i].val;
377 return gTrue;
379 ++i;
381 return gFalse;
384 Guint JBIG2HuffmanDecoder::readBits(Guint n) {
385 Guint x, mask, nLeft;
387 mask = (n == 32) ? 0xffffffff : ((1 << n) - 1);
388 if (bufLen >= n) {
389 x = (buf >> (bufLen - n)) & mask;
390 bufLen -= n;
391 } else {
392 x = buf & ((1 << bufLen) - 1);
393 nLeft = n - bufLen;
394 bufLen = 0;
395 while (nLeft >= 8) {
396 x = (x << 8) | (str->getChar() & 0xff);
397 nLeft -= 8;
399 if (nLeft > 0) {
400 buf = str->getChar();
401 bufLen = 8 - nLeft;
402 x = (x << nLeft) | ((buf >> bufLen) & ((1 << nLeft) - 1));
405 return x;
408 Guint JBIG2HuffmanDecoder::readBit() {
409 if (bufLen == 0) {
410 buf = str->getChar();
411 bufLen = 8;
413 --bufLen;
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) ;
428 if (j == len) {
429 break;
431 for (k = j + 1; k < len; ++k) {
432 if (table[k].prefixLen > 0 &&
433 table[k].prefixLen < table[j].prefixLen) {
434 j = k;
437 if (j != i) {
438 tab = table[j];
439 for (k = j; k > i; --k) {
440 table[k] = table[k - 1];
442 table[i] = tab;
445 table[i] = table[len];
447 // assign prefixes
448 if (table[0].rangeLen != jbig2HuffmanEOT) {
449 i = 0;
450 prefix = 0;
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 //------------------------------------------------------------------------
460 // JBIG2MMRDecoder
461 //------------------------------------------------------------------------
463 class JBIG2MMRDecoder {
464 public:
466 JBIG2MMRDecoder();
467 ~JBIG2MMRDecoder();
468 void setStream(Stream *strA) { str = strA; }
469 void reset();
470 int get2DCode();
471 int getBlackCode();
472 int getWhiteCode();
473 Guint get24Bits();
474 void skipTo(Guint length);
476 private:
478 Stream *str;
479 Guint buf;
480 Guint bufLen;
481 Guint nBytesRead;
484 JBIG2MMRDecoder::JBIG2MMRDecoder() {
485 str = NULL;
486 reset();
489 JBIG2MMRDecoder::~JBIG2MMRDecoder() {
492 void JBIG2MMRDecoder::reset() {
493 buf = 0;
494 bufLen = 0;
495 nBytesRead = 0;
498 int JBIG2MMRDecoder::get2DCode() {
499 const CCITTCode *p;
501 if (bufLen == 0) {
502 buf = str->getChar() & 0xff;
503 bufLen = 8;
504 ++nBytesRead;
505 p = &twoDimTab1[(buf >> 1) & 0x7f];
506 } else if (bufLen == 8) {
507 p = &twoDimTab1[(buf >> 1) & 0x7f];
508 } else {
509 p = &twoDimTab1[(buf << (7 - bufLen)) & 0x7f];
510 if (p->bits < 0 || p->bits > (int)bufLen) {
511 buf = (buf << 8) | (str->getChar() & 0xff);
512 bufLen += 8;
513 ++nBytesRead;
514 p = &twoDimTab1[(buf >> (bufLen - 7)) & 0x7f];
517 if (p->bits < 0) {
518 error(errSyntaxError, str->getPos(), "Bad two dim code in JBIG2 MMR stream");
519 return EOF;
521 bufLen -= p->bits;
522 return p->n;
525 int JBIG2MMRDecoder::getWhiteCode() {
526 const CCITTCode *p;
527 Guint code;
529 if (bufLen == 0) {
530 buf = str->getChar() & 0xff;
531 bufLen = 8;
532 ++nBytesRead;
534 while (1) {
535 if (bufLen >= 11 && ((buf >> (bufLen - 7)) & 0x7f) == 0) {
536 if (bufLen <= 12) {
537 code = buf << (12 - bufLen);
538 } else {
539 code = buf >> (bufLen - 12);
541 p = &whiteTab1[code & 0x1f];
542 } else {
543 if (bufLen <= 9) {
544 code = buf << (9 - bufLen);
545 } else {
546 code = buf >> (bufLen - 9);
548 p = &whiteTab2[code & 0x1ff];
550 if (p->bits > 0 && p->bits <= (int)bufLen) {
551 bufLen -= p->bits;
552 return p->n;
554 if (bufLen >= 12) {
555 break;
557 buf = (buf << 8) | (str->getChar() & 0xff);
558 bufLen += 8;
559 ++nBytesRead;
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
564 --bufLen;
565 return 1;
568 int JBIG2MMRDecoder::getBlackCode() {
569 const CCITTCode *p;
570 Guint code;
572 if (bufLen == 0) {
573 buf = str->getChar() & 0xff;
574 bufLen = 8;
575 ++nBytesRead;
577 while (1) {
578 if (bufLen >= 10 && ((buf >> (bufLen - 6)) & 0x3f) == 0) {
579 if (bufLen <= 13) {
580 code = buf << (13 - bufLen);
581 } else {
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) {
587 if (bufLen <= 12) {
588 code = buf << (12 - bufLen);
589 } else {
590 code = buf >> (bufLen - 12);
592 if (unlikely((code & 0xff) < 64)) {
593 break;
595 p = &blackTab2[(code & 0xff) - 64];
596 } else {
597 if (bufLen <= 6) {
598 code = buf << (6 - bufLen);
599 } else {
600 code = buf >> (bufLen - 6);
602 p = &blackTab3[code & 0x3f];
604 if (p->bits > 0 && p->bits <= (int)bufLen) {
605 bufLen -= p->bits;
606 return p->n;
608 if (bufLen >= 13) {
609 break;
611 buf = (buf << 8) | (str->getChar() & 0xff);
612 bufLen += 8;
613 ++nBytesRead;
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
618 --bufLen;
619 return 1;
622 Guint JBIG2MMRDecoder::get24Bits() {
623 while (bufLen < 24) {
624 buf = (buf << 8) | (str->getChar() & 0xff);
625 bufLen += 8;
626 ++nBytesRead;
628 return (buf >> (bufLen - 24)) & 0xffffff;
631 void JBIG2MMRDecoder::skipTo(Guint length) {
632 while (nBytesRead < length) {
633 str->getChar();
634 ++nBytesRead;
638 //------------------------------------------------------------------------
639 // JBIG2Segment
640 //------------------------------------------------------------------------
642 enum JBIG2SegmentType {
643 jbig2SegBitmap,
644 jbig2SegSymbolDict,
645 jbig2SegPatternDict,
646 jbig2SegCodeTable
649 class JBIG2Segment {
650 public:
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;
658 private:
660 Guint segNum;
663 //------------------------------------------------------------------------
664 // JBIG2Bitmap
665 //------------------------------------------------------------------------
667 struct JBIG2BitmapPtr {
668 Guchar *p;
669 int shift;
670 int x;
673 class JBIG2Bitmap: public JBIG2Segment {
674 public:
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);
682 void clearToZero();
683 void clearToOne();
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; }
702 private:
704 JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap);
706 int w, h, line;
707 Guchar *data;
710 JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, int wA, int hA):
711 JBIG2Segment(segNumA)
713 w = wA;
714 h = hA;
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");
719 data = NULL;
720 return;
722 // need to allocate one extra guard byte for use in combine()
723 data = (Guchar *)gmalloc_checkoverflow(h * line + 1);
724 if (data != NULL) {
725 data[h * line] = 0;
729 JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap):
730 JBIG2Segment(segNumA)
732 if (unlikely(bitmap == NULL)) {
733 error(errSyntaxError, -1, "NULL bitmap in JBIG2Bitmap");
734 w = h = line = 0;
735 data = NULL;
736 return;
739 w = bitmap->w;
740 h = bitmap->h;
741 line = bitmap->line;
743 if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) {
744 error(errSyntaxError, -1, "invalid width/height");
745 data = NULL;
746 return;
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);
751 data[h * line] = 0;
754 JBIG2Bitmap::~JBIG2Bitmap() {
755 gfree(data);
758 //~ optimize this
759 JBIG2Bitmap *JBIG2Bitmap::getSlice(Guint x, Guint y, Guint wA, Guint hA) {
760 JBIG2Bitmap *slice;
761 Guint xx, yy;
763 slice = new JBIG2Bitmap(0, wA, hA);
764 if (slice->isOk()) {
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);
773 } else {
774 delete slice;
775 slice = NULL;
777 return slice;
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");
783 gfree(data);
784 data = NULL;
785 return;
787 // need to allocate one extra guard byte for use in combine()
788 data = (Guchar *)grealloc(data, newH * line + 1);
789 if (pixel) {
790 memset(data + h * line, 0xff, (newH - h) * line);
791 } else {
792 memset(data + h * line, 0x00, (newH - h) * line);
794 h = newH;
795 data[h * line] = 0;
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) {
808 ptr->p = NULL;
809 ptr->shift = 0; // make gcc happy
810 ptr->x = 0; // make gcc happy
811 } else if (x < 0) {
812 ptr->p = &data[y * line];
813 ptr->shift = 7;
814 ptr->x = x;
815 } else {
816 ptr->p = &data[y * line + (x >> 3)];
817 ptr->shift = 7 - (x & 7);
818 ptr->x = x;
822 inline int JBIG2Bitmap::nextPixel(JBIG2BitmapPtr *ptr) {
823 int pix;
825 if (!ptr->p) {
826 pix = 0;
827 } else if (ptr->x < 0) {
828 ++ptr->x;
829 pix = 0;
830 } else {
831 pix = (*ptr->p >> ptr->shift) & 1;
832 if (++ptr->x == w) {
833 ptr->p = NULL;
834 } else if (ptr->shift == 0) {
835 ++ptr->p;
836 ptr->shift = 7;
837 } else {
838 --ptr->shift;
841 return pix;
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,
849 Guint combOp) {
850 int x0, x1, y0, y1, xx, yy;
851 Guchar *srcPtr, *destPtr;
852 Guint src0, src1, src, dest, s1, s2, m1, m2, m3;
853 GBool oneByte;
855 // check for the pathological case where y = -2^31
856 if (y < -0x7fffffff) {
857 return;
859 if (y < 0) {
860 y0 = -y;
861 } else {
862 y0 = 0;
864 if (y + bitmap->h > h) {
865 y1 = h - y;
866 } else {
867 y1 = bitmap->h;
869 if (y0 >= y1) {
870 return;
873 if (x >= 0) {
874 x0 = x & ~7;
875 } else {
876 x0 = 0;
878 x1 = x + bitmap->w;
879 if (x1 > w) {
880 x1 = w;
882 if (x0 >= x1) {
883 return;
886 s1 = x & 7;
887 s2 = 8 - s1;
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
897 if (oneByte) {
898 if (x >= 0) {
899 destPtr = data + (y + yy) * line + (x >> 3);
900 srcPtr = bitmap->data + yy * bitmap->line;
901 dest = *destPtr;
902 src1 = *srcPtr;
903 switch (combOp) {
904 case 0: // or
905 dest |= (src1 >> s1) & m2;
906 break;
907 case 1: // and
908 dest &= ((0xff00 | src1) >> s1) | m1;
909 break;
910 case 2: // xor
911 dest ^= (src1 >> s1) & m2;
912 break;
913 case 3: // xnor
914 dest ^= ((src1 ^ 0xff) >> s1) & m2;
915 break;
916 case 4: // replace
917 dest = (dest & ~m3) | ((src1 >> s1) & m3);
918 break;
920 *destPtr = dest;
921 } else {
922 destPtr = data + (y + yy) * line;
923 srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3);
924 dest = *destPtr;
925 src1 = *srcPtr;
926 switch (combOp) {
927 case 0: // or
928 dest |= src1 & m2;
929 break;
930 case 1: // and
931 dest &= src1 | m1;
932 break;
933 case 2: // xor
934 dest ^= src1 & m2;
935 break;
936 case 3: // xnor
937 dest ^= (src1 ^ 0xff) & m2;
938 break;
939 case 4: // replace
940 dest = (src1 & m2) | (dest & m1);
941 break;
943 *destPtr = dest;
946 // multiple bytes per line -- need to mask left side of left-most
947 // byte and right side of right-most byte
948 } else {
950 // left-most byte
951 if (x >= 0) {
952 destPtr = data + (y + yy) * line + (x >> 3);
953 srcPtr = bitmap->data + yy * bitmap->line;
954 src1 = *srcPtr++;
955 dest = *destPtr;
956 switch (combOp) {
957 case 0: // or
958 dest |= src1 >> s1;
959 break;
960 case 1: // and
961 dest &= (0xff00 | src1) >> s1;
962 break;
963 case 2: // xor
964 dest ^= src1 >> s1;
965 break;
966 case 3: // xnor
967 dest ^= (src1 ^ 0xff) >> s1;
968 break;
969 case 4: // replace
970 dest = (dest & (0xff << s2)) | (src1 >> s1);
971 break;
973 *destPtr++ = dest;
974 xx = x0 + 8;
975 } else {
976 destPtr = data + (y + yy) * line;
977 srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3);
978 src1 = *srcPtr++;
979 xx = x0;
982 // middle bytes
983 for (; xx < x1 - 8; xx += 8) {
984 dest = *destPtr;
985 src0 = src1;
986 src1 = *srcPtr++;
987 src = (((src0 << 8) | src1) >> s1) & 0xff;
988 switch (combOp) {
989 case 0: // or
990 dest |= src;
991 break;
992 case 1: // and
993 dest &= src;
994 break;
995 case 2: // xor
996 dest ^= src;
997 break;
998 case 3: // xnor
999 dest ^= src ^ 0xff;
1000 break;
1001 case 4: // replace
1002 dest = src;
1003 break;
1005 *destPtr++ = dest;
1008 // right-most byte
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
1013 dest = *destPtr;
1014 src0 = src1;
1015 src1 = *srcPtr++;
1016 src = (((src0 << 8) | src1) >> s1) & 0xff;
1017 switch (combOp) {
1018 case 0: // or
1019 dest |= src & m2;
1020 break;
1021 case 1: // and
1022 dest &= src | m1;
1023 break;
1024 case 2: // xor
1025 dest ^= src & m2;
1026 break;
1027 case 3: // xnor
1028 dest ^= (src ^ 0xff) & m2;
1029 break;
1030 case 4: // replace
1031 dest = (src & m2) | (dest & m1);
1032 break;
1034 *destPtr = dest;
1039 //------------------------------------------------------------------------
1040 // JBIG2SymbolDict
1041 //------------------------------------------------------------------------
1043 class JBIG2SymbolDict: public JBIG2Segment {
1044 public:
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; }
1062 private:
1064 Guint size;
1065 JBIG2Bitmap **bitmaps;
1066 JArithmeticDecoderStats *genericRegionStats;
1067 JArithmeticDecoderStats *refinementRegionStats;
1070 JBIG2SymbolDict::JBIG2SymbolDict(Guint segNumA, Guint sizeA):
1071 JBIG2Segment(segNumA)
1073 Guint i;
1075 size = sizeA;
1076 bitmaps = (JBIG2Bitmap **)gmallocn_checkoverflow(size, sizeof(JBIG2Bitmap *));
1077 if (!bitmaps) size = 0;
1078 for (i = 0; i < size; ++i) {
1079 bitmaps[i] = NULL;
1081 genericRegionStats = NULL;
1082 refinementRegionStats = NULL;
1085 JBIG2SymbolDict::~JBIG2SymbolDict() {
1086 Guint i;
1088 for (i = 0; i < size; ++i) {
1089 delete bitmaps[i];
1091 gfree(bitmaps);
1092 if (genericRegionStats) {
1093 delete genericRegionStats;
1095 if (refinementRegionStats) {
1096 delete refinementRegionStats;
1100 //------------------------------------------------------------------------
1101 // JBIG2PatternDict
1102 //------------------------------------------------------------------------
1104 class JBIG2PatternDict: public JBIG2Segment {
1105 public:
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; }
1114 private:
1116 Guint size;
1117 JBIG2Bitmap **bitmaps;
1120 JBIG2PatternDict::JBIG2PatternDict(Guint segNumA, Guint sizeA):
1121 JBIG2Segment(segNumA)
1123 bitmaps = (JBIG2Bitmap **)gmallocn_checkoverflow(sizeA, sizeof(JBIG2Bitmap *));
1124 if (bitmaps) {
1125 size = sizeA;
1126 } else {
1127 size = 0;
1128 error(errSyntaxError, -1, "JBIG2PatternDict: can't allocate bitmaps");
1132 JBIG2PatternDict::~JBIG2PatternDict() {
1133 Guint i;
1135 for (i = 0; i < size; ++i) {
1136 delete bitmaps[i];
1138 gfree(bitmaps);
1141 //------------------------------------------------------------------------
1142 // JBIG2CodeTable
1143 //------------------------------------------------------------------------
1145 class JBIG2CodeTable: public JBIG2Segment {
1146 public:
1148 JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA);
1149 virtual ~JBIG2CodeTable();
1150 virtual JBIG2SegmentType getType() { return jbig2SegCodeTable; }
1151 JBIG2HuffmanTable *getHuffTable() { return table; }
1153 private:
1155 JBIG2HuffmanTable *table;
1158 JBIG2CodeTable::JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA):
1159 JBIG2Segment(segNumA)
1161 table = tableA;
1164 JBIG2CodeTable::~JBIG2CodeTable() {
1165 gfree(table);
1168 //------------------------------------------------------------------------
1169 // JBIG2Stream
1170 //------------------------------------------------------------------------
1172 JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStreamA, Object *globalsStreamRefA):
1173 FilterStream(strA)
1175 pageBitmap = NULL;
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;
1204 curStr = NULL;
1205 dataPtr = dataEnd = NULL;
1208 JBIG2Stream::~JBIG2Stream() {
1209 close();
1210 globalsStream.free();
1211 delete arithDecoder;
1212 delete genericRegionStats;
1213 delete refinementRegionStats;
1214 delete iadhStats;
1215 delete iadwStats;
1216 delete iaexStats;
1217 delete iaaiStats;
1218 delete iadtStats;
1219 delete iaitStats;
1220 delete iafsStats;
1221 delete iadsStats;
1222 delete iardxStats;
1223 delete iardyStats;
1224 delete iardwStats;
1225 delete iardhStats;
1226 delete iariStats;
1227 delete iaidStats;
1228 delete huffDecoder;
1229 delete mmrDecoder;
1230 delete str;
1233 void JBIG2Stream::reset() {
1234 // read the globals stream
1235 globalSegments = new GooList();
1236 if (globalsStream.isStream()) {
1237 segments = globalSegments;
1238 curStr = globalsStream.getStream();
1239 curStr->reset();
1240 arithDecoder->setStream(curStr);
1241 huffDecoder->setStream(curStr);
1242 mmrDecoder->setStream(curStr);
1243 readSegments();
1244 curStr->close();
1247 // read the main stream
1248 segments = new GooList();
1249 curStr = str;
1250 curStr->reset();
1251 arithDecoder->setStream(curStr);
1252 huffDecoder->setStream(curStr);
1253 mmrDecoder->setStream(curStr);
1254 readSegments();
1256 if (pageBitmap) {
1257 dataPtr = pageBitmap->getDataPtr();
1258 dataEnd = dataPtr + pageBitmap->getDataSize();
1259 } else {
1260 dataPtr = dataEnd = NULL;
1264 void JBIG2Stream::close() {
1265 if (pageBitmap) {
1266 delete pageBitmap;
1267 pageBitmap = NULL;
1269 if (segments) {
1270 deleteGooList(segments, JBIG2Segment);
1271 segments = NULL;
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;
1285 return EOF;
1288 int JBIG2Stream::lookChar() {
1289 if (dataPtr && dataPtr < dataEnd) {
1290 return (*dataPtr ^ 0xff) & 0xff;
1292 return EOF;
1295 Goffset JBIG2Stream::getPos() {
1296 if (pageBitmap == NULL) {
1297 return 0;
1299 return dataPtr - pageBitmap->getDataPtr();
1302 int JBIG2Stream::getChars(int nChars, Guchar *buffer) {
1303 int n, i;
1305 if (nChars <= 0) {
1306 return 0;
1308 if (dataEnd - dataPtr < nChars) {
1309 n = (int)(dataEnd - dataPtr);
1310 } else {
1311 n = nChars;
1313 for (i = 0; i < n; ++i) {
1314 buffer[i] = *dataPtr++ ^ 0xff;
1316 return n;
1319 GooString *JBIG2Stream::getPSFilter(int psLevel, const char *indent) {
1320 return NULL;
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;
1330 Guint *refSegs;
1331 Goffset segDataPos;
1332 int c1, c2, c3;
1333 Guint i;
1335 while (readULong(&segNum)) {
1337 // segment header flags
1338 if (!readUByte(&segFlags)) {
1339 goto eofError1;
1341 segType = segFlags & 0x3f;
1343 // referred-to segment count and retention flags
1344 if (!readUByte(&refFlags)) {
1345 goto eofError1;
1347 nRefSegs = refFlags >> 5;
1348 if (nRefSegs == 7) {
1349 if ((c1 = curStr->getChar()) == EOF ||
1350 (c2 = curStr->getChar()) == EOF ||
1351 (c3 = curStr->getChar()) == EOF) {
1352 goto eofError1;
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) {
1358 goto eofError1;
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])) {
1368 goto eofError2;
1371 } else if (segNum <= 65536) {
1372 for (i = 0; i < nRefSegs; ++i) {
1373 if (!readUWord(&refSegs[i])) {
1374 goto eofError2;
1377 } else {
1378 for (i = 0; i < nRefSegs; ++i) {
1379 if (!readULong(&refSegs[i])) {
1380 goto eofError2;
1385 // segment page association
1386 if (segFlags & 0x40) {
1387 if (!readULong(&page)) {
1388 goto eofError2;
1390 } else {
1391 if (!readUByte(&page)) {
1392 goto eofError2;
1396 // segment data length
1397 if (!readULong(&segLength)) {
1398 goto eofError2;
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");
1408 goto syntaxError;
1411 // read the segment data
1412 switch (segType) {
1413 case 0:
1414 if (!readSymbolDictSeg(segNum, segLength, refSegs, nRefSegs)) {
1415 goto syntaxError;
1417 break;
1418 case 4:
1419 readTextRegionSeg(segNum, gFalse, gFalse, segLength, refSegs, nRefSegs);
1420 break;
1421 case 6:
1422 readTextRegionSeg(segNum, gTrue, gFalse, segLength, refSegs, nRefSegs);
1423 break;
1424 case 7:
1425 readTextRegionSeg(segNum, gTrue, gTrue, segLength, refSegs, nRefSegs);
1426 break;
1427 case 16:
1428 readPatternDictSeg(segNum, segLength);
1429 break;
1430 case 20:
1431 readHalftoneRegionSeg(segNum, gFalse, gFalse, segLength,
1432 refSegs, nRefSegs);
1433 break;
1434 case 22:
1435 readHalftoneRegionSeg(segNum, gTrue, gFalse, segLength,
1436 refSegs, nRefSegs);
1437 break;
1438 case 23:
1439 readHalftoneRegionSeg(segNum, gTrue, gTrue, segLength,
1440 refSegs, nRefSegs);
1441 break;
1442 case 36:
1443 readGenericRegionSeg(segNum, gFalse, gFalse, segLength);
1444 break;
1445 case 38:
1446 readGenericRegionSeg(segNum, gTrue, gFalse, segLength);
1447 break;
1448 case 39:
1449 readGenericRegionSeg(segNum, gTrue, gTrue, segLength);
1450 break;
1451 case 40:
1452 readGenericRefinementRegionSeg(segNum, gFalse, gFalse, segLength,
1453 refSegs, nRefSegs);
1454 break;
1455 case 42:
1456 readGenericRefinementRegionSeg(segNum, gTrue, gFalse, segLength,
1457 refSegs, nRefSegs);
1458 break;
1459 case 43:
1460 readGenericRefinementRegionSeg(segNum, gTrue, gTrue, segLength,
1461 refSegs, nRefSegs);
1462 break;
1463 case 48:
1464 readPageInfoSeg(segLength);
1465 break;
1466 case 50:
1467 readEndOfStripeSeg(segLength);
1468 break;
1469 case 52:
1470 readProfilesSeg(segLength);
1471 break;
1472 case 53:
1473 readCodeTableSeg(segNum, segLength);
1474 break;
1475 case 62:
1476 readExtensionSeg(segLength);
1477 break;
1478 default:
1479 error(errSyntaxError, curStr->getPos(), "Unknown segment type in JBIG2 stream");
1480 for (i = 0; i < segLength; ++i) {
1481 if ((c1 = curStr->getChar()) == EOF) {
1482 goto eofError2;
1485 break;
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
1511 int trash;
1512 for (Goffset i = segExtraBytes; i > 0; i--) {
1513 readByte(&trash);
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");
1527 gfree(refSegs);
1530 return;
1532 syntaxError:
1533 gfree(refSegs);
1534 return;
1536 eofError2:
1537 gfree(refSegs);
1538 eofError1:
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;
1547 JBIG2Segment *seg;
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;
1557 Guint *symWidths;
1558 Guint symHeight, symWidth, totalWidth, x, symID;
1559 int dh, dw, refAggNum, refDX, refDY, bmSize;
1560 GBool ex;
1561 int run, cnt, c;
1562 Guint i, j, k;
1563 Guchar *p;
1565 symWidths = NULL;
1567 // symbol dictionary flags
1568 if (!readUWord(&flags)) {
1569 goto eofError;
1571 sdTemplate = (flags >> 10) & 3;
1572 sdrTemplate = (flags >> 12) & 1;
1573 huff = flags & 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
1583 if (!huff) {
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])) {
1593 goto eofError;
1595 } else {
1596 if (!readByte(&sdATX[0]) ||
1597 !readByte(&sdATY[0])) {
1598 goto eofError;
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])) {
1609 goto eofError;
1613 // SDNUMEXSYMS and SDNUMNEWSYMS
1614 if (!readULong(&numExSyms) || !readULong(&numNewSyms)) {
1615 goto eofError;
1618 // get referenced segments: input symbol dictionaries and code tables
1619 codeTables = new GooList();
1620 numInputSyms = 0;
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
1624 // part of it
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");
1630 delete codeTables;
1631 goto eofError;
1633 numInputSyms += j;
1634 } else if (seg->getType() == jbig2SegCodeTable) {
1635 codeTables->append(seg);
1637 } else {
1638 delete codeTables;
1639 return gFalse;
1642 if (numInputSyms > UINT_MAX - numNewSyms) {
1643 error(errSyntaxError, curStr->getPos(), "Too many input symbols in JBIG2 symbol dictionary");
1644 delete codeTables;
1645 goto eofError;
1648 // compute symbol code length, per 6.5.8.2.3
1649 // symCodeLen = ceil( log2( numInputSyms + numNewSyms ) )
1650 i = numInputSyms + numNewSyms;
1651 if (i <= 1) {
1652 symCodeLen = huff ? 1 : 0;
1653 } else {
1654 --i;
1655 symCodeLen = 0;
1656 // i = floor((numSyms-1) / 2^symCodeLen)
1657 while (i > 0) {
1658 ++symCodeLen;
1659 i >>= 1;
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");
1668 delete codeTables;
1669 goto eofError;
1671 for (i = 0; i < numInputSyms + numNewSyms; ++i) {
1672 bitmaps[i] = NULL;
1674 k = 0;
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
1689 i = 0;
1690 if (huff) {
1691 if (huffDH == 0) {
1692 huffDHTable = huffTableD;
1693 } else if (huffDH == 1) {
1694 huffDHTable = huffTableE;
1695 } else {
1696 if (i >= (Guint)codeTables->getLength()) {
1697 goto codeTableError;
1699 huffDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1701 if (huffDW == 0) {
1702 huffDWTable = huffTableB;
1703 } else if (huffDW == 1) {
1704 huffDWTable = huffTableC;
1705 } else {
1706 if (i >= (Guint)codeTables->getLength()) {
1707 goto codeTableError;
1709 huffDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1711 if (huffBMSize == 0) {
1712 huffBMSizeTable = huffTableA;
1713 } else {
1714 if (i >= (Guint)codeTables->getLength()) {
1715 goto codeTableError;
1717 huffBMSizeTable =
1718 ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1720 if (huffAggInst == 0) {
1721 huffAggInstTable = huffTableA;
1722 } else {
1723 if (i >= (Guint)codeTables->getLength()) {
1724 goto codeTableError;
1726 huffAggInstTable =
1727 ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1730 delete codeTables;
1732 // set up the Huffman decoder
1733 if (huff) {
1734 huffDecoder->reset();
1736 // set up the arithmetic decoder
1737 } else {
1738 if (contextUsed && inputSymbolDict) {
1739 resetGenericStats(sdTemplate, inputSymbolDict->getGenericRegionStats());
1740 } else {
1741 resetGenericStats(sdTemplate, NULL);
1743 resetIntStats(symCodeLen);
1744 arithDecoder->start();
1747 // set up the arithmetic decoder for refinement/aggregation
1748 if (refAgg) {
1749 if (contextUsed && inputSymbolDict) {
1750 resetRefinementStats(sdrTemplate,
1751 inputSymbolDict->getRefinementRegionStats());
1752 } else {
1753 resetRefinementStats(sdrTemplate, NULL);
1757 // allocate symbol widths storage
1758 if (huff && !refAgg) {
1759 symWidths = (Guint *)gmallocn(numNewSyms, sizeof(Guint));
1762 symHeight = 0;
1763 i = 0;
1764 while (i < numNewSyms) {
1766 // read the height class delta height
1767 if (huff) {
1768 huffDecoder->decodeInt(&dh, huffDHTable);
1769 } else {
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");
1774 goto syntaxError;
1776 symHeight += dh;
1777 if (unlikely(symHeight > 0x40000000)) {
1778 error(errSyntaxError, curStr->getPos(), "Bad height value in JBIG2 symbol dictionary");
1779 goto syntaxError;
1781 symWidth = 0;
1782 totalWidth = 0;
1783 j = i;
1785 // read the symbols in this height class
1786 while (1) {
1788 // read the delta width
1789 if (huff) {
1790 if (!huffDecoder->decodeInt(&dw, huffDWTable)) {
1791 break;
1793 } else {
1794 if (!arithDecoder->decodeInt(&dw, iadwStats)) {
1795 break;
1798 if (dw < 0 && (Guint)-dw >= symWidth) {
1799 error(errSyntaxError, curStr->getPos(), "Bad delta-height value in JBIG2 symbol dictionary");
1800 goto syntaxError;
1802 symWidth += dw;
1803 if (i >= numNewSyms) {
1804 error(errSyntaxError, curStr->getPos(), "Too many symbols in JBIG2 symbol dictionary");
1805 goto syntaxError;
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) {
1815 if (huff) {
1816 if (!huffDecoder->decodeInt(&refAggNum, huffAggInstTable)) {
1817 break;
1819 } else {
1820 if (!arithDecoder->decodeInt(&refAggNum, iaaiStats)) {
1821 break;
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.
1827 if (0) {
1828 #else
1829 if (refAggNum == 1) {
1830 #endif
1831 if (huff) {
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();
1838 } else {
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");
1845 goto syntaxError;
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);
1850 goto syntaxError;
1852 bitmaps[numInputSyms + i] =
1853 readGenericRefinementRegion(symWidth, symHeight,
1854 sdrTemplate, gFalse,
1855 refBitmap, refDX, refDY,
1856 sdrATX, sdrATY);
1857 //~ do we need to use the bmSize value here (in Huffman mode)?
1858 } else {
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
1869 } else {
1870 bitmaps[numInputSyms + i] =
1871 readGenericBitmap(gFalse, symWidth, symHeight,
1872 sdTemplate, gFalse, gFalse, NULL,
1873 sdATX, sdATY, 0);
1876 ++i;
1879 // read the collective bitmap
1880 if (huff && !refAgg) {
1881 huffDecoder->decodeInt(&bmSize, huffBMSizeTable);
1882 huffDecoder->reset();
1883 if (bmSize == 0) {
1884 collBitmap = new JBIG2Bitmap(0, totalWidth, symHeight);
1885 bmSize = symHeight * ((totalWidth + 7) >> 3);
1886 p = collBitmap->getDataPtr();
1887 if (unlikely(p == NULL)) {
1888 delete collBitmap;
1889 goto syntaxError;
1891 for (k = 0; k < (Guint)bmSize; ++k) {
1892 if ((c = curStr->getChar()) == EOF) {
1893 break;
1895 *p++ = (Guchar)c;
1897 } else {
1898 collBitmap = readGenericBitmap(gTrue, totalWidth, symHeight,
1899 0, gFalse, gFalse, NULL, NULL, NULL,
1900 bmSize);
1902 if (likely(collBitmap != NULL)) {
1903 x = 0;
1904 for (; j < i; ++j) {
1905 bitmaps[numInputSyms + j] =
1906 collBitmap->getSlice(x, 0, symWidths[j], symHeight);
1907 x += symWidths[j];
1909 delete collBitmap;
1910 } else {
1911 error(errSyntaxError, curStr->getPos(), "collBitmap was null");
1912 goto syntaxError;
1917 // create the symbol dict object
1918 symbolDict = new JBIG2SymbolDict(segNum, numExSyms);
1919 if (!symbolDict->isOk()) {
1920 delete symbolDict;
1921 goto syntaxError;
1924 // exported symbol list
1925 i = j = 0;
1926 ex = gFalse;
1927 while (i < numInputSyms + numNewSyms) {
1928 if (huff) {
1929 huffDecoder->decodeInt(&run, huffTableA);
1930 } else {
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);
1937 delete symbolDict;
1938 goto syntaxError;
1940 if (ex) {
1941 for (cnt = 0; cnt < run; ++cnt) {
1942 symbolDict->setBitmap(j++, bitmaps[i++]->copy());
1944 } else {
1945 i += run;
1947 ex = !ex;
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);
1952 delete symbolDict;
1953 goto syntaxError;
1956 for (i = 0; i < numNewSyms; ++i) {
1957 delete bitmaps[numInputSyms + i];
1959 gfree(bitmaps);
1960 if (symWidths) {
1961 gfree(symWidths);
1964 // save the arithmetic decoder stats
1965 if (!huff && contextRetained) {
1966 symbolDict->setGenericRegionStats(genericRegionStats->copy());
1967 if (refAgg) {
1968 symbolDict->setRefinementRegionStats(refinementRegionStats->copy());
1972 // store the new symbol dict
1973 segments->append(symbolDict);
1975 return gTrue;
1977 codeTableError:
1978 error(errSyntaxError, curStr->getPos(), "Missing code table in JBIG2 symbol dictionary");
1979 delete codeTables;
1981 syntaxError:
1982 for (i = 0; i < numNewSyms; ++i) {
1983 if (bitmaps[numInputSyms + i]) {
1984 delete bitmaps[numInputSyms + i];
1987 gfree(bitmaps);
1988 if (symWidths) {
1989 gfree(symWidths);
1991 return gFalse;
1993 eofError:
1994 error(errSyntaxError, curStr->getPos(), "Unexpected EOF in JBIG2 stream");
1995 return gFalse;
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;
2007 JBIG2Segment *seg;
2008 GooList *codeTables;
2009 JBIG2SymbolDict *symbolDict;
2010 JBIG2Bitmap **syms;
2011 Guint w, h, x, y, segInfoFlags, extCombOp;
2012 Guint flags, huff, refine, logStrips, refCorner, transposed;
2013 Guint combOp, defPixel, templ;
2014 int sOffset;
2015 Guint huffFlags, huffFS, huffDS, huffDT;
2016 Guint huffRDW, huffRDH, huffRDX, huffRDY, huffRSize;
2017 Guint numInstances, numSyms, symCodeLen;
2018 int atx[2], aty[2];
2019 Guint i, k, kk;
2020 int j;
2022 // region segment info field
2023 if (!readULong(&w) || !readULong(&h) ||
2024 !readULong(&x) || !readULong(&y) ||
2025 !readUByte(&segInfoFlags)) {
2026 goto eofError;
2028 extCombOp = segInfoFlags & 7;
2030 // rest of the text region header
2031 if (!readUWord(&flags)) {
2032 goto eofError;
2034 huff = flags & 1;
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
2048 if (huff) {
2049 if (!readUWord(&huffFlags)) {
2050 goto eofError;
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])) {
2064 goto eofError;
2067 if (!readULong(&numInstances)) {
2068 goto eofError;
2071 // get symbol dictionaries and tables
2072 codeTables = new GooList();
2073 numSyms = 0;
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);
2081 } else {
2082 error(errSyntaxError, curStr->getPos(), "Invalid segment reference in JBIG2 text region");
2083 delete codeTables;
2084 return;
2087 i = numSyms;
2088 if (i <= 1) {
2089 symCodeLen = huff ? 1 : 0;
2090 } else {
2091 --i;
2092 symCodeLen = 0;
2093 // i = floor((numSyms-1) / 2^symCodeLen)
2094 while (i > 0) {
2095 ++symCodeLen;
2096 i >>= 1;
2100 // get the symbol bitmaps
2101 syms = (JBIG2Bitmap **)gmallocn(numSyms, sizeof(JBIG2Bitmap *));
2102 kk = 0;
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
2118 i = 0;
2119 if (huff) {
2120 if (huffFS == 0) {
2121 huffFSTable = huffTableF;
2122 } else if (huffFS == 1) {
2123 huffFSTable = huffTableG;
2124 } else {
2125 if (i >= (Guint)codeTables->getLength()) {
2126 goto codeTableError;
2128 huffFSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2130 if (huffDS == 0) {
2131 huffDSTable = huffTableH;
2132 } else if (huffDS == 1) {
2133 huffDSTable = huffTableI;
2134 } else if (huffDS == 2) {
2135 huffDSTable = huffTableJ;
2136 } else {
2137 if (i >= (Guint)codeTables->getLength()) {
2138 goto codeTableError;
2140 huffDSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2142 if (huffDT == 0) {
2143 huffDTTable = huffTableK;
2144 } else if (huffDT == 1) {
2145 huffDTTable = huffTableL;
2146 } else if (huffDT == 2) {
2147 huffDTTable = huffTableM;
2148 } else {
2149 if (i >= (Guint)codeTables->getLength()) {
2150 goto codeTableError;
2152 huffDTTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2154 if (huffRDW == 0) {
2155 huffRDWTable = huffTableN;
2156 } else if (huffRDW == 1) {
2157 huffRDWTable = huffTableO;
2158 } else {
2159 if (i >= (Guint)codeTables->getLength()) {
2160 goto codeTableError;
2162 huffRDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2164 if (huffRDH == 0) {
2165 huffRDHTable = huffTableN;
2166 } else if (huffRDH == 1) {
2167 huffRDHTable = huffTableO;
2168 } else {
2169 if (i >= (Guint)codeTables->getLength()) {
2170 goto codeTableError;
2172 huffRDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2174 if (huffRDX == 0) {
2175 huffRDXTable = huffTableN;
2176 } else if (huffRDX == 1) {
2177 huffRDXTable = huffTableO;
2178 } else {
2179 if (i >= (Guint)codeTables->getLength()) {
2180 goto codeTableError;
2182 huffRDXTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2184 if (huffRDY == 0) {
2185 huffRDYTable = huffTableN;
2186 } else if (huffRDY == 1) {
2187 huffRDYTable = huffTableO;
2188 } else {
2189 if (i >= (Guint)codeTables->getLength()) {
2190 goto codeTableError;
2192 huffRDYTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2194 if (huffRSize == 0) {
2195 huffRSizeTable = huffTableA;
2196 } else {
2197 if (i >= (Guint)codeTables->getLength()) {
2198 goto codeTableError;
2200 huffRSizeTable =
2201 ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2204 delete codeTables;
2206 // symbol ID Huffman decoding table
2207 if (huff) {
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;
2232 i = 0;
2233 while (i < numSyms) {
2234 huffDecoder->decodeInt(&j, runLengthTab);
2235 if (j > 0x200) {
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;
2243 ++i;
2245 } else {
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
2255 } else {
2256 symCodeTab = NULL;
2257 resetIntStats(symCodeLen);
2258 arithDecoder->start();
2260 if (refine) {
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,
2270 templ, atx, aty);
2272 gfree(syms);
2274 if (bitmap) {
2275 // combine the region bitmap into the page bitmap
2276 if (imm) {
2277 if (pageH == 0xffffffff && y + h > curPageH) {
2278 pageBitmap->expand(y + h, pageDefPixel);
2280 pageBitmap->combine(bitmap, x, y, extCombOp);
2281 delete bitmap;
2283 // store the region bitmap
2284 } else {
2285 bitmap->setSegNum(segNum);
2286 segments->append(bitmap);
2290 // clean up the Huffman decoder
2291 if (huff) {
2292 gfree(symCodeTab);
2295 return;
2297 codeTableError:
2298 error(errSyntaxError, curStr->getPos(), "Missing code table in JBIG2 text region");
2299 delete codeTables;
2300 gfree(syms);
2301 return;
2303 eofError:
2304 error(errSyntaxError, curStr->getPos(), "Unexpected EOF in JBIG2 stream");
2305 return;
2308 JBIG2Bitmap *JBIG2Stream::readTextRegion(GBool huff, GBool refine,
2309 int w, int h,
2310 Guint numInstances,
2311 Guint logStrips,
2312 int numSyms,
2313 JBIG2HuffmanTable *symCodeTab,
2314 Guint symCodeLen,
2315 JBIG2Bitmap **syms,
2316 Guint defPixel, Guint combOp,
2317 Guint transposed, Guint refCorner,
2318 int sOffset,
2319 JBIG2HuffmanTable *huffFSTable,
2320 JBIG2HuffmanTable *huffDSTable,
2321 JBIG2HuffmanTable *huffDTTable,
2322 JBIG2HuffmanTable *huffRDWTable,
2323 JBIG2HuffmanTable *huffRDHTable,
2324 JBIG2HuffmanTable *huffRDXTable,
2325 JBIG2HuffmanTable *huffRDYTable,
2326 JBIG2HuffmanTable *huffRSizeTable,
2327 Guint templ,
2328 int *atx, int *aty) {
2329 JBIG2Bitmap *bitmap;
2330 JBIG2Bitmap *symbolBitmap;
2331 Guint strips;
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()) {
2341 delete bitmap;
2342 return NULL;
2344 if (defPixel) {
2345 bitmap->clearToOne();
2346 } else {
2347 bitmap->clearToZero();
2350 // decode initial T value
2351 if (huff) {
2352 huffDecoder->decodeInt(&t, huffDTTable);
2353 } else {
2354 arithDecoder->decodeInt(&t, iadtStats);
2356 t *= -(int)strips;
2358 inst = 0;
2359 sFirst = 0;
2360 while (inst < numInstances) {
2362 // decode delta-T
2363 if (huff) {
2364 huffDecoder->decodeInt(&dt, huffDTTable);
2365 } else {
2366 arithDecoder->decodeInt(&dt, iadtStats);
2368 t += dt * strips;
2370 // first S value
2371 if (huff) {
2372 huffDecoder->decodeInt(&ds, huffFSTable);
2373 } else {
2374 arithDecoder->decodeInt(&ds, iafsStats);
2376 sFirst += ds;
2377 s = sFirst;
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) {
2384 // T value
2385 if (strips == 1) {
2386 dt = 0;
2387 } else if (huff) {
2388 dt = huffDecoder->readBits(logStrips);
2389 } else {
2390 arithDecoder->decodeInt(&dt, iaitStats);
2392 tt = t + dt;
2394 // symbol ID
2395 if (huff) {
2396 if (symCodeTab) {
2397 huffDecoder->decodeInt(&j, symCodeTab);
2398 symID = (Guint)j;
2399 } else {
2400 symID = huffDecoder->readBits(symCodeLen);
2402 } else {
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
2410 delete bitmap;
2411 return NULL;
2413 } else {
2415 // get the symbol bitmap
2416 symbolBitmap = NULL;
2417 if (refine) {
2418 if (huff) {
2419 ri = (int)huffDecoder->readBit();
2420 } else {
2421 arithDecoder->decodeInt(&ri, iariStats);
2423 } else {
2424 ri = 0;
2426 if (ri) {
2427 GBool decodeSuccess;
2428 if (huff) {
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();
2436 } else {
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;
2448 symbolBitmap =
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)?
2455 } else {
2456 symbolBitmap = syms[symID];
2459 if (symbolBitmap) {
2460 // combine the symbol bitmap into the region bitmap
2461 //~ something is wrong here - refCorner shouldn't degenerate into
2462 //~ two cases
2463 bw = symbolBitmap->getWidth() - 1;
2464 if (unlikely(symbolBitmap->getHeight() == 0)) {
2465 error(errSyntaxError, curStr->getPos(), "Invalid symbol bitmap height");
2466 if (ri) {
2467 delete symbolBitmap;
2469 delete bitmap;
2470 return NULL;
2472 bh = symbolBitmap->getHeight() - 1;
2473 if (transposed) {
2474 if (unlikely(s > 2 * bitmap->getHeight())) {
2475 error(errSyntaxError, curStr->getPos(), "Invalid JBIG2 combine");
2476 if (ri) {
2477 delete symbolBitmap;
2479 delete bitmap;
2480 return NULL;
2482 switch (refCorner) {
2483 case 0: // bottom left
2484 bitmap->combine(symbolBitmap, tt, s, combOp);
2485 break;
2486 case 1: // top left
2487 bitmap->combine(symbolBitmap, tt, s, combOp);
2488 break;
2489 case 2: // bottom right
2490 bitmap->combine(symbolBitmap, tt - bw, s, combOp);
2491 break;
2492 case 3: // top right
2493 bitmap->combine(symbolBitmap, tt - bw, s, combOp);
2494 break;
2496 s += bh;
2497 } else {
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");
2502 if (ri) {
2503 delete symbolBitmap;
2505 delete bitmap;
2506 return NULL;
2508 bitmap->combine(symbolBitmap, s, tt - bh, combOp);
2509 break;
2510 case 1: // top left
2511 if (unlikely(tt > 2 * bitmap->getHeight())) {
2512 error(errSyntaxError, curStr->getPos(), "Invalid JBIG2 combine");
2513 if (ri) {
2514 delete symbolBitmap;
2516 delete bitmap;
2517 return NULL;
2519 bitmap->combine(symbolBitmap, s, tt, combOp);
2520 break;
2521 case 2: // bottom right
2522 if (unlikely(tt - (int) bh > 2 * bitmap->getHeight())) {
2523 error(errSyntaxError, curStr->getPos(), "Invalid JBIG2 combine");
2524 if (ri) {
2525 delete symbolBitmap;
2527 delete bitmap;
2528 return NULL;
2530 bitmap->combine(symbolBitmap, s, tt - bh, combOp);
2531 break;
2532 case 3: // top right
2533 if (unlikely(tt > 2 * bitmap->getHeight())) {
2534 error(errSyntaxError, curStr->getPos(), "Invalid JBIG2 combine");
2535 if (ri) {
2536 delete symbolBitmap;
2538 delete bitmap;
2539 return NULL;
2541 bitmap->combine(symbolBitmap, s, tt, combOp);
2542 break;
2544 s += bw;
2546 if (ri) {
2547 delete symbolBitmap;
2549 } else {
2550 // NULL symbolBitmap only happens on error
2551 delete bitmap;
2552 return NULL;
2556 // next instance
2557 ++inst;
2559 // next S value
2560 if (huff) {
2561 if (!huffDecoder->decodeInt(&ds, huffDSTable)) {
2562 break;
2564 } else {
2565 if (!arithDecoder->decodeInt(&ds, iadsStats)) {
2566 break;
2569 s += sOffset + ds;
2573 return bitmap;
2576 void JBIG2Stream::readPatternDictSeg(Guint segNum, Guint length) {
2577 JBIG2PatternDict *patternDict;
2578 JBIG2Bitmap *bitmap;
2579 Guint flags, patternW, patternH, grayMax, templ, mmr;
2580 int atx[4], aty[4];
2581 Guint i, x;
2583 // halftone dictionary flags, pattern width and height, max gray value
2584 if (!readUByte(&flags) ||
2585 !readUByte(&patternW) ||
2586 !readUByte(&patternH) ||
2587 !readULong(&grayMax)) {
2588 goto eofError;
2590 templ = (flags >> 1) & 3;
2591 mmr = flags & 1;
2593 // set up the arithmetic decoder
2594 if (!mmr) {
2595 resetGenericStats(templ, NULL);
2596 arithDecoder->start();
2599 // read the bitmap
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);
2608 if (!bitmap)
2609 return;
2611 // create the pattern dict object
2612 patternDict = new JBIG2PatternDict(segNum, grayMax + 1);
2614 // split up the bitmap
2615 x = 0;
2616 for (i = 0; i <= grayMax && i < patternDict->getSize(); ++i) {
2617 patternDict->setBitmap(i, bitmap->getSlice(x, 0, patternW, patternH));
2618 x += patternW;
2621 // free memory
2622 delete bitmap;
2624 // store the new pattern dict
2625 segments->append(patternDict);
2627 return;
2629 eofError:
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;
2637 JBIG2Segment *seg;
2638 JBIG2PatternDict *patternDict;
2639 JBIG2Bitmap *skipBitmap;
2640 Guint *grayImg;
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;
2646 int atx[4], aty[4];
2647 int gridX, gridY, xx, yy, bit, j;
2648 Guint bpp, m, n, i;
2650 // region segment info field
2651 if (!readULong(&w) || !readULong(&h) ||
2652 !readULong(&x) || !readULong(&y) ||
2653 !readUByte(&segInfoFlags)) {
2654 goto eofError;
2656 extCombOp = segInfoFlags & 7;
2658 // rest of the halftone region header
2659 if (!readUByte(&flags)) {
2660 goto eofError;
2662 mmr = flags & 1;
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)) {
2669 goto eofError;
2671 if (w == 0 || h == 0 || w >= INT_MAX / h) {
2672 error(errSyntaxError, curStr->getPos(), "Bad bitmap size in JBIG2 halftone segment");
2673 return;
2675 if (gridH == 0 || gridW >= INT_MAX / gridH) {
2676 error(errSyntaxError, curStr->getPos(), "Bad grid size in JBIG2 halftone segment");
2677 return;
2680 // get pattern dictionary
2681 if (nRefSegs != 1) {
2682 error(errSyntaxError, curStr->getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
2683 return;
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");
2688 return;
2691 patternDict = (JBIG2PatternDict *)seg;
2692 i = patternDict->getSize();
2693 if (i <= 1) {
2694 bpp = 0;
2695 } else {
2696 --i;
2697 bpp = 0;
2698 // i = floor((size-1) / 2^bpp)
2699 while (i > 0) {
2700 ++bpp;
2701 i >>= 1;
2704 patternBitmap = patternDict->getBitmap(0);
2705 if (unlikely(patternBitmap == NULL)) {
2706 error(errSyntaxError, curStr->getPos(), "Bad pattern bitmap");
2707 return;
2709 patW = patternBitmap->getWidth();
2710 patH = patternBitmap->getHeight();
2712 // set up the arithmetic decoder
2713 if (!mmr) {
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();
2722 } else {
2723 bitmap->clearToZero();
2726 // compute the skip bitmap
2727 skipBitmap = NULL;
2728 if (enableSkip) {
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);
2753 i = 0;
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;
2758 ++i;
2761 delete grayBitmap;
2764 // decode the image
2765 i = 0;
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");
2774 return;
2776 bitmap->combine(patternBitmap, xx >> 8, yy >> 8, combOp);
2778 xx += stepX;
2779 yy -= stepY;
2780 ++i;
2784 gfree(grayImg);
2785 if (skipBitmap) {
2786 delete skipBitmap;
2789 // combine the region bitmap into the page bitmap
2790 if (imm) {
2791 if (pageH == 0xffffffff && y + h > curPageH) {
2792 pageBitmap->expand(y + h, pageDefPixel);
2794 pageBitmap->combine(bitmap, x, y, extCombOp);
2795 delete bitmap;
2797 // store the region bitmap
2798 } else {
2799 segments->append(bitmap);
2802 return;
2804 eofError:
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;
2813 int atx[4], aty[4];
2815 // region segment info field
2816 if (!readULong(&w) || !readULong(&h) ||
2817 !readULong(&x) || !readULong(&y) ||
2818 !readUByte(&segInfoFlags)) {
2819 goto eofError;
2821 extCombOp = segInfoFlags & 7;
2823 // rest of the generic region segment header
2824 if (!readUByte(&flags)) {
2825 goto eofError;
2827 mmr = flags & 1;
2828 templ = (flags >> 1) & 3;
2829 tpgdOn = (flags >> 3) & 1;
2831 // AT flags
2832 if (!mmr) {
2833 if (templ == 0) {
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])) {
2842 goto eofError;
2844 } else {
2845 if (!readByte(&atx[0]) ||
2846 !readByte(&aty[0])) {
2847 goto eofError;
2852 // set up the arithmetic decoder
2853 if (!mmr) {
2854 resetGenericStats(templ, NULL);
2855 arithDecoder->start();
2858 // read the bitmap
2859 bitmap = readGenericBitmap(mmr, w, h, templ, tpgdOn, gFalse,
2860 NULL, atx, aty, mmr ? length - 18 : 0);
2861 if (!bitmap)
2862 return;
2864 // combine the region bitmap into the page bitmap
2865 if (imm) {
2866 if (pageH == 0xffffffff && y + h > curPageH) {
2867 pageBitmap->expand(y + h, pageDefPixel);
2869 pageBitmap->combine(bitmap, x, y, extCombOp);
2870 delete bitmap;
2872 // store the region bitmap
2873 } else {
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);
2884 return;
2886 eofError:
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]) {
2893 if (a1 > w) {
2894 error(errSyntaxError, curStr->getPos(), "JBIG2 MMR row is wrong length ({0:d})", a1);
2895 a1 = w;
2897 if ((*a0i & 1) ^ blackPixels) {
2898 ++*a0i;
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]) {
2907 if (a1 > w) {
2908 error(errSyntaxError, curStr->getPos(), "JBIG2 MMR row is wrong length ({0:d})", a1);
2909 a1 = w;
2911 if ((*a0i & 1) ^ blackPixels) {
2912 ++*a0i;
2914 codingLine[*a0i] = a1;
2915 } else if (a1 < codingLine[*a0i]) {
2916 if (a1 < 0) {
2917 error(errSyntaxError, curStr->getPos(), "Invalid JBIG2 MMR code");
2918 a1 = 0;
2920 while (*a0i > 0 && a1 <= codingLine[*a0i - 1]) {
2921 --*a0i;
2923 codingLine[*a0i] = a1;
2927 JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h,
2928 int templ, GBool tpgdOn,
2929 GBool useSkip, JBIG2Bitmap *skip,
2930 int *atx, int *aty,
2931 int mmrDataLength) {
2932 JBIG2Bitmap *bitmap;
2933 GBool ltp;
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;
2942 Guchar mask;
2943 int x, y, x0, x1, a0i, b1i, blackPixels, pix, i;
2945 bitmap = new JBIG2Bitmap(0, w, h);
2946 if (!bitmap->isOk()) {
2947 delete bitmap;
2948 return NULL;
2950 bitmap->clearToZero();
2952 //----- MMR decode
2954 if (mmr) {
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
2960 w = -3;
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];
2977 refLine[i++] = w;
2978 refLine[i] = w;
2980 // decode a line
2981 codingLine[0] = 0;
2982 a0i = 0;
2983 b1i = 0;
2984 blackPixels = 0;
2985 // invariant:
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();
2993 switch (code1) {
2994 case twoDimPass:
2995 if (unlikely(b1i + 1 >= w + 2)) {
2996 break;
2998 mmrAddPixels(refLine[b1i + 1], blackPixels, codingLine, &a0i, w);
2999 if (refLine[b1i + 1] < w) {
3000 b1i += 2;
3002 break;
3003 case twoDimHoriz:
3004 code1 = code2 = 0;
3005 if (blackPixels) {
3006 do {
3007 code1 += code3 = mmrDecoder->getBlackCode();
3008 } while (code3 >= 64);
3009 do {
3010 code2 += code3 = mmrDecoder->getWhiteCode();
3011 } while (code3 >= 64);
3012 } else {
3013 do {
3014 code1 += code3 = mmrDecoder->getWhiteCode();
3015 } while (code3 >= 64);
3016 do {
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) {
3027 b1i += 2;
3029 break;
3030 case twoDimVertR3:
3031 if (unlikely(b1i >= w + 2)) {
3032 break;
3034 mmrAddPixels(refLine[b1i] + 3, blackPixels, codingLine, &a0i, w);
3035 blackPixels ^= 1;
3036 if (codingLine[a0i] < w) {
3037 ++b1i;
3038 while (likely(b1i < w + 2) && refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
3039 b1i += 2;
3042 break;
3043 case twoDimVertR2:
3044 if (unlikely(b1i >= w + 2)) {
3045 break;
3047 mmrAddPixels(refLine[b1i] + 2, blackPixels, codingLine, &a0i, w);
3048 blackPixels ^= 1;
3049 if (codingLine[a0i] < w) {
3050 ++b1i;
3051 while (likely(b1i < w + 2) && refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
3052 b1i += 2;
3055 break;
3056 case twoDimVertR1:
3057 if (unlikely(b1i >= w + 2)) {
3058 break;
3060 mmrAddPixels(refLine[b1i] + 1, blackPixels, codingLine, &a0i, w);
3061 blackPixels ^= 1;
3062 if (codingLine[a0i] < w) {
3063 ++b1i;
3064 while (likely(b1i < w + 2) && refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
3065 b1i += 2;
3068 break;
3069 case twoDimVert0:
3070 if (unlikely(b1i >= w + 2)) {
3071 break;
3073 mmrAddPixels(refLine[b1i], blackPixels, codingLine, &a0i, w);
3074 blackPixels ^= 1;
3075 if (codingLine[a0i] < w) {
3076 ++b1i;
3077 while (likely(b1i < w + 2) && refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
3078 b1i += 2;
3081 break;
3082 case twoDimVertL3:
3083 if (unlikely(b1i >= w + 2)) {
3084 break;
3086 mmrAddPixelsNeg(refLine[b1i] - 3, blackPixels, codingLine, &a0i, w);
3087 blackPixels ^= 1;
3088 if (codingLine[a0i] < w) {
3089 if (b1i > 0) {
3090 --b1i;
3091 } else {
3092 ++b1i;
3094 while (likely(b1i < w + 2) && refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
3095 b1i += 2;
3098 break;
3099 case twoDimVertL2:
3100 if (unlikely(b1i >= w + 2)) {
3101 break;
3103 mmrAddPixelsNeg(refLine[b1i] - 2, blackPixels, codingLine, &a0i, w);
3104 blackPixels ^= 1;
3105 if (codingLine[a0i] < w) {
3106 if (b1i > 0) {
3107 --b1i;
3108 } else {
3109 ++b1i;
3111 while (likely(b1i < w + 2) && refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
3112 b1i += 2;
3115 break;
3116 case twoDimVertL1:
3117 if (unlikely(b1i >= w + 2)) {
3118 break;
3120 mmrAddPixelsNeg(refLine[b1i] - 1, blackPixels, codingLine, &a0i, w);
3121 blackPixels ^= 1;
3122 if (codingLine[a0i] < w) {
3123 if (b1i > 0) {
3124 --b1i;
3125 } else {
3126 ++b1i;
3128 while (likely(b1i < w + 2) && refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
3129 b1i += 2;
3132 break;
3133 case EOF:
3134 mmrAddPixels(w, 0, codingLine, &a0i, w);
3135 break;
3136 default:
3137 error(errSyntaxError, curStr->getPos(), "Illegal code in JBIG2 MMR bitmap data");
3138 mmrAddPixels(w, 0, codingLine, &a0i, w);
3139 break;
3143 // convert the run lengths to a bitmap line
3144 i = 0;
3145 while (1) {
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) {
3150 break;
3152 i += 2;
3156 if (mmrDataLength >= 0) {
3157 mmrDecoder->skipTo(mmrDataLength);
3158 } else {
3159 if (mmrDecoder->get24Bits() != 0x001001) {
3160 error(errSyntaxError, curStr->getPos(), "Missing EOFB in JBIG2 MMR bitmap data");
3164 gfree(refLine);
3165 gfree(codingLine);
3167 //----- arithmetic decode
3169 } else {
3170 // set up the typical row context
3171 ltpCX = 0; // make gcc happy
3172 if (tpgdOn) {
3173 switch (templ) {
3174 case 0:
3175 ltpCX = 0x3953; // 001 11001 0101 0011
3176 break;
3177 case 1:
3178 ltpCX = 0x079a; // 0011 11001 101 0
3179 break;
3180 case 2:
3181 ltpCX = 0x0e3; // 001 1100 01 1
3182 break;
3183 case 3:
3184 ltpCX = 0x18a; // 01100 0101 1
3185 break;
3189 ltp = 0;
3190 cx = cx0 = cx1 = cx2 = 0; // make gcc happy
3191 for (y = 0; y < h; ++y) {
3193 // check for a "typical" (duplicate) row
3194 if (tpgdOn) {
3195 if (arithDecoder->decodeBit(ltpCX, genericRegionStats)) {
3196 ltp = !ltp;
3198 if (ltp) {
3199 if (y > 0) {
3200 bitmap->duplicateRow(y, y-1);
3202 continue;
3206 switch (templ) {
3207 case 0:
3209 // set up the context
3210 p2 = pp = bitmap->getDataPtr() + y * bitmap->getLineSize();
3211 buf2 = *p2++ << 8;
3212 if (y >= 1) {
3213 p1 = bitmap->getDataPtr() + (y - 1) * bitmap->getLineSize();
3214 buf1 = *p1++ << 8;
3215 if (y >= 2) {
3216 p0 = bitmap->getDataPtr() + (y - 2) * bitmap->getLineSize();
3217 buf0 = *p0++ << 8;
3218 } else {
3219 p0 = NULL;
3220 buf0 = 0;
3222 } else {
3223 p1 = p0 = NULL;
3224 buf1 = buf0 = 0;
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;
3235 } else {
3236 atP0 = NULL;
3237 atBuf0 = 0;
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;
3243 } else {
3244 atP1 = NULL;
3245 atBuf1 = 0;
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;
3251 } else {
3252 atP2 = NULL;
3253 atBuf2 = 0;
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;
3259 } else {
3260 atP3 = NULL;
3261 atBuf3 = 0;
3263 atShift3 = 15 - atx[3];
3265 // decode the row
3266 for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3267 if (x0 + 8 < w) {
3268 if (p0) {
3269 buf0 |= *p0++;
3271 if (p1) {
3272 buf1 |= *p1++;
3274 buf2 |= *p2++;
3275 if (atP0) {
3276 atBuf0 |= *atP0++;
3278 if (atP1) {
3279 atBuf1 |= *atP1++;
3281 if (atP2) {
3282 atBuf2 |= *atP2++;
3284 if (atP3) {
3285 atBuf3 |= *atP3++;
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))) {
3303 // decode the pixel
3304 if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
3305 *pp |= mask;
3306 buf2 |= 0x8000;
3307 if (aty[0] == 0) {
3308 atBuf0 |= 0x8000;
3310 if (aty[1] == 0) {
3311 atBuf1 |= 0x8000;
3313 if (aty[2] == 0) {
3314 atBuf2 |= 0x8000;
3316 if (aty[3] == 0) {
3317 atBuf3 |= 0x8000;
3322 // update the context
3323 buf0 <<= 1;
3324 buf1 <<= 1;
3325 buf2 <<= 1;
3326 atBuf0 <<= 1;
3327 atBuf1 <<= 1;
3328 atBuf2 <<= 1;
3329 atBuf3 <<= 1;
3333 } else {
3334 // decode the row
3335 for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3336 if (x0 + 8 < w) {
3337 if (p0) {
3338 buf0 |= *p0++;
3340 if (p1) {
3341 buf1 |= *p1++;
3343 buf2 |= *p2++;
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))) {
3360 // decode the pixel
3361 if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
3362 *pp |= mask;
3363 buf2 |= 0x8000;
3367 // update the context
3368 buf0 <<= 1;
3369 buf1 <<= 1;
3370 buf2 <<= 1;
3374 break;
3376 case 1:
3378 // set up the context
3379 p2 = pp = bitmap->getDataPtr() + y * bitmap->getLineSize();
3380 buf2 = *p2++ << 8;
3381 if (y >= 1) {
3382 p1 = bitmap->getDataPtr() + (y - 1) * bitmap->getLineSize();
3383 buf1 = *p1++ << 8;
3384 if (y >= 2) {
3385 p0 = bitmap->getDataPtr() + (y - 2) * bitmap->getLineSize();
3386 buf0 = *p0++ << 8;
3387 } else {
3388 p0 = NULL;
3389 buf0 = 0;
3391 } else {
3392 p1 = p0 = NULL;
3393 buf1 = buf0 = 0;
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;
3402 } else {
3403 atP0 = NULL;
3404 atBuf0 = 0;
3406 atShift0 = 15 - atx[0];
3408 // decode the row
3409 for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3410 if (x0 + 8 < w) {
3411 if (p0) {
3412 buf0 |= *p0++;
3414 if (p1) {
3415 buf1 |= *p1++;
3417 buf2 |= *p2++;
3418 if (atP0) {
3419 atBuf0 |= *atP0++;
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))) {
3434 // decode the pixel
3435 if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
3436 *pp |= mask;
3437 buf2 |= 0x8000;
3438 if (aty[0] == 0) {
3439 atBuf0 |= 0x8000;
3444 // update the context
3445 buf0 <<= 1;
3446 buf1 <<= 1;
3447 buf2 <<= 1;
3448 atBuf0 <<= 1;
3452 } else {
3453 // decode the row
3454 for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3455 if (x0 + 8 < w) {
3456 if (p0) {
3457 buf0 |= *p0++;
3459 if (p1) {
3460 buf1 |= *p1++;
3462 buf2 |= *p2++;
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))) {
3476 // decode the pixel
3477 if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
3478 *pp |= mask;
3479 buf2 |= 0x8000;
3483 // update the context
3484 buf0 <<= 1;
3485 buf1 <<= 1;
3486 buf2 <<= 1;
3490 break;
3492 case 2:
3494 // set up the context
3495 p2 = pp = bitmap->getDataPtr() + y * bitmap->getLineSize();
3496 buf2 = *p2++ << 8;
3497 if (y >= 1) {
3498 p1 = bitmap->getDataPtr() + (y - 1) * bitmap->getLineSize();
3499 buf1 = *p1++ << 8;
3500 if (y >= 2) {
3501 p0 = bitmap->getDataPtr() + (y - 2) * bitmap->getLineSize();
3502 buf0 = *p0++ << 8;
3503 } else {
3504 p0 = NULL;
3505 buf0 = 0;
3507 } else {
3508 p1 = p0 = NULL;
3509 buf1 = buf0 = 0;
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;
3518 } else {
3519 atP0 = NULL;
3520 atBuf0 = 0;
3522 atShift0 = 15 - atx[0];
3524 // decode the row
3525 for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3526 if (x0 + 8 < w) {
3527 if (p0) {
3528 buf0 |= *p0++;
3530 if (p1) {
3531 buf1 |= *p1++;
3533 buf2 |= *p2++;
3534 if (atP0) {
3535 atBuf0 |= *atP0++;
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))) {
3550 // decode the pixel
3551 if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
3552 *pp |= mask;
3553 buf2 |= 0x8000;
3554 if (aty[0] == 0) {
3555 atBuf0 |= 0x8000;
3560 // update the context
3561 buf0 <<= 1;
3562 buf1 <<= 1;
3563 buf2 <<= 1;
3564 atBuf0 <<= 1;
3568 } else {
3569 // decode the row
3570 for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3571 if (x0 + 8 < w) {
3572 if (p0) {
3573 buf0 |= *p0++;
3575 if (p1) {
3576 buf1 |= *p1++;
3578 buf2 |= *p2++;
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))) {
3592 // decode the pixel
3593 if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
3594 *pp |= mask;
3595 buf2 |= 0x8000;
3599 // update the context
3600 buf0 <<= 1;
3601 buf1 <<= 1;
3602 buf2 <<= 1;
3606 break;
3608 case 3:
3610 // set up the context
3611 p2 = pp = bitmap->getDataPtr() + y * bitmap->getLineSize();
3612 buf2 = *p2++ << 8;
3613 if (y >= 1) {
3614 p1 = bitmap->getDataPtr() + (y - 1) * bitmap->getLineSize();
3615 buf1 = *p1++ << 8;
3616 } else {
3617 p1 = NULL;
3618 buf1 = 0;
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;
3627 } else {
3628 atP0 = NULL;
3629 atBuf0 = 0;
3631 atShift0 = 15 - atx[0];
3633 // decode the row
3634 for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3635 if (x0 + 8 < w) {
3636 if (p1) {
3637 buf1 |= *p1++;
3639 buf2 |= *p2++;
3640 if (atP0) {
3641 atBuf0 |= *atP0++;
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))) {
3655 // decode the pixel
3656 if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
3657 *pp |= mask;
3658 buf2 |= 0x8000;
3659 if (aty[0] == 0) {
3660 atBuf0 |= 0x8000;
3665 // update the context
3666 buf1 <<= 1;
3667 buf2 <<= 1;
3668 atBuf0 <<= 1;
3672 } else {
3673 // decode the row
3674 for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3675 if (x0 + 8 < w) {
3676 if (p1) {
3677 buf1 |= *p1++;
3679 buf2 |= *p2++;
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))) {
3692 // decode the pixel
3693 if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
3694 *pp |= mask;
3695 buf2 |= 0x8000;
3699 // update the context
3700 buf1 <<= 1;
3701 buf2 <<= 1;
3705 break;
3710 return bitmap;
3713 void JBIG2Stream::readGenericRefinementRegionSeg(Guint segNum, GBool imm,
3714 GBool lossless, Guint length,
3715 Guint *refSegs,
3716 Guint nRefSegs) {
3717 JBIG2Bitmap *bitmap, *refBitmap;
3718 Guint w, h, x, y, segInfoFlags, extCombOp;
3719 Guint flags, templ, tpgrOn;
3720 int atx[2], aty[2];
3721 JBIG2Segment *seg;
3723 // region segment info field
3724 if (!readULong(&w) || !readULong(&h) ||
3725 !readULong(&x) || !readULong(&y) ||
3726 !readUByte(&segInfoFlags)) {
3727 goto eofError;
3729 extCombOp = segInfoFlags & 7;
3731 // rest of the generic refinement region segment header
3732 if (!readUByte(&flags)) {
3733 goto eofError;
3735 templ = flags & 1;
3736 tpgrOn = (flags >> 1) & 1;
3738 // AT flags
3739 if (!templ) {
3740 if (!readByte(&atx[0]) || !readByte(&aty[0]) ||
3741 !readByte(&atx[1]) || !readByte(&aty[1])) {
3742 goto eofError;
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
3754 if (nRefSegs > 1) {
3755 error(errSyntaxError, curStr->getPos(), "Bad reference in JBIG2 generic refinement segment");
3756 return;
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");
3762 return;
3764 refBitmap = (JBIG2Bitmap *)seg;
3765 } else {
3766 refBitmap = pageBitmap->getSlice(x, y, w, h);
3769 // set up the arithmetic decoder
3770 resetRefinementStats(templ, NULL);
3771 arithDecoder->start();
3773 // read
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);
3780 delete bitmap;
3782 // store the region bitmap
3783 } else {
3784 if (bitmap) {
3785 bitmap->setSegNum(segNum);
3786 segments->append(bitmap);
3787 } else {
3788 error(errSyntaxError, curStr->getPos(), "readGenericRefinementRegionSeg with null bitmap");
3792 // delete the referenced bitmap
3793 if (nRefSegs == 1) {
3794 discardSegment(refSegs[0]);
3795 } else {
3796 delete refBitmap;
3799 return;
3801 eofError:
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;
3811 GBool ltp;
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};
3823 int x, y, pix;
3825 bitmap = new JBIG2Bitmap(0, w, h);
3826 if (!bitmap->isOk())
3828 delete bitmap;
3829 return NULL;
3831 bitmap->clearToZero();
3833 // set up the typical row context
3834 if (templ) {
3835 ltpCX = 0x008;
3836 } else {
3837 ltpCX = 0x0010;
3840 ltp = 0;
3841 for (y = 0; y < h; ++y) {
3843 if (templ) {
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
3858 if (tpgrOn) {
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);
3871 } else {
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;
3884 if (tpgrOn) {
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)) {
3892 ltp = !ltp;
3894 if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) {
3895 bitmap->clearPixel(x, y);
3896 continue;
3897 } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) {
3898 bitmap->setPixel(x, y);
3899 continue;
3903 // build the context
3904 cx = (cx0 << 7) | (bitmap->nextPixel(&cxPtr1) << 6) |
3905 (refBitmap->nextPixel(&cxPtr2) << 5) |
3906 (cx3 << 2) | cx4;
3908 // decode the pixel
3909 if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) {
3910 bitmap->setPixel(x, y);
3914 } else {
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
3933 if (tpgrOn) {
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);
3946 } else {
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;
3960 if (tpgrOn) {
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)) {
3968 ltp = !ltp;
3970 if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) {
3971 bitmap->clearPixel(x, y);
3972 continue;
3973 } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) {
3974 bitmap->setPixel(x, y);
3975 continue;
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);
3985 // decode the pixel
3986 if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) {
3987 bitmap->setPixel(x, y);
3993 return bitmap;
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)) {
4002 goto eofError;
4004 pageDefPixel = (flags >> 2) & 1;
4005 defCombOp = (flags >> 3) & 3;
4007 // allocate the page bitmap
4008 if (pageH == 0xffffffff) {
4009 curPageH = striping & 0x7fff;
4010 } else {
4011 curPageH = pageH;
4013 pageBitmap = new JBIG2Bitmap(0, pageW, curPageH);
4015 if (!pageBitmap->isOk()) {
4016 delete pageBitmap;
4017 pageBitmap = NULL;
4018 return;
4021 // default pixel value
4022 if (pageDefPixel) {
4023 pageBitmap->clearToOne();
4024 } else {
4025 pageBitmap->clearToZero();
4028 return;
4030 eofError:
4031 error(errSyntaxError, curStr->getPos(), "Unexpected EOF in JBIG2 stream");
4034 void JBIG2Stream::readEndOfStripeSeg(Guint length) {
4035 Guint i;
4037 // skip the segment
4038 for (i = 0; i < length; ++i) {
4039 if (curStr->getChar() == EOF) {
4040 break;
4045 void JBIG2Stream::readProfilesSeg(Guint length) {
4046 Guint i;
4048 // skip the segment
4049 for (i = 0; i < length; ++i) {
4050 if (curStr->getChar() == EOF) {
4051 break;
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)) {
4063 goto eofError;
4065 oob = flags & 1;
4066 prefixBits = ((flags >> 1) & 7) + 1;
4067 rangeBits = ((flags >> 4) & 7) + 1;
4069 huffDecoder->reset();
4070 huffTabSize = 8;
4071 huffTab = (JBIG2HuffmanTable *)
4072 gmallocn(huffTabSize, sizeof(JBIG2HuffmanTable));
4073 i = 0;
4074 val = lowVal;
4075 while (val < highVal) {
4076 if (i == huffTabSize) {
4077 huffTabSize *= 2;
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;
4085 ++i;
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;
4095 ++i;
4096 huffTab[i].val = highVal;
4097 huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
4098 huffTab[i].rangeLen = 32;
4099 ++i;
4100 if (oob) {
4101 huffTab[i].val = 0;
4102 huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
4103 huffTab[i].rangeLen = jbig2HuffmanOOB;
4104 ++i;
4106 huffTab[i].val = 0;
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));
4114 return;
4116 eofError:
4117 error(errSyntaxError, curStr->getPos(), "Unexpected EOF in JBIG2 stream");
4120 void JBIG2Stream::readExtensionSeg(Guint length) {
4121 Guint i;
4123 // skip the segment
4124 for (i = 0; i < length; ++i) {
4125 if (curStr->getChar() == EOF) {
4126 break;
4131 JBIG2Segment *JBIG2Stream::findSegment(Guint segNum) {
4132 JBIG2Segment *seg;
4133 int i;
4135 for (i = 0; i < globalSegments->getLength(); ++i) {
4136 seg = (JBIG2Segment *)globalSegments->get(i);
4137 if (seg->getSegNum() == segNum) {
4138 return seg;
4141 for (i = 0; i < segments->getLength(); ++i) {
4142 seg = (JBIG2Segment *)segments->get(i);
4143 if (seg->getSegNum() == segNum) {
4144 return seg;
4147 return NULL;
4150 void JBIG2Stream::discardSegment(Guint segNum) {
4151 JBIG2Segment *seg;
4152 int i;
4154 for (i = 0; i < globalSegments->getLength(); ++i) {
4155 seg = (JBIG2Segment *)globalSegments->get(i);
4156 if (seg->getSegNum() == segNum) {
4157 globalSegments->del(i);
4158 return;
4161 for (i = 0; i < segments->getLength(); ++i) {
4162 seg = (JBIG2Segment *)segments->get(i);
4163 if (seg->getSegNum() == segNum) {
4164 segments->del(i);
4165 return;
4170 void JBIG2Stream::resetGenericStats(Guint templ,
4171 JArithmeticDecoderStats *prevStats) {
4172 int size;
4174 size = contextSize[templ];
4175 if (prevStats && prevStats->getContextSize() == size) {
4176 if (genericRegionStats->getContextSize() == size) {
4177 genericRegionStats->copyFrom(prevStats);
4178 } else {
4179 delete genericRegionStats;
4180 genericRegionStats = prevStats->copy();
4182 } else {
4183 if (genericRegionStats->getContextSize() == size) {
4184 genericRegionStats->reset();
4185 } else {
4186 delete genericRegionStats;
4187 genericRegionStats = new JArithmeticDecoderStats(1 << size);
4192 void JBIG2Stream::resetRefinementStats(Guint templ,
4193 JArithmeticDecoderStats *prevStats) {
4194 int size;
4196 size = refContextSize[templ];
4197 if (prevStats && prevStats->getContextSize() == size) {
4198 if (refinementRegionStats->getContextSize() == size) {
4199 refinementRegionStats->copyFrom(prevStats);
4200 } else {
4201 delete refinementRegionStats;
4202 refinementRegionStats = prevStats->copy();
4204 } else {
4205 if (refinementRegionStats->getContextSize() == size) {
4206 refinementRegionStats->reset();
4207 } else {
4208 delete refinementRegionStats;
4209 refinementRegionStats = new JArithmeticDecoderStats(1 << size);
4214 void JBIG2Stream::resetIntStats(int symCodeLen) {
4215 iadhStats->reset();
4216 iadwStats->reset();
4217 iaexStats->reset();
4218 iaaiStats->reset();
4219 iadtStats->reset();
4220 iaitStats->reset();
4221 iafsStats->reset();
4222 iadsStats->reset();
4223 iardxStats->reset();
4224 iardyStats->reset();
4225 iardwStats->reset();
4226 iardhStats->reset();
4227 iariStats->reset();
4228 if (iaidStats->getContextSize() == 1 << (symCodeLen + 1)) {
4229 iaidStats->reset();
4230 } else {
4231 delete iaidStats;
4232 iaidStats = new JArithmeticDecoderStats(1 << (symCodeLen + 1));
4236 GBool JBIG2Stream::readUByte(Guint *x) {
4237 int c0;
4239 if ((c0 = curStr->getChar()) == EOF) {
4240 return gFalse;
4242 *x = (Guint)c0;
4243 return gTrue;
4246 GBool JBIG2Stream::readByte(int *x) {
4247 int c0;
4249 if ((c0 = curStr->getChar()) == EOF) {
4250 return gFalse;
4252 *x = c0;
4253 if (c0 & 0x80) {
4254 *x |= -1 - 0xff;
4256 return gTrue;
4259 GBool JBIG2Stream::readUWord(Guint *x) {
4260 int c0, c1;
4262 if ((c0 = curStr->getChar()) == EOF ||
4263 (c1 = curStr->getChar()) == EOF) {
4264 return gFalse;
4266 *x = (Guint)((c0 << 8) | c1);
4267 return gTrue;
4270 GBool JBIG2Stream::readULong(Guint *x) {
4271 int c0, c1, c2, c3;
4273 if ((c0 = curStr->getChar()) == EOF ||
4274 (c1 = curStr->getChar()) == EOF ||
4275 (c2 = curStr->getChar()) == EOF ||
4276 (c3 = curStr->getChar()) == EOF) {
4277 return gFalse;
4279 *x = (Guint)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
4280 return gTrue;
4283 GBool JBIG2Stream::readLong(int *x) {
4284 int c0, c1, c2, c3;
4286 if ((c0 = curStr->getChar()) == EOF ||
4287 (c1 = curStr->getChar()) == EOF ||
4288 (c2 = curStr->getChar()) == EOF ||
4289 (c3 = curStr->getChar()) == EOF) {
4290 return gFalse;
4292 *x = ((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
4293 if (c0 & 0x80) {
4294 *x |= -1 - (int)0xffffffff;
4296 return gTrue;