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