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