"Fossies" - the Fresh Open Source Software Archive 
Member "xpdf-4.04/xpdf/JBIG2Stream.cc" (18 Apr 2022, 109724 Bytes) of package /linux/misc/xpdf-4.04.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "JBIG2Stream.cc" see the
Fossies "Dox" file reference documentation and the latest
Fossies "Diffs" side-by-side code changes report:
4.03_vs_4.04.
1 //========================================================================
2 //
3 // JBIG2Stream.cc
4 //
5 // Copyright 2002-2003 Glyph & Cog, LLC
6 //
7 //========================================================================
8
9 #include <aconf.h>
10
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
13 #endif
14
15 #include <stdlib.h>
16 #include <limits.h>
17 #include "gmempp.h"
18 #include "GList.h"
19 #include "Error.h"
20 #include "JArithmeticDecoder.h"
21 #include "JBIG2Stream.h"
22
23 //~ share these tables
24 #include "Stream-CCITT.h"
25
26 //------------------------------------------------------------------------
27
28 static int contextSize[4] = { 16, 13, 10, 10 };
29 static int refContextSize[2] = { 13, 10 };
30
31 //------------------------------------------------------------------------
32 // JBIG2HuffmanTable
33 //------------------------------------------------------------------------
34
35 #define jbig2HuffmanLOW 0xfffffffd
36 #define jbig2HuffmanOOB 0xfffffffe
37 #define jbig2HuffmanEOT 0xffffffff
38
39 struct JBIG2HuffmanTable {
40 int val;
41 Guint prefixLen;
42 Guint rangeLen; // can also be LOW, OOB, or EOT
43 Guint prefix;
44 };
45
46 JBIG2HuffmanTable huffTableA[] = {
47 { 0, 1, 4, 0x000 },
48 { 16, 2, 8, 0x002 },
49 { 272, 3, 16, 0x006 },
50 { 65808, 3, 32, 0x007 },
51 { 0, 0, jbig2HuffmanEOT, 0 }
52 };
53
54 JBIG2HuffmanTable huffTableB[] = {
55 { 0, 1, 0, 0x000 },
56 { 1, 2, 0, 0x002 },
57 { 2, 3, 0, 0x006 },
58 { 3, 4, 3, 0x00e },
59 { 11, 5, 6, 0x01e },
60 { 75, 6, 32, 0x03e },
61 { 0, 6, jbig2HuffmanOOB, 0x03f },
62 { 0, 0, jbig2HuffmanEOT, 0 }
63 };
64
65 JBIG2HuffmanTable huffTableC[] = {
66 { 0, 1, 0, 0x000 },
67 { 1, 2, 0, 0x002 },
68 { 2, 3, 0, 0x006 },
69 { 3, 4, 3, 0x00e },
70 { 11, 5, 6, 0x01e },
71 { 0, 6, jbig2HuffmanOOB, 0x03e },
72 { 75, 7, 32, 0x0fe },
73 { -256, 8, 8, 0x0fe },
74 { -257, 8, jbig2HuffmanLOW, 0x0ff },
75 { 0, 0, jbig2HuffmanEOT, 0 }
76 };
77
78 JBIG2HuffmanTable huffTableD[] = {
79 { 1, 1, 0, 0x000 },
80 { 2, 2, 0, 0x002 },
81 { 3, 3, 0, 0x006 },
82 { 4, 4, 3, 0x00e },
83 { 12, 5, 6, 0x01e },
84 { 76, 5, 32, 0x01f },
85 { 0, 0, jbig2HuffmanEOT, 0 }
86 };
87
88 JBIG2HuffmanTable huffTableE[] = {
89 { 1, 1, 0, 0x000 },
90 { 2, 2, 0, 0x002 },
91 { 3, 3, 0, 0x006 },
92 { 4, 4, 3, 0x00e },
93 { 12, 5, 6, 0x01e },
94 { 76, 6, 32, 0x03e },
95 { -255, 7, 8, 0x07e },
96 { -256, 7, jbig2HuffmanLOW, 0x07f },
97 { 0, 0, jbig2HuffmanEOT, 0 }
98 };
99
100 JBIG2HuffmanTable huffTableF[] = {
101 { 0, 2, 7, 0x000 },
102 { 128, 3, 7, 0x002 },
103 { 256, 3, 8, 0x003 },
104 { -1024, 4, 9, 0x008 },
105 { -512, 4, 8, 0x009 },
106 { -256, 4, 7, 0x00a },
107 { -32, 4, 5, 0x00b },
108 { 512, 4, 9, 0x00c },
109 { 1024, 4, 10, 0x00d },
110 { -2048, 5, 10, 0x01c },
111 { -128, 5, 6, 0x01d },
112 { -64, 5, 5, 0x01e },
113 { -2049, 6, jbig2HuffmanLOW, 0x03e },
114 { 2048, 6, 32, 0x03f },
115 { 0, 0, jbig2HuffmanEOT, 0 }
116 };
117
118 JBIG2HuffmanTable huffTableG[] = {
119 { -512, 3, 8, 0x000 },
120 { 256, 3, 8, 0x001 },
121 { 512, 3, 9, 0x002 },
122 { 1024, 3, 10, 0x003 },
123 { -1024, 4, 9, 0x008 },
124 { -256, 4, 7, 0x009 },
125 { -32, 4, 5, 0x00a },
126 { 0, 4, 5, 0x00b },
127 { 128, 4, 7, 0x00c },
128 { -128, 5, 6, 0x01a },
129 { -64, 5, 5, 0x01b },
130 { 32, 5, 5, 0x01c },
131 { 64, 5, 6, 0x01d },
132 { -1025, 5, jbig2HuffmanLOW, 0x01e },
133 { 2048, 5, 32, 0x01f },
134 { 0, 0, jbig2HuffmanEOT, 0 }
135 };
136
137 JBIG2HuffmanTable huffTableH[] = {
138 { 0, 2, 1, 0x000 },
139 { 0, 2, jbig2HuffmanOOB, 0x001 },
140 { 4, 3, 4, 0x004 },
141 { -1, 4, 0, 0x00a },
142 { 22, 4, 4, 0x00b },
143 { 38, 4, 5, 0x00c },
144 { 2, 5, 0, 0x01a },
145 { 70, 5, 6, 0x01b },
146 { 134, 5, 7, 0x01c },
147 { 3, 6, 0, 0x03a },
148 { 20, 6, 1, 0x03b },
149 { 262, 6, 7, 0x03c },
150 { 646, 6, 10, 0x03d },
151 { -2, 7, 0, 0x07c },
152 { 390, 7, 8, 0x07d },
153 { -15, 8, 3, 0x0fc },
154 { -5, 8, 1, 0x0fd },
155 { -7, 9, 1, 0x1fc },
156 { -3, 9, 0, 0x1fd },
157 { -16, 9, jbig2HuffmanLOW, 0x1fe },
158 { 1670, 9, 32, 0x1ff },
159 { 0, 0, jbig2HuffmanEOT, 0 }
160 };
161
162 JBIG2HuffmanTable huffTableI[] = {
163 { 0, 2, jbig2HuffmanOOB, 0x000 },
164 { -1, 3, 1, 0x002 },
165 { 1, 3, 1, 0x003 },
166 { 7, 3, 5, 0x004 },
167 { -3, 4, 1, 0x00a },
168 { 43, 4, 5, 0x00b },
169 { 75, 4, 6, 0x00c },
170 { 3, 5, 1, 0x01a },
171 { 139, 5, 7, 0x01b },
172 { 267, 5, 8, 0x01c },
173 { 5, 6, 1, 0x03a },
174 { 39, 6, 2, 0x03b },
175 { 523, 6, 8, 0x03c },
176 { 1291, 6, 11, 0x03d },
177 { -5, 7, 1, 0x07c },
178 { 779, 7, 9, 0x07d },
179 { -31, 8, 4, 0x0fc },
180 { -11, 8, 2, 0x0fd },
181 { -15, 9, 2, 0x1fc },
182 { -7, 9, 1, 0x1fd },
183 { -32, 9, jbig2HuffmanLOW, 0x1fe },
184 { 3339, 9, 32, 0x1ff },
185 { 0, 0, jbig2HuffmanEOT, 0 }
186 };
187
188 JBIG2HuffmanTable huffTableJ[] = {
189 { -2, 2, 2, 0x000 },
190 { 6, 2, 6, 0x001 },
191 { 0, 2, jbig2HuffmanOOB, 0x002 },
192 { -3, 5, 0, 0x018 },
193 { 2, 5, 0, 0x019 },
194 { 70, 5, 5, 0x01a },
195 { 3, 6, 0, 0x036 },
196 { 102, 6, 5, 0x037 },
197 { 134, 6, 6, 0x038 },
198 { 198, 6, 7, 0x039 },
199 { 326, 6, 8, 0x03a },
200 { 582, 6, 9, 0x03b },
201 { 1094, 6, 10, 0x03c },
202 { -21, 7, 4, 0x07a },
203 { -4, 7, 0, 0x07b },
204 { 4, 7, 0, 0x07c },
205 { 2118, 7, 11, 0x07d },
206 { -5, 8, 0, 0x0fc },
207 { 5, 8, 0, 0x0fd },
208 { -22, 8, jbig2HuffmanLOW, 0x0fe },
209 { 4166, 8, 32, 0x0ff },
210 { 0, 0, jbig2HuffmanEOT, 0 }
211 };
212
213 JBIG2HuffmanTable huffTableK[] = {
214 { 1, 1, 0, 0x000 },
215 { 2, 2, 1, 0x002 },
216 { 4, 4, 0, 0x00c },
217 { 5, 4, 1, 0x00d },
218 { 7, 5, 1, 0x01c },
219 { 9, 5, 2, 0x01d },
220 { 13, 6, 2, 0x03c },
221 { 17, 7, 2, 0x07a },
222 { 21, 7, 3, 0x07b },
223 { 29, 7, 4, 0x07c },
224 { 45, 7, 5, 0x07d },
225 { 77, 7, 6, 0x07e },
226 { 141, 7, 32, 0x07f },
227 { 0, 0, jbig2HuffmanEOT, 0 }
228 };
229
230 JBIG2HuffmanTable huffTableL[] = {
231 { 1, 1, 0, 0x000 },
232 { 2, 2, 0, 0x002 },
233 { 3, 3, 1, 0x006 },
234 { 5, 5, 0, 0x01c },
235 { 6, 5, 1, 0x01d },
236 { 8, 6, 1, 0x03c },
237 { 10, 7, 0, 0x07a },
238 { 11, 7, 1, 0x07b },
239 { 13, 7, 2, 0x07c },
240 { 17, 7, 3, 0x07d },
241 { 25, 7, 4, 0x07e },
242 { 41, 8, 5, 0x0fe },
243 { 73, 8, 32, 0x0ff },
244 { 0, 0, jbig2HuffmanEOT, 0 }
245 };
246
247 JBIG2HuffmanTable huffTableM[] = {
248 { 1, 1, 0, 0x000 },
249 { 2, 3, 0, 0x004 },
250 { 7, 3, 3, 0x005 },
251 { 3, 4, 0, 0x00c },
252 { 5, 4, 1, 0x00d },
253 { 4, 5, 0, 0x01c },
254 { 15, 6, 1, 0x03a },
255 { 17, 6, 2, 0x03b },
256 { 21, 6, 3, 0x03c },
257 { 29, 6, 4, 0x03d },
258 { 45, 6, 5, 0x03e },
259 { 77, 7, 6, 0x07e },
260 { 141, 7, 32, 0x07f },
261 { 0, 0, jbig2HuffmanEOT, 0 }
262 };
263
264 JBIG2HuffmanTable huffTableN[] = {
265 { 0, 1, 0, 0x000 },
266 { -2, 3, 0, 0x004 },
267 { -1, 3, 0, 0x005 },
268 { 1, 3, 0, 0x006 },
269 { 2, 3, 0, 0x007 },
270 { 0, 0, jbig2HuffmanEOT, 0 }
271 };
272
273 JBIG2HuffmanTable huffTableO[] = {
274 { 0, 1, 0, 0x000 },
275 { -1, 3, 0, 0x004 },
276 { 1, 3, 0, 0x005 },
277 { -2, 4, 0, 0x00c },
278 { 2, 4, 0, 0x00d },
279 { -4, 5, 1, 0x01c },
280 { 3, 5, 1, 0x01d },
281 { -8, 6, 2, 0x03c },
282 { 5, 6, 2, 0x03d },
283 { -24, 7, 4, 0x07c },
284 { 9, 7, 4, 0x07d },
285 { -25, 7, jbig2HuffmanLOW, 0x07e },
286 { 25, 7, 32, 0x07f },
287 { 0, 0, jbig2HuffmanEOT, 0 }
288 };
289
290 //------------------------------------------------------------------------
291 // JBIG2HuffmanDecoder
292 //------------------------------------------------------------------------
293
294 class JBIG2HuffmanDecoder {
295 public:
296
297 JBIG2HuffmanDecoder();
298 ~JBIG2HuffmanDecoder();
299 void setStream(Stream *strA) { str = strA; }
300
301 void reset();
302
303 // Returns false for OOB, otherwise sets *<x> and returns true.
304 GBool decodeInt(int *x, JBIG2HuffmanTable *table);
305
306 Guint readBits(Guint n);
307 Guint readBit();
308
309 // Sort the table by prefix length and assign prefix values.
310 void buildTable(JBIG2HuffmanTable *table, Guint len);
311
312 void resetByteCounter() { byteCounter = 0; }
313 Guint getByteCounter() { return byteCounter; }
314
315 private:
316
317 Stream *str;
318 Guint buf;
319 Guint bufLen;
320 Guint byteCounter;
321 };
322
323 JBIG2HuffmanDecoder::JBIG2HuffmanDecoder() {
324 str = NULL;
325 byteCounter = 0;
326 reset();
327 }
328
329 JBIG2HuffmanDecoder::~JBIG2HuffmanDecoder() {
330 }
331
332 void JBIG2HuffmanDecoder::reset() {
333 buf = 0;
334 bufLen = 0;
335 }
336
337 //~ optimize this
338 GBool JBIG2HuffmanDecoder::decodeInt(int *x, JBIG2HuffmanTable *table) {
339 Guint i, len, prefix;
340
341 i = 0;
342 len = 0;
343 prefix = 0;
344 while (table[i].rangeLen != jbig2HuffmanEOT) {
345 while (len < table[i].prefixLen) {
346 prefix = (prefix << 1) | readBit();
347 ++len;
348 }
349 if (prefix == table[i].prefix) {
350 if (table[i].rangeLen == jbig2HuffmanOOB) {
351 return gFalse;
352 }
353 if (table[i].rangeLen == jbig2HuffmanLOW) {
354 *x = table[i].val - readBits(32);
355 } else if (table[i].rangeLen > 0) {
356 *x = table[i].val + readBits(table[i].rangeLen);
357 } else {
358 *x = table[i].val;
359 }
360 return gTrue;
361 }
362 ++i;
363 }
364 return gFalse;
365 }
366
367 Guint JBIG2HuffmanDecoder::readBits(Guint n) {
368 Guint x, mask, nLeft;
369
370 mask = (n == 32) ? 0xffffffff : ((1 << n) - 1);
371 if (bufLen >= n) {
372 x = (buf >> (bufLen - n)) & mask;
373 bufLen -= n;
374 } else {
375 x = buf & ((1 << bufLen) - 1);
376 nLeft = n - bufLen;
377 bufLen = 0;
378 while (nLeft >= 8) {
379 x = (x << 8) | (str->getChar() & 0xff);
380 ++byteCounter;
381 nLeft -= 8;
382 }
383 if (nLeft > 0) {
384 buf = str->getChar();
385 ++byteCounter;
386 bufLen = 8 - nLeft;
387 x = (x << nLeft) | ((buf >> bufLen) & ((1 << nLeft) - 1));
388 }
389 }
390 return x;
391 }
392
393 Guint JBIG2HuffmanDecoder::readBit() {
394 if (bufLen == 0) {
395 buf = str->getChar();
396 ++byteCounter;
397 bufLen = 8;
398 }
399 --bufLen;
400 return (buf >> bufLen) & 1;
401 }
402
403 void JBIG2HuffmanDecoder::buildTable(JBIG2HuffmanTable *table, Guint len) {
404 Guint i, j, k, prefix;
405 JBIG2HuffmanTable tab;
406
407 // stable selection sort:
408 // - entries with prefixLen > 0, in ascending prefixLen order
409 // - entry with prefixLen = 0, rangeLen = EOT
410 // - all other entries with prefixLen = 0
411 // (on entry, table[len] has prefixLen = 0, rangeLen = EOT)
412 for (i = 0; i < len; ++i) {
413 for (j = i; j < len && table[j].prefixLen == 0; ++j) ;
414 if (j == len) {
415 break;
416 }
417 for (k = j + 1; k < len; ++k) {
418 if (table[k].prefixLen > 0 &&
419 table[k].prefixLen < table[j].prefixLen) {
420 j = k;
421 }
422 }
423 if (j != i) {
424 tab = table[j];
425 for (k = j; k > i; --k) {
426 table[k] = table[k - 1];
427 }
428 table[i] = tab;
429 }
430 }
431 table[i] = table[len];
432
433 // assign prefixes
434 if (table[0].rangeLen != jbig2HuffmanEOT) {
435 i = 0;
436 prefix = 0;
437 table[i++].prefix = prefix++;
438 for (; table[i].rangeLen != jbig2HuffmanEOT; ++i) {
439 prefix <<= table[i].prefixLen - table[i-1].prefixLen;
440 table[i].prefix = prefix++;
441 }
442 }
443 }
444
445 //------------------------------------------------------------------------
446 // JBIG2MMRDecoder
447 //------------------------------------------------------------------------
448
449 class JBIG2MMRDecoder {
450 public:
451
452 JBIG2MMRDecoder();
453 ~JBIG2MMRDecoder();
454 void setStream(Stream *strA) { str = strA; }
455 void reset();
456 int get2DCode();
457 int getBlackCode();
458 int getWhiteCode();
459 Guint get24Bits();
460 void resetByteCounter() { byteCounter = 0; }
461 Guint getByteCounter() { return byteCounter; }
462 void skipTo(Guint length);
463
464 private:
465
466 Stream *str;
467 Guint buf;
468 Guint bufLen;
469 Guint nBytesRead;
470 Guint byteCounter;
471 };
472
473 JBIG2MMRDecoder::JBIG2MMRDecoder() {
474 str = NULL;
475 byteCounter = 0;
476 reset();
477 }
478
479 JBIG2MMRDecoder::~JBIG2MMRDecoder() {
480 }
481
482 void JBIG2MMRDecoder::reset() {
483 buf = 0;
484 bufLen = 0;
485 nBytesRead = 0;
486 }
487
488 int JBIG2MMRDecoder::get2DCode() {
489 CCITTCode *p;
490
491 if (bufLen == 0) {
492 buf = str->getChar() & 0xff;
493 bufLen = 8;
494 ++nBytesRead;
495 ++byteCounter;
496 p = &twoDimTab1[(buf >> 1) & 0x7f];
497 } else if (bufLen >= 7) {
498 p = &twoDimTab1[(buf >> (bufLen - 7)) & 0x7f];
499 } else {
500 p = &twoDimTab1[(buf << (7 - bufLen)) & 0x7f];
501 if (p->bits < 0 || p->bits > (int)bufLen) {
502 buf = (buf << 8) | (str->getChar() & 0xff);
503 bufLen += 8;
504 ++nBytesRead;
505 ++byteCounter;
506 p = &twoDimTab1[(buf >> (bufLen - 7)) & 0x7f];
507 }
508 }
509 if (p->bits < 0) {
510 error(errSyntaxError, str->getPos(),
511 "Bad two dim code in JBIG2 MMR stream");
512 return EOF;
513 }
514 bufLen -= p->bits;
515 return p->n;
516 }
517
518 int JBIG2MMRDecoder::getWhiteCode() {
519 CCITTCode *p;
520 Guint code;
521
522 if (bufLen == 0) {
523 buf = str->getChar() & 0xff;
524 bufLen = 8;
525 ++nBytesRead;
526 ++byteCounter;
527 }
528 while (1) {
529 if (bufLen >= 11 && ((buf >> (bufLen - 7)) & 0x7f) == 0) {
530 if (bufLen <= 12) {
531 code = buf << (12 - bufLen);
532 } else {
533 code = buf >> (bufLen - 12);
534 }
535 p = &whiteTab1[code & 0x1f];
536 } else {
537 if (bufLen <= 9) {
538 code = buf << (9 - bufLen);
539 } else {
540 code = buf >> (bufLen - 9);
541 }
542 p = &whiteTab2[code & 0x1ff];
543 }
544 if (p->bits > 0 && p->bits <= (int)bufLen) {
545 bufLen -= p->bits;
546 return p->n;
547 }
548 if (bufLen >= 12) {
549 break;
550 }
551 buf = (buf << 8) | (str->getChar() & 0xff);
552 bufLen += 8;
553 ++nBytesRead;
554 ++byteCounter;
555 }
556 error(errSyntaxError, str->getPos(), "Bad white code in JBIG2 MMR stream");
557 // eat a bit and return a positive number so that the caller doesn't
558 // go into an infinite loop
559 --bufLen;
560 return 1;
561 }
562
563 int JBIG2MMRDecoder::getBlackCode() {
564 CCITTCode *p;
565 Guint code;
566
567 if (bufLen == 0) {
568 buf = str->getChar() & 0xff;
569 bufLen = 8;
570 ++nBytesRead;
571 ++byteCounter;
572 }
573 while (1) {
574 if (bufLen >= 10 && ((buf >> (bufLen - 6)) & 0x3f) == 0) {
575 if (bufLen <= 13) {
576 code = buf << (13 - bufLen);
577 } else {
578 code = buf >> (bufLen - 13);
579 }
580 p = &blackTab1[code & 0x7f];
581 } else if (bufLen >= 7 && ((buf >> (bufLen - 4)) & 0x0f) == 0 &&
582 ((buf >> (bufLen - 6)) & 0x03) != 0) {
583 if (bufLen <= 12) {
584 code = buf << (12 - bufLen);
585 } else {
586 code = buf >> (bufLen - 12);
587 }
588 p = &blackTab2[(code & 0xff) - 64];
589 } else {
590 if (bufLen <= 6) {
591 code = buf << (6 - bufLen);
592 } else {
593 code = buf >> (bufLen - 6);
594 }
595 p = &blackTab3[code & 0x3f];
596 }
597 if (p->bits > 0 && p->bits <= (int)bufLen) {
598 bufLen -= p->bits;
599 return p->n;
600 }
601 if (bufLen >= 13) {
602 break;
603 }
604 buf = (buf << 8) | (str->getChar() & 0xff);
605 bufLen += 8;
606 ++nBytesRead;
607 ++byteCounter;
608 }
609 error(errSyntaxError, str->getPos(), "Bad black code in JBIG2 MMR stream");
610 // eat a bit and return a positive number so that the caller doesn't
611 // go into an infinite loop
612 --bufLen;
613 return 1;
614 }
615
616 Guint JBIG2MMRDecoder::get24Bits() {
617 while (bufLen < 24) {
618 buf = (buf << 8) | (str->getChar() & 0xff);
619 bufLen += 8;
620 ++nBytesRead;
621 ++byteCounter;
622 }
623 return (buf >> (bufLen - 24)) & 0xffffff;
624 }
625
626 void JBIG2MMRDecoder::skipTo(Guint length) {
627 int n;
628
629 n = str->discardChars(length - nBytesRead);
630 nBytesRead += n;
631 byteCounter += n;
632 }
633
634 //------------------------------------------------------------------------
635 // JBIG2Segment
636 //------------------------------------------------------------------------
637
638 enum JBIG2SegmentType {
639 jbig2SegBitmap,
640 jbig2SegSymbolDict,
641 jbig2SegPatternDict,
642 jbig2SegCodeTable
643 };
644
645 class JBIG2Segment {
646 public:
647
648 JBIG2Segment(Guint segNumA) { segNum = segNumA; }
649 virtual ~JBIG2Segment() {}
650 void setSegNum(Guint segNumA) { segNum = segNumA; }
651 Guint getSegNum() { return segNum; }
652 virtual JBIG2SegmentType getType() = 0;
653
654 private:
655
656 Guint segNum;
657 };
658
659 //------------------------------------------------------------------------
660 // JBIG2Bitmap
661 //------------------------------------------------------------------------
662
663 struct JBIG2BitmapPtr {
664 Guchar *p;
665 int shift;
666 int x;
667 };
668
669 class JBIG2Bitmap: public JBIG2Segment {
670 public:
671
672 JBIG2Bitmap(Guint segNumA, int wA, int hA);
673 virtual ~JBIG2Bitmap();
674 virtual JBIG2SegmentType getType() { return jbig2SegBitmap; }
675 JBIG2Bitmap *copy() { return new JBIG2Bitmap(0, this); }
676 JBIG2Bitmap *getSlice(Guint x, Guint y, Guint wA, Guint hA);
677 void expand(int newH, Guint pixel);
678 void clearToZero();
679 void clearToOne();
680 int getWidth() { return w; }
681 int getHeight() { return h; }
682 int getLineSize() { return line; }
683 int getPixel(int x, int y)
684 { return (x < 0 || x >= w || y < 0 || y >= h) ? 0 :
685 (data[y * line + (x >> 3)] >> (7 - (x & 7))) & 1; }
686 void setPixel(int x, int y)
687 { data[y * line + (x >> 3)] |= (Guchar)(1 << (7 - (x & 7))); }
688 void clearPixel(int x, int y)
689 { data[y * line + (x >> 3)] &= (Guchar)(0x7f7f >> (x & 7)); }
690 void getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr);
691 int nextPixel(JBIG2BitmapPtr *ptr);
692 void duplicateRow(int yDest, int ySrc);
693 void combine(JBIG2Bitmap *bitmap, int x, int y, Guint combOp);
694 Guchar *getDataPtr() { return data; }
695 int getDataSize() { return h * line; }
696
697 private:
698
699 JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap);
700
701 int w, h, line;
702 Guchar *data;
703 };
704
705 JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, int wA, int hA):
706 JBIG2Segment(segNumA)
707 {
708 w = wA;
709 h = hA;
710 line = (wA + 7) >> 3;
711 if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) {
712 // force a call to gmalloc(-1), which will throw an exception
713 h = -1;
714 line = 2;
715 }
716 // need to allocate one extra guard byte for use in combine()
717 data = (Guchar *)gmalloc(h * line + 1);
718 data[h * line] = 0;
719 }
720
721 JBIG2Bitmap::JBIG2Bitmap(Guint segNumA, JBIG2Bitmap *bitmap):
722 JBIG2Segment(segNumA)
723 {
724 w = bitmap->w;
725 h = bitmap->h;
726 line = bitmap->line;
727 if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) {
728 // force a call to gmalloc(-1), which will throw an exception
729 h = -1;
730 line = 2;
731 }
732 // need to allocate one extra guard byte for use in combine()
733 data = (Guchar *)gmalloc(h * line + 1);
734 memcpy(data, bitmap->data, h * line);
735 data[h * line] = 0;
736 }
737
738 JBIG2Bitmap::~JBIG2Bitmap() {
739 gfree(data);
740 }
741
742 //~ optimize this
743 JBIG2Bitmap *JBIG2Bitmap::getSlice(Guint x, Guint y, Guint wA, Guint hA) {
744 JBIG2Bitmap *slice;
745 Guint xx, yy;
746
747 slice = new JBIG2Bitmap(0, wA, hA);
748 slice->clearToZero();
749 for (yy = 0; yy < hA; ++yy) {
750 for (xx = 0; xx < wA; ++xx) {
751 if (getPixel(x + xx, y + yy)) {
752 slice->setPixel(xx, yy);
753 }
754 }
755 }
756 return slice;
757 }
758
759 void JBIG2Bitmap::expand(int newH, Guint pixel) {
760 if (newH <= h || line <= 0 || newH >= (INT_MAX - 1) / line) {
761 return;
762 }
763 // need to allocate one extra guard byte for use in combine()
764 data = (Guchar *)grealloc(data, newH * line + 1);
765 if (pixel) {
766 memset(data + h * line, 0xff, (newH - h) * line);
767 } else {
768 memset(data + h * line, 0x00, (newH - h) * line);
769 }
770 h = newH;
771 data[h * line] = 0;
772 }
773
774 void JBIG2Bitmap::clearToZero() {
775 memset(data, 0, h * line);
776 }
777
778 void JBIG2Bitmap::clearToOne() {
779 memset(data, 0xff, h * line);
780 }
781
782 inline void JBIG2Bitmap::getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr) {
783 if (y < 0 || y >= h || x >= w) {
784 ptr->p = NULL;
785 ptr->shift = 0; // make gcc happy
786 ptr->x = 0; // make gcc happy
787 } else if (x < 0) {
788 ptr->p = &data[y * line];
789 ptr->shift = 7;
790 ptr->x = x;
791 } else {
792 ptr->p = &data[y * line + (x >> 3)];
793 ptr->shift = 7 - (x & 7);
794 ptr->x = x;
795 }
796 }
797
798 inline int JBIG2Bitmap::nextPixel(JBIG2BitmapPtr *ptr) {
799 int pix;
800
801 if (!ptr->p) {
802 pix = 0;
803 } else if (ptr->x < 0) {
804 ++ptr->x;
805 pix = 0;
806 } else {
807 pix = (*ptr->p >> ptr->shift) & 1;
808 if (++ptr->x == w) {
809 ptr->p = NULL;
810 } else if (ptr->shift == 0) {
811 ++ptr->p;
812 ptr->shift = 7;
813 } else {
814 --ptr->shift;
815 }
816 }
817 return pix;
818 }
819
820 void JBIG2Bitmap::duplicateRow(int yDest, int ySrc) {
821 memcpy(data + yDest * line, data + ySrc * line, line);
822 }
823
824 void JBIG2Bitmap::combine(JBIG2Bitmap *bitmap, int x, int y,
825 Guint combOp) {
826 int x0, x1, y0, y1, xx, yy;
827 Guchar *srcPtr, *destPtr;
828 Guchar dest, src0, src1, src, m1, m2, m3;
829 Guint s1, s2;
830 GBool oneByte;
831
832 // check for the pathological case where y = -2^31
833 if (y < -0x7fffffff) {
834 return;
835 }
836 if (y < 0) {
837 y0 = -y;
838 } else {
839 y0 = 0;
840 }
841 if (y > INT_MAX - bitmap->h) {
842 return;
843 }
844 if (y + bitmap->h > h) {
845 y1 = h - y;
846 } else {
847 y1 = bitmap->h;
848 }
849 if (y0 >= y1) {
850 return;
851 }
852
853 if (x >= 0) {
854 x0 = x & ~7;
855 } else {
856 x0 = 0;
857 }
858 x1 = x + bitmap->w;
859 if (x1 > w) {
860 x1 = w;
861 }
862 if (x0 >= x1) {
863 return;
864 }
865
866 s1 = x & 7;
867 s2 = 8 - s1;
868 m1 = (Guchar)(0xff >> (x1 & 7));
869 m2 = (Guchar)(0xff << (((x1 & 7) == 0) ? 0 : 8 - (x1 & 7)));
870 m3 = (Guchar)((0xff >> s1) & m2);
871
872 oneByte = x0 == ((x1 - 1) & ~7);
873
874 for (yy = y0; yy < y1; ++yy) {
875
876 // one byte per line -- need to mask both left and right side
877 if (oneByte) {
878 if (x >= 0) {
879 destPtr = data + (y + yy) * line + (x >> 3);
880 srcPtr = bitmap->data + yy * bitmap->line;
881 dest = *destPtr;
882 src1 = *srcPtr;
883 switch (combOp) {
884 case 0: // or
885 dest |= (Guchar)((src1 >> s1) & m2);
886 break;
887 case 1: // and
888 dest &= (Guchar)(((0xff00 | src1) >> s1) | m1);
889 break;
890 case 2: // xor
891 dest ^= (Guchar)((src1 >> s1) & m2);
892 break;
893 case 3: // xnor
894 dest ^= (Guchar)(((src1 ^ 0xff) >> s1) & m2);
895 break;
896 case 4: // replace
897 dest = (Guchar)((dest & ~m3) | ((src1 >> s1) & m3));
898 break;
899 }
900 *destPtr = dest;
901 } else {
902 destPtr = data + (y + yy) * line;
903 srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3);
904 dest = *destPtr;
905 src1 = *srcPtr;
906 switch (combOp) {
907 case 0: // or
908 dest |= src1 & m2;
909 break;
910 case 1: // and
911 dest &= src1 | m1;
912 break;
913 case 2: // xor
914 dest ^= src1 & m2;
915 break;
916 case 3: // xnor
917 dest ^= (src1 ^ 0xff) & m2;
918 break;
919 case 4: // replace
920 dest = (src1 & m2) | (dest & m1);
921 break;
922 }
923 *destPtr = dest;
924 }
925
926 // multiple bytes per line -- need to mask left side of left-most
927 // byte and right side of right-most byte
928 } else {
929
930 // left-most byte
931 if (x >= 0) {
932 destPtr = data + (y + yy) * line + (x >> 3);
933 srcPtr = bitmap->data + yy * bitmap->line;
934 src1 = *srcPtr++;
935 dest = *destPtr;
936 switch (combOp) {
937 case 0: // or
938 dest |= (Guchar)(src1 >> s1);
939 break;
940 case 1: // and
941 dest &= (Guchar)((0xff00 | src1) >> s1);
942 break;
943 case 2: // xor
944 dest ^= (Guchar)(src1 >> s1);
945 break;
946 case 3: // xnor
947 dest ^= (Guchar)((src1 ^ 0xff) >> s1);
948 break;
949 case 4: // replace
950 dest = (Guchar)((dest & (0xff << s2)) | (src1 >> s1));
951 break;
952 }
953 *destPtr++ = dest;
954 xx = x0 + 8;
955 } else {
956 destPtr = data + (y + yy) * line;
957 srcPtr = bitmap->data + yy * bitmap->line + (-x >> 3);
958 src1 = *srcPtr++;
959 xx = x0;
960 }
961
962 // middle bytes
963 for (; xx < x1 - 8; xx += 8) {
964 dest = *destPtr;
965 src0 = src1;
966 src1 = *srcPtr++;
967 src = (Guchar)(((src0 << 8) | src1) >> s1);
968 switch (combOp) {
969 case 0: // or
970 dest |= src;
971 break;
972 case 1: // and
973 dest &= src;
974 break;
975 case 2: // xor
976 dest ^= src;
977 break;
978 case 3: // xnor
979 dest ^= src ^ 0xff;
980 break;
981 case 4: // replace
982 dest = src;
983 break;
984 }
985 *destPtr++ = dest;
986 }
987
988 // right-most byte
989 // note: this last byte (src1) may not actually be used, depending
990 // on the values of s1, m1, and m2 - and in fact, it may be off
991 // the edge of the source bitmap, which means we need to allocate
992 // one extra guard byte at the end of each bitmap
993 dest = *destPtr;
994 src0 = src1;
995 src1 = *srcPtr++;
996 src = (Guchar)(((src0 << 8) | src1) >> s1);
997 switch (combOp) {
998 case 0: // or
999 dest |= src & m2;
1000 break;
1001 case 1: // and
1002 dest &= src | m1;
1003 break;
1004 case 2: // xor
1005 dest ^= src & m2;
1006 break;
1007 case 3: // xnor
1008 dest ^= (src ^ 0xff) & m2;
1009 break;
1010 case 4: // replace
1011 dest = (src & m2) | (dest & m1);
1012 break;
1013 }
1014 *destPtr = dest;
1015 }
1016 }
1017 }
1018
1019 //------------------------------------------------------------------------
1020 // JBIG2SymbolDict
1021 //------------------------------------------------------------------------
1022
1023 class JBIG2SymbolDict: public JBIG2Segment {
1024 public:
1025
1026 JBIG2SymbolDict(Guint segNumA, Guint sizeA);
1027 virtual ~JBIG2SymbolDict();
1028 virtual JBIG2SegmentType getType() { return jbig2SegSymbolDict; }
1029 Guint getSize() { return size; }
1030 void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; }
1031 JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; }
1032 void setGenericRegionStats(JArithmeticDecoderStats *stats)
1033 { genericRegionStats = stats; }
1034 void setRefinementRegionStats(JArithmeticDecoderStats *stats)
1035 { refinementRegionStats = stats; }
1036 JArithmeticDecoderStats *getGenericRegionStats()
1037 { return genericRegionStats; }
1038 JArithmeticDecoderStats *getRefinementRegionStats()
1039 { return refinementRegionStats; }
1040
1041 private:
1042
1043 Guint size;
1044 JBIG2Bitmap **bitmaps;
1045 JArithmeticDecoderStats *genericRegionStats;
1046 JArithmeticDecoderStats *refinementRegionStats;
1047 };
1048
1049 JBIG2SymbolDict::JBIG2SymbolDict(Guint segNumA, Guint sizeA):
1050 JBIG2Segment(segNumA)
1051 {
1052 Guint i;
1053
1054 size = sizeA;
1055 bitmaps = (JBIG2Bitmap **)gmallocn(size, sizeof(JBIG2Bitmap *));
1056 for (i = 0; i < size; ++i) {
1057 bitmaps[i] = NULL;
1058 }
1059 genericRegionStats = NULL;
1060 refinementRegionStats = NULL;
1061 }
1062
1063 JBIG2SymbolDict::~JBIG2SymbolDict() {
1064 Guint i;
1065
1066 for (i = 0; i < size; ++i) {
1067 if (bitmaps[i]) {
1068 delete bitmaps[i];
1069 }
1070 }
1071 gfree(bitmaps);
1072 if (genericRegionStats) {
1073 delete genericRegionStats;
1074 }
1075 if (refinementRegionStats) {
1076 delete refinementRegionStats;
1077 }
1078 }
1079
1080 //------------------------------------------------------------------------
1081 // JBIG2PatternDict
1082 //------------------------------------------------------------------------
1083
1084 class JBIG2PatternDict: public JBIG2Segment {
1085 public:
1086
1087 JBIG2PatternDict(Guint segNumA, Guint sizeA);
1088 virtual ~JBIG2PatternDict();
1089 virtual JBIG2SegmentType getType() { return jbig2SegPatternDict; }
1090 Guint getSize() { return size; }
1091 void setBitmap(Guint idx, JBIG2Bitmap *bitmap) { bitmaps[idx] = bitmap; }
1092 JBIG2Bitmap *getBitmap(Guint idx) { return bitmaps[idx]; }
1093
1094 private:
1095
1096 Guint size;
1097 JBIG2Bitmap **bitmaps;
1098 };
1099
1100 JBIG2PatternDict::JBIG2PatternDict(Guint segNumA, Guint sizeA):
1101 JBIG2Segment(segNumA)
1102 {
1103 size = sizeA;
1104 bitmaps = (JBIG2Bitmap **)gmallocn(size, sizeof(JBIG2Bitmap *));
1105 }
1106
1107 JBIG2PatternDict::~JBIG2PatternDict() {
1108 Guint i;
1109
1110 for (i = 0; i < size; ++i) {
1111 delete bitmaps[i];
1112 }
1113 gfree(bitmaps);
1114 }
1115
1116 //------------------------------------------------------------------------
1117 // JBIG2CodeTable
1118 //------------------------------------------------------------------------
1119
1120 class JBIG2CodeTable: public JBIG2Segment {
1121 public:
1122
1123 JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA);
1124 virtual ~JBIG2CodeTable();
1125 virtual JBIG2SegmentType getType() { return jbig2SegCodeTable; }
1126 JBIG2HuffmanTable *getHuffTable() { return table; }
1127
1128 private:
1129
1130 JBIG2HuffmanTable *table;
1131 };
1132
1133 JBIG2CodeTable::JBIG2CodeTable(Guint segNumA, JBIG2HuffmanTable *tableA):
1134 JBIG2Segment(segNumA)
1135 {
1136 table = tableA;
1137 }
1138
1139 JBIG2CodeTable::~JBIG2CodeTable() {
1140 gfree(table);
1141 }
1142
1143 //------------------------------------------------------------------------
1144 // JBIG2Stream
1145 //------------------------------------------------------------------------
1146
1147 JBIG2Stream::JBIG2Stream(Stream *strA, Object *globalsStreamA):
1148 FilterStream(strA)
1149 {
1150 decoded = gFalse;
1151 pageBitmap = NULL;
1152
1153 arithDecoder = new JArithmeticDecoder();
1154 genericRegionStats = new JArithmeticDecoderStats(1 << 1);
1155 refinementRegionStats = new JArithmeticDecoderStats(1 << 1);
1156 iadhStats = new JArithmeticDecoderStats(1 << 9);
1157 iadwStats = new JArithmeticDecoderStats(1 << 9);
1158 iaexStats = new JArithmeticDecoderStats(1 << 9);
1159 iaaiStats = new JArithmeticDecoderStats(1 << 9);
1160 iadtStats = new JArithmeticDecoderStats(1 << 9);
1161 iaitStats = new JArithmeticDecoderStats(1 << 9);
1162 iafsStats = new JArithmeticDecoderStats(1 << 9);
1163 iadsStats = new JArithmeticDecoderStats(1 << 9);
1164 iardxStats = new JArithmeticDecoderStats(1 << 9);
1165 iardyStats = new JArithmeticDecoderStats(1 << 9);
1166 iardwStats = new JArithmeticDecoderStats(1 << 9);
1167 iardhStats = new JArithmeticDecoderStats(1 << 9);
1168 iariStats = new JArithmeticDecoderStats(1 << 9);
1169 iaidStats = new JArithmeticDecoderStats(1 << 1);
1170 huffDecoder = new JBIG2HuffmanDecoder();
1171 mmrDecoder = new JBIG2MMRDecoder();
1172
1173 globalsStreamA->copy(&globalsStream);
1174 segments = globalSegments = NULL;
1175 curStr = NULL;
1176 dataPtr = dataEnd = NULL;
1177 }
1178
1179 JBIG2Stream::~JBIG2Stream() {
1180 close();
1181 globalsStream.free();
1182 delete arithDecoder;
1183 delete genericRegionStats;
1184 delete refinementRegionStats;
1185 delete iadhStats;
1186 delete iadwStats;
1187 delete iaexStats;
1188 delete iaaiStats;
1189 delete iadtStats;
1190 delete iaitStats;
1191 delete iafsStats;
1192 delete iadsStats;
1193 delete iardxStats;
1194 delete iardyStats;
1195 delete iardwStats;
1196 delete iardhStats;
1197 delete iariStats;
1198 delete iaidStats;
1199 delete huffDecoder;
1200 delete mmrDecoder;
1201 delete str;
1202 }
1203
1204 Stream *JBIG2Stream::copy() {
1205 return new JBIG2Stream(str->copy(), &globalsStream);
1206 }
1207
1208 void JBIG2Stream::reset() {
1209 segments = new GList();
1210 globalSegments = new GList();
1211 decoded = gFalse;
1212 }
1213
1214 void JBIG2Stream::close() {
1215 if (pageBitmap) {
1216 delete pageBitmap;
1217 pageBitmap = NULL;
1218 }
1219 if (segments) {
1220 deleteGList(segments, JBIG2Segment);
1221 segments = NULL;
1222 }
1223 if (globalSegments) {
1224 deleteGList(globalSegments, JBIG2Segment);
1225 globalSegments = NULL;
1226 }
1227 dataPtr = dataEnd = NULL;
1228 FilterStream::close();
1229 }
1230
1231 int JBIG2Stream::getChar() {
1232 if (!decoded) {
1233 decodeImage();
1234 }
1235 if (dataPtr && dataPtr < dataEnd) {
1236 return (*dataPtr++ ^ 0xff) & 0xff;
1237 }
1238 return EOF;
1239 }
1240
1241 int JBIG2Stream::lookChar() {
1242 if (!decoded) {
1243 decodeImage();
1244 }
1245 if (dataPtr && dataPtr < dataEnd) {
1246 return (*dataPtr ^ 0xff) & 0xff;
1247 }
1248 return EOF;
1249 }
1250
1251 int JBIG2Stream::getBlock(char *blk, int size) {
1252 int n, i;
1253
1254 if (!decoded) {
1255 decodeImage();
1256 }
1257 if (size <= 0) {
1258 return 0;
1259 }
1260 if (dataEnd - dataPtr < size) {
1261 n = (int)(dataEnd - dataPtr);
1262 } else {
1263 n = size;
1264 }
1265 for (i = 0; i < n; ++i) {
1266 blk[i] = *dataPtr++ ^ 0xff;
1267 }
1268 return n;
1269 }
1270
1271 GString *JBIG2Stream::getPSFilter(int psLevel, const char *indent,
1272 GBool okToReadStream) {
1273 return NULL;
1274 }
1275
1276 GBool JBIG2Stream::isBinary(GBool last) {
1277 return str->isBinary(gTrue);
1278 }
1279
1280 void JBIG2Stream::decodeImage() {
1281 GList *t;
1282
1283 // read the globals stream
1284 if (globalsStream.isStream()) {
1285 curStr = globalsStream.getStream();
1286 curStr->reset();
1287 arithDecoder->setStream(curStr);
1288 huffDecoder->setStream(curStr);
1289 mmrDecoder->setStream(curStr);
1290 readSegments();
1291 curStr->close();
1292 // swap the newly read segments list into globalSegments
1293 t = segments;
1294 segments = globalSegments;
1295 globalSegments = t;
1296 }
1297
1298 // read the main stream
1299 curStr = str;
1300 curStr->reset();
1301 arithDecoder->setStream(curStr);
1302 huffDecoder->setStream(curStr);
1303 mmrDecoder->setStream(curStr);
1304 readSegments();
1305
1306 if (pageBitmap) {
1307 dataPtr = pageBitmap->getDataPtr();
1308 dataEnd = dataPtr + pageBitmap->getDataSize();
1309 } else {
1310 dataPtr = dataEnd = NULL;
1311 }
1312
1313 decoded = gTrue;
1314 }
1315
1316 void JBIG2Stream::readSegments() {
1317 Guint segNum, segFlags, segType, page, segLength;
1318 Guint refFlags, nRefSegs;
1319 Guint *refSegs;
1320 int c1, c2, c3;
1321 Guint i;
1322
1323 done = gFalse;
1324 while (!done && readULong(&segNum)) {
1325
1326 // segment header flags
1327 if (!readUByte(&segFlags)) {
1328 goto eofError1;
1329 }
1330 segType = segFlags & 0x3f;
1331
1332 // referred-to segment count and retention flags
1333 if (!readUByte(&refFlags)) {
1334 goto eofError1;
1335 }
1336 nRefSegs = refFlags >> 5;
1337 if (nRefSegs == 7) {
1338 if ((c1 = curStr->getChar()) == EOF ||
1339 (c2 = curStr->getChar()) == EOF ||
1340 (c3 = curStr->getChar()) == EOF) {
1341 goto eofError1;
1342 }
1343 refFlags = (refFlags << 24) | (c1 << 16) | (c2 << 8) | c3;
1344 nRefSegs = refFlags & 0x1fffffff;
1345 i = (nRefSegs + 9) >> 3;
1346 if (curStr->discardChars(i) != i) {
1347 goto eofError1;
1348 }
1349 }
1350
1351 // referred-to segment numbers
1352 refSegs = (Guint *)gmallocn(nRefSegs, sizeof(Guint));
1353 if (segNum <= 256) {
1354 for (i = 0; i < nRefSegs; ++i) {
1355 if (!readUByte(&refSegs[i])) {
1356 goto eofError2;
1357 }
1358 }
1359 } else if (segNum <= 65536) {
1360 for (i = 0; i < nRefSegs; ++i) {
1361 if (!readUWord(&refSegs[i])) {
1362 goto eofError2;
1363 }
1364 }
1365 } else {
1366 for (i = 0; i < nRefSegs; ++i) {
1367 if (!readULong(&refSegs[i])) {
1368 goto eofError2;
1369 }
1370 }
1371 }
1372
1373 // segment page association
1374 if (segFlags & 0x40) {
1375 if (!readULong(&page)) {
1376 goto eofError2;
1377 }
1378 } else {
1379 if (!readUByte(&page)) {
1380 goto eofError2;
1381 }
1382 }
1383
1384 // segment data length
1385 if (!readULong(&segLength)) {
1386 goto eofError2;
1387 }
1388
1389 // check for missing page information segment
1390 if (!pageBitmap && ((segType >= 4 && segType <= 7) ||
1391 (segType >= 20 && segType <= 43))) {
1392 error(errSyntaxError, getPos(),
1393 "First JBIG2 segment associated with a page must be a page information segment");
1394 goto syntaxError;
1395 }
1396
1397 // read the segment data
1398 arithDecoder->resetByteCounter();
1399 huffDecoder->resetByteCounter();
1400 mmrDecoder->resetByteCounter();
1401 byteCounter = 0;
1402 switch (segType) {
1403 case 0:
1404 if (!readSymbolDictSeg(segNum, segLength, refSegs, nRefSegs)) {
1405 goto syntaxError;
1406 }
1407 break;
1408 case 4:
1409 readTextRegionSeg(segNum, gFalse, gFalse, segLength, refSegs, nRefSegs);
1410 break;
1411 case 6:
1412 readTextRegionSeg(segNum, gTrue, gFalse, segLength, refSegs, nRefSegs);
1413 break;
1414 case 7:
1415 readTextRegionSeg(segNum, gTrue, gTrue, segLength, refSegs, nRefSegs);
1416 break;
1417 case 16:
1418 readPatternDictSeg(segNum, segLength);
1419 break;
1420 case 20:
1421 readHalftoneRegionSeg(segNum, gFalse, gFalse, segLength,
1422 refSegs, nRefSegs);
1423 break;
1424 case 22:
1425 readHalftoneRegionSeg(segNum, gTrue, gFalse, segLength,
1426 refSegs, nRefSegs);
1427 break;
1428 case 23:
1429 readHalftoneRegionSeg(segNum, gTrue, gTrue, segLength,
1430 refSegs, nRefSegs);
1431 break;
1432 case 36:
1433 readGenericRegionSeg(segNum, gFalse, gFalse, segLength);
1434 break;
1435 case 38:
1436 readGenericRegionSeg(segNum, gTrue, gFalse, segLength);
1437 break;
1438 case 39:
1439 readGenericRegionSeg(segNum, gTrue, gTrue, segLength);
1440 break;
1441 case 40:
1442 readGenericRefinementRegionSeg(segNum, gFalse, gFalse, segLength,
1443 refSegs, nRefSegs);
1444 break;
1445 case 42:
1446 readGenericRefinementRegionSeg(segNum, gTrue, gFalse, segLength,
1447 refSegs, nRefSegs);
1448 break;
1449 case 43:
1450 readGenericRefinementRegionSeg(segNum, gTrue, gTrue, segLength,
1451 refSegs, nRefSegs);
1452 break;
1453 case 48:
1454 readPageInfoSeg(segLength);
1455 break;
1456 case 50:
1457 readEndOfStripeSeg(segLength);
1458 break;
1459 case 51:
1460 // end of file segment
1461 done = gTrue;
1462 break;
1463 case 52:
1464 readProfilesSeg(segLength);
1465 break;
1466 case 53:
1467 readCodeTableSeg(segNum, segLength);
1468 break;
1469 case 62:
1470 readExtensionSeg(segLength);
1471 break;
1472 default:
1473 error(errSyntaxError, getPos(), "Unknown segment type in JBIG2 stream");
1474 if (curStr->discardChars(segLength) != segLength) {
1475 goto eofError2;
1476 }
1477 break;
1478 }
1479
1480 // skip any unused data at the end of the segment
1481 // (except for immediate generic region segments which have
1482 // 0xffffffff = unspecified length)
1483 if (!(segType == 38 && segLength == 0xffffffff)) {
1484 byteCounter += arithDecoder->getByteCounter();
1485 byteCounter += huffDecoder->getByteCounter();
1486 byteCounter += mmrDecoder->getByteCounter();
1487 // do a sanity check on byteCounter vs segLength -- if there is
1488 // a problem, abort the decode
1489 if (byteCounter > segLength ||
1490 segLength - byteCounter > 65536) {
1491 error(errSyntaxError, getPos(),
1492 "Invalid segment length in JBIG2 stream");
1493 gfree(refSegs);
1494 break;
1495 }
1496 byteCounter += curStr->discardChars(segLength - byteCounter);
1497 }
1498
1499 gfree(refSegs);
1500 }
1501
1502 return;
1503
1504 syntaxError:
1505 gfree(refSegs);
1506 return;
1507
1508 eofError2:
1509 gfree(refSegs);
1510 eofError1:
1511 error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
1512 }
1513
1514 GBool JBIG2Stream::readSymbolDictSeg(Guint segNum, Guint length,
1515 Guint *refSegs, Guint nRefSegs) {
1516 JBIG2SymbolDict *symbolDict;
1517 JBIG2HuffmanTable *huffDHTable, *huffDWTable;
1518 JBIG2HuffmanTable *huffBMSizeTable, *huffAggInstTable;
1519 JBIG2Segment *seg;
1520 GList *codeTables;
1521 JBIG2SymbolDict *inputSymbolDict;
1522 Guint flags, sdTemplate, sdrTemplate, huff, refAgg;
1523 Guint huffDH, huffDW, huffBMSize, huffAggInst;
1524 Guint contextUsed, contextRetained;
1525 int sdATX[4], sdATY[4], sdrATX[2], sdrATY[2];
1526 Guint numExSyms, numNewSyms, numInputSyms, symCodeLen;
1527 JBIG2Bitmap **bitmaps;
1528 JBIG2Bitmap *collBitmap, *refBitmap;
1529 Guint *symWidths;
1530 Guint symHeight, symWidth, totalWidth, x, symID;
1531 int dh, dw, refAggNum, refDX, refDY, bmSize;
1532 GBool ex;
1533 int run, prevRun, cnt;
1534 Guint i, j, k;
1535
1536 symWidths = NULL;
1537
1538 // symbol dictionary flags
1539 if (!readUWord(&flags)) {
1540 goto eofError;
1541 }
1542 sdTemplate = (flags >> 10) & 3;
1543 sdrTemplate = (flags >> 12) & 1;
1544 huff = flags & 1;
1545 refAgg = (flags >> 1) & 1;
1546 huffDH = (flags >> 2) & 3;
1547 huffDW = (flags >> 4) & 3;
1548 huffBMSize = (flags >> 6) & 1;
1549 huffAggInst = (flags >> 7) & 1;
1550 contextUsed = (flags >> 8) & 1;
1551 contextRetained = (flags >> 9) & 1;
1552
1553 // symbol dictionary AT flags
1554 if (!huff) {
1555 if (sdTemplate == 0) {
1556 if (!readByte(&sdATX[0]) ||
1557 !readByte(&sdATY[0]) ||
1558 !readByte(&sdATX[1]) ||
1559 !readByte(&sdATY[1]) ||
1560 !readByte(&sdATX[2]) ||
1561 !readByte(&sdATY[2]) ||
1562 !readByte(&sdATX[3]) ||
1563 !readByte(&sdATY[3])) {
1564 goto eofError;
1565 }
1566 } else {
1567 if (!readByte(&sdATX[0]) ||
1568 !readByte(&sdATY[0])) {
1569 goto eofError;
1570 }
1571 }
1572 }
1573
1574 // symbol dictionary refinement AT flags
1575 if (refAgg && !sdrTemplate) {
1576 if (!readByte(&sdrATX[0]) ||
1577 !readByte(&sdrATY[0]) ||
1578 !readByte(&sdrATX[1]) ||
1579 !readByte(&sdrATY[1])) {
1580 goto eofError;
1581 }
1582 }
1583
1584 // SDNUMEXSYMS and SDNUMNEWSYMS
1585 if (!readULong(&numExSyms) || !readULong(&numNewSyms)) {
1586 goto eofError;
1587 }
1588
1589 // get referenced segments: input symbol dictionaries and code tables
1590 codeTables = new GList();
1591 numInputSyms = 0;
1592 for (i = 0; i < nRefSegs; ++i) {
1593 if ((seg = findSegment(refSegs[i]))) {
1594 if (seg->getType() == jbig2SegSymbolDict) {
1595 j = ((JBIG2SymbolDict *)seg)->getSize();
1596 if (j > INT_MAX || numInputSyms > INT_MAX - j) {
1597 error(errSyntaxError, getPos(),
1598 "Too many input symbols in JBIG2 symbol dictionary");
1599 delete codeTables;
1600 goto eofError;
1601 }
1602 numInputSyms += j;
1603 } else if (seg->getType() == jbig2SegCodeTable) {
1604 codeTables->append(seg);
1605 }
1606 }
1607 }
1608 if (numNewSyms > INT_MAX || numInputSyms > INT_MAX - numNewSyms) {
1609 error(errSyntaxError, getPos(),
1610 "Too many input symbols in JBIG2 symbol dictionary");
1611 delete codeTables;
1612 goto eofError;
1613 }
1614
1615 // compute symbol code length
1616 i = numInputSyms + numNewSyms;
1617 if (i <= 1) {
1618 symCodeLen = huff ? 1 : 0;
1619 } else {
1620 --i;
1621 symCodeLen = 0;
1622 // i = floor((numSyms-1) / 2^symCodeLen)
1623 while (i > 0) {
1624 ++symCodeLen;
1625 i >>= 1;
1626 }
1627 }
1628
1629 // get the input symbol bitmaps
1630 bitmaps = (JBIG2Bitmap **)gmallocn(numInputSyms + numNewSyms,
1631 sizeof(JBIG2Bitmap *));
1632 for (i = 0; i < numInputSyms + numNewSyms; ++i) {
1633 bitmaps[i] = NULL;
1634 }
1635 k = 0;
1636 inputSymbolDict = NULL;
1637 for (i = 0; i < nRefSegs; ++i) {
1638 if ((seg = findSegment(refSegs[i]))) {
1639 if (seg->getType() == jbig2SegSymbolDict) {
1640 inputSymbolDict = (JBIG2SymbolDict *)seg;
1641 for (j = 0; j < inputSymbolDict->getSize(); ++j) {
1642 bitmaps[k++] = inputSymbolDict->getBitmap(j);
1643 }
1644 }
1645 }
1646 }
1647
1648 // get the Huffman tables
1649 huffDHTable = huffDWTable = NULL; // make gcc happy
1650 huffBMSizeTable = huffAggInstTable = NULL; // make gcc happy
1651 i = 0;
1652 if (huff) {
1653 if (huffDH == 0) {
1654 huffDHTable = huffTableD;
1655 } else if (huffDH == 1) {
1656 huffDHTable = huffTableE;
1657 } else {
1658 if (i >= (Guint)codeTables->getLength()) {
1659 goto codeTableError;
1660 }
1661 huffDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1662 }
1663 if (huffDW == 0) {
1664 huffDWTable = huffTableB;
1665 } else if (huffDW == 1) {
1666 huffDWTable = huffTableC;
1667 } else {
1668 if (i >= (Guint)codeTables->getLength()) {
1669 goto codeTableError;
1670 }
1671 huffDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1672 }
1673 if (huffBMSize == 0) {
1674 huffBMSizeTable = huffTableA;
1675 } else {
1676 if (i >= (Guint)codeTables->getLength()) {
1677 goto codeTableError;
1678 }
1679 huffBMSizeTable =
1680 ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1681 }
1682 if (huffAggInst == 0) {
1683 huffAggInstTable = huffTableA;
1684 } else {
1685 if (i >= (Guint)codeTables->getLength()) {
1686 goto codeTableError;
1687 }
1688 huffAggInstTable =
1689 ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
1690 }
1691 }
1692 delete codeTables;
1693
1694 // set up the Huffman decoder
1695 if (huff) {
1696 huffDecoder->reset();
1697
1698 // set up the arithmetic decoder
1699 } else {
1700 if (contextUsed && inputSymbolDict) {
1701 resetGenericStats(sdTemplate, inputSymbolDict->getGenericRegionStats());
1702 } else {
1703 resetGenericStats(sdTemplate, NULL);
1704 }
1705 resetIntStats(symCodeLen);
1706 arithDecoder->start();
1707 }
1708
1709 // set up the arithmetic decoder for refinement/aggregation
1710 if (refAgg) {
1711 if (contextUsed && inputSymbolDict) {
1712 resetRefinementStats(sdrTemplate,
1713 inputSymbolDict->getRefinementRegionStats());
1714 } else {
1715 resetRefinementStats(sdrTemplate, NULL);
1716 }
1717 }
1718
1719 // allocate symbol widths storage
1720 if (huff && !refAgg) {
1721 symWidths = (Guint *)gmallocn(numNewSyms, sizeof(Guint));
1722 }
1723
1724 symHeight = 0;
1725 i = 0;
1726 while (i < numNewSyms) {
1727
1728 // read the height class delta height
1729 if (huff) {
1730 huffDecoder->decodeInt(&dh, huffDHTable);
1731 } else {
1732 arithDecoder->decodeInt(&dh, iadhStats);
1733 }
1734 if ((dh <= 0 && (Guint)-dh >= symHeight) ||
1735 (dh > 0 && (Guint)dh > UINT_MAX - symHeight)) {
1736 error(errSyntaxError, getPos(),
1737 "Bad delta-height value in JBIG2 symbol dictionary");
1738 goto syntaxError;
1739 }
1740 symHeight += dh;
1741 symWidth = 0;
1742 totalWidth = 0;
1743 j = i;
1744
1745 // sanity check to avoid extremely long run-times with damaged streams
1746 if (symHeight > 100000) {
1747 error(errSyntaxError, getPos(),
1748 "Bogus symbol height value in JBIG2 symbol dictionary");
1749 goto syntaxError;
1750 }
1751
1752 // read the symbols in this height class
1753 while (1) {
1754
1755 // read the delta width
1756 if (huff) {
1757 if (!huffDecoder->decodeInt(&dw, huffDWTable)) {
1758 break;
1759 }
1760 } else {
1761 if (!arithDecoder->decodeInt(&dw, iadwStats)) {
1762 break;
1763 }
1764 }
1765 if ((dw <= 0 && (Guint)-dw >= symWidth) ||
1766 (dw > 0 && (Guint)dw > UINT_MAX - symWidth)) {
1767 error(errSyntaxError, getPos(),
1768 "Bad delta-height value in JBIG2 symbol dictionary");
1769 goto syntaxError;
1770 }
1771 symWidth += dw;
1772 if (i >= numNewSyms) {
1773 error(errSyntaxError, getPos(),
1774 "Too many symbols in JBIG2 symbol dictionary");
1775 goto syntaxError;
1776 }
1777
1778 // sanity check to avoid extremely long run-times with damaged streams
1779 if (symWidth > 100000) {
1780 error(errSyntaxError, getPos(),
1781 "Bogus symbol width value in JBIG2 symbol dictionary");
1782 goto syntaxError;
1783 }
1784
1785 // using a collective bitmap, so don't read a bitmap here
1786 if (huff && !refAgg) {
1787 symWidths[i] = symWidth;
1788 totalWidth += symWidth;
1789
1790 // refinement/aggregate coding
1791 } else if (refAgg) {
1792 if (huff) {
1793 if (!huffDecoder->decodeInt(&refAggNum, huffAggInstTable)) {
1794 break;
1795 }
1796 } else {
1797 if (!arithDecoder->decodeInt(&refAggNum, iaaiStats)) {
1798 break;
1799 }
1800 }
1801 #if 0 //~ This special case was added about a year before the final draft
1802 //~ of the JBIG2 spec was released. I have encountered some old
1803 //~ JBIG2 images that predate it.
1804 if (0) {
1805 #else
1806 if (refAggNum == 1) {
1807 #endif
1808 if (huff) {
1809 symID = huffDecoder->readBits(symCodeLen);
1810 huffDecoder->decodeInt(&refDX, huffTableO);
1811 huffDecoder->decodeInt(&refDY, huffTableO);
1812 huffDecoder->decodeInt(&bmSize, huffTableA);
1813 huffDecoder->reset();
1814 arithDecoder->start();
1815 } else {
1816 symID = arithDecoder->decodeIAID(symCodeLen, iaidStats);
1817 arithDecoder->decodeInt(&refDX, iardxStats);
1818 arithDecoder->decodeInt(&refDY, iardyStats);
1819 }
1820 if (symID >= numInputSyms + i) {
1821 error(errSyntaxError, getPos(),
1822 "Invalid symbol ID in JBIG2 symbol dictionary");
1823 goto syntaxError;
1824 }
1825 refBitmap = bitmaps[symID];
1826 bitmaps[numInputSyms + i] =
1827 readGenericRefinementRegion(symWidth, symHeight,
1828 sdrTemplate, gFalse,
1829 refBitmap, refDX, refDY,
1830 sdrATX, sdrATY);
1831 //~ do we need to use the bmSize value here (in Huffman mode)?
1832 } else {
1833 bitmaps[numInputSyms + i] =
1834 readTextRegion(huff, gTrue, symWidth, symHeight,
1835 refAggNum, 0, numInputSyms + i, NULL,
1836 symCodeLen, bitmaps, 0, 0, 0, 1, 0,
1837 huffTableF, huffTableH, huffTableK, huffTableO,
1838 huffTableO, huffTableO, huffTableO, huffTableA,
1839 sdrTemplate, sdrATX, sdrATY);
1840 }
1841
1842 // non-ref/agg coding
1843 } else {
1844 bitmaps[numInputSyms + i] =
1845 readGenericBitmap(gFalse, symWidth, symHeight,
1846 sdTemplate, gFalse, gFalse, NULL,
1847 sdATX, sdATY, 0);
1848 }
1849
1850 ++i;
1851 }
1852
1853 // read the collective bitmap
1854 if (huff && !refAgg) {
1855 if (totalWidth == 0) {
1856 error(errSyntaxError, getPos(),
1857 "Invalid height class width in JBIG2 symbol dictionary");
1858 goto syntaxError;
1859 }
1860 huffDecoder->decodeInt(&bmSize, huffBMSizeTable);
1861 huffDecoder->reset();
1862 if (bmSize == 0) {
1863 collBitmap = new JBIG2Bitmap(0, totalWidth, symHeight);
1864 bmSize = symHeight * ((totalWidth + 7) >> 3);
1865 byteCounter += curStr->getBlock((char *)collBitmap->getDataPtr(),
1866 bmSize);
1867 } else {
1868 collBitmap = readGenericBitmap(gTrue, totalWidth, symHeight,
1869 0, gFalse, gFalse, NULL, NULL, NULL,
1870 bmSize);
1871 }
1872 x = 0;
1873 for (; j < i; ++j) {
1874 bitmaps[numInputSyms + j] =
1875 collBitmap->getSlice(x, 0, symWidths[j], symHeight);
1876 x += symWidths[j];
1877 }
1878 delete collBitmap;
1879 }
1880 }
1881
1882 // create the symbol dict object
1883 symbolDict = new JBIG2SymbolDict(segNum, numExSyms);
1884
1885 // exported symbol list
1886 i = j = 0;
1887 ex = gFalse;
1888 prevRun = 1;
1889 while (i < numInputSyms + numNewSyms) {
1890 if (huff) {
1891 huffDecoder->decodeInt(&run, huffTableA);
1892 } else {
1893 arithDecoder->decodeInt(&run, iaexStats);
1894 }
1895 if (run == 0 && prevRun == 0) {
1896 // this avoids infinite loops with damaged files (consecutive
1897 // zero runs are never useful)
1898 error(errSyntaxError, getPos(),
1899 "Invalid exported symbol list in JBIG2 symbol dictionary");
1900 delete symbolDict;
1901 goto syntaxError;
1902 }
1903 if (i + run > numInputSyms + numNewSyms ||
1904 (ex && j + run > numExSyms)) {
1905 error(errSyntaxError, getPos(),
1906 "Too many exported symbols in JBIG2 symbol dictionary");
1907 delete symbolDict;
1908 goto syntaxError;
1909 }
1910 if (ex) {
1911 for (cnt = 0; cnt < run; ++cnt) {
1912 symbolDict->setBitmap(j++, bitmaps[i++]->copy());
1913 }
1914 } else {
1915 i += run;
1916 }
1917 ex = !ex;
1918 prevRun = run;
1919 }
1920 if (j != numExSyms) {
1921 error(errSyntaxError, getPos(), "Too few symbols in JBIG2 symbol dictionary");
1922 delete symbolDict;
1923 goto syntaxError;
1924 }
1925
1926 for (i = 0; i < numNewSyms; ++i) {
1927 delete bitmaps[numInputSyms + i];
1928 }
1929 gfree(bitmaps);
1930 if (symWidths) {
1931 gfree(symWidths);
1932 }
1933
1934 // save the arithmetic decoder stats
1935 if (!huff && contextRetained) {
1936 symbolDict->setGenericRegionStats(genericRegionStats->copy());
1937 if (refAgg) {
1938 symbolDict->setRefinementRegionStats(refinementRegionStats->copy());
1939 }
1940 }
1941
1942 // store the new symbol dict
1943 segments->append(symbolDict);
1944
1945 return gTrue;
1946
1947 codeTableError:
1948 error(errSyntaxError, getPos(), "Missing code table in JBIG2 symbol dictionary");
1949 delete codeTables;
1950
1951 syntaxError:
1952 for (i = 0; i < numNewSyms; ++i) {
1953 if (bitmaps[numInputSyms + i]) {
1954 delete bitmaps[numInputSyms + i];
1955 }
1956 }
1957 gfree(bitmaps);
1958 if (symWidths) {
1959 gfree(symWidths);
1960 }
1961 return gFalse;
1962
1963 eofError:
1964 error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
1965 return gFalse;
1966 }
1967
1968 void JBIG2Stream::readTextRegionSeg(Guint segNum, GBool imm,
1969 GBool lossless, Guint length,
1970 Guint *refSegs, Guint nRefSegs) {
1971 JBIG2Bitmap *bitmap;
1972 JBIG2HuffmanTable runLengthTab[36];
1973 JBIG2HuffmanTable *symCodeTab;
1974 JBIG2HuffmanTable *huffFSTable, *huffDSTable, *huffDTTable;
1975 JBIG2HuffmanTable *huffRDWTable, *huffRDHTable;
1976 JBIG2HuffmanTable *huffRDXTable, *huffRDYTable, *huffRSizeTable;
1977 JBIG2Segment *seg;
1978 GList *codeTables;
1979 JBIG2SymbolDict *symbolDict;
1980 JBIG2Bitmap **syms;
1981 Guint w, h, x, y, segInfoFlags, extCombOp;
1982 Guint flags, huff, refine, logStrips, refCorner, transposed;
1983 Guint combOp, defPixel, templ;
1984 int sOffset;
1985 Guint huffFlags, huffFS, huffDS, huffDT;
1986 Guint huffRDW, huffRDH, huffRDX, huffRDY, huffRSize;
1987 Guint numInstances, numSyms, symCodeLen;
1988 int atx[2], aty[2];
1989 Guint i, k, kk;
1990 int j;
1991
1992 // region segment info field
1993 if (!readULong(&w) || !readULong(&h) ||
1994 !readULong(&x) || !readULong(&y) ||
1995 !readUByte(&segInfoFlags)) {
1996 goto eofError;
1997 }
1998 if (w == 0 || h == 0) {
1999 error(errSyntaxError, getPos(), "Bad size in JBIG2 text region segment");
2000 return;
2001 }
2002 // sanity check: if the w/h/x/y values are way out of range, it likely
2003 // indicates a damaged JBIG2 stream
2004 if (w / 10 > pageW || h / 10 > pageH ||
2005 x / 10 > pageW || y / 10 > pageH) {
2006 error(errSyntaxError, getPos(),
2007 "Bad size or position in JBIG2 text region segment");
2008 done = gTrue;
2009 return;
2010 }
2011 extCombOp = segInfoFlags & 7;
2012
2013 // rest of the text region header
2014 if (!readUWord(&flags)) {
2015 goto eofError;
2016 }
2017 huff = flags & 1;
2018 refine = (flags >> 1) & 1;
2019 logStrips = (flags >> 2) & 3;
2020 refCorner = (flags >> 4) & 3;
2021 transposed = (flags >> 6) & 1;
2022 combOp = (flags >> 7) & 3;
2023 defPixel = (flags >> 9) & 1;
2024 sOffset = (flags >> 10) & 0x1f;
2025 if (sOffset & 0x10) {
2026 sOffset |= -1 - 0x0f;
2027 }
2028 templ = (flags >> 15) & 1;
2029 huffFS = huffDS = huffDT = 0; // make gcc happy
2030 huffRDW = huffRDH = huffRDX = huffRDY = huffRSize = 0; // make gcc happy
2031 if (huff) {
2032 if (!readUWord(&huffFlags)) {
2033 goto eofError;
2034 }
2035 huffFS = huffFlags & 3;
2036 huffDS = (huffFlags >> 2) & 3;
2037 huffDT = (huffFlags >> 4) & 3;
2038 huffRDW = (huffFlags >> 6) & 3;
2039 huffRDH = (huffFlags >> 8) & 3;
2040 huffRDX = (huffFlags >> 10) & 3;
2041 huffRDY = (huffFlags >> 12) & 3;
2042 huffRSize = (huffFlags >> 14) & 1;
2043 }
2044 if (refine && templ == 0) {
2045 if (!readByte(&atx[0]) || !readByte(&aty[0]) ||
2046 !readByte(&atx[1]) || !readByte(&aty[1])) {
2047 goto eofError;
2048 }
2049 }
2050 if (!readULong(&numInstances)) {
2051 goto eofError;
2052 }
2053
2054 // get symbol dictionaries and tables
2055 codeTables = new GList();
2056 numSyms = 0;
2057 for (i = 0; i < nRefSegs; ++i) {
2058 if ((seg = findSegment(refSegs[i]))) {
2059 if (seg->getType() == jbig2SegSymbolDict) {
2060 Guint segSize = ((JBIG2SymbolDict *)seg)->getSize();
2061 if (segSize > INT_MAX || numSyms > INT_MAX - segSize) {
2062 error(errSyntaxError, getPos(),
2063 "Too many symbols in JBIG2 text region");
2064 delete codeTables;
2065 return;
2066 }
2067 numSyms += segSize;
2068 } else if (seg->getType() == jbig2SegCodeTable) {
2069 codeTables->append(seg);
2070 }
2071 } else {
2072 error(errSyntaxError, getPos(),
2073 "Invalid segment reference in JBIG2 text region");
2074 delete codeTables;
2075 return;
2076 }
2077 }
2078 i = numSyms;
2079 if (i <= 1) {
2080 symCodeLen = huff ? 1 : 0;
2081 } else {
2082 --i;
2083 symCodeLen = 0;
2084 // i = floor((numSyms-1) / 2^symCodeLen)
2085 while (i > 0) {
2086 ++symCodeLen;
2087 i >>= 1;
2088 }
2089 }
2090
2091 // get the symbol bitmaps
2092 syms = (JBIG2Bitmap **)gmallocn(numSyms, sizeof(JBIG2Bitmap *));
2093 kk = 0;
2094 for (i = 0; i < nRefSegs; ++i) {
2095 if ((seg = findSegment(refSegs[i]))) {
2096 if (seg->getType() == jbig2SegSymbolDict) {
2097 symbolDict = (JBIG2SymbolDict *)seg;
2098 for (k = 0; k < symbolDict->getSize(); ++k) {
2099 syms[kk++] = symbolDict->getBitmap(k);
2100 }
2101 }
2102 }
2103 }
2104
2105 // get the Huffman tables
2106 huffFSTable = huffDSTable = huffDTTable = NULL; // make gcc happy
2107 huffRDWTable = huffRDHTable = NULL; // make gcc happy
2108 huffRDXTable = huffRDYTable = huffRSizeTable = NULL; // make gcc happy
2109 i = 0;
2110 if (huff) {
2111 if (huffFS == 0) {
2112 huffFSTable = huffTableF;
2113 } else if (huffFS == 1) {
2114 huffFSTable = huffTableG;
2115 } else {
2116 if (i >= (Guint)codeTables->getLength()) {
2117 goto codeTableError;
2118 }
2119 huffFSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2120 }
2121 if (huffDS == 0) {
2122 huffDSTable = huffTableH;
2123 } else if (huffDS == 1) {
2124 huffDSTable = huffTableI;
2125 } else if (huffDS == 2) {
2126 huffDSTable = huffTableJ;
2127 } else {
2128 if (i >= (Guint)codeTables->getLength()) {
2129 goto codeTableError;
2130 }
2131 huffDSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2132 }
2133 if (huffDT == 0) {
2134 huffDTTable = huffTableK;
2135 } else if (huffDT == 1) {
2136 huffDTTable = huffTableL;
2137 } else if (huffDT == 2) {
2138 huffDTTable = huffTableM;
2139 } else {
2140 if (i >= (Guint)codeTables->getLength()) {
2141 goto codeTableError;
2142 }
2143 huffDTTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2144 }
2145 if (huffRDW == 0) {
2146 huffRDWTable = huffTableN;
2147 } else if (huffRDW == 1) {
2148 huffRDWTable = huffTableO;
2149 } else {
2150 if (i >= (Guint)codeTables->getLength()) {
2151 goto codeTableError;
2152 }
2153 huffRDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2154 }
2155 if (huffRDH == 0) {
2156 huffRDHTable = huffTableN;
2157 } else if (huffRDH == 1) {
2158 huffRDHTable = huffTableO;
2159 } else {
2160 if (i >= (Guint)codeTables->getLength()) {
2161 goto codeTableError;
2162 }
2163 huffRDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2164 }
2165 if (huffRDX == 0) {
2166 huffRDXTable = huffTableN;
2167 } else if (huffRDX == 1) {
2168 huffRDXTable = huffTableO;
2169 } else {
2170 if (i >= (Guint)codeTables->getLength()) {
2171 goto codeTableError;
2172 }
2173 huffRDXTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2174 }
2175 if (huffRDY == 0) {
2176 huffRDYTable = huffTableN;
2177 } else if (huffRDY == 1) {
2178 huffRDYTable = huffTableO;
2179 } else {
2180 if (i >= (Guint)codeTables->getLength()) {
2181 goto codeTableError;
2182 }
2183 huffRDYTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2184 }
2185 if (huffRSize == 0) {
2186 huffRSizeTable = huffTableA;
2187 } else {
2188 if (i >= (Guint)codeTables->getLength()) {
2189 goto codeTableError;
2190 }
2191 huffRSizeTable =
2192 ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
2193 }
2194 }
2195 delete codeTables;
2196
2197 // symbol ID Huffman decoding table
2198 if (huff) {
2199 huffDecoder->reset();
2200 for (i = 0; i < 32; ++i) {
2201 runLengthTab[i].val = i;
2202 runLengthTab[i].prefixLen = huffDecoder->readBits(4);
2203 runLengthTab[i].rangeLen = 0;
2204 runLengthTab[i].prefix = 0;
2205 }
2206 runLengthTab[32].val = 0x103;
2207 runLengthTab[32].prefixLen = huffDecoder->readBits(4);
2208 runLengthTab[32].rangeLen = 2;
2209 runLengthTab[32].prefix = 0;
2210 runLengthTab[33].val = 0x203;
2211 runLengthTab[33].prefixLen = huffDecoder->readBits(4);
2212 runLengthTab[33].rangeLen = 3;
2213 runLengthTab[33].prefix = 0;
2214 runLengthTab[34].val = 0x20b;
2215 runLengthTab[34].prefixLen = huffDecoder->readBits(4);
2216 runLengthTab[34].rangeLen = 7;
2217 runLengthTab[34].prefix = 0;
2218 runLengthTab[35].prefixLen = 0;
2219 runLengthTab[35].rangeLen = jbig2HuffmanEOT;
2220 runLengthTab[35].prefix = 0;
2221 huffDecoder->buildTable(runLengthTab, 35);
2222 symCodeTab = (JBIG2HuffmanTable *)gmallocn(numSyms + 1,
2223 sizeof(JBIG2HuffmanTable));
2224 for (i = 0; i < numSyms; ++i) {
2225 symCodeTab[i].val = i;
2226 symCodeTab[i].rangeLen = 0;
2227 }
2228 i = 0;
2229 while (i < numSyms) {
2230 huffDecoder->decodeInt(&j, runLengthTab);
2231 if (j > 0x200) {
2232 for (j -= 0x200; j && i < numSyms; --j) {
2233 symCodeTab[i++].prefixLen = 0;
2234 }
2235 } else if (j > 0x100) {
2236 if (i == 0) {
2237 error(errSyntaxError, getPos(), "Invalid code in JBIG2 text region");
2238 gfree(syms);
2239 gfree(symCodeTab);
2240 return;
2241 }
2242 for (j -= 0x100; j && i < numSyms; --j) {
2243 symCodeTab[i].prefixLen = symCodeTab[i-1].prefixLen;
2244 ++i;
2245 }
2246 } else {
2247 symCodeTab[i++].prefixLen = j;
2248 }
2249 }
2250 symCodeTab[numSyms].prefixLen = 0;
2251 symCodeTab[numSyms].rangeLen = jbig2HuffmanEOT;
2252 huffDecoder->buildTable(symCodeTab, numSyms);
2253 huffDecoder->reset();
2254
2255 // set up the arithmetic decoder
2256 } else {
2257 symCodeTab = NULL;
2258 resetIntStats(symCodeLen);
2259 arithDecoder->start();
2260 }
2261 if (refine) {
2262 resetRefinementStats(templ, NULL);
2263 }
2264
2265 bitmap = readTextRegion(huff, refine, w, h, numInstances,
2266 logStrips, numSyms, symCodeTab, symCodeLen, syms,
2267 defPixel, combOp, transposed, refCorner, sOffset,
2268 huffFSTable, huffDSTable, huffDTTable,
2269 huffRDWTable, huffRDHTable,
2270 huffRDXTable, huffRDYTable, huffRSizeTable,
2271 templ, atx, aty);
2272
2273 gfree(syms);
2274
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);
2279 }
2280 pageBitmap->combine(bitmap, x, y, extCombOp);
2281 delete bitmap;
2282
2283 // store the region bitmap
2284 } else {
2285 bitmap->setSegNum(segNum);
2286 segments->append(bitmap);
2287 }
2288
2289 // clean up the Huffman decoder
2290 if (huff) {
2291 gfree(symCodeTab);
2292 }
2293
2294 return;
2295
2296 codeTableError:
2297 error(errSyntaxError, getPos(), "Missing code table in JBIG2 text region");
2298 delete codeTables;
2299 gfree(syms);
2300 return;
2301
2302 eofError:
2303 error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
2304 return;
2305 }
2306
2307 JBIG2Bitmap *JBIG2Stream::readTextRegion(GBool huff, GBool refine,
2308 int w, int h,
2309 Guint numInstances,
2310 Guint logStrips,
2311 int numSyms,
2312 JBIG2HuffmanTable *symCodeTab,
2313 Guint symCodeLen,
2314 JBIG2Bitmap **syms,
2315 Guint defPixel, Guint combOp,
2316 Guint transposed, Guint refCorner,
2317 int sOffset,
2318 JBIG2HuffmanTable *huffFSTable,
2319 JBIG2HuffmanTable *huffDSTable,
2320 JBIG2HuffmanTable *huffDTTable,
2321 JBIG2HuffmanTable *huffRDWTable,
2322 JBIG2HuffmanTable *huffRDHTable,
2323 JBIG2HuffmanTable *huffRDXTable,
2324 JBIG2HuffmanTable *huffRDYTable,
2325 JBIG2HuffmanTable *huffRSizeTable,
2326 Guint templ,
2327 int *atx, int *aty) {
2328 JBIG2Bitmap *bitmap;
2329 JBIG2Bitmap *symbolBitmap;
2330 Guint strips;
2331 int t, dt, tt, s, ds, sFirst, j;
2332 int rdw, rdh, rdx, rdy, ri, refDX, refDY, bmSize;
2333 Guint symID, inst, bw, bh;
2334
2335 strips = 1 << logStrips;
2336
2337 // allocate the bitmap
2338 bitmap = new JBIG2Bitmap(0, w, h);
2339 if (defPixel) {
2340 bitmap->clearToOne();
2341 } else {
2342 bitmap->clearToZero();
2343 }
2344
2345 // decode initial T value
2346 if (huff) {
2347 huffDecoder->decodeInt(&t, huffDTTable);
2348 } else {
2349 arithDecoder->decodeInt(&t, iadtStats);
2350 }
2351 t *= -(int)strips;
2352
2353 inst = 0;
2354 sFirst = 0;
2355 while (inst < numInstances) {
2356
2357 // decode delta-T
2358 if (huff) {
2359 if (!huffDecoder->decodeInt(&dt, huffDTTable)) {
2360 break;
2361 }
2362 } else {
2363 if (!arithDecoder->decodeInt(&dt, iadtStats)) {
2364 break;
2365 }
2366 }
2367 t += dt * strips;
2368
2369 // first S value
2370 if (huff) {
2371 if (!huffDecoder->decodeInt(&ds, huffFSTable)) {
2372 break;
2373 }
2374 } else {
2375 if (!arithDecoder->decodeInt(&ds, iafsStats)) {
2376 break;
2377 }
2378 }
2379 sFirst += ds;
2380 s = sFirst;
2381
2382 // read the instances
2383 // (this loop test is here to avoid an infinite loop with damaged
2384 // JBIG2 streams where the normal loop exit doesn't get triggered)
2385 while (inst < numInstances) {
2386
2387 // T value
2388 if (strips == 1) {
2389 dt = 0;
2390 } else if (huff) {
2391 dt = huffDecoder->readBits(logStrips);
2392 } else {
2393 arithDecoder->decodeInt(&dt, iaitStats);
2394 }
2395 tt = t + dt;
2396
2397 // symbol ID
2398 if (huff) {
2399 if (symCodeTab) {
2400 huffDecoder->decodeInt(&j, symCodeTab);
2401 symID = (Guint)j;
2402 } else {
2403 symID = huffDecoder->readBits(symCodeLen);
2404 }
2405 } else {
2406 symID = arithDecoder->decodeIAID(symCodeLen, iaidStats);
2407 }
2408
2409 if (symID >= (Guint)numSyms) {
2410 error(errSyntaxError, getPos(),
2411 "Invalid symbol number in JBIG2 text region");
2412 } else {
2413
2414 // get the symbol bitmap
2415 symbolBitmap = NULL;
2416 if (refine) {
2417 if (huff) {
2418 ri = (int)huffDecoder->readBit();
2419 } else {
2420 arithDecoder->decodeInt(&ri, iariStats);
2421 }
2422 } else {
2423 ri = 0;
2424 }
2425 if (ri) {
2426 if (huff) {
2427 huffDecoder->decodeInt(&rdw, huffRDWTable);
2428 huffDecoder->decodeInt(&rdh, huffRDHTable);
2429 huffDecoder->decodeInt(&rdx, huffRDXTable);
2430 huffDecoder->decodeInt(&rdy, huffRDYTable);
2431 huffDecoder->decodeInt(&bmSize, huffRSizeTable);
2432 huffDecoder->reset();
2433 arithDecoder->start();
2434 } else {
2435 arithDecoder->decodeInt(&rdw, iardwStats);
2436 arithDecoder->decodeInt(&rdh, iardhStats);
2437 arithDecoder->decodeInt(&rdx, iardxStats);
2438 arithDecoder->decodeInt(&rdy, iardyStats);
2439 }
2440 refDX = ((rdw >= 0) ? rdw : rdw - 1) / 2 + rdx;
2441 refDY = ((rdh >= 0) ? rdh : rdh - 1) / 2 + rdy;
2442
2443 symbolBitmap =
2444 readGenericRefinementRegion(rdw + syms[symID]->getWidth(),
2445 rdh + syms[symID]->getHeight(),
2446 templ, gFalse, syms[symID],
2447 refDX, refDY, atx, aty);
2448 //~ do we need to use the bmSize value here (in Huffman mode)?
2449 } else {
2450 symbolBitmap = syms[symID];
2451 }
2452
2453 // combine the symbol bitmap into the region bitmap
2454 //~ something is wrong here - refCorner shouldn't degenerate into
2455 //~ two cases
2456 bw = symbolBitmap->getWidth() - 1;
2457 bh = symbolBitmap->getHeight() - 1;
2458 if (transposed) {
2459 switch (refCorner) {
2460 case 0: // bottom left
2461 bitmap->combine(symbolBitmap, tt, s, combOp);
2462 break;
2463 case 1: // top left
2464 bitmap->combine(symbolBitmap, tt, s, combOp);
2465 break;
2466 case 2: // bottom right
2467 bitmap->combine(symbolBitmap, tt - bw, s, combOp);
2468 break;
2469 case 3: // top right
2470 bitmap->combine(symbolBitmap, tt - bw, s, combOp);
2471 break;
2472 }
2473 s += bh;
2474 } else {
2475 switch (refCorner) {
2476 case 0: // bottom left
2477 bitmap->combine(symbolBitmap, s, tt - bh, combOp);
2478 break;
2479 case 1: // top left
2480 bitmap->combine(symbolBitmap, s, tt, combOp);
2481 break;
2482 case 2: // bottom right
2483 bitmap->combine(symbolBitmap, s, tt - bh, combOp);
2484 break;
2485 case 3: // top right
2486 bitmap->combine(symbolBitmap, s, tt, combOp);
2487 break;
2488 }
2489 s += bw;
2490 }
2491 if (ri) {
2492 delete symbolBitmap;
2493 }
2494 }
2495
2496 // next instance
2497 ++inst;
2498
2499 // next S value
2500 if (huff) {
2501 if (!huffDecoder->decodeInt(&ds, huffDSTable)) {
2502 break;
2503 }
2504 } else {
2505 if (!arithDecoder->decodeInt(&ds, iadsStats)) {
2506 break;
2507 }
2508 }
2509 s += sOffset + ds;
2510 }
2511 }
2512
2513 return bitmap;
2514 }
2515
2516 void JBIG2Stream::readPatternDictSeg(Guint segNum, Guint length) {
2517 JBIG2PatternDict *patternDict;
2518 JBIG2Bitmap *bitmap;
2519 Guint flags, patternW, patternH, grayMax, templ, mmr;
2520 int atx[4], aty[4];
2521 Guint i, x;
2522
2523 // halftone dictionary flags, pattern width and height, max gray value
2524 if (!readUByte(&flags) ||
2525 !readUByte(&patternW) ||
2526 !readUByte(&patternH) ||
2527 !readULong(&grayMax)) {
2528 goto eofError;
2529 }
2530 if (patternW == 0 || patternH == 0) {
2531 error(errSyntaxError, getPos(),
2532 "Bad size in JBIG2 pattern dictionary segment");
2533 return;
2534 }
2535 templ = (flags >> 1) & 3;
2536 mmr = flags & 1;
2537
2538 // set up the arithmetic decoder
2539 if (!mmr) {
2540 resetGenericStats(templ, NULL);
2541 arithDecoder->start();
2542 }
2543
2544 // read the bitmap
2545 atx[0] = -(int)patternW; aty[0] = 0;
2546 atx[1] = -3; aty[1] = -1;
2547 atx[2] = 2; aty[2] = -2;
2548 atx[3] = -2; aty[3] = -2;
2549 bitmap = readGenericBitmap(mmr, (grayMax + 1) * patternW, patternH,
2550 templ, gFalse, gFalse, NULL,
2551 atx, aty, length - 7);
2552
2553 // create the pattern dict object
2554 patternDict = new JBIG2PatternDict(segNum, grayMax + 1);
2555
2556 // split up the bitmap
2557 x = 0;
2558 for (i = 0; i <= grayMax; ++i) {
2559 patternDict->setBitmap(i, bitmap->getSlice(x, 0, patternW, patternH));
2560 x += patternW;
2561 }
2562
2563 // free memory
2564 delete bitmap;
2565
2566 // store the new pattern dict
2567 segments->append(patternDict);
2568
2569 return;
2570
2571 eofError:
2572 error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
2573 }
2574
2575 void JBIG2Stream::readHalftoneRegionSeg(Guint segNum, GBool imm,
2576 GBool lossless, Guint length,
2577 Guint *refSegs, Guint nRefSegs) {
2578 JBIG2Bitmap *bitmap;
2579 JBIG2Segment *seg;
2580 JBIG2PatternDict *patternDict;
2581 JBIG2Bitmap *skipBitmap;
2582 Guint *grayImg;
2583 JBIG2Bitmap *grayBitmap;
2584 JBIG2Bitmap *patternBitmap;
2585 Guint w, h, x, y, segInfoFlags, extCombOp;
2586 Guint flags, mmr, templ, enableSkip, combOp;
2587 Guint gridW, gridH, stepX, stepY, patW, patH;
2588 int atx[4], aty[4];
2589 int gridX, gridY, xx, yy, bit, j;
2590 Guint bpp, m, n, i;
2591
2592 // region segment info field
2593 if (!readULong(&w) || !readULong(&h) ||
2594 !readULong(&x) || !readULong(&y) ||
2595 !readUByte(&segInfoFlags)) {
2596 goto eofError;
2597 }
2598 // sanity check: if the w/h/x/y values are way out of range, it likely
2599 // indicates a damaged JBIG2 stream
2600 if (w / 10 > pageW || h / 10 > pageH ||
2601 x / 10 > pageW || y / 10 > pageH) {
2602 error(errSyntaxError, getPos(),
2603 "Bad size or position in JBIG2 halftone region segment");
2604 done = gTrue;
2605 return;
2606 }
2607 extCombOp = segInfoFlags & 7;
2608
2609 // rest of the halftone region header
2610 if (!readUByte(&flags)) {
2611 goto eofError;
2612 }
2613 mmr = flags & 1;
2614 templ = (flags >> 1) & 3;
2615 enableSkip = (flags >> 3) & 1;
2616 combOp = (flags >> 4) & 7;
2617 if (!readULong(&gridW) || !readULong(&gridH) ||
2618 !readLong(&gridX) || !readLong(&gridY) ||
2619 !readUWord(&stepX) || !readUWord(&stepY)) {
2620 goto eofError;
2621 }
2622 if (w == 0 || h == 0 || w >= INT_MAX / h) {
2623 error(errSyntaxError, getPos(),
2624 "Bad bitmap size in JBIG2 halftone segment");
2625 return;
2626 }
2627 if (gridW == 0 || gridH == 0 || gridW >= INT_MAX / gridH) {
2628 error(errSyntaxError, getPos(), "Bad grid size in JBIG2 halftone segment");
2629 return;
2630 }
2631
2632 // get pattern dictionary
2633 if (nRefSegs != 1) {
2634 error(errSyntaxError, getPos(),
2635 "Bad symbol dictionary reference in JBIG2 halftone segment");
2636 return;
2637 }
2638 if (!(seg = findSegment(refSegs[0])) ||
2639 seg->getType() != jbig2SegPatternDict) {
2640 error(errSyntaxError, getPos(),
2641 "Bad symbol dictionary reference in JBIG2 halftone segment");
2642 return;
2643 }
2644 patternDict = (JBIG2PatternDict *)seg;
2645 i = patternDict->getSize();
2646 if (i <= 1) {
2647 bpp = 0;
2648 } else {
2649 --i;
2650 bpp = 0;
2651 // i = floor((size-1) / 2^bpp)
2652 while (i > 0) {
2653 ++bpp;
2654 i >>= 1;
2655 }
2656 }
2657 patW = patternDict->getBitmap(0)->getWidth();
2658 patH = patternDict->getBitmap(0)->getHeight();
2659
2660 // set up the arithmetic decoder
2661 if (!mmr) {
2662 resetGenericStats(templ, NULL);
2663 arithDecoder->start();
2664 }
2665
2666 // allocate the bitmap
2667 bitmap = new JBIG2Bitmap(segNum, w, h);
2668 if (flags & 0x80) { // HDEFPIXEL
2669 bitmap->clearToOne();
2670 } else {
2671 bitmap->clearToZero();
2672 }
2673
2674 // compute the skip bitmap
2675 skipBitmap = NULL;
2676 if (enableSkip) {
2677 skipBitmap = new JBIG2Bitmap(0, gridW, gridH);
2678 skipBitmap->clearToZero();
2679 for (m = 0; m < gridH; ++m) {
2680 for (n = 0; n < gridW; ++n) {
2681 xx = gridX + m * stepY + n * stepX;
2682 yy = gridY + m * stepX - n * stepY;
2683 if (((xx + (int)patW) >> 8) <= 0 || (xx >> 8) >= (int)w ||
2684 ((yy + (int)patH) >> 8) <= 0 || (yy >> 8) >= (int)h) {
2685 skipBitmap->setPixel(n, m);
2686 }
2687 }
2688 }
2689 }
2690
2691 // read the gray-scale image
2692 grayImg = (Guint *)gmallocn(gridW * gridH, sizeof(Guint));
2693 memset(grayImg, 0, gridW * gridH * sizeof(Guint));
2694 atx[0] = templ <= 1 ? 3 : 2; aty[0] = -1;
2695 atx[1] = -3; aty[1] = -1;
2696 atx[2] = 2; aty[2] = -2;
2697 atx[3] = -2; aty[3] = -2;
2698 for (j = bpp - 1; j >= 0; --j) {
2699 grayBitmap = readGenericBitmap(mmr, gridW, gridH, templ, gFalse,
2700 enableSkip, skipBitmap, atx, aty, -1);
2701 i = 0;
2702 for (m = 0; m < gridH; ++m) {
2703 for (n = 0; n < gridW; ++n) {
2704 bit = grayBitmap->getPixel(n, m) ^ (grayImg[i] & 1);
2705 grayImg[i] = (grayImg[i] << 1) | bit;
2706 ++i;
2707 }
2708 }
2709 delete grayBitmap;
2710 }
2711
2712 // decode the image
2713 i = 0;
2714 for (m = 0; m < gridH; ++m) {
2715 xx = gridX + m * stepY;
2716 yy = gridY + m * stepX;
2717 for (n = 0; n < gridW; ++n) {
2718 if (!(enableSkip && skipBitmap->getPixel(n, m))) {
2719 patternBitmap = patternDict->getBitmap(grayImg[i]);
2720 bitmap->combine(patternBitmap, xx >> 8, yy >> 8, combOp);
2721 }
2722 xx += stepX;
2723 yy -= stepY;
2724 ++i;
2725 }
2726 }
2727
2728 gfree(grayImg);
2729 if (skipBitmap) {
2730 delete skipBitmap;
2731 }
2732
2733 // combine the region bitmap into the page bitmap
2734 if (imm) {
2735 if (pageH == 0xffffffff && y + h > curPageH) {
2736 pageBitmap->expand(y + h, pageDefPixel);
2737 }
2738 pageBitmap->combine(bitmap, x, y, extCombOp);
2739 delete bitmap;
2740
2741 // store the region bitmap
2742 } else {
2743 segments->append(bitmap);
2744 }
2745
2746 return;
2747
2748 eofError:
2749 error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
2750 }
2751
2752 void JBIG2Stream::readGenericRegionSeg(Guint segNum, GBool imm,
2753 GBool lossless, Guint length) {
2754 JBIG2Bitmap *bitmap;
2755 Guint w, h, x, y, segInfoFlags, extCombOp, rowCount;
2756 Guint flags, mmr, templ, tpgdOn;
2757 int atx[4], aty[4];
2758
2759 // region segment info field
2760 if (!readULong(&w) || !readULong(&h) ||
2761 !readULong(&x) || !readULong(&y) ||
2762 !readUByte(&segInfoFlags)) {
2763 goto eofError;
2764 }
2765 if (w == 0 || h == 0) {
2766 error(errSyntaxError, getPos(),
2767 "Bad bitmap size in JBIG2 generic region segment");
2768 return;
2769 }
2770 // sanity check: if the w/h/x/y values are way out of range, it likely
2771 // indicates a damaged JBIG2 stream
2772 if (w / 10 > pageW || h / 10 > pageH ||
2773 x / 10 > pageW || y / 10 > pageH) {
2774 error(errSyntaxError, getPos(),
2775 "Bad size or position in JBIG2 generic region segment");
2776 done = gTrue;
2777 return;
2778 }
2779 extCombOp = segInfoFlags & 7;
2780
2781 // rest of the generic region segment header
2782 if (!readUByte(&flags)) {
2783 goto eofError;
2784 }
2785 mmr = flags & 1;
2786 templ = (flags >> 1) & 3;
2787 tpgdOn = (flags >> 3) & 1;
2788
2789 // AT flags
2790 if (!mmr) {
2791 if (templ == 0) {
2792 if (!readByte(&atx[0]) ||
2793 !readByte(&aty[0]) ||
2794 !readByte(&atx[1]) ||
2795 !readByte(&aty[1]) ||
2796 !readByte(&atx[2]) ||
2797 !readByte(&aty[2]) ||
2798 !readByte(&atx[3]) ||
2799 !readByte(&aty[3])) {
2800 goto eofError;
2801 }
2802 } else {
2803 if (!readByte(&atx[0]) ||
2804 !readByte(&aty[0])) {
2805 goto eofError;
2806 }
2807 }
2808 }
2809
2810 // set up the arithmetic decoder
2811 if (!mmr) {
2812 resetGenericStats(templ, NULL);
2813 arithDecoder->start();
2814 }
2815
2816 // read the bitmap
2817 bitmap = readGenericBitmap(mmr, w, h, templ, tpgdOn, gFalse,
2818 NULL, atx, aty, mmr ? length - 18 : 0);
2819
2820 // combine the region bitmap into the page bitmap
2821 if (imm) {
2822 if (pageH == 0xffffffff && y + h > curPageH) {
2823 pageBitmap->expand(y + h, pageDefPixel);
2824 }
2825 pageBitmap->combine(bitmap, x, y, extCombOp);
2826 delete bitmap;
2827
2828 // store the region bitmap
2829 } else {
2830 bitmap->setSegNum(segNum);
2831 segments->append(bitmap);
2832 }
2833
2834 // immediate generic segments can have an unspecified length, in
2835 // which case, a row count is stored at the end of the segment
2836 if (imm && length == 0xffffffff) {
2837 readULong(&rowCount);
2838 }
2839
2840 return;
2841
2842 eofError:
2843 error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
2844 }
2845
2846 inline void JBIG2Stream::mmrAddPixels(int a1, int blackPixels,
2847 int *codingLine, int *a0i, int w) {
2848 if (a1 > codingLine[*a0i]) {
2849 if (a1 > w) {
2850 error(errSyntaxError, getPos(),
2851 "JBIG2 MMR row is wrong length ({0:d})", a1);
2852 a1 = w;
2853 }
2854 if ((*a0i & 1) ^ blackPixels) {
2855 ++*a0i;
2856 }
2857 codingLine[*a0i] = a1;
2858 }
2859 }
2860
2861 inline void JBIG2Stream::mmrAddPixelsNeg(int a1, int blackPixels,
2862 int *codingLine, int *a0i, int w) {
2863 if (a1 > codingLine[*a0i]) {
2864 if (a1 > w) {
2865 error(errSyntaxError, getPos(),
2866 "JBIG2 MMR row is wrong length ({0:d})", a1);
2867 a1 = w;
2868 }
2869 if ((*a0i & 1) ^ blackPixels) {
2870 ++*a0i;
2871 }
2872 codingLine[*a0i] = a1;
2873 } else if (a1 < codingLine[*a0i]) {
2874 if (a1 < 0) {
2875 error(errSyntaxError, getPos(), "Invalid JBIG2 MMR code");
2876 a1 = 0;
2877 }
2878 while (*a0i > 0 && a1 <= codingLine[*a0i - 1]) {
2879 --*a0i;
2880 }
2881 codingLine[*a0i] = a1;
2882 }
2883 }
2884
2885 JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h,
2886 int templ, GBool tpgdOn,
2887 GBool useSkip, JBIG2Bitmap *skip,
2888 int *atx, int *aty,
2889 int mmrDataLength) {
2890 JBIG2Bitmap *bitmap;
2891 GBool ltp;
2892 Guint ltpCX, cx, cx0, cx1, cx2;
2893 int *refLine, *codingLine;
2894 int code1, code2, code3;
2895 Guchar *p0, *p1, *p2, *pp;
2896 Guchar *atP0, *atP1, *atP2, *atP3;
2897 Guint buf0, buf1, buf2;
2898 Guint atBuf0, atBuf1, atBuf2, atBuf3;
2899 int atShift0, atShift1, atShift2, atShift3;
2900 Guchar mask;
2901 int x, y, x0, x1, a0i, b1i, blackPixels, pix, i;
2902
2903 bitmap = new JBIG2Bitmap(0, w, h);
2904 bitmap->clearToZero();
2905
2906 //----- MMR decode
2907
2908 if (mmr) {
2909
2910 mmrDecoder->reset();
2911 if (w > INT_MAX - 3) {
2912 error(errSyntaxError, getPos(), "Bad width in JBIG2 generic bitmap");
2913 // force a call to gmalloc(-1), which will throw an exception
2914 w = -4;
2915 }
2916 // 0 <= codingLine[0] < codingLine[1] < ... < codingLine[n] = w
2917 // ---> max codingLine size = w + 1
2918 // refLine has two extra guard entries at the end
2919 // ---> max refLine size = w + 3
2920 codingLine = (int *)gmallocn(w + 1, sizeof(int));
2921 refLine = (int *)gmallocn(w + 3, sizeof(int));
2922 codingLine[0] = w;
2923
2924 for (y = 0; y < h; ++y) {
2925
2926 // copy coding line to ref line
2927 for (i = 0; codingLine[i] < w; ++i) {
2928 refLine[i] = codingLine[i];
2929 }
2930 refLine[i++] = w;
2931 refLine[i++] = w;
2932 refLine[i] = w;
2933
2934 // decode a line
2935 codingLine[0] = 0;
2936 a0i = 0;
2937 b1i = 0;
2938 blackPixels = 0;
2939 // invariant:
2940 // refLine[b1i-1] <= codingLine[a0i] < refLine[b1i] < refLine[b1i+1] <= w
2941 // exception at left edge:
2942 // codingLine[a0i = 0] = refLine[b1i = 0] = 0 is possible
2943 // exception at right edge:
2944 // refLine[b1i] = refLine[b1i+1] = w is possible
2945 while (codingLine[a0i] < w) {
2946 code1 = mmrDecoder->get2DCode();
2947 switch (code1) {
2948 case twoDimPass:
2949 mmrAddPixels(refLine[b1i + 1], blackPixels, codingLine, &a0i, w);
2950 if (refLine[b1i + 1] < w) {
2951 b1i += 2;
2952 }
2953 break;
2954 case twoDimHoriz:
2955 code1 = code2 = 0;
2956 if (blackPixels) {
2957 do {
2958 code1 += code3 = mmrDecoder->getBlackCode();
2959 } while (code3 >= 64);
2960 do {
2961 code2 += code3 = mmrDecoder->getWhiteCode();
2962 } while (code3 >= 64);
2963 } else {
2964 do {
2965 code1 += code3 = mmrDecoder->getWhiteCode();
2966 } while (code3 >= 64);
2967 do {
2968 code2 += code3 = mmrDecoder->getBlackCode();
2969 } while (code3 >= 64);
2970 }
2971 mmrAddPixels(codingLine[a0i] + code1, blackPixels,
2972 codingLine, &a0i, w);
2973 if (codingLine[a0i] < w) {
2974 mmrAddPixels(codingLine[a0i] + code2, blackPixels ^ 1,
2975 codingLine, &a0i, w);
2976 }
2977 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
2978 b1i += 2;
2979 }
2980 break;
2981 case twoDimVertR3:
2982 mmrAddPixels(refLine[b1i] + 3, blackPixels, codingLine, &a0i, w);
2983 blackPixels ^= 1;
2984 if (codingLine[a0i] < w) {
2985 ++b1i;
2986 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
2987 b1i += 2;
2988 }
2989 }
2990 break;
2991 case twoDimVertR2:
2992 mmrAddPixels(refLine[b1i] + 2, blackPixels, codingLine, &a0i, w);
2993 blackPixels ^= 1;
2994 if (codingLine[a0i] < w) {
2995 ++b1i;
2996 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
2997 b1i += 2;
2998 }
2999 }
3000 break;
3001 case twoDimVertR1:
3002 mmrAddPixels(refLine[b1i] + 1, blackPixels, codingLine, &a0i, w);
3003 blackPixels ^= 1;
3004 if (codingLine[a0i] < w) {
3005 ++b1i;
3006 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
3007 b1i += 2;
3008 }
3009 }
3010 break;
3011 case twoDimVert0:
3012 mmrAddPixels(refLine[b1i], blackPixels, codingLine, &a0i, w);
3013 blackPixels ^= 1;
3014 if (codingLine[a0i] < w) {
3015 ++b1i;
3016 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
3017 b1i += 2;
3018 }
3019 }
3020 break;
3021 case twoDimVertL3:
3022 mmrAddPixelsNeg(refLine[b1i] - 3, blackPixels, codingLine, &a0i, w);
3023 blackPixels ^= 1;
3024 if (codingLine[a0i] < w) {
3025 if (b1i > 0) {
3026 --b1i;
3027 } else {
3028 ++b1i;
3029 }
3030 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
3031 b1i += 2;
3032 }
3033 }
3034 break;
3035 case twoDimVertL2:
3036 mmrAddPixelsNeg(refLine[b1i] - 2, blackPixels, codingLine, &a0i, w);
3037 blackPixels ^= 1;
3038 if (codingLine[a0i] < w) {
3039 if (b1i > 0) {
3040 --b1i;
3041 } else {
3042 ++b1i;
3043 }
3044 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
3045 b1i += 2;
3046 }
3047 }
3048 break;
3049 case twoDimVertL1:
3050 mmrAddPixelsNeg(refLine[b1i] - 1, blackPixels, codingLine, &a0i, w);
3051 blackPixels ^= 1;
3052 if (codingLine[a0i] < w) {
3053 if (b1i > 0) {
3054 --b1i;
3055 } else {
3056 ++b1i;
3057 }
3058 while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) {
3059 b1i += 2;
3060 }
3061 }
3062 break;
3063 case EOF:
3064 mmrAddPixels(w, 0, codingLine, &a0i, w);
3065 break;
3066 default:
3067 error(errSyntaxError, getPos(),
3068 "Illegal code in JBIG2 MMR bitmap data");
3069 mmrAddPixels(w, 0, codingLine, &a0i, w);
3070 break;
3071 }
3072 }
3073
3074 // convert the run lengths to a bitmap line
3075 i = 0;
3076 while (1) {
3077 if (codingLine[i] >= w) {
3078 break;
3079 }
3080 for (x = codingLine[i]; x < codingLine[i+1]; ++x) {
3081 bitmap->setPixel(x, y);
3082 }
3083 if (codingLine[i+1] >= w) {
3084 break;
3085 }
3086 i += 2;
3087 }
3088 }
3089
3090 if (mmrDataLength >= 0) {
3091 mmrDecoder->skipTo(mmrDataLength);
3092 } else {
3093 if (mmrDecoder->get24Bits() != 0x001001) {
3094 error(errSyntaxError, getPos(),
3095 "Missing EOFB in JBIG2 MMR bitmap data");
3096 }
3097 }
3098
3099 gfree(refLine);
3100 gfree(codingLine);
3101
3102 //----- arithmetic decode
3103
3104 } else {
3105 // set up the typical row context
3106 ltpCX = 0; // make gcc happy
3107 if (tpgdOn) {
3108 switch (templ) {
3109 case 0:
3110 ltpCX = 0x3953; // 001 11001 0101 0011
3111 break;
3112 case 1:
3113 ltpCX = 0x079a; // 0011 11001 101 0
3114 break;
3115 case 2:
3116 ltpCX = 0x0e3; // 001 1100 01 1
3117 break;
3118 case 3:
3119 ltpCX = 0x18b; // 01100 0101 1
3120 break;
3121 }
3122 }
3123
3124 ltp = 0;
3125 cx = cx0 = cx1 = cx2 = 0; // make gcc happy
3126 for (y = 0; y < h; ++y) {
3127
3128 // check for a "typical" (duplicate) row
3129 if (tpgdOn) {
3130 if (arithDecoder->decodeBit(ltpCX, genericRegionStats)) {
3131 ltp = !ltp;
3132 }
3133 if (ltp) {
3134 if (y > 0) {
3135 bitmap->duplicateRow(y, y-1);
3136 }
3137 continue;
3138 }
3139 }
3140
3141 switch (templ) {
3142 case 0:
3143
3144 // set up the context
3145 p2 = pp = bitmap->getDataPtr() + y * bitmap->getLineSize();
3146 buf2 = *p2++ << 8;
3147 if (y >= 1) {
3148 p1 = bitmap->getDataPtr() + (y - 1) * bitmap->getLineSize();
3149 buf1 = *p1++ << 8;
3150 if (y >= 2) {
3151 p0 = bitmap->getDataPtr() + (y - 2) * bitmap->getLineSize();
3152 buf0 = *p0++ << 8;
3153 } else {
3154 p0 = NULL;
3155 buf0 = 0;
3156 }
3157 } else {
3158 p1 = p0 = NULL;
3159 buf1 = buf0 = 0;
3160 }
3161
3162 if (atx[0] >= -8 && atx[0] <= 8 &&
3163 atx[1] >= -8 && atx[1] <= 8 &&
3164 atx[2] >= -8 && atx[2] <= 8 &&
3165 atx[3] >= -8 && atx[3] <= 8) {
3166 // set up the adaptive context
3167 if (aty[0] <= 0 && y + aty[0] >= 0) {
3168 atP0 = bitmap->getDataPtr() + (y + aty[0]) * bitmap->getLineSize();
3169 atBuf0 = *atP0++ << 8;
3170 } else {
3171 atP0 = NULL;
3172 atBuf0 = 0;
3173 }
3174 atShift0 = 15 - atx[0];
3175 if (aty[1] <= 0 && y + aty[1] >= 0) {
3176 atP1 = bitmap->getDataPtr() + (y + aty[1]) * bitmap->getLineSize();
3177 atBuf1 = *atP1++ << 8;
3178 } else {
3179 atP1 = NULL;
3180 atBuf1 = 0;
3181 }
3182 atShift1 = 15 - atx[1];
3183 if (aty[2] <= 0 && y + aty[2] >= 0) {
3184 atP2 = bitmap->getDataPtr() + (y + aty[2]) * bitmap->getLineSize();
3185 atBuf2 = *atP2++ << 8;
3186 } else {
3187 atP2 = NULL;
3188 atBuf2 = 0;
3189 }
3190 atShift2 = 15 - atx[2];
3191 if (aty[3] <= 0 && y + aty[3] >= 0) {
3192 atP3 = bitmap->getDataPtr() + (y + aty[3]) * bitmap->getLineSize();
3193 atBuf3 = *atP3++ << 8;
3194 } else {
3195 atP3 = NULL;
3196 atBuf3 = 0;
3197 }
3198 atShift3 = 15 - atx[3];
3199
3200 // decode the row
3201 for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3202 if (x0 + 8 < w) {
3203 if (p0) {
3204 buf0 |= *p0++;
3205 }
3206 if (p1) {
3207 buf1 |= *p1++;
3208 }
3209 buf2 |= *p2++;
3210 if (atP0) {
3211 atBuf0 |= *atP0++;
3212 }
3213 if (atP1) {
3214 atBuf1 |= *atP1++;
3215 }
3216 if (atP2) {
3217 atBuf2 |= *atP2++;
3218 }
3219 if (atP3) {
3220 atBuf3 |= *atP3++;
3221 }
3222 }
3223 for (x1 = 0, mask = 0x80;
3224 x1 < 8 && x < w;
3225 ++x1, ++x, mask = (Guchar)(mask >> 1)) {
3226
3227 // build the context
3228 cx0 = (buf0 >> 14) & 0x07;
3229 cx1 = (buf1 >> 13) & 0x1f;
3230 cx2 = (buf2 >> 16) & 0x0f;
3231 cx = (cx0 << 13) | (cx1 << 8) | (cx2 << 4) |
3232 (((atBuf0 >> atShift0) & 1) << 3) |
3233 (((atBuf1 >> atShift1) & 1) << 2) |
3234 (((atBuf2 >> atShift2) & 1) << 1) |
3235 ((atBuf3 >> atShift3) & 1);
3236
3237 // check for a skipped pixel
3238 if (!(useSkip && skip->getPixel(x, y))) {
3239
3240 // decode the pixel
3241 if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
3242 *pp |= mask;
3243 buf2 |= 0x8000;
3244 if (aty[0] == 0) {
3245 atBuf0 |= 0x8000;
3246 }
3247 if (aty[1] == 0) {
3248 atBuf1 |= 0x8000;
3249 }
3250 if (aty[2] == 0) {
3251 atBuf2 |= 0x8000;
3252 }
3253 if (aty[3] == 0) {
3254 atBuf3 |= 0x8000;
3255 }
3256 }
3257 }
3258
3259 // update the context
3260 buf0 <<= 1;
3261 buf1 <<= 1;
3262 buf2 <<= 1;
3263 atBuf0 <<= 1;
3264 atBuf1 <<= 1;
3265 atBuf2 <<= 1;
3266 atBuf3 <<= 1;
3267 }
3268 }
3269
3270 } else {
3271 // decode the row
3272 for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3273 if (x0 + 8 < w) {
3274 if (p0) {
3275 buf0 |= *p0++;
3276 }
3277 if (p1) {
3278 buf1 |= *p1++;
3279 }
3280 buf2 |= *p2++;
3281 }
3282 for (x1 = 0, mask = 0x80;
3283 x1 < 8 && x < w;
3284 ++x1, ++x, mask = (Guchar)(mask >> 1)) {
3285
3286 // build the context
3287 cx0 = (buf0 >> 14) & 0x07;
3288 cx1 = (buf1 >> 13) & 0x1f;
3289 cx2 = (buf2 >> 16) & 0x0f;
3290 cx = (cx0 << 13) | (cx1 << 8) | (cx2 << 4) |
3291 (bitmap->getPixel(x + atx[0], y + aty[0]) << 3) |
3292 (bitmap->getPixel(x + atx[1], y + aty[1]) << 2) |
3293 (bitmap->getPixel(x + atx[2], y + aty[2]) << 1) |
3294 bitmap->getPixel(x + atx[3], y + aty[3]);
3295
3296 // check for a skipped pixel
3297 if (!(useSkip && skip->getPixel(x, y))) {
3298
3299 // decode the pixel
3300 if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
3301 *pp |= mask;
3302 buf2 |= 0x8000;
3303 }
3304 }
3305
3306 // update the context
3307 buf0 <<= 1;
3308 buf1 <<= 1;
3309 buf2 <<= 1;
3310 }
3311 }
3312 }
3313 break;
3314
3315 case 1:
3316
3317 // set up the context
3318 p2 = pp = bitmap->getDataPtr() + y * bitmap->getLineSize();
3319 buf2 = *p2++ << 8;
3320 if (y >= 1) {
3321 p1 = bitmap->getDataPtr() + (y - 1) * bitmap->getLineSize();
3322 buf1 = *p1++ << 8;
3323 if (y >= 2) {
3324 p0 = bitmap->getDataPtr() + (y - 2) * bitmap->getLineSize();
3325 buf0 = *p0++ << 8;
3326 } else {
3327 p0 = NULL;
3328 buf0 = 0;
3329 }
3330 } else {
3331 p1 = p0 = NULL;
3332 buf1 = buf0 = 0;
3333 }
3334
3335 if (atx[0] >= -8 && atx[0] <= 8) {
3336 // set up the adaptive context
3337 if (aty[0] <= 0 && y + aty[0] >= 0) {
3338 atP0 = bitmap->getDataPtr() + (y + aty[0]) * bitmap->getLineSize();
3339 atBuf0 = *atP0++ << 8;
3340 } else {
3341 atP0 = NULL;
3342 atBuf0 = 0;
3343 }
3344 atShift0 = 15 - atx[0];
3345
3346 // decode the row
3347 for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3348 if (x0 + 8 < w) {
3349 if (p0) {
3350 buf0 |= *p0++;
3351 }
3352 if (p1) {
3353 buf1 |= *p1++;
3354 }
3355 buf2 |= *p2++;
3356 if (atP0) {
3357 atBuf0 |= *atP0++;
3358 }
3359 }
3360 for (x1 = 0, mask = 0x80;
3361 x1 < 8 && x < w;
3362 ++x1, ++x, mask = (Guchar)(mask >> 1)) {
3363
3364 // build the context
3365 cx0 = (buf0 >> 13) & 0x0f;
3366 cx1 = (buf1 >> 13) & 0x1f;
3367 cx2 = (buf2 >> 16) & 0x07;
3368 cx = (cx0 << 9) | (cx1 << 4) | (cx2 << 1) |
3369 ((atBuf0 >> atShift0) & 1);
3370
3371 // check for a skipped pixel
3372 if (!(useSkip && skip->getPixel(x, y))) {
3373
3374 // decode the pixel
3375 if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
3376 *pp |= mask;
3377 buf2 |= 0x8000;
3378 if (aty[0] == 0) {
3379 atBuf0 |= 0x8000;
3380 }
3381 }
3382 }
3383
3384 // update the context
3385 buf0 <<= 1;
3386 buf1 <<= 1;
3387 buf2 <<= 1;
3388 atBuf0 <<= 1;
3389 }
3390 }
3391
3392 } else {
3393 // decode the row
3394 for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3395 if (x0 + 8 < w) {
3396 if (p0) {
3397 buf0 |= *p0++;
3398 }
3399 if (p1) {
3400 buf1 |= *p1++;
3401 }
3402 buf2 |= *p2++;
3403 }
3404 for (x1 = 0, mask = 0x80;
3405 x1 < 8 && x < w;
3406 ++x1, ++x, mask = (Guchar)(mask >> 1)) {
3407
3408 // build the context
3409 cx0 = (buf0 >> 13) & 0x0f;
3410 cx1 = (buf1 >> 13) & 0x1f;
3411 cx2 = (buf2 >> 16) & 0x07;
3412 cx = (cx0 << 9) | (cx1 << 4) | (cx2 << 1) |
3413 bitmap->getPixel(x + atx[0], y + aty[0]);
3414
3415 // check for a skipped pixel
3416 if (!(useSkip && skip->getPixel(x, y))) {
3417
3418 // decode the pixel
3419 if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
3420 *pp |= mask;
3421 buf2 |= 0x8000;
3422 }
3423 }
3424
3425 // update the context
3426 buf0 <<= 1;
3427 buf1 <<= 1;
3428 buf2 <<= 1;
3429 }
3430 }
3431 }
3432 break;
3433
3434 case 2:
3435
3436 // set up the context
3437 p2 = pp = bitmap->getDataPtr() + y * bitmap->getLineSize();
3438 buf2 = *p2++ << 8;
3439 if (y >= 1) {
3440 p1 = bitmap->getDataPtr() + (y - 1) * bitmap->getLineSize();
3441 buf1 = *p1++ << 8;
3442 if (y >= 2) {
3443 p0 = bitmap->getDataPtr() + (y - 2) * bitmap->getLineSize();
3444 buf0 = *p0++ << 8;
3445 } else {
3446 p0 = NULL;
3447 buf0 = 0;
3448 }
3449 } else {
3450 p1 = p0 = NULL;
3451 buf1 = buf0 = 0;
3452 }
3453
3454 if (atx[0] >= -8 && atx[0] <= 8) {
3455 // set up the adaptive context
3456 if (aty[0] <= 0 && y + aty[0] >= 0) {
3457 atP0 = bitmap->getDataPtr() + (y + aty[0]) * bitmap->getLineSize();
3458 atBuf0 = *atP0++ << 8;
3459 } else {
3460 atP0 = NULL;
3461 atBuf0 = 0;
3462 }
3463 atShift0 = 15 - atx[0];
3464
3465 // decode the row
3466 for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3467 if (x0 + 8 < w) {
3468 if (p0) {
3469 buf0 |= *p0++;
3470 }
3471 if (p1) {
3472 buf1 |= *p1++;
3473 }
3474 buf2 |= *p2++;
3475 if (atP0) {
3476 atBuf0 |= *atP0++;
3477 }
3478 }
3479 for (x1 = 0, mask = 0x80;
3480 x1 < 8 && x < w;
3481 ++x1, ++x, mask = (Guchar)(mask >> 1)) {
3482
3483 // build the context
3484 cx0 = (buf0 >> 14) & 0x07;
3485 cx1 = (buf1 >> 14) & 0x0f;
3486 cx2 = (buf2 >> 16) & 0x03;
3487 cx = (cx0 << 7) | (cx1 << 3) | (cx2 << 1) |
3488 ((atBuf0 >> atShift0) & 1);
3489
3490 // check for a skipped pixel
3491 if (!(useSkip && skip->getPixel(x, y))) {
3492
3493 // decode the pixel
3494 if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
3495 *pp |= mask;
3496 buf2 |= 0x8000;
3497 if (aty[0] == 0) {
3498 atBuf0 |= 0x8000;
3499 }
3500 }
3501 }
3502
3503 // update the context
3504 buf0 <<= 1;
3505 buf1 <<= 1;
3506 buf2 <<= 1;
3507 atBuf0 <<= 1;
3508 }
3509 }
3510
3511 } else {
3512 // decode the row
3513 for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3514 if (x0 + 8 < w) {
3515 if (p0) {
3516 buf0 |= *p0++;
3517 }
3518 if (p1) {
3519 buf1 |= *p1++;
3520 }
3521 buf2 |= *p2++;
3522 }
3523 for (x1 = 0, mask = 0x80;
3524 x1 < 8 && x < w;
3525 ++x1, ++x, mask = (Guchar)(mask >> 1)) {
3526
3527 // build the context
3528 cx0 = (buf0 >> 14) & 0x07;
3529 cx1 = (buf1 >> 14) & 0x0f;
3530 cx2 = (buf2 >> 16) & 0x03;
3531 cx = (cx0 << 7) | (cx1 << 3) | (cx2 << 1) |
3532 bitmap->getPixel(x + atx[0], y + aty[0]);
3533
3534 // check for a skipped pixel
3535 if (!(useSkip && skip->getPixel(x, y))) {
3536
3537 // decode the pixel
3538 if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
3539 *pp |= mask;
3540 buf2 |= 0x8000;
3541 }
3542 }
3543
3544 // update the context
3545 buf0 <<= 1;
3546 buf1 <<= 1;
3547 buf2 <<= 1;
3548 }
3549 }
3550 }
3551 break;
3552
3553 case 3:
3554
3555 // set up the context
3556 p2 = pp = bitmap->getDataPtr() + y * bitmap->getLineSize();
3557 buf2 = *p2++ << 8;
3558 if (y >= 1) {
3559 p1 = bitmap->getDataPtr() + (y - 1) * bitmap->getLineSize();
3560 buf1 = *p1++ << 8;
3561 } else {
3562 p1 = NULL;
3563 buf1 = 0;
3564 }
3565
3566 if (atx[0] >= -8 && atx[0] <= 8) {
3567 // set up the adaptive context
3568 if (aty[0] <= 0 && y + aty[0] >= 0) {
3569 atP0 = bitmap->getDataPtr() + (y + aty[0]) * bitmap->getLineSize();
3570 atBuf0 = *atP0++ << 8;
3571 } else {
3572 atP0 = NULL;
3573 atBuf0 = 0;
3574 }
3575 atShift0 = 15 - atx[0];
3576
3577 // decode the row
3578 for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3579 if (x0 + 8 < w) {
3580 if (p1) {
3581 buf1 |= *p1++;
3582 }
3583 buf2 |= *p2++;
3584 if (atP0) {
3585 atBuf0 |= *atP0++;
3586 }
3587 }
3588 for (x1 = 0, mask = 0x80;
3589 x1 < 8 && x < w;
3590 ++x1, ++x, mask = (Guchar)(mask >> 1)) {
3591
3592 // build the context
3593 cx1 = (buf1 >> 14) & 0x1f;
3594 cx2 = (buf2 >> 16) & 0x0f;
3595 cx = (cx1 << 5) | (cx2 << 1) |
3596 ((atBuf0 >> atShift0) & 1);
3597
3598 // check for a skipped pixel
3599 if (!(useSkip && skip->getPixel(x, y))) {
3600
3601 // decode the pixel
3602 if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
3603 *pp |= mask;
3604 buf2 |= 0x8000;
3605 if (aty[0] == 0) {
3606 atBuf0 |= 0x8000;
3607 }
3608 }
3609 }
3610
3611 // update the context
3612 buf1 <<= 1;
3613 buf2 <<= 1;
3614 atBuf0 <<= 1;
3615 }
3616 }
3617
3618 } else {
3619 // decode the row
3620 for (x0 = 0, x = 0; x0 < w; x0 += 8, ++pp) {
3621 if (x0 + 8 < w) {
3622 if (p1) {
3623 buf1 |= *p1++;
3624 }
3625 buf2 |= *p2++;
3626 }
3627 for (x1 = 0, mask = 0x80;
3628 x1 < 8 && x < w;
3629 ++x1, ++x, mask = (Guchar)(mask >> 1)) {
3630
3631 // build the context
3632 cx1 = (buf1 >> 14) & 0x1f;
3633 cx2 = (buf2 >> 16) & 0x0f;
3634 cx = (cx1 << 5) | (cx2 << 1) |
3635 bitmap->getPixel(x + atx[0], y + aty[0]);
3636
3637 // check for a skipped pixel
3638 if (!(useSkip && skip->getPixel(x, y))) {
3639
3640 // decode the pixel
3641 if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) {
3642 *pp |= mask;
3643 buf2 |= 0x8000;
3644 }
3645 }
3646
3647 // update the context
3648 buf1 <<= 1;
3649 buf2 <<= 1;
3650 }
3651 }
3652 }
3653 break;
3654 }
3655 }
3656 }
3657
3658 return bitmap;
3659 }
3660
3661 void JBIG2Stream::readGenericRefinementRegionSeg(Guint segNum, GBool imm,
3662 GBool lossless, Guint length,
3663 Guint *refSegs,
3664 Guint nRefSegs) {
3665 JBIG2Bitmap *bitmap, *refBitmap;
3666 Guint w, h, x, y, segInfoFlags, extCombOp;
3667 Guint flags, templ, tpgrOn;
3668 int atx[2], aty[2];
3669 JBIG2Segment *seg;
3670
3671 // region segment info field
3672 if (!readULong(&w) || !readULong(&h) ||
3673 !readULong(&x) || !readULong(&y) ||
3674 !readUByte(&segInfoFlags)) {
3675 goto eofError;
3676 }
3677 if (w == 0 || h == 0) {
3678 error(errSyntaxError, getPos(),
3679 "Bad size in JBIG2 generic refinement region segment");
3680 return;
3681 }
3682 // sanity check: if the w/h/x/y values are way out of range, it likely
3683 // indicates a damaged JBIG2 stream
3684 if (w / 10 > pageW || h / 10 > pageH ||
3685 x / 10 > pageW || y / 10 > pageH) {
3686 error(errSyntaxError, getPos(),
3687 "Bad size or position in JBIG2 generic refinement region segment");
3688 done = gTrue;
3689 return;
3690 }
3691 extCombOp = segInfoFlags & 7;
3692
3693 // rest of the generic refinement region segment header
3694 if (!readUByte(&flags)) {
3695 goto eofError;
3696 }
3697 templ = flags & 1;
3698 tpgrOn = (flags >> 1) & 1;
3699
3700 // AT flags
3701 if (!templ) {
3702 if (!readByte(&atx[0]) || !readByte(&aty[0]) ||
3703 !readByte(&atx[1]) || !readByte(&aty[1])) {
3704 goto eofError;
3705 }
3706 }
3707
3708 // resize the page bitmap if needed
3709 if (nRefSegs == 0 || imm) {
3710 if (pageH == 0xffffffff && y + h > curPageH) {
3711 pageBitmap->expand(y + h, pageDefPixel);
3712 }
3713 }
3714
3715 // get referenced bitmap
3716 if (nRefSegs > 1) {
3717 error(errSyntaxError, getPos(),
3718 "Bad reference in JBIG2 generic refinement segment");
3719 return;
3720 }
3721 if (nRefSegs == 1) {
3722 if (!(seg = findSegment(refSegs[0])) ||
3723 seg->getType() != jbig2SegBitmap) {
3724 error(errSyntaxError, getPos(),
3725 "Bad bitmap reference in JBIG2 generic refinement segment");
3726 return;
3727 }
3728 refBitmap = (JBIG2Bitmap *)seg;
3729 } else {
3730 refBitmap = pageBitmap->getSlice(x, y, w, h);
3731 }
3732
3733 // set up the arithmetic decoder
3734 resetRefinementStats(templ, NULL);
3735 arithDecoder->start();
3736
3737 // read
3738 bitmap = readGenericRefinementRegion(w, h, templ, tpgrOn,
3739 refBitmap, 0, 0, atx, aty);
3740
3741 // combine the region bitmap into the page bitmap
3742 if (imm) {
3743 pageBitmap->combine(bitmap, x, y, extCombOp);
3744 delete bitmap;
3745
3746 // store the region bitmap
3747 } else {
3748 bitmap->setSegNum(segNum);
3749 segments->append(bitmap);
3750 }
3751
3752 // delete the referenced bitmap
3753 if (nRefSegs == 1) {
3754 discardSegment(refSegs[0]);
3755 } else {
3756 delete refBitmap;
3757 }
3758
3759 return;
3760
3761 eofError:
3762 error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
3763 }
3764
3765 JBIG2Bitmap *JBIG2Stream::readGenericRefinementRegion(int w, int h,
3766 int templ, GBool tpgrOn,
3767 JBIG2Bitmap *refBitmap,
3768 int refDX, int refDY,
3769 int *atx, int *aty) {
3770 JBIG2Bitmap *bitmap;
3771 GBool ltp;
3772 Guint ltpCX, cx, cx0, cx2, cx3, cx4, tpgrCX0, tpgrCX1, tpgrCX2;
3773 JBIG2BitmapPtr cxPtr0, cxPtr1, cxPtr2, cxPtr3, cxPtr4, cxPtr5, cxPtr6;
3774 JBIG2BitmapPtr tpgrCXPtr0, tpgrCXPtr1, tpgrCXPtr2;
3775 int x, y, pix;
3776
3777 bitmap = new JBIG2Bitmap(0, w, h);
3778 bitmap->clearToZero();
3779
3780 // set up the typical row context
3781 if (templ) {
3782 ltpCX = 0x008;
3783 } else {
3784 ltpCX = 0x0010;
3785 }
3786
3787 ltp = 0;
3788 for (y = 0; y < h; ++y) {
3789
3790 if (templ) {
3791
3792 // set up the context
3793 bitmap->getPixelPtr(0, y-1, &cxPtr0);
3794 cx0 = bitmap->nextPixel(&cxPtr0);
3795 bitmap->getPixelPtr(-1, y, &cxPtr1);
3796 refBitmap->getPixelPtr(-refDX, y-1-refDY, &cxPtr2);
3797 refBitmap->getPixelPtr(-1-refDX, y-refDY, &cxPtr3);
3798 cx3 = refBitmap->nextPixel(&cxPtr3);
3799 cx3 = (cx3 << 1) | refBitmap->nextPixel(&cxPtr3);
3800 refBitmap->getPixelPtr(-refDX, y+1-refDY, &cxPtr4);
3801 cx4 = refBitmap->nextPixel(&cxPtr4);
3802
3803 // set up the typical prediction context
3804 tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy
3805 if (tpgrOn) {
3806 refBitmap->getPixelPtr(-1-refDX, y-1-refDY, &tpgrCXPtr0);
3807 tpgrCX0 = refBitmap->nextPixel(&tpgrCXPtr0);
3808 tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
3809 tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
3810 refBitmap->getPixelPtr(-1-refDX, y-refDY, &tpgrCXPtr1);
3811 tpgrCX1 = refBitmap->nextPixel(&tpgrCXPtr1);
3812 tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
3813 tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
3814 refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &tpgrCXPtr2);
3815 tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2);
3816 tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
3817 tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
3818 } else {
3819 tpgrCXPtr0.p = tpgrCXPtr1.p = tpgrCXPtr2.p = NULL; // make gcc happy
3820 tpgrCXPtr0.shift = tpgrCXPtr1.shift = tpgrCXPtr2.shift = 0;
3821 tpgrCXPtr0.x = tpgrCXPtr1.x = tpgrCXPtr2.x = 0;
3822 }
3823
3824 for (x = 0; x < w; ++x) {
3825
3826 // update the context
3827 cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 7;
3828 cx3 = ((cx3 << 1) | refBitmap->nextPixel(&cxPtr3)) & 7;
3829 cx4 = ((cx4 << 1) | refBitmap->nextPixel(&cxPtr4)) & 3;
3830
3831 if (tpgrOn) {
3832 // update the typical predictor context
3833 tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0)) & 7;
3834 tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1)) & 7;
3835 tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2)) & 7;
3836
3837 // check for a "typical" pixel
3838 if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) {
3839 ltp = !ltp;
3840 }
3841 if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) {
3842 bitmap->clearPixel(x, y);
3843 continue;
3844 } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) {
3845 bitmap->setPixel(x, y);
3846 continue;
3847 }
3848 }
3849
3850 // build the context
3851 cx = (cx0 << 7) | (bitmap->nextPixel(&cxPtr1) << 6) |
3852 (refBitmap->nextPixel(&cxPtr2) << 5) |
3853 (cx3 << 2) | cx4;
3854
3855 // decode the pixel
3856 if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) {
3857 bitmap->setPixel(x, y);
3858 }
3859 }
3860
3861 } else {
3862
3863 // set up the context
3864 bitmap->getPixelPtr(0, y-1, &cxPtr0);
3865 cx0 = bitmap->nextPixel(&cxPtr0);
3866 bitmap->getPixelPtr(-1, y, &cxPtr1);
3867 refBitmap->getPixelPtr(-refDX, y-1-refDY, &cxPtr2);
3868 cx2 = refBitmap->nextPixel(&cxPtr2);
3869 refBitmap->getPixelPtr(-1-refDX, y-refDY, &cxPtr3);
3870 cx3 = refBitmap->nextPixel(&cxPtr3);
3871 cx3 = (cx3 << 1) | refBitmap->nextPixel(&cxPtr3);
3872 refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &cxPtr4);
3873 cx4 = refBitmap->nextPixel(&cxPtr4);
3874 cx4 = (cx4 << 1) | refBitmap->nextPixel(&cxPtr4);
3875 bitmap->getPixelPtr(atx[0], y+aty[0], &cxPtr5);
3876 refBitmap->getPixelPtr(atx[1]-refDX, y+aty[1]-refDY, &cxPtr6);
3877
3878 // set up the typical prediction context
3879 tpgrCX0 = tpgrCX1 = tpgrCX2 = 0; // make gcc happy
3880 if (tpgrOn) {
3881 refBitmap->getPixelPtr(-1-refDX, y-1-refDY, &tpgrCXPtr0);
3882 tpgrCX0 = refBitmap->nextPixel(&tpgrCXPtr0);
3883 tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
3884 tpgrCX0 = (tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0);
3885 refBitmap->getPixelPtr(-1-refDX, y-refDY, &tpgrCXPtr1);
3886 tpgrCX1 = refBitmap->nextPixel(&tpgrCXPtr1);
3887 tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
3888 tpgrCX1 = (tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1);
3889 refBitmap->getPixelPtr(-1-refDX, y+1-refDY, &tpgrCXPtr2);
3890 tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2);
3891 tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
3892 tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2);
3893 } else {
3894 tpgrCXPtr0.p = tpgrCXPtr1.p = tpgrCXPtr2.p = NULL; // make gcc happy
3895 tpgrCXPtr0.shift = tpgrCXPtr1.shift = tpgrCXPtr2.shift = 0;
3896 tpgrCXPtr0.x = tpgrCXPtr1.x = tpgrCXPtr2.x = 0;
3897 }
3898
3899 for (x = 0; x < w; ++x) {
3900
3901 // update the context
3902 cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 3;
3903 cx2 = ((cx2 << 1) | refBitmap->nextPixel(&cxPtr2)) & 3;
3904 cx3 = ((cx3 << 1) | refBitmap->nextPixel(&cxPtr3)) & 7;
3905 cx4 = ((cx4 << 1) | refBitmap->nextPixel(&cxPtr4)) & 7;
3906
3907 if (tpgrOn) {
3908 // update the typical predictor context
3909 tpgrCX0 = ((tpgrCX0 << 1) | refBitmap->nextPixel(&tpgrCXPtr0)) & 7;
3910 tpgrCX1 = ((tpgrCX1 << 1) | refBitmap->nextPixel(&tpgrCXPtr1)) & 7;
3911 tpgrCX2 = ((tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2)) & 7;
3912
3913 // check for a "typical" pixel
3914 if (arithDecoder->decodeBit(ltpCX, refinementRegionStats)) {
3915 ltp = !ltp;
3916 }
3917 if (tpgrCX0 == 0 && tpgrCX1 == 0 && tpgrCX2 == 0) {
3918 bitmap->clearPixel(x, y);
3919 continue;
3920 } else if (tpgrCX0 == 7 && tpgrCX1 == 7 && tpgrCX2 == 7) {
3921 bitmap->setPixel(x, y);
3922 continue;
3923 }
3924 }
3925
3926 // build the context
3927 cx = (cx0 << 11) | (bitmap->nextPixel(&cxPtr1) << 10) |
3928 (cx2 << 8) | (cx3 << 5) | (cx4 << 2) |
3929 (bitmap->nextPixel(&cxPtr5) << 1) |
3930 refBitmap->nextPixel(&cxPtr6);
3931
3932 // decode the pixel
3933 if ((pix = arithDecoder->decodeBit(cx, refinementRegionStats))) {
3934 bitmap->setPixel(x, y);
3935 }
3936 }
3937 }
3938 }
3939
3940 return bitmap;
3941 }
3942
3943 void JBIG2Stream::readPageInfoSeg(Guint length) {
3944 Guint xRes, yRes, flags, striping;
3945
3946 if (!readULong(&pageW) || !readULong(&pageH) ||
3947 !readULong(&xRes) || !readULong(&yRes) ||
3948 !readUByte(&flags) || !readUWord(&striping)) {
3949 goto eofError;
3950 }
3951 if (pageW == 0 || pageH == 0 || pageW > INT_MAX / pageW) {
3952 error(errSyntaxError, getPos(), "Bad page size in JBIG2 stream");
3953 return;
3954 }
3955 pageDefPixel = (flags >> 2) & 1;
3956 defCombOp = (flags >> 3) & 3;
3957
3958 // this will only happen if there are multiple page info segments
3959 if (pageBitmap) {
3960 delete pageBitmap;
3961 }
3962
3963 // allocate the page bitmap
3964 if (pageH == 0xffffffff) {
3965 curPageH = striping & 0x7fff;
3966 } else {
3967 curPageH = pageH;
3968 }
3969 pageBitmap = new JBIG2Bitmap(0, pageW, curPageH);
3970
3971 // default pixel value
3972 if (pageDefPixel) {
3973 pageBitmap->clearToOne();
3974 } else {
3975 pageBitmap->clearToZero();
3976 }
3977
3978 return;
3979
3980 eofError:
3981 error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
3982 }
3983
3984 void JBIG2Stream::readEndOfStripeSeg(Guint length) {
3985 // skip the segment
3986 byteCounter += curStr->discardChars(length);
3987 }
3988
3989 void JBIG2Stream::readProfilesSeg(Guint length) {
3990 // skip the segment
3991 byteCounter += curStr->discardChars(length);
3992 }
3993
3994 void JBIG2Stream::readCodeTableSeg(Guint segNum, Guint length) {
3995 JBIG2HuffmanTable *huffTab;
3996 Guint flags, oob, prefixBits, rangeBits;
3997 int lowVal, highVal, val;
3998 Guint huffTabSize, i;
3999
4000 if (!readUByte(&flags) || !readLong(&lowVal) || !readLong(&highVal)) {
4001 goto eofError;
4002 }
4003 oob = flags & 1;
4004 prefixBits = ((flags >> 1) & 7) + 1;
4005 rangeBits = ((flags >> 4) & 7) + 1;
4006
4007 huffDecoder->reset();
4008 huffTabSize = 8;
4009 huffTab = (JBIG2HuffmanTable *)
4010 gmallocn(huffTabSize, sizeof(JBIG2HuffmanTable));
4011 i = 0;
4012 val = lowVal;
4013 while (val < highVal) {
4014 if (i == huffTabSize) {
4015 huffTabSize *= 2;
4016 huffTab = (JBIG2HuffmanTable *)
4017 greallocn(huffTab, huffTabSize, sizeof(JBIG2HuffmanTable));
4018 }
4019 huffTab[i].val = val;
4020 huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
4021 huffTab[i].rangeLen = huffDecoder->readBits(rangeBits);
4022 val += 1 << huffTab[i].rangeLen;
4023 ++i;
4024 }
4025 if (i + oob + 3 > huffTabSize) {
4026 huffTabSize = i + oob + 3;
4027 huffTab = (JBIG2HuffmanTable *)
4028 greallocn(huffTab, huffTabSize, sizeof(JBIG2HuffmanTable));
4029 }
4030 huffTab[i].val = lowVal - 1;
4031 huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
4032 huffTab[i].rangeLen = jbig2HuffmanLOW;
4033 ++i;
4034 huffTab[i].val = highVal;
4035 huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
4036 huffTab[i].rangeLen = 32;
4037 ++i;
4038 if (oob) {
4039 huffTab[i].val = 0;
4040 huffTab[i].prefixLen = huffDecoder->readBits(prefixBits);
4041 huffTab[i].rangeLen = jbig2HuffmanOOB;
4042 ++i;
4043 }
4044 huffTab[i].val = 0;
4045 huffTab[i].prefixLen = 0;
4046 huffTab[i].rangeLen = jbig2HuffmanEOT;
4047 huffDecoder->buildTable(huffTab, i);
4048
4049 // create and store the new table segment
4050 segments->append(new JBIG2CodeTable(segNum, huffTab));
4051
4052 return;
4053
4054 eofError:
4055 error(errSyntaxError, getPos(), "Unexpected EOF in JBIG2 stream");
4056 }
4057
4058 void JBIG2Stream::readExtensionSeg(Guint length) {
4059 // skip the segment
4060 byteCounter += curStr->discardChars(length);
4061 }
4062
4063 JBIG2Segment *JBIG2Stream::findSegment(Guint segNum) {
4064 JBIG2Segment *seg;
4065 int i;
4066
4067 for (i = 0; i < globalSegments->getLength(); ++i) {
4068 seg = (JBIG2Segment *)globalSegments->get(i);
4069 if (seg->getSegNum() == segNum) {
4070 return seg;
4071 }
4072 }
4073 for (i = 0; i < segments->getLength(); ++i) {
4074 seg = (JBIG2Segment *)segments->get(i);
4075 if (seg->getSegNum() == segNum) {
4076 return seg;
4077 }
4078 }
4079 return NULL;
4080 }
4081
4082 void JBIG2Stream::discardSegment(Guint segNum) {
4083 JBIG2Segment *seg;
4084 int i;
4085
4086 for (i = 0; i < globalSegments->getLength(); ++i) {
4087 seg = (JBIG2Segment *)globalSegments->get(i);
4088 if (seg->getSegNum() == segNum) {
4089 globalSegments->del(i);
4090 return;
4091 }
4092 }
4093 for (i = 0; i < segments->getLength(); ++i) {
4094 seg = (JBIG2Segment *)segments->get(i);
4095 if (seg->getSegNum() == segNum) {
4096 segments->del(i);
4097 return;
4098 }
4099 }
4100 }
4101
4102 void JBIG2Stream::resetGenericStats(Guint templ,
4103 JArithmeticDecoderStats *prevStats) {
4104 int size;
4105
4106 size = contextSize[templ];
4107 if (prevStats && prevStats->getContextSize() == size) {
4108 if (genericRegionStats->getContextSize() == size) {
4109 genericRegionStats->copyFrom(prevStats);
4110 } else {
4111 delete genericRegionStats;
4112 genericRegionStats = prevStats->copy();
4113 }
4114 } else {
4115 if (genericRegionStats->getContextSize() == size) {
4116 genericRegionStats->reset();
4117 } else {
4118 delete genericRegionStats;
4119 genericRegionStats = new JArithmeticDecoderStats(1 << size);
4120 }
4121 }
4122 }
4123
4124 void JBIG2Stream::resetRefinementStats(Guint templ,
4125 JArithmeticDecoderStats *prevStats) {
4126 int size;
4127
4128 size = refContextSize[templ];
4129 if (prevStats && prevStats->getContextSize() == size) {
4130 if (refinementRegionStats->getContextSize() == size) {
4131 refinementRegionStats->copyFrom(prevStats);
4132 } else {
4133 delete refinementRegionStats;
4134 refinementRegionStats = prevStats->copy();
4135 }
4136 } else {
4137 if (refinementRegionStats->getContextSize() == size) {
4138 refinementRegionStats->reset();
4139 } else {
4140 delete refinementRegionStats;
4141 refinementRegionStats = new JArithmeticDecoderStats(1 << size);
4142 }
4143 }
4144 }
4145
4146 void JBIG2Stream::resetIntStats(int symCodeLen) {
4147 iadhStats->reset();
4148 iadwStats->reset();
4149 iaexStats->reset();
4150 iaaiStats->reset();
4151 iadtStats->reset();
4152 iaitStats->reset();
4153 iafsStats->reset();
4154 iadsStats->reset();
4155 iardxStats->reset();
4156 iardyStats->reset();
4157 iardwStats->reset();
4158 iardhStats->reset();
4159 iariStats->reset();
4160 if (iaidStats->getContextSize() == 1 << (symCodeLen + 1)) {
4161 iaidStats->reset();
4162 } else {
4163 delete iaidStats;
4164 iaidStats = new JArithmeticDecoderStats(1 << (symCodeLen + 1));
4165 }
4166 }
4167
4168 GBool JBIG2Stream::readUByte(Guint *x) {
4169 int c0;
4170
4171 if ((c0 = curStr->getChar()) == EOF) {
4172 return gFalse;
4173 }
4174 ++byteCounter;
4175 *x = (Guint)c0;
4176 return gTrue;
4177 }
4178
4179 GBool JBIG2Stream::readByte(int *x) {
4180 int c0;
4181
4182 if ((c0 = curStr->getChar()) == EOF) {
4183 return gFalse;
4184 }
4185 ++byteCounter;
4186 *x = c0;
4187 if (c0 & 0x80) {
4188 *x |= -1 - 0xff;
4189 }
4190 return gTrue;
4191 }
4192
4193 GBool JBIG2Stream::readUWord(Guint *x) {
4194 int c0, c1;
4195
4196 if ((c0 = curStr->getChar()) == EOF ||
4197 (c1 = curStr->getChar()) == EOF) {
4198 return gFalse;
4199 }
4200 byteCounter += 2;
4201 *x = (Guint)((c0 << 8) | c1);
4202 return gTrue;
4203 }
4204
4205 GBool JBIG2Stream::readULong(Guint *x) {
4206 int c0, c1, c2, c3;
4207
4208 if ((c0 = curStr->getChar()) == EOF ||
4209 (c1 = curStr->getChar()) == EOF ||
4210 (c2 = curStr->getChar()) == EOF ||
4211 (c3 = curStr->getChar()) == EOF) {
4212 return gFalse;
4213 }
4214 byteCounter += 4;
4215 *x = (Guint)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
4216 return gTrue;
4217 }
4218
4219 GBool JBIG2Stream::readLong(int *x) {
4220 int c0, c1, c2, c3;
4221
4222 if ((c0 = curStr->getChar()) == EOF ||
4223 (c1 = curStr->getChar()) == EOF ||
4224 (c2 = curStr->getChar()) == EOF ||
4225 (c3 = curStr->getChar()) == EOF) {
4226 return gFalse;
4227 }
4228 byteCounter += 4;
4229 *x = ((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
4230 if (c0 & 0x80) {
4231 *x |= -1 - (int)0xffffffff;
4232 }
4233 return gTrue;
4234 }