"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.
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 }