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