]> git.ipfire.org Git - thirdparty/cups.git/blame - pdftops/JPXStream.cxx
Merge changes from CUPS 1.4svn-r7199.
[thirdparty/cups.git] / pdftops / JPXStream.cxx
CommitLineData
ef416fc2 1//========================================================================
2//
3// JPXStream.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
bd7854cb 15#include <limits.h>
ef416fc2 16#include "gmem.h"
17#include "Error.h"
18#include "JArithmeticDecoder.h"
19#include "JPXStream.h"
20
21//~ to do:
22// - precincts
23// - ROI
24// - progression order changes
25// - packed packet headers
26// - support for palettes, channel maps, etc.
27// - make sure all needed JP2/JPX subboxes are parsed (readBoxes)
28// - can we assume that QCC segments must come after the QCD segment?
29// - skip EPH markers (readTilePartData)
30// - handle tilePartToEOC in readTilePartData
31// - deal with multiple codeword segments (readTilePartData,
32// readCodeBlockData)
33// - progression orders 2, 3, and 4
34// - in coefficient decoding (readCodeBlockData):
35// - termination pattern: terminate after every coding pass
36// - error resilience segmentation symbol
37// - selective arithmetic coding bypass
38// - vertically causal context formation
39// - coeffs longer than 31 bits (should just ignore the extra bits?)
40// - handle boxes larger than 2^32 bytes
41// - the fixed-point arithmetic won't handle 16-bit pixels
42
43//------------------------------------------------------------------------
44
45// number of contexts for the arithmetic decoder
46#define jpxNContexts 19
47
48#define jpxContextSigProp 0 // 0 - 8: significance prop and cleanup
49#define jpxContextSign 9 // 9 - 13: sign
50#define jpxContextMagRef 14 // 14 -16: magnitude refinement
51#define jpxContextRunLength 17 // cleanup: run length
52#define jpxContextUniform 18 // cleanup: first signif coeff
53
54//------------------------------------------------------------------------
55
56#define jpxPassSigProp 0
57#define jpxPassMagRef 1
58#define jpxPassCleanup 2
59
60//------------------------------------------------------------------------
61
62// arithmetic decoder context for the significance propagation and
63// cleanup passes:
64// [horiz][vert][diag][subband]
65// where subband = 0 for HL
66// = 1 for LH and LL
67// = 2 for HH
68static Guint sigPropContext[3][3][5][3] = {
69 {{{ 0, 0, 0 }, // horiz=0, vert=0, diag=0
70 { 1, 1, 3 }, // horiz=0, vert=0, diag=1
71 { 2, 2, 6 }, // horiz=0, vert=0, diag=2
72 { 2, 2, 8 }, // horiz=0, vert=0, diag=3
73 { 2, 2, 8 }}, // horiz=0, vert=0, diag=4
74 {{ 5, 3, 1 }, // horiz=0, vert=1, diag=0
75 { 6, 3, 4 }, // horiz=0, vert=1, diag=1
76 { 6, 3, 7 }, // horiz=0, vert=1, diag=2
77 { 6, 3, 8 }, // horiz=0, vert=1, diag=3
78 { 6, 3, 8 }}, // horiz=0, vert=1, diag=4
79 {{ 8, 4, 2 }, // horiz=0, vert=2, diag=0
80 { 8, 4, 5 }, // horiz=0, vert=2, diag=1
81 { 8, 4, 7 }, // horiz=0, vert=2, diag=2
82 { 8, 4, 8 }, // horiz=0, vert=2, diag=3
83 { 8, 4, 8 }}}, // horiz=0, vert=2, diag=4
84 {{{ 3, 5, 1 }, // horiz=1, vert=0, diag=0
85 { 3, 6, 4 }, // horiz=1, vert=0, diag=1
86 { 3, 6, 7 }, // horiz=1, vert=0, diag=2
87 { 3, 6, 8 }, // horiz=1, vert=0, diag=3
88 { 3, 6, 8 }}, // horiz=1, vert=0, diag=4
89 {{ 7, 7, 2 }, // horiz=1, vert=1, diag=0
90 { 7, 7, 5 }, // horiz=1, vert=1, diag=1
91 { 7, 7, 7 }, // horiz=1, vert=1, diag=2
92 { 7, 7, 8 }, // horiz=1, vert=1, diag=3
93 { 7, 7, 8 }}, // horiz=1, vert=1, diag=4
94 {{ 8, 7, 2 }, // horiz=1, vert=2, diag=0
95 { 8, 7, 5 }, // horiz=1, vert=2, diag=1
96 { 8, 7, 7 }, // horiz=1, vert=2, diag=2
97 { 8, 7, 8 }, // horiz=1, vert=2, diag=3
98 { 8, 7, 8 }}}, // horiz=1, vert=2, diag=4
99 {{{ 4, 8, 2 }, // horiz=2, vert=0, diag=0
100 { 4, 8, 5 }, // horiz=2, vert=0, diag=1
101 { 4, 8, 7 }, // horiz=2, vert=0, diag=2
102 { 4, 8, 8 }, // horiz=2, vert=0, diag=3
103 { 4, 8, 8 }}, // horiz=2, vert=0, diag=4
104 {{ 7, 8, 2 }, // horiz=2, vert=1, diag=0
105 { 7, 8, 5 }, // horiz=2, vert=1, diag=1
106 { 7, 8, 7 }, // horiz=2, vert=1, diag=2
107 { 7, 8, 8 }, // horiz=2, vert=1, diag=3
108 { 7, 8, 8 }}, // horiz=2, vert=1, diag=4
109 {{ 8, 8, 2 }, // horiz=2, vert=2, diag=0
110 { 8, 8, 5 }, // horiz=2, vert=2, diag=1
111 { 8, 8, 7 }, // horiz=2, vert=2, diag=2
112 { 8, 8, 8 }, // horiz=2, vert=2, diag=3
113 { 8, 8, 8 }}} // horiz=2, vert=2, diag=4
114};
115
116// arithmetic decoder context and xor bit for the sign bit in the
117// significance propagation pass:
118// [horiz][vert][k]
119// where horiz/vert are offset by 2 (i.e., range is -2 .. 2)
120// and k = 0 for the context
121// = 1 for the xor bit
122static Guint signContext[5][5][2] = {
123 {{ 13, 1 }, // horiz=-2, vert=-2
124 { 13, 1 }, // horiz=-2, vert=-1
125 { 12, 1 }, // horiz=-2, vert= 0
126 { 11, 1 }, // horiz=-2, vert=+1
127 { 11, 1 }}, // horiz=-2, vert=+2
128 {{ 13, 1 }, // horiz=-1, vert=-2
129 { 13, 1 }, // horiz=-1, vert=-1
130 { 12, 1 }, // horiz=-1, vert= 0
131 { 11, 1 }, // horiz=-1, vert=+1
132 { 11, 1 }}, // horiz=-1, vert=+2
133 {{ 10, 1 }, // horiz= 0, vert=-2
134 { 10, 1 }, // horiz= 0, vert=-1
135 { 9, 0 }, // horiz= 0, vert= 0
136 { 10, 0 }, // horiz= 0, vert=+1
137 { 10, 0 }}, // horiz= 0, vert=+2
138 {{ 11, 0 }, // horiz=+1, vert=-2
139 { 11, 0 }, // horiz=+1, vert=-1
140 { 12, 0 }, // horiz=+1, vert= 0
141 { 13, 0 }, // horiz=+1, vert=+1
142 { 13, 0 }}, // horiz=+1, vert=+2
143 {{ 11, 0 }, // horiz=+2, vert=-2
144 { 11, 0 }, // horiz=+2, vert=-1
145 { 12, 0 }, // horiz=+2, vert= 0
146 { 13, 0 }, // horiz=+2, vert=+1
147 { 13, 0 }}, // horiz=+2, vert=+2
148};
149
150//------------------------------------------------------------------------
151
152// constants used in the IDWT
153#define idwtAlpha -1.586134342059924
154#define idwtBeta -0.052980118572961
155#define idwtGamma 0.882911075530934
156#define idwtDelta 0.443506852043971
157#define idwtKappa 1.230174104914001
158#define idwtIKappa (1.0 / idwtKappa)
159
160// number of bits to the right of the decimal point for the fixed
161// point arithmetic used in the IDWT
162#define fracBits 16
163
164//------------------------------------------------------------------------
165
166// floor(x / y)
167#define jpxFloorDiv(x, y) ((x) / (y))
168
169// floor(x / 2^y)
170#define jpxFloorDivPow2(x, y) ((x) >> (y))
171
172// ceil(x / y)
173#define jpxCeilDiv(x, y) (((x) + (y) - 1) / (y))
174
175// ceil(x / 2^y)
176#define jpxCeilDivPow2(x, y) (((x) + (1 << (y)) - 1) >> (y))
177
178//------------------------------------------------------------------------
179
180JPXStream::JPXStream(Stream *strA):
181 FilterStream(strA)
182{
183 nComps = 0;
184 bpc = NULL;
185 width = height = 0;
186 haveCS = gFalse;
187 havePalette = gFalse;
188 haveCompMap = gFalse;
189 haveChannelDefn = gFalse;
190
191 img.tiles = NULL;
192 bitBuf = 0;
193 bitBufLen = 0;
194 bitBufSkip = gFalse;
195 byteCount = 0;
196}
197
198JPXStream::~JPXStream() {
199 JPXTile *tile;
200 JPXTileComp *tileComp;
201 JPXResLevel *resLevel;
202 JPXPrecinct *precinct;
203 JPXSubband *subband;
204 JPXCodeBlock *cb;
205 Guint comp, i, k, r, pre, sb;
206
207 gfree(bpc);
208 if (havePalette) {
209 gfree(palette.bpc);
210 gfree(palette.c);
211 }
212 if (haveCompMap) {
213 gfree(compMap.comp);
214 gfree(compMap.type);
215 gfree(compMap.pComp);
216 }
217 if (haveChannelDefn) {
218 gfree(channelDefn.idx);
219 gfree(channelDefn.type);
220 gfree(channelDefn.assoc);
221 }
222
223 if (img.tiles) {
224 for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
225 tile = &img.tiles[i];
226 if (tile->tileComps) {
227 for (comp = 0; comp < img.nComps; ++comp) {
228 tileComp = &tile->tileComps[comp];
229 gfree(tileComp->quantSteps);
230 gfree(tileComp->data);
231 gfree(tileComp->buf);
232 if (tileComp->resLevels) {
233 for (r = 0; r <= tileComp->nDecompLevels; ++r) {
234 resLevel = &tileComp->resLevels[r];
235 if (resLevel->precincts) {
236 for (pre = 0; pre < 1; ++pre) {
237 precinct = &resLevel->precincts[pre];
238 if (precinct->subbands) {
239 for (sb = 0; sb < (r == 0 ? 1 : 3); ++sb) {
240 subband = &precinct->subbands[sb];
241 gfree(subband->inclusion);
242 gfree(subband->zeroBitPlane);
243 if (subband->cbs) {
244 for (k = 0; k < subband->nXCBs * subband->nYCBs; ++k) {
245 cb = &subband->cbs[k];
246 gfree(cb->coeffs);
247 if (cb->arithDecoder) {
248 delete cb->arithDecoder;
249 }
250 if (cb->stats) {
251 delete cb->stats;
252 }
253 }
254 gfree(subband->cbs);
255 }
256 }
257 gfree(precinct->subbands);
258 }
259 }
260 gfree(img.tiles[i].tileComps[comp].resLevels[r].precincts);
261 }
262 }
263 gfree(img.tiles[i].tileComps[comp].resLevels);
264 }
265 }
266 gfree(img.tiles[i].tileComps);
267 }
268 }
269 gfree(img.tiles);
270 }
271 delete str;
272}
273
274void JPXStream::reset() {
275 str->reset();
276 if (readBoxes()) {
277 curY = img.yOffset;
278 } else {
279 // readBoxes reported an error, so we go immediately to EOF
280 curY = img.ySize;
281 }
282 curX = img.xOffset;
283 curComp = 0;
284 readBufLen = 0;
285}
286
287int JPXStream::getChar() {
288 int c;
289
290 if (readBufLen < 8) {
291 fillReadBuf();
292 }
293 if (readBufLen == 8) {
294 c = readBuf & 0xff;
295 readBufLen = 0;
296 } else if (readBufLen > 8) {
297 c = (readBuf >> (readBufLen - 8)) & 0xff;
298 readBufLen -= 8;
299 } else if (readBufLen == 0) {
300 c = EOF;
301 } else {
302 c = (readBuf << (8 - readBufLen)) & 0xff;
303 readBufLen = 0;
304 }
305 return c;
306}
307
308int JPXStream::lookChar() {
309 int c;
310
311 if (readBufLen < 8) {
312 fillReadBuf();
313 }
314 if (readBufLen == 8) {
315 c = readBuf & 0xff;
316 } else if (readBufLen > 8) {
317 c = (readBuf >> (readBufLen - 8)) & 0xff;
318 } else if (readBufLen == 0) {
319 c = EOF;
320 } else {
321 c = (readBuf << (8 - readBufLen)) & 0xff;
322 }
323 return c;
324}
325
326void JPXStream::fillReadBuf() {
327 JPXTileComp *tileComp;
328 Guint tileIdx, tx, ty;
329 int pix, pixBits;
330
331 do {
332 if (curY >= img.ySize) {
333 return;
334 }
335 tileIdx = ((curY - img.yTileOffset) / img.yTileSize) * img.nXTiles
336 + (curX - img.xTileOffset) / img.xTileSize;
337#if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid
338 tileComp = &img.tiles[tileIdx].tileComps[curComp];
339#else
340 tileComp = &img.tiles[tileIdx].tileComps[havePalette ? 0 : curComp];
341#endif
342 tx = jpxCeilDiv((curX - img.xTileOffset) % img.xTileSize, tileComp->hSep);
343 ty = jpxCeilDiv((curY - img.yTileOffset) % img.yTileSize, tileComp->vSep);
344 pix = (int)tileComp->data[ty * (tileComp->x1 - tileComp->x0) + tx];
345 pixBits = tileComp->prec;
346#if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid
347 if (++curComp == img.nComps) {
348#else
349 if (havePalette) {
350 if (pix >= 0 && pix < palette.nEntries) {
351 pix = palette.c[pix * palette.nComps + curComp];
352 } else {
353 pix =
354 pixBits = palette.bpc[curComp];
355 }
356 if (++curComp == (Guint)(havePalette ? palette.nComps : img.nComps)) {
357#endif
358 curComp = 0;
359 if (++curX == img.xSize) {
360 curX = img.xOffset;
361 ++curY;
362 }
363 }
364 if (pixBits == 8) {
365 readBuf = (readBuf << 8) | (pix & 0xff);
366 } else {
367 readBuf = (readBuf << pixBits) | (pix & ((1 << pixBits) - 1));
368 }
369 readBufLen += pixBits;
370 } while (readBufLen < 8);
371}
372
373GString *JPXStream::getPSFilter(int psLevel, char *indent) {
374 return NULL;
375}
376
377GBool JPXStream::isBinary(GBool last) {
378 return str->isBinary(gTrue);
379}
380
381void JPXStream::getImageParams(int *bitsPerComponent,
382 StreamColorSpaceMode *csMode) {
383 Guint boxType, boxLen, dataLen, csEnum;
384 Guint bpc1, dummy, i;
385 int csMeth, csPrec, csPrec1, dummy2;
386 StreamColorSpaceMode csMode1;
387 GBool haveBPC, haveCSMode;
388
389 csPrec = 0; // make gcc happy
390 haveBPC = haveCSMode = gFalse;
391 str->reset();
392 if (str->lookChar() == 0xff) {
393 getImageParams2(bitsPerComponent, csMode);
394 } else {
395 while (readBoxHdr(&boxType, &boxLen, &dataLen)) {
396 if (boxType == 0x6a703268) { // JP2 header
397 // skip the superbox
398 } else if (boxType == 0x69686472) { // image header
399 if (readULong(&dummy) &&
400 readULong(&dummy) &&
401 readUWord(&dummy) &&
402 readUByte(&bpc1) &&
403 readUByte(&dummy) &&
404 readUByte(&dummy) &&
405 readUByte(&dummy)) {
406 *bitsPerComponent = bpc1 + 1;
407 haveBPC = gTrue;
408 }
409 } else if (boxType == 0x636F6C72) { // color specification
410 if (readByte(&csMeth) &&
411 readByte(&csPrec1) &&
412 readByte(&dummy2)) {
413 if (csMeth == 1) {
414 if (readULong(&csEnum)) {
415 csMode1 = streamCSNone;
416 if (csEnum == jpxCSBiLevel ||
417 csEnum == jpxCSGrayscale) {
418 csMode1 = streamCSDeviceGray;
419 } else if (csEnum == jpxCSCMYK) {
420 csMode1 = streamCSDeviceCMYK;
421 } else if (csEnum == jpxCSsRGB ||
422 csEnum == jpxCSCISesRGB ||
423 csEnum == jpxCSROMMRGB) {
424 csMode1 = streamCSDeviceRGB;
425 }
426 if (csMode1 != streamCSNone &&
427 (!haveCSMode || csPrec1 > csPrec)) {
428 *csMode = csMode1;
429 csPrec = csPrec1;
430 haveCSMode = gTrue;
431 }
432 for (i = 0; i < dataLen - 7; ++i) {
433 str->getChar();
434 }
435 }
436 } else {
437 for (i = 0; i < dataLen - 3; ++i) {
438 str->getChar();
439 }
440 }
441 }
442 } else if (boxType == 0x6A703263) { // codestream
443 if (!(haveBPC && haveCSMode)) {
444 getImageParams2(bitsPerComponent, csMode);
445 }
446 break;
447 } else {
448 for (i = 0; i < dataLen; ++i) {
449 str->getChar();
450 }
451 }
452 }
453 }
454 str->close();
455}
456
457// Get image parameters from the codestream.
458void JPXStream::getImageParams2(int *bitsPerComponent,
459 StreamColorSpaceMode *csMode) {
460 int segType;
461 Guint segLen, nComps1, bpc1, dummy, i;
462
463 while (readMarkerHdr(&segType, &segLen)) {
464 if (segType == 0x51) { // SIZ - image and tile size
465 if (readUWord(&dummy) &&
466 readULong(&dummy) &&
467 readULong(&dummy) &&
468 readULong(&dummy) &&
469 readULong(&dummy) &&
470 readULong(&dummy) &&
471 readULong(&dummy) &&
472 readULong(&dummy) &&
473 readULong(&dummy) &&
474 readUWord(&nComps1) &&
475 readUByte(&bpc1)) {
476 *bitsPerComponent = (bpc1 & 0x7f) + 1;
477 // if there's no color space info, take a guess
478 if (nComps1 == 1) {
479 *csMode = streamCSDeviceGray;
480 } else if (nComps1 == 3) {
481 *csMode = streamCSDeviceRGB;
482 } else if (nComps1 == 4) {
483 *csMode = streamCSDeviceCMYK;
484 }
485 }
486 break;
487 } else {
488 if (segLen > 2) {
489 for (i = 0; i < segLen - 2; ++i) {
490 str->getChar();
491 }
492 }
493 }
494 }
495}
496
497GBool JPXStream::readBoxes() {
498 Guint boxType, boxLen, dataLen;
499 Guint bpc1, compression, unknownColorspace, ipr;
500 Guint i, j;
501
502 haveImgHdr = gFalse;
503
504 // check for a naked JPEG 2000 codestream (without the JP2/JPX
505 // wrapper) -- this appears to be a violation of the PDF spec, but
506 // Acrobat allows it
507 if (str->lookChar() == 0xff) {
508 error(getPos(), "Naked JPEG 2000 codestream, missing JP2/JPX wrapper");
509 readCodestream(0);
510 nComps = img.nComps;
511 bpc = (Guint *)gmallocn(nComps, sizeof(Guint));
512 for (i = 0; i < nComps; ++i) {
513 bpc[i] = img.tiles[0].tileComps[i].prec;
514 }
515 width = img.xSize - img.xOffset;
516 height = img.ySize - img.yOffset;
517 return gTrue;
518 }
519
520 while (readBoxHdr(&boxType, &boxLen, &dataLen)) {
521 switch (boxType) {
522 case 0x6a703268: // JP2 header
523 // this is a grouping box ('superbox') which has no real
524 // contents and doesn't appear to be used consistently, i.e.,
525 // some things which should be subboxes of the JP2 header box
526 // show up outside of it - so we simply ignore the JP2 header
527 // box
528 break;
529 case 0x69686472: // image header
530 if (!readULong(&height) ||
531 !readULong(&width) ||
532 !readUWord(&nComps) ||
533 !readUByte(&bpc1) ||
534 !readUByte(&compression) ||
535 !readUByte(&unknownColorspace) ||
536 !readUByte(&ipr)) {
537 error(getPos(), "Unexpected EOF in JPX stream");
538 return gFalse;
539 }
540 if (compression != 7) {
541 error(getPos(), "Unknown compression type in JPX stream");
542 return gFalse;
543 }
544 bpc = (Guint *)gmallocn(nComps, sizeof(Guint));
545 for (i = 0; i < nComps; ++i) {
546 bpc[i] = bpc1;
547 }
548 haveImgHdr = gTrue;
549 break;
550 case 0x62706363: // bits per component
551 if (!haveImgHdr) {
552 error(getPos(), "Found bits per component box before image header box in JPX stream");
553 return gFalse;
554 }
555 if (dataLen != nComps) {
556 error(getPos(), "Invalid bits per component box in JPX stream");
557 return gFalse;
558 }
559 for (i = 0; i < nComps; ++i) {
560 if (!readUByte(&bpc[i])) {
561 error(getPos(), "Unexpected EOF in JPX stream");
562 return gFalse;
563 }
564 }
565 break;
566 case 0x636F6C72: // color specification
567 if (!readColorSpecBox(dataLen)) {
568 return gFalse;
569 }
570 break;
571 case 0x70636c72: // palette
572 if (!readUWord(&palette.nEntries) ||
573 !readUByte(&palette.nComps)) {
574 error(getPos(), "Unexpected EOF in JPX stream");
575 return gFalse;
576 }
577 palette.bpc = (Guint *)gmallocn(palette.nComps, sizeof(Guint));
578 palette.c =
579 (int *)gmallocn(palette.nEntries * palette.nComps, sizeof(int));
580 for (i = 0; i < palette.nComps; ++i) {
581 if (!readUByte(&palette.bpc[i])) {
582 error(getPos(), "Unexpected EOF in JPX stream");
583 return gFalse;
584 }
585 ++palette.bpc[i];
586 }
587 for (i = 0; i < palette.nEntries; ++i) {
588 for (j = 0; j < palette.nComps; ++j) {
589 if (!readNBytes(((palette.bpc[j] & 0x7f) + 7) >> 3,
590 (palette.bpc[j] & 0x80) ? gTrue : gFalse,
591 &palette.c[i * palette.nComps + j])) {
592 error(getPos(), "Unexpected EOF in JPX stream");
593 return gFalse;
594 }
595 }
596 }
597 havePalette = gTrue;
598 break;
599 case 0x636d6170: // component mapping
600 compMap.nChannels = dataLen / 4;
601 compMap.comp = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint));
602 compMap.type = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint));
603 compMap.pComp = (Guint *)gmallocn(compMap.nChannels, sizeof(Guint));
604 for (i = 0; i < compMap.nChannels; ++i) {
605 if (!readUWord(&compMap.comp[i]) ||
606 !readUByte(&compMap.type[i]) ||
607 !readUByte(&compMap.pComp[i])) {
608 error(getPos(), "Unexpected EOF in JPX stream");
609 return gFalse;
610 }
611 }
612 haveCompMap = gTrue;
613 break;
614 case 0x63646566: // channel definition
615 if (!readUWord(&channelDefn.nChannels)) {
616 error(getPos(), "Unexpected EOF in JPX stream");
617 return gFalse;
618 }
619 channelDefn.idx =
620 (Guint *)gmallocn(channelDefn.nChannels, sizeof(Guint));
621 channelDefn.type =
622 (Guint *)gmallocn(channelDefn.nChannels, sizeof(Guint));
623 channelDefn.assoc =
624 (Guint *)gmallocn(channelDefn.nChannels, sizeof(Guint));
625 for (i = 0; i < channelDefn.nChannels; ++i) {
626 if (!readUWord(&channelDefn.idx[i]) ||
627 !readUWord(&channelDefn.type[i]) ||
628 !readUWord(&channelDefn.assoc[i])) {
629 error(getPos(), "Unexpected EOF in JPX stream");
630 return gFalse;
631 }
632 }
633 haveChannelDefn = gTrue;
634 break;
635 case 0x6A703263: // contiguous codestream
636 if (!bpc) {
637 error(getPos(), "JPX stream is missing the image header box");
638 }
639 if (!haveCS) {
640 error(getPos(), "JPX stream has no supported color spec");
641 }
642 if (!readCodestream(dataLen)) {
643 return gFalse;
644 }
645 break;
646 default:
647 for (i = 0; i < dataLen; ++i) {
648 if (str->getChar() == EOF) {
649 error(getPos(), "Unexpected EOF in JPX stream");
650 return gFalse;
651 }
652 }
653 break;
654 }
655 }
656 return gTrue;
657}
658
659GBool JPXStream::readColorSpecBox(Guint dataLen) {
660 JPXColorSpec newCS;
661 Guint csApprox, csEnum;
662 Guint i;
663 GBool ok;
664
665 ok = gFalse;
666 if (!readUByte(&newCS.meth) ||
667 !readByte(&newCS.prec) ||
668 !readUByte(&csApprox)) {
669 goto err;
670 }
671 switch (newCS.meth) {
672 case 1: // enumerated colorspace
673 if (!readULong(&csEnum)) {
674 goto err;
675 }
676 newCS.enumerated.type = (JPXColorSpaceType)csEnum;
677 switch (newCS.enumerated.type) {
678 case jpxCSBiLevel:
679 ok = gTrue;
680 break;
681 case jpxCSYCbCr1:
682 ok = gTrue;
683 break;
684 case jpxCSYCbCr2:
685 ok = gTrue;
686 break;
687 case jpxCSYCBCr3:
688 ok = gTrue;
689 break;
690 case jpxCSPhotoYCC:
691 ok = gTrue;
692 break;
693 case jpxCSCMY:
694 ok = gTrue;
695 break;
696 case jpxCSCMYK:
697 ok = gTrue;
698 break;
699 case jpxCSYCCK:
700 ok = gTrue;
701 break;
702 case jpxCSCIELab:
703 if (dataLen == 7 + 7*4) {
704 if (!readULong(&newCS.enumerated.cieLab.rl) ||
705 !readULong(&newCS.enumerated.cieLab.ol) ||
706 !readULong(&newCS.enumerated.cieLab.ra) ||
707 !readULong(&newCS.enumerated.cieLab.oa) ||
708 !readULong(&newCS.enumerated.cieLab.rb) ||
709 !readULong(&newCS.enumerated.cieLab.ob) ||
710 !readULong(&newCS.enumerated.cieLab.il)) {
711 goto err;
712 }
713 } else if (dataLen == 7) {
714 //~ this assumes the 8-bit case
715 newCS.enumerated.cieLab.rl = 100;
716 newCS.enumerated.cieLab.ol = 0;
717 newCS.enumerated.cieLab.ra = 255;
718 newCS.enumerated.cieLab.oa = 128;
719 newCS.enumerated.cieLab.rb = 255;
720 newCS.enumerated.cieLab.ob = 96;
721 newCS.enumerated.cieLab.il = 0x00443530;
722 } else {
723 goto err;
724 }
725 ok = gTrue;
726 break;
727 case jpxCSsRGB:
728 ok = gTrue;
729 break;
730 case jpxCSGrayscale:
731 ok = gTrue;
732 break;
733 case jpxCSBiLevel2:
734 ok = gTrue;
735 break;
736 case jpxCSCIEJab:
737 // not allowed in PDF
738 goto err;
739 case jpxCSCISesRGB:
740 ok = gTrue;
741 break;
742 case jpxCSROMMRGB:
743 ok = gTrue;
744 break;
745 case jpxCSsRGBYCbCr:
746 ok = gTrue;
747 break;
748 case jpxCSYPbPr1125:
749 ok = gTrue;
750 break;
751 case jpxCSYPbPr1250:
752 ok = gTrue;
753 break;
754 default:
755 goto err;
756 }
757 break;
758 case 2: // restricted ICC profile
759 case 3: // any ICC profile (JPX)
760 case 4: // vendor color (JPX)
761 for (i = 0; i < dataLen - 3; ++i) {
762 if (str->getChar() == EOF) {
763 goto err;
764 }
765 }
766 break;
767 }
768
769 if (ok && (!haveCS || newCS.prec > cs.prec)) {
770 cs = newCS;
771 haveCS = gTrue;
772 }
773
774 return gTrue;
775
776 err:
777 error(getPos(), "Error in JPX color spec");
778 return gFalse;
779}
780
781GBool JPXStream::readCodestream(Guint len) {
782 JPXTile *tile;
783 JPXTileComp *tileComp;
784 int segType;
785 GBool haveSIZ, haveCOD, haveQCD, haveSOT;
786 Guint precinctSize, style;
bd7854cb 787 Guint segLen, capabilities, comp, i, j, r;
ef416fc2 788
789 //----- main header
790 haveSIZ = haveCOD = haveQCD = haveSOT = gFalse;
791 do {
792 if (!readMarkerHdr(&segType, &segLen)) {
793 error(getPos(), "Error in JPX codestream");
794 return gFalse;
795 }
796 switch (segType) {
797 case 0x4f: // SOC - start of codestream
798 // marker only
799 break;
800 case 0x51: // SIZ - image and tile size
801 if (!readUWord(&capabilities) ||
802 !readULong(&img.xSize) ||
803 !readULong(&img.ySize) ||
804 !readULong(&img.xOffset) ||
805 !readULong(&img.yOffset) ||
806 !readULong(&img.xTileSize) ||
807 !readULong(&img.yTileSize) ||
808 !readULong(&img.xTileOffset) ||
809 !readULong(&img.yTileOffset) ||
810 !readUWord(&img.nComps)) {
811 error(getPos(), "Error in JPX SIZ marker segment");
812 return gFalse;
813 }
814 if (haveImgHdr && img.nComps != nComps) {
815 error(getPos(), "Different number of components in JPX SIZ marker segment");
816 return gFalse;
817 }
818 img.nXTiles = (img.xSize - img.xTileOffset + img.xTileSize - 1)
819 / img.xTileSize;
820 img.nYTiles = (img.ySize - img.yTileOffset + img.yTileSize - 1)
821 / img.yTileSize;
ef416fc2 822 // check for overflow before allocating memory
bd7854cb 823 if (img.nXTiles <= 0 || img.nYTiles <= 0 ||
824 img.nXTiles >= INT_MAX / img.nYTiles) {
ef416fc2 825 error(getPos(), "Bad tile count in JPX SIZ marker segment");
826 return gFalse;
827 }
bd7854cb 828 img.tiles = (JPXTile *)gmallocn(img.nXTiles * img.nYTiles,
829 sizeof(JPXTile));
ef416fc2 830 for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
831 img.tiles[i].tileComps = (JPXTileComp *)gmallocn(img.nComps,
832 sizeof(JPXTileComp));
833 for (comp = 0; comp < img.nComps; ++comp) {
834 img.tiles[i].tileComps[comp].quantSteps = NULL;
835 img.tiles[i].tileComps[comp].data = NULL;
836 img.tiles[i].tileComps[comp].buf = NULL;
837 img.tiles[i].tileComps[comp].resLevels = NULL;
838 }
839 }
840 for (comp = 0; comp < img.nComps; ++comp) {
841 if (!readUByte(&img.tiles[0].tileComps[comp].prec) ||
842 !readUByte(&img.tiles[0].tileComps[comp].hSep) ||
843 !readUByte(&img.tiles[0].tileComps[comp].vSep)) {
844 error(getPos(), "Error in JPX SIZ marker segment");
845 return gFalse;
846 }
847 img.tiles[0].tileComps[comp].sgned =
848 (img.tiles[0].tileComps[comp].prec & 0x80) ? gTrue : gFalse;
849 img.tiles[0].tileComps[comp].prec =
850 (img.tiles[0].tileComps[comp].prec & 0x7f) + 1;
851 for (i = 1; i < img.nXTiles * img.nYTiles; ++i) {
852 img.tiles[i].tileComps[comp] = img.tiles[0].tileComps[comp];
853 }
854 }
855 haveSIZ = gTrue;
856 break;
857 case 0x52: // COD - coding style default
858 if (!readUByte(&img.tiles[0].tileComps[0].style) ||
859 !readUByte(&img.tiles[0].progOrder) ||
860 !readUWord(&img.tiles[0].nLayers) ||
861 !readUByte(&img.tiles[0].multiComp) ||
862 !readUByte(&img.tiles[0].tileComps[0].nDecompLevels) ||
863 !readUByte(&img.tiles[0].tileComps[0].codeBlockW) ||
864 !readUByte(&img.tiles[0].tileComps[0].codeBlockH) ||
865 !readUByte(&img.tiles[0].tileComps[0].codeBlockStyle) ||
866 !readUByte(&img.tiles[0].tileComps[0].transform)) {
867 error(getPos(), "Error in JPX COD marker segment");
868 return gFalse;
869 }
870 img.tiles[0].tileComps[0].codeBlockW += 2;
871 img.tiles[0].tileComps[0].codeBlockH += 2;
872 for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
873 if (i != 0) {
874 img.tiles[i].progOrder = img.tiles[0].progOrder;
875 img.tiles[i].nLayers = img.tiles[0].nLayers;
876 img.tiles[i].multiComp = img.tiles[0].multiComp;
877 }
878 for (comp = 0; comp < img.nComps; ++comp) {
879 if (!(i == 0 && comp == 0)) {
880 img.tiles[i].tileComps[comp].style =
881 img.tiles[0].tileComps[0].style;
882 img.tiles[i].tileComps[comp].nDecompLevels =
883 img.tiles[0].tileComps[0].nDecompLevels;
884 img.tiles[i].tileComps[comp].codeBlockW =
885 img.tiles[0].tileComps[0].codeBlockW;
886 img.tiles[i].tileComps[comp].codeBlockH =
887 img.tiles[0].tileComps[0].codeBlockH;
888 img.tiles[i].tileComps[comp].codeBlockStyle =
889 img.tiles[0].tileComps[0].codeBlockStyle;
890 img.tiles[i].tileComps[comp].transform =
891 img.tiles[0].tileComps[0].transform;
892 }
893 img.tiles[i].tileComps[comp].resLevels =
894 (JPXResLevel *)gmallocn(
895 (img.tiles[i].tileComps[comp].nDecompLevels + 1),
896 sizeof(JPXResLevel));
897 for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) {
898 img.tiles[i].tileComps[comp].resLevels[r].precincts = NULL;
899 }
900 }
901 }
902 for (r = 0; r <= img.tiles[0].tileComps[0].nDecompLevels; ++r) {
903 if (img.tiles[0].tileComps[0].style & 0x01) {
904 if (!readUByte(&precinctSize)) {
905 error(getPos(), "Error in JPX COD marker segment");
906 return gFalse;
907 }
908 img.tiles[0].tileComps[0].resLevels[r].precinctWidth =
909 precinctSize & 0x0f;
910 img.tiles[0].tileComps[0].resLevels[r].precinctHeight =
911 (precinctSize >> 4) & 0x0f;
912 } else {
913 img.tiles[0].tileComps[0].resLevels[r].precinctWidth = 15;
914 img.tiles[0].tileComps[0].resLevels[r].precinctHeight = 15;
915 }
916 }
917 for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
918 for (comp = 0; comp < img.nComps; ++comp) {
919 if (!(i == 0 && comp == 0)) {
920 for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) {
921 img.tiles[i].tileComps[comp].resLevels[r].precinctWidth =
922 img.tiles[0].tileComps[0].resLevels[r].precinctWidth;
923 img.tiles[i].tileComps[comp].resLevels[r].precinctHeight =
924 img.tiles[0].tileComps[0].resLevels[r].precinctHeight;
925 }
926 }
927 }
928 }
929 haveCOD = gTrue;
930 break;
931 case 0x53: // COC - coding style component
932 if (!haveCOD) {
933 error(getPos(), "JPX COC marker segment before COD segment");
934 return gFalse;
935 }
936 if ((img.nComps > 256 && !readUWord(&comp)) ||
937 (img.nComps <= 256 && !readUByte(&comp)) ||
938 comp >= img.nComps ||
939 !readUByte(&style) ||
940 !readUByte(&img.tiles[0].tileComps[comp].nDecompLevels) ||
941 !readUByte(&img.tiles[0].tileComps[comp].codeBlockW) ||
942 !readUByte(&img.tiles[0].tileComps[comp].codeBlockH) ||
943 !readUByte(&img.tiles[0].tileComps[comp].codeBlockStyle) ||
944 !readUByte(&img.tiles[0].tileComps[comp].transform)) {
945 error(getPos(), "Error in JPX COC marker segment");
946 return gFalse;
947 }
948 img.tiles[0].tileComps[comp].style =
949 (img.tiles[0].tileComps[comp].style & ~1) | (style & 1);
950 img.tiles[0].tileComps[comp].codeBlockW += 2;
951 img.tiles[0].tileComps[comp].codeBlockH += 2;
952 for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
953 if (i != 0) {
954 img.tiles[i].tileComps[comp].style =
955 img.tiles[0].tileComps[comp].style;
956 img.tiles[i].tileComps[comp].nDecompLevels =
957 img.tiles[0].tileComps[comp].nDecompLevels;
958 img.tiles[i].tileComps[comp].codeBlockW =
959 img.tiles[0].tileComps[comp].codeBlockW;
960 img.tiles[i].tileComps[comp].codeBlockH =
961 img.tiles[0].tileComps[comp].codeBlockH;
962 img.tiles[i].tileComps[comp].codeBlockStyle =
963 img.tiles[0].tileComps[comp].codeBlockStyle;
964 img.tiles[i].tileComps[comp].transform =
965 img.tiles[0].tileComps[comp].transform;
966 }
967 img.tiles[i].tileComps[comp].resLevels =
968 (JPXResLevel *)greallocn(
969 img.tiles[i].tileComps[comp].resLevels,
970 (img.tiles[i].tileComps[comp].nDecompLevels + 1),
971 sizeof(JPXResLevel));
972 for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) {
973 img.tiles[i].tileComps[comp].resLevels[r].precincts = NULL;
974 }
975 }
976 for (r = 0; r <= img.tiles[0].tileComps[comp].nDecompLevels; ++r) {
977 if (img.tiles[0].tileComps[comp].style & 0x01) {
978 if (!readUByte(&precinctSize)) {
979 error(getPos(), "Error in JPX COD marker segment");
980 return gFalse;
981 }
982 img.tiles[0].tileComps[comp].resLevels[r].precinctWidth =
983 precinctSize & 0x0f;
984 img.tiles[0].tileComps[comp].resLevels[r].precinctHeight =
985 (precinctSize >> 4) & 0x0f;
986 } else {
987 img.tiles[0].tileComps[comp].resLevels[r].precinctWidth = 15;
988 img.tiles[0].tileComps[comp].resLevels[r].precinctHeight = 15;
989 }
990 }
991 for (i = 1; i < img.nXTiles * img.nYTiles; ++i) {
992 for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) {
993 img.tiles[i].tileComps[comp].resLevels[r].precinctWidth =
994 img.tiles[0].tileComps[comp].resLevels[r].precinctWidth;
995 img.tiles[i].tileComps[comp].resLevels[r].precinctHeight =
996 img.tiles[0].tileComps[comp].resLevels[r].precinctHeight;
997 }
998 }
999 break;
1000 case 0x5c: // QCD - quantization default
1001 if (!readUByte(&img.tiles[0].tileComps[0].quantStyle)) {
1002 error(getPos(), "Error in JPX QCD marker segment");
1003 return gFalse;
1004 }
1005 if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x00) {
1006 img.tiles[0].tileComps[0].nQuantSteps = segLen - 3;
1007 img.tiles[0].tileComps[0].quantSteps =
1008 (Guint *)greallocn(img.tiles[0].tileComps[0].quantSteps,
1009 img.tiles[0].tileComps[0].nQuantSteps,
1010 sizeof(Guint));
1011 for (i = 0; i < img.tiles[0].tileComps[0].nQuantSteps; ++i) {
1012 if (!readUByte(&img.tiles[0].tileComps[0].quantSteps[i])) {
1013 error(getPos(), "Error in JPX QCD marker segment");
1014 return gFalse;
1015 }
1016 }
1017 } else if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x01) {
1018 img.tiles[0].tileComps[0].nQuantSteps = 1;
1019 img.tiles[0].tileComps[0].quantSteps =
1020 (Guint *)greallocn(img.tiles[0].tileComps[0].quantSteps,
1021 img.tiles[0].tileComps[0].nQuantSteps,
1022 sizeof(Guint));
1023 if (!readUWord(&img.tiles[0].tileComps[0].quantSteps[0])) {
1024 error(getPos(), "Error in JPX QCD marker segment");
1025 return gFalse;
1026 }
1027 } else if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x02) {
1028 img.tiles[0].tileComps[0].nQuantSteps = (segLen - 3) / 2;
1029 img.tiles[0].tileComps[0].quantSteps =
1030 (Guint *)greallocn(img.tiles[0].tileComps[0].quantSteps,
1031 img.tiles[0].tileComps[0].nQuantSteps,
1032 sizeof(Guint));
1033 for (i = 0; i < img.tiles[0].tileComps[0].nQuantSteps; ++i) {
1034 if (!readUWord(&img.tiles[0].tileComps[0].quantSteps[i])) {
1035 error(getPos(), "Error in JPX QCD marker segment");
1036 return gFalse;
1037 }
1038 }
1039 } else {
1040 error(getPos(), "Error in JPX QCD marker segment");
1041 return gFalse;
1042 }
1043 for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
1044 for (comp = 0; comp < img.nComps; ++comp) {
1045 if (!(i == 0 && comp == 0)) {
1046 img.tiles[i].tileComps[comp].quantStyle =
1047 img.tiles[0].tileComps[0].quantStyle;
1048 img.tiles[i].tileComps[comp].nQuantSteps =
1049 img.tiles[0].tileComps[0].nQuantSteps;
1050 img.tiles[i].tileComps[comp].quantSteps =
1051 (Guint *)greallocn(img.tiles[i].tileComps[comp].quantSteps,
1052 img.tiles[0].tileComps[0].nQuantSteps,
1053 sizeof(Guint));
1054 for (j = 0; j < img.tiles[0].tileComps[0].nQuantSteps; ++j) {
1055 img.tiles[i].tileComps[comp].quantSteps[j] =
1056 img.tiles[0].tileComps[0].quantSteps[j];
1057 }
1058 }
1059 }
1060 }
1061 haveQCD = gTrue;
1062 break;
1063 case 0x5d: // QCC - quantization component
1064 if (!haveQCD) {
1065 error(getPos(), "JPX QCC marker segment before QCD segment");
1066 return gFalse;
1067 }
1068 if ((img.nComps > 256 && !readUWord(&comp)) ||
1069 (img.nComps <= 256 && !readUByte(&comp)) ||
1070 comp >= img.nComps ||
1071 !readUByte(&img.tiles[0].tileComps[comp].quantStyle)) {
1072 error(getPos(), "Error in JPX QCC marker segment");
1073 return gFalse;
1074 }
1075 if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x00) {
1076 img.tiles[0].tileComps[comp].nQuantSteps =
1077 segLen - (img.nComps > 256 ? 5 : 4);
1078 img.tiles[0].tileComps[comp].quantSteps =
1079 (Guint *)greallocn(img.tiles[0].tileComps[comp].quantSteps,
1080 img.tiles[0].tileComps[comp].nQuantSteps,
1081 sizeof(Guint));
1082 for (i = 0; i < img.tiles[0].tileComps[comp].nQuantSteps; ++i) {
1083 if (!readUByte(&img.tiles[0].tileComps[comp].quantSteps[i])) {
1084 error(getPos(), "Error in JPX QCC marker segment");
1085 return gFalse;
1086 }
1087 }
1088 } else if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x01) {
1089 img.tiles[0].tileComps[comp].nQuantSteps = 1;
1090 img.tiles[0].tileComps[comp].quantSteps =
1091 (Guint *)greallocn(img.tiles[0].tileComps[comp].quantSteps,
1092 img.tiles[0].tileComps[comp].nQuantSteps,
1093 sizeof(Guint));
1094 if (!readUWord(&img.tiles[0].tileComps[comp].quantSteps[0])) {
1095 error(getPos(), "Error in JPX QCC marker segment");
1096 return gFalse;
1097 }
1098 } else if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x02) {
1099 img.tiles[0].tileComps[comp].nQuantSteps =
1100 (segLen - (img.nComps > 256 ? 5 : 4)) / 2;
1101 img.tiles[0].tileComps[comp].quantSteps =
1102 (Guint *)greallocn(img.tiles[0].tileComps[comp].quantSteps,
1103 img.tiles[0].tileComps[comp].nQuantSteps,
1104 sizeof(Guint));
1105 for (i = 0; i < img.tiles[0].tileComps[comp].nQuantSteps; ++i) {
1106 if (!readUWord(&img.tiles[0].tileComps[comp].quantSteps[i])) {
1107 error(getPos(), "Error in JPX QCD marker segment");
1108 return gFalse;
1109 }
1110 }
1111 } else {
1112 error(getPos(), "Error in JPX QCC marker segment");
1113 return gFalse;
1114 }
1115 for (i = 1; i < img.nXTiles * img.nYTiles; ++i) {
1116 img.tiles[i].tileComps[comp].quantStyle =
1117 img.tiles[0].tileComps[comp].quantStyle;
1118 img.tiles[i].tileComps[comp].nQuantSteps =
1119 img.tiles[0].tileComps[comp].nQuantSteps;
1120 img.tiles[i].tileComps[comp].quantSteps =
1121 (Guint *)greallocn(img.tiles[i].tileComps[comp].quantSteps,
1122 img.tiles[0].tileComps[comp].nQuantSteps,
1123 sizeof(Guint));
1124 for (j = 0; j < img.tiles[0].tileComps[comp].nQuantSteps; ++j) {
1125 img.tiles[i].tileComps[comp].quantSteps[j] =
1126 img.tiles[0].tileComps[comp].quantSteps[j];
1127 }
1128 }
1129 break;
1130 case 0x5e: // RGN - region of interest
1131#if 1 //~ ROI is unimplemented
1132 fprintf(stderr, "RGN\n");
1133 for (i = 0; i < segLen - 2; ++i) {
1134 if (str->getChar() == EOF) {
1135 error(getPos(), "Error in JPX PPM marker segment");
1136 return gFalse;
1137 }
1138 }
1139#else
1140 if ((img.nComps > 256 && !readUWord(&comp)) ||
1141 (img.nComps <= 256 && !readUByte(&comp)) ||
1142 comp >= img.nComps ||
1143 !readUByte(&compInfo[comp].defROI.style) ||
1144 !readUByte(&compInfo[comp].defROI.shift)) {
1145 error(getPos(), "Error in JPX RGN marker segment");
1146 return gFalse;
1147 }
1148#endif
1149 break;
1150 case 0x5f: // POC - progression order change
1151#if 1 //~ progression order changes are unimplemented
1152 fprintf(stderr, "POC\n");
1153 for (i = 0; i < segLen - 2; ++i) {
1154 if (str->getChar() == EOF) {
1155 error(getPos(), "Error in JPX PPM marker segment");
1156 return gFalse;
1157 }
1158 }
1159#else
1160 nProgs = (segLen - 2) / (img.nComps > 256 ? 9 : 7);
1161 progs = (JPXProgOrder *)gmallocn(nProgs, sizeof(JPXProgOrder));
1162 for (i = 0; i < nProgs; ++i) {
1163 if (!readUByte(&progs[i].startRes) ||
1164 !(img.nComps > 256 && readUWord(&progs[i].startComp)) ||
1165 !(img.nComps <= 256 && readUByte(&progs[i].startComp)) ||
1166 !readUWord(&progs[i].endLayer) ||
1167 !readUByte(&progs[i].endRes) ||
1168 !(img.nComps > 256 && readUWord(&progs[i].endComp)) ||
1169 !(img.nComps <= 256 && readUByte(&progs[i].endComp)) ||
1170 !readUByte(&progs[i].progOrder)) {
1171 error(getPos(), "Error in JPX POC marker segment");
1172 return gFalse;
1173 }
1174 }
1175#endif
1176 break;
1177 case 0x60: // PPM - packed packet headers, main header
1178#if 1 //~ packed packet headers are unimplemented
1179 fprintf(stderr, "PPM\n");
1180 for (i = 0; i < segLen - 2; ++i) {
1181 if (str->getChar() == EOF) {
1182 error(getPos(), "Error in JPX PPM marker segment");
1183 return gFalse;
1184 }
1185 }
1186#endif
1187 break;
1188 case 0x55: // TLM - tile-part lengths
1189 // skipped
1190 for (i = 0; i < segLen - 2; ++i) {
1191 if (str->getChar() == EOF) {
1192 error(getPos(), "Error in JPX TLM marker segment");
1193 return gFalse;
1194 }
1195 }
1196 break;
1197 case 0x57: // PLM - packet length, main header
1198 // skipped
1199 for (i = 0; i < segLen - 2; ++i) {
1200 if (str->getChar() == EOF) {
1201 error(getPos(), "Error in JPX PLM marker segment");
1202 return gFalse;
1203 }
1204 }
1205 break;
1206 case 0x63: // CRG - component registration
1207 // skipped
1208 for (i = 0; i < segLen - 2; ++i) {
1209 if (str->getChar() == EOF) {
1210 error(getPos(), "Error in JPX CRG marker segment");
1211 return gFalse;
1212 }
1213 }
1214 break;
1215 case 0x64: // COM - comment
1216 // skipped
1217 for (i = 0; i < segLen - 2; ++i) {
1218 if (str->getChar() == EOF) {
1219 error(getPos(), "Error in JPX COM marker segment");
1220 return gFalse;
1221 }
1222 }
1223 break;
1224 case 0x90: // SOT - start of tile
1225 haveSOT = gTrue;
1226 break;
1227 default:
1228 error(getPos(), "Unknown marker segment %02x in JPX stream", segType);
1229 for (i = 0; i < segLen - 2; ++i) {
1230 if (str->getChar() == EOF) {
1231 break;
1232 }
1233 }
1234 break;
1235 }
1236 } while (!haveSOT);
1237
1238 if (!haveSIZ) {
1239 error(getPos(), "Missing SIZ marker segment in JPX stream");
1240 return gFalse;
1241 }
1242 if (!haveCOD) {
1243 error(getPos(), "Missing COD marker segment in JPX stream");
1244 return gFalse;
1245 }
1246 if (!haveQCD) {
1247 error(getPos(), "Missing QCD marker segment in JPX stream");
1248 return gFalse;
1249 }
1250
1251 //----- read the tile-parts
1252 while (1) {
1253 if (!readTilePart()) {
1254 return gFalse;
1255 }
1256 if (!readMarkerHdr(&segType, &segLen)) {
1257 error(getPos(), "Error in JPX codestream");
1258 return gFalse;
1259 }
1260 if (segType != 0x90) { // SOT - start of tile
1261 break;
1262 }
1263 }
1264
1265 if (segType != 0xd9) { // EOC - end of codestream
1266 error(getPos(), "Missing EOC marker in JPX codestream");
1267 return gFalse;
1268 }
1269
1270 //----- finish decoding the image
1271 for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
1272 tile = &img.tiles[i];
1273 for (comp = 0; comp < img.nComps; ++comp) {
1274 tileComp = &tile->tileComps[comp];
1275 inverseTransform(tileComp);
1276 }
1277 if (!inverseMultiCompAndDC(tile)) {
1278 return gFalse;
1279 }
1280 }
1281
1282 //~ can free memory below tileComps here, and also tileComp.buf
1283
1284 return gTrue;
1285}
1286
1287GBool JPXStream::readTilePart() {
1288 JPXTile *tile;
1289 JPXTileComp *tileComp;
1290 JPXResLevel *resLevel;
1291 JPXPrecinct *precinct;
1292 JPXSubband *subband;
1293 JPXCodeBlock *cb;
1294 GBool haveSOD;
1295 Guint tileIdx, tilePartLen, tilePartIdx, nTileParts;
1296 GBool tilePartToEOC;
1297 Guint precinctSize, style;
1298 Guint n, nSBs, nx, ny, sbx0, sby0, comp, segLen;
1299 Guint i, j, k, cbX, cbY, r, pre, sb, cbi;
1300 int segType, level;
1301
1302 // process the SOT marker segment
1303 if (!readUWord(&tileIdx) ||
1304 !readULong(&tilePartLen) ||
1305 !readUByte(&tilePartIdx) ||
1306 !readUByte(&nTileParts)) {
1307 error(getPos(), "Error in JPX SOT marker segment");
1308 return gFalse;
1309 }
1310
1311 if (tileIdx >= img.nXTiles * img.nYTiles) {
1312 error(getPos(), "Weird tile index in JPX stream");
1313 return gFalse;
1314 }
1315
1316 tilePartToEOC = tilePartLen == 0;
1317 tilePartLen -= 12; // subtract size of SOT segment
1318
1319 haveSOD = gFalse;
1320 do {
1321 if (!readMarkerHdr(&segType, &segLen)) {
1322 error(getPos(), "Error in JPX tile-part codestream");
1323 return gFalse;
1324 }
1325 tilePartLen -= 2 + segLen;
1326 switch (segType) {
1327 case 0x52: // COD - coding style default
1328 if (!readUByte(&img.tiles[tileIdx].tileComps[0].style) ||
1329 !readUByte(&img.tiles[tileIdx].progOrder) ||
1330 !readUWord(&img.tiles[tileIdx].nLayers) ||
1331 !readUByte(&img.tiles[tileIdx].multiComp) ||
1332 !readUByte(&img.tiles[tileIdx].tileComps[0].nDecompLevels) ||
1333 !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockW) ||
1334 !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockH) ||
1335 !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockStyle) ||
1336 !readUByte(&img.tiles[tileIdx].tileComps[0].transform)) {
1337 error(getPos(), "Error in JPX COD marker segment");
1338 return gFalse;
1339 }
1340 img.tiles[tileIdx].tileComps[0].codeBlockW += 2;
1341 img.tiles[tileIdx].tileComps[0].codeBlockH += 2;
1342 for (comp = 0; comp < img.nComps; ++comp) {
1343 if (comp != 0) {
1344 img.tiles[tileIdx].tileComps[comp].style =
1345 img.tiles[tileIdx].tileComps[0].style;
1346 img.tiles[tileIdx].tileComps[comp].nDecompLevels =
1347 img.tiles[tileIdx].tileComps[0].nDecompLevels;
1348 img.tiles[tileIdx].tileComps[comp].codeBlockW =
1349 img.tiles[tileIdx].tileComps[0].codeBlockW;
1350 img.tiles[tileIdx].tileComps[comp].codeBlockH =
1351 img.tiles[tileIdx].tileComps[0].codeBlockH;
1352 img.tiles[tileIdx].tileComps[comp].codeBlockStyle =
1353 img.tiles[tileIdx].tileComps[0].codeBlockStyle;
1354 img.tiles[tileIdx].tileComps[comp].transform =
1355 img.tiles[tileIdx].tileComps[0].transform;
1356 }
1357 img.tiles[tileIdx].tileComps[comp].resLevels =
1358 (JPXResLevel *)greallocn(
1359 img.tiles[tileIdx].tileComps[comp].resLevels,
1360 (img.tiles[tileIdx].tileComps[comp].nDecompLevels + 1),
1361 sizeof(JPXResLevel));
1362 for (r = 0;
1363 r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels;
1364 ++r) {
1365 img.tiles[tileIdx].tileComps[comp].resLevels[r].precincts = NULL;
1366 }
1367 }
1368 for (r = 0; r <= img.tiles[tileIdx].tileComps[0].nDecompLevels; ++r) {
1369 if (img.tiles[tileIdx].tileComps[0].style & 0x01) {
1370 if (!readUByte(&precinctSize)) {
1371 error(getPos(), "Error in JPX COD marker segment");
1372 return gFalse;
1373 }
1374 img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth =
1375 precinctSize & 0x0f;
1376 img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight =
1377 (precinctSize >> 4) & 0x0f;
1378 } else {
1379 img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth = 15;
1380 img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight = 15;
1381 }
1382 }
1383 for (comp = 1; comp < img.nComps; ++comp) {
1384 for (r = 0;
1385 r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels;
1386 ++r) {
1387 img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth =
1388 img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth;
1389 img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight =
1390 img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight;
1391 }
1392 }
1393 break;
1394 case 0x53: // COC - coding style component
1395 if ((img.nComps > 256 && !readUWord(&comp)) ||
1396 (img.nComps <= 256 && !readUByte(&comp)) ||
1397 comp >= img.nComps ||
1398 !readUByte(&style) ||
1399 !readUByte(&img.tiles[tileIdx].tileComps[comp].nDecompLevels) ||
1400 !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockW) ||
1401 !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockH) ||
1402 !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockStyle) ||
1403 !readUByte(&img.tiles[tileIdx].tileComps[comp].transform)) {
1404 error(getPos(), "Error in JPX COC marker segment");
1405 return gFalse;
1406 }
1407 img.tiles[tileIdx].tileComps[comp].style =
1408 (img.tiles[tileIdx].tileComps[comp].style & ~1) | (style & 1);
1409 img.tiles[tileIdx].tileComps[comp].codeBlockW += 2;
1410 img.tiles[tileIdx].tileComps[comp].codeBlockH += 2;
1411 img.tiles[tileIdx].tileComps[comp].resLevels =
1412 (JPXResLevel *)greallocn(
1413 img.tiles[tileIdx].tileComps[comp].resLevels,
1414 (img.tiles[tileIdx].tileComps[comp].nDecompLevels + 1),
1415 sizeof(JPXResLevel));
1416 for (r = 0; r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; ++r) {
1417 img.tiles[tileIdx].tileComps[comp].resLevels[r].precincts = NULL;
1418 }
1419 for (r = 0; r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; ++r) {
1420 if (img.tiles[tileIdx].tileComps[comp].style & 0x01) {
1421 if (!readUByte(&precinctSize)) {
1422 error(getPos(), "Error in JPX COD marker segment");
1423 return gFalse;
1424 }
1425 img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth =
1426 precinctSize & 0x0f;
1427 img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight =
1428 (precinctSize >> 4) & 0x0f;
1429 } else {
1430 img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth = 15;
1431 img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight = 15;
1432 }
1433 }
1434 break;
1435 case 0x5c: // QCD - quantization default
1436 if (!readUByte(&img.tiles[tileIdx].tileComps[0].quantStyle)) {
1437 error(getPos(), "Error in JPX QCD marker segment");
1438 return gFalse;
1439 }
1440 if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x00) {
1441 img.tiles[tileIdx].tileComps[0].nQuantSteps =
1442 segLen - 3;
1443 img.tiles[tileIdx].tileComps[0].quantSteps =
1444 (Guint *)greallocn(img.tiles[tileIdx].tileComps[0].quantSteps,
1445 img.tiles[tileIdx].tileComps[0].nQuantSteps,
1446 sizeof(Guint));
1447 for (i = 0; i < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++i) {
1448 if (!readUByte(&img.tiles[tileIdx].tileComps[0].quantSteps[i])) {
1449 error(getPos(), "Error in JPX QCD marker segment");
1450 return gFalse;
1451 }
1452 }
1453 } else if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x01) {
1454 img.tiles[tileIdx].tileComps[0].nQuantSteps = 1;
1455 img.tiles[tileIdx].tileComps[0].quantSteps =
1456 (Guint *)greallocn(img.tiles[tileIdx].tileComps[0].quantSteps,
1457 img.tiles[tileIdx].tileComps[0].nQuantSteps,
1458 sizeof(Guint));
1459 if (!readUWord(&img.tiles[tileIdx].tileComps[0].quantSteps[0])) {
1460 error(getPos(), "Error in JPX QCD marker segment");
1461 return gFalse;
1462 }
1463 } else if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x02) {
1464 img.tiles[tileIdx].tileComps[0].nQuantSteps = (segLen - 3) / 2;
1465 img.tiles[tileIdx].tileComps[0].quantSteps =
1466 (Guint *)greallocn(img.tiles[tileIdx].tileComps[0].quantSteps,
1467 img.tiles[tileIdx].tileComps[0].nQuantSteps,
1468 sizeof(Guint));
1469 for (i = 0; i < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++i) {
1470 if (!readUWord(&img.tiles[tileIdx].tileComps[0].quantSteps[i])) {
1471 error(getPos(), "Error in JPX QCD marker segment");
1472 return gFalse;
1473 }
1474 }
1475 } else {
1476 error(getPos(), "Error in JPX QCD marker segment");
1477 return gFalse;
1478 }
1479 for (comp = 1; comp < img.nComps; ++comp) {
1480 img.tiles[tileIdx].tileComps[comp].quantStyle =
1481 img.tiles[tileIdx].tileComps[0].quantStyle;
1482 img.tiles[tileIdx].tileComps[comp].nQuantSteps =
1483 img.tiles[tileIdx].tileComps[0].nQuantSteps;
1484 img.tiles[tileIdx].tileComps[comp].quantSteps =
1485 (Guint *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps,
1486 img.tiles[tileIdx].tileComps[0].nQuantSteps,
1487 sizeof(Guint));
1488 for (j = 0; j < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++j) {
1489 img.tiles[tileIdx].tileComps[comp].quantSteps[j] =
1490 img.tiles[tileIdx].tileComps[0].quantSteps[j];
1491 }
1492 }
1493 break;
1494 case 0x5d: // QCC - quantization component
1495 if ((img.nComps > 256 && !readUWord(&comp)) ||
1496 (img.nComps <= 256 && !readUByte(&comp)) ||
1497 comp >= img.nComps ||
1498 !readUByte(&img.tiles[tileIdx].tileComps[comp].quantStyle)) {
1499 error(getPos(), "Error in JPX QCC marker segment");
1500 return gFalse;
1501 }
1502 if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f) == 0x00) {
1503 img.tiles[tileIdx].tileComps[comp].nQuantSteps =
1504 segLen - (img.nComps > 256 ? 5 : 4);
1505 img.tiles[tileIdx].tileComps[comp].quantSteps =
1506 (Guint *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps,
1507 img.tiles[tileIdx].tileComps[comp].nQuantSteps,
1508 sizeof(Guint));
1509 for (i = 0; i < img.tiles[tileIdx].tileComps[comp].nQuantSteps; ++i) {
1510 if (!readUByte(&img.tiles[tileIdx].tileComps[comp].quantSteps[i])) {
1511 error(getPos(), "Error in JPX QCC marker segment");
1512 return gFalse;
1513 }
1514 }
1515 } else if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f)
1516 == 0x01) {
1517 img.tiles[tileIdx].tileComps[comp].nQuantSteps = 1;
1518 img.tiles[tileIdx].tileComps[comp].quantSteps =
1519 (Guint *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps,
1520 img.tiles[tileIdx].tileComps[comp].nQuantSteps,
1521 sizeof(Guint));
1522 if (!readUWord(&img.tiles[tileIdx].tileComps[comp].quantSteps[0])) {
1523 error(getPos(), "Error in JPX QCC marker segment");
1524 return gFalse;
1525 }
1526 } else if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f)
1527 == 0x02) {
1528 img.tiles[tileIdx].tileComps[comp].nQuantSteps =
1529 (segLen - (img.nComps > 256 ? 5 : 4)) / 2;
1530 img.tiles[tileIdx].tileComps[comp].quantSteps =
1531 (Guint *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps,
1532 img.tiles[tileIdx].tileComps[comp].nQuantSteps,
1533 sizeof(Guint));
1534 for (i = 0; i < img.tiles[tileIdx].tileComps[comp].nQuantSteps; ++i) {
1535 if (!readUWord(&img.tiles[tileIdx].tileComps[comp].quantSteps[i])) {
1536 error(getPos(), "Error in JPX QCD marker segment");
1537 return gFalse;
1538 }
1539 }
1540 } else {
1541 error(getPos(), "Error in JPX QCC marker segment");
1542 return gFalse;
1543 }
1544 break;
1545 case 0x5e: // RGN - region of interest
1546#if 1 //~ ROI is unimplemented
1547 fprintf(stderr, "RGN\n");
1548 for (i = 0; i < segLen - 2; ++i) {
1549 if (str->getChar() == EOF) {
1550 error(getPos(), "Error in JPX PPM marker segment");
1551 return gFalse;
1552 }
1553 }
1554#else
1555 if ((img.nComps > 256 && !readUWord(&comp)) ||
1556 (img.nComps <= 256 && !readUByte(&comp)) ||
1557 comp >= img.nComps ||
1558 !readUByte(&compInfo[comp].roi.style) ||
1559 !readUByte(&compInfo[comp].roi.shift)) {
1560 error(getPos(), "Error in JPX RGN marker segment");
1561 return gFalse;
1562 }
1563#endif
1564 break;
1565 case 0x5f: // POC - progression order change
1566#if 1 //~ progression order changes are unimplemented
1567 fprintf(stderr, "POC\n");
1568 for (i = 0; i < segLen - 2; ++i) {
1569 if (str->getChar() == EOF) {
1570 error(getPos(), "Error in JPX PPM marker segment");
1571 return gFalse;
1572 }
1573 }
1574#else
1575 nTileProgs = (segLen - 2) / (img.nComps > 256 ? 9 : 7);
1576 tileProgs = (JPXProgOrder *)gmallocn(nTileProgs, sizeof(JPXProgOrder));
1577 for (i = 0; i < nTileProgs; ++i) {
1578 if (!readUByte(&tileProgs[i].startRes) ||
1579 !(img.nComps > 256 && readUWord(&tileProgs[i].startComp)) ||
1580 !(img.nComps <= 256 && readUByte(&tileProgs[i].startComp)) ||
1581 !readUWord(&tileProgs[i].endLayer) ||
1582 !readUByte(&tileProgs[i].endRes) ||
1583 !(img.nComps > 256 && readUWord(&tileProgs[i].endComp)) ||
1584 !(img.nComps <= 256 && readUByte(&tileProgs[i].endComp)) ||
1585 !readUByte(&tileProgs[i].progOrder)) {
1586 error(getPos(), "Error in JPX POC marker segment");
1587 return gFalse;
1588 }
1589 }
1590#endif
1591 break;
1592 case 0x61: // PPT - packed packet headers, tile-part hdr
1593#if 1 //~ packed packet headers are unimplemented
1594 fprintf(stderr, "PPT\n");
1595 for (i = 0; i < segLen - 2; ++i) {
1596 if (str->getChar() == EOF) {
1597 error(getPos(), "Error in JPX PPT marker segment");
1598 return gFalse;
1599 }
1600 }
1601#endif
1602 case 0x58: // PLT - packet length, tile-part header
1603 // skipped
1604 for (i = 0; i < segLen - 2; ++i) {
1605 if (str->getChar() == EOF) {
1606 error(getPos(), "Error in JPX PLT marker segment");
1607 return gFalse;
1608 }
1609 }
1610 break;
1611 case 0x64: // COM - comment
1612 // skipped
1613 for (i = 0; i < segLen - 2; ++i) {
1614 if (str->getChar() == EOF) {
1615 error(getPos(), "Error in JPX COM marker segment");
1616 return gFalse;
1617 }
1618 }
1619 break;
1620 case 0x93: // SOD - start of data
1621 haveSOD = gTrue;
1622 break;
1623 default:
1624 error(getPos(), "Unknown marker segment %02x in JPX tile-part stream",
1625 segType);
1626 for (i = 0; i < segLen - 2; ++i) {
1627 if (str->getChar() == EOF) {
1628 break;
1629 }
1630 }
1631 break;
1632 }
1633 } while (!haveSOD);
1634
1635 //----- initialize the tile, precincts, and code-blocks
1636 if (tilePartIdx == 0) {
1637 tile = &img.tiles[tileIdx];
1638 i = tileIdx / img.nXTiles;
1639 j = tileIdx % img.nXTiles;
1640 if ((tile->x0 = img.xTileOffset + j * img.xTileSize) < img.xOffset) {
1641 tile->x0 = img.xOffset;
1642 }
1643 if ((tile->y0 = img.yTileOffset + i * img.yTileSize) < img.yOffset) {
1644 tile->y0 = img.yOffset;
1645 }
1646 if ((tile->x1 = img.xTileOffset + (j + 1) * img.xTileSize) > img.xSize) {
1647 tile->x1 = img.xSize;
1648 }
1649 if ((tile->y1 = img.yTileOffset + (i + 1) * img.yTileSize) > img.ySize) {
1650 tile->y1 = img.ySize;
1651 }
1652 tile->comp = 0;
1653 tile->res = 0;
1654 tile->precinct = 0;
1655 tile->layer = 0;
1656 tile->maxNDecompLevels = 0;
1657 for (comp = 0; comp < img.nComps; ++comp) {
1658 tileComp = &tile->tileComps[comp];
1659 if (tileComp->nDecompLevels > tile->maxNDecompLevels) {
1660 tile->maxNDecompLevels = tileComp->nDecompLevels;
1661 }
1662 tileComp->x0 = jpxCeilDiv(tile->x0, tileComp->hSep);
1663 tileComp->y0 = jpxCeilDiv(tile->y0, tileComp->hSep);
1664 tileComp->x1 = jpxCeilDiv(tile->x1, tileComp->hSep);
1665 tileComp->y1 = jpxCeilDiv(tile->y1, tileComp->hSep);
1666 tileComp->cbW = 1 << tileComp->codeBlockW;
1667 tileComp->cbH = 1 << tileComp->codeBlockH;
1668 tileComp->data = (int *)gmallocn((tileComp->x1 - tileComp->x0) *
1669 (tileComp->y1 - tileComp->y0),
1670 sizeof(int));
1671 if (tileComp->x1 - tileComp->x0 > tileComp->y1 - tileComp->y0) {
1672 n = tileComp->x1 - tileComp->x0;
1673 } else {
1674 n = tileComp->y1 - tileComp->y0;
1675 }
1676 tileComp->buf = (int *)gmallocn(n + 8, sizeof(int));
1677 for (r = 0; r <= tileComp->nDecompLevels; ++r) {
1678 resLevel = &tileComp->resLevels[r];
1679 k = r == 0 ? tileComp->nDecompLevels
1680 : tileComp->nDecompLevels - r + 1;
1681 resLevel->x0 = jpxCeilDivPow2(tileComp->x0, k);
1682 resLevel->y0 = jpxCeilDivPow2(tileComp->y0, k);
1683 resLevel->x1 = jpxCeilDivPow2(tileComp->x1, k);
1684 resLevel->y1 = jpxCeilDivPow2(tileComp->y1, k);
1685 if (r == 0) {
1686 resLevel->bx0[0] = resLevel->x0;
1687 resLevel->by0[0] = resLevel->y0;
1688 resLevel->bx1[0] = resLevel->x1;
1689 resLevel->by1[0] = resLevel->y1;
1690 } else {
1691 resLevel->bx0[0] = jpxCeilDivPow2(tileComp->x0 - (1 << (k-1)), k);
1692 resLevel->by0[0] = resLevel->y0;
1693 resLevel->bx1[0] = jpxCeilDivPow2(tileComp->x1 - (1 << (k-1)), k);
1694 resLevel->by1[0] = resLevel->y1;
1695 resLevel->bx0[1] = resLevel->x0;
1696 resLevel->by0[1] = jpxCeilDivPow2(tileComp->y0 - (1 << (k-1)), k);
1697 resLevel->bx1[1] = resLevel->x1;
1698 resLevel->by1[1] = jpxCeilDivPow2(tileComp->y1 - (1 << (k-1)), k);
1699 resLevel->bx0[2] = jpxCeilDivPow2(tileComp->x0 - (1 << (k-1)), k);
1700 resLevel->by0[2] = jpxCeilDivPow2(tileComp->y0 - (1 << (k-1)), k);
1701 resLevel->bx1[2] = jpxCeilDivPow2(tileComp->x1 - (1 << (k-1)), k);
1702 resLevel->by1[2] = jpxCeilDivPow2(tileComp->y1 - (1 << (k-1)), k);
1703 }
1704 resLevel->precincts = (JPXPrecinct *)gmallocn(1, sizeof(JPXPrecinct));
1705 for (pre = 0; pre < 1; ++pre) {
1706 precinct = &resLevel->precincts[pre];
1707 precinct->x0 = resLevel->x0;
1708 precinct->y0 = resLevel->y0;
1709 precinct->x1 = resLevel->x1;
1710 precinct->y1 = resLevel->y1;
1711 nSBs = r == 0 ? 1 : 3;
1712 precinct->subbands =
1713 (JPXSubband *)gmallocn(nSBs, sizeof(JPXSubband));
1714 for (sb = 0; sb < nSBs; ++sb) {
1715 subband = &precinct->subbands[sb];
1716 subband->x0 = resLevel->bx0[sb];
1717 subband->y0 = resLevel->by0[sb];
1718 subband->x1 = resLevel->bx1[sb];
1719 subband->y1 = resLevel->by1[sb];
1720 subband->nXCBs = jpxCeilDivPow2(subband->x1,
1721 tileComp->codeBlockW)
1722 - jpxFloorDivPow2(subband->x0,
1723 tileComp->codeBlockW);
1724 subband->nYCBs = jpxCeilDivPow2(subband->y1,
1725 tileComp->codeBlockH)
1726 - jpxFloorDivPow2(subband->y0,
1727 tileComp->codeBlockH);
1728 n = subband->nXCBs > subband->nYCBs ? subband->nXCBs
1729 : subband->nYCBs;
1730 for (subband->maxTTLevel = 0, --n;
1731 n;
1732 ++subband->maxTTLevel, n >>= 1) ;
1733 n = 0;
1734 for (level = subband->maxTTLevel; level >= 0; --level) {
1735 nx = jpxCeilDivPow2(subband->nXCBs, level);
1736 ny = jpxCeilDivPow2(subband->nYCBs, level);
1737 n += nx * ny;
1738 }
1739 subband->inclusion =
1740 (JPXTagTreeNode *)gmallocn(n, sizeof(JPXTagTreeNode));
1741 subband->zeroBitPlane =
1742 (JPXTagTreeNode *)gmallocn(n, sizeof(JPXTagTreeNode));
1743 for (k = 0; k < n; ++k) {
1744 subband->inclusion[k].finished = gFalse;
1745 subband->inclusion[k].val = 0;
1746 subband->zeroBitPlane[k].finished = gFalse;
1747 subband->zeroBitPlane[k].val = 0;
1748 }
1749 subband->cbs = (JPXCodeBlock *)gmallocn(subband->nXCBs *
1750 subband->nYCBs,
1751 sizeof(JPXCodeBlock));
1752 sbx0 = jpxFloorDivPow2(subband->x0, tileComp->codeBlockW);
1753 sby0 = jpxFloorDivPow2(subband->y0, tileComp->codeBlockH);
1754 cb = subband->cbs;
1755 for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
1756 for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
1757 cb->x0 = (sbx0 + cbX) << tileComp->codeBlockW;
1758 cb->x1 = cb->x0 + tileComp->cbW;
1759 if (subband->x0 > cb->x0) {
1760 cb->x0 = subband->x0;
1761 }
1762 if (subband->x1 < cb->x1) {
1763 cb->x1 = subband->x1;
1764 }
1765 cb->y0 = (sby0 + cbY) << tileComp->codeBlockH;
1766 cb->y1 = cb->y0 + tileComp->cbH;
1767 if (subband->y0 > cb->y0) {
1768 cb->y0 = subband->y0;
1769 }
1770 if (subband->y1 < cb->y1) {
1771 cb->y1 = subband->y1;
1772 }
1773 cb->seen = gFalse;
1774 cb->lBlock = 3;
1775 cb->nextPass = jpxPassCleanup;
1776 cb->nZeroBitPlanes = 0;
1777 cb->coeffs =
1778 (JPXCoeff *)gmallocn((1 << (tileComp->codeBlockW
1779 + tileComp->codeBlockH)),
1780 sizeof(JPXCoeff));
1781 for (cbi = 0;
1782 cbi < (Guint)(1 << (tileComp->codeBlockW
1783 + tileComp->codeBlockH));
1784 ++cbi) {
1785 cb->coeffs[cbi].flags = 0;
1786 cb->coeffs[cbi].len = 0;
1787 cb->coeffs[cbi].mag = 0;
1788 }
1789 cb->arithDecoder = NULL;
1790 cb->stats = NULL;
1791 ++cb;
1792 }
1793 }
1794 }
1795 }
1796 }
1797 }
1798 }
1799
1800 return readTilePartData(tileIdx, tilePartLen, tilePartToEOC);
1801}
1802
1803GBool JPXStream::readTilePartData(Guint tileIdx,
1804 Guint tilePartLen, GBool tilePartToEOC) {
1805 JPXTile *tile;
1806 JPXTileComp *tileComp;
1807 JPXResLevel *resLevel;
1808 JPXPrecinct *precinct;
1809 JPXSubband *subband;
1810 JPXCodeBlock *cb;
1811 Guint ttVal;
1812 Guint bits, cbX, cbY, nx, ny, i, j, n, sb;
1813 int level;
1814
1815 tile = &img.tiles[tileIdx];
1816
1817 // read all packets from this tile-part
1818 while (1) {
1819 if (tilePartToEOC) {
1820 //~ peek for an EOC marker
1821 } else if (tilePartLen == 0) {
1822 break;
1823 }
1824
1825 tileComp = &tile->tileComps[tile->comp];
1826 resLevel = &tileComp->resLevels[tile->res];
1827 precinct = &resLevel->precincts[tile->precinct];
1828
1829 //----- packet header
1830
1831 // zero-length flag
1832 if (!readBits(1, &bits)) {
1833 goto err;
1834 }
1835 if (!bits) {
1836 // packet is empty -- clear all code-block inclusion flags
1837 for (sb = 0; sb < (tile->res == 0 ? 1 : 3); ++sb) {
1838 subband = &precinct->subbands[sb];
1839 for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
1840 for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
1841 cb = &subband->cbs[cbY * subband->nXCBs + cbX];
1842 cb->included = gFalse;
1843 }
1844 }
1845 }
1846 } else {
1847
1848 for (sb = 0; sb < (tile->res == 0 ? 1 : 3); ++sb) {
1849 subband = &precinct->subbands[sb];
1850 for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
1851 for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
1852 cb = &subband->cbs[cbY * subband->nXCBs + cbX];
1853
1854 // skip code-blocks with no coefficients
1855 if (cb->x0 >= cb->x1 || cb->y0 >= cb->y1) {
1856 cb->included = gFalse;
1857 continue;
1858 }
1859
1860 // code-block inclusion
1861 if (cb->seen) {
1862 if (!readBits(1, &cb->included)) {
1863 goto err;
1864 }
1865 } else {
1866 ttVal = 0;
1867 i = 0;
1868 for (level = subband->maxTTLevel; level >= 0; --level) {
1869 nx = jpxCeilDivPow2(subband->nXCBs, level);
1870 ny = jpxCeilDivPow2(subband->nYCBs, level);
1871 j = i + (cbY >> level) * nx + (cbX >> level);
1872 if (!subband->inclusion[j].finished &&
1873 !subband->inclusion[j].val) {
1874 subband->inclusion[j].val = ttVal;
1875 } else {
1876 ttVal = subband->inclusion[j].val;
1877 }
1878 while (!subband->inclusion[j].finished &&
1879 ttVal <= tile->layer) {
1880 if (!readBits(1, &bits)) {
1881 goto err;
1882 }
1883 if (bits == 1) {
1884 subband->inclusion[j].finished = gTrue;
1885 } else {
1886 ++ttVal;
1887 }
1888 }
1889 subband->inclusion[j].val = ttVal;
1890 if (ttVal > tile->layer) {
1891 break;
1892 }
1893 i += nx * ny;
1894 }
1895 cb->included = level < 0;
1896 }
1897
1898 if (cb->included) {
1899
1900 // zero bit-plane count
1901 if (!cb->seen) {
1902 ttVal = 0;
1903 i = 0;
1904 for (level = subband->maxTTLevel; level >= 0; --level) {
1905 nx = jpxCeilDivPow2(subband->nXCBs, level);
1906 ny = jpxCeilDivPow2(subband->nYCBs, level);
1907 j = i + (cbY >> level) * nx + (cbX >> level);
1908 if (!subband->zeroBitPlane[j].finished &&
1909 !subband->zeroBitPlane[j].val) {
1910 subband->zeroBitPlane[j].val = ttVal;
1911 } else {
1912 ttVal = subband->zeroBitPlane[j].val;
1913 }
1914 while (!subband->zeroBitPlane[j].finished) {
1915 if (!readBits(1, &bits)) {
1916 goto err;
1917 }
1918 if (bits == 1) {
1919 subband->zeroBitPlane[j].finished = gTrue;
1920 } else {
1921 ++ttVal;
1922 }
1923 }
1924 subband->zeroBitPlane[j].val = ttVal;
1925 i += nx * ny;
1926 }
1927 cb->nZeroBitPlanes = ttVal;
1928 }
1929
1930 // number of coding passes
1931 if (!readBits(1, &bits)) {
1932 goto err;
1933 }
1934 if (bits == 0) {
1935 cb->nCodingPasses = 1;
1936 } else {
1937 if (!readBits(1, &bits)) {
1938 goto err;
1939 }
1940 if (bits == 0) {
1941 cb->nCodingPasses = 2;
1942 } else {
1943 if (!readBits(2, &bits)) {
1944 goto err;
1945 }
1946 if (bits < 3) {
1947 cb->nCodingPasses = 3 + bits;
1948 } else {
1949 if (!readBits(5, &bits)) {
1950 goto err;
1951 }
1952 if (bits < 31) {
1953 cb->nCodingPasses = 6 + bits;
1954 } else {
1955 if (!readBits(7, &bits)) {
1956 goto err;
1957 }
1958 cb->nCodingPasses = 37 + bits;
1959 }
1960 }
1961 }
1962 }
1963
1964 // update Lblock
1965 while (1) {
1966 if (!readBits(1, &bits)) {
1967 goto err;
1968 }
1969 if (!bits) {
1970 break;
1971 }
1972 ++cb->lBlock;
1973 }
1974
1975 // length of compressed data
1976 //~ deal with multiple codeword segments
1977 for (n = cb->lBlock, i = cb->nCodingPasses >> 1;
1978 i;
1979 ++n, i >>= 1) ;
1980 if (!readBits(n, &cb->dataLen)) {
1981 goto err;
1982 }
1983 }
1984 }
1985 }
1986 }
1987 }
1988 tilePartLen -= byteCount;
1989 clearBitBuf();
1990
1991 //----- packet data
1992
1993 for (sb = 0; sb < (tile->res == 0 ? 1 : 3); ++sb) {
1994 subband = &precinct->subbands[sb];
1995 for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
1996 for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
1997 cb = &subband->cbs[cbY * subband->nXCBs + cbX];
1998 if (cb->included) {
1999 if (!readCodeBlockData(tileComp, resLevel, precinct, subband,
2000 tile->res, sb, cb)) {
2001 return gFalse;
2002 }
2003 tilePartLen -= cb->dataLen;
2004 cb->seen = gTrue;
2005 }
2006 }
2007 }
2008 }
2009
2010 //----- next packet
2011
2012 switch (tile->progOrder) {
2013 case 0: // layer, resolution level, component, precinct
2014 if (++tile->comp == img.nComps) {
2015 tile->comp = 0;
2016 if (++tile->res == tile->maxNDecompLevels + 1) {
2017 tile->res = 0;
2018 if (++tile->layer == tile->nLayers) {
2019 tile->layer = 0;
2020 }
2021 }
2022 }
2023 break;
2024 case 1: // resolution level, layer, component, precinct
2025 if (++tile->comp == img.nComps) {
2026 tile->comp = 0;
2027 if (++tile->layer == tile->nLayers) {
2028 tile->layer = 0;
2029 if (++tile->res == tile->maxNDecompLevels + 1) {
2030 tile->res = 0;
2031 }
2032 }
2033 }
2034 break;
2035 case 2: // resolution level, precinct, component, layer
2036 //~ this isn't correct -- see B.12.1.3
2037 if (++tile->layer == tile->nLayers) {
2038 tile->layer = 0;
2039 if (++tile->comp == img.nComps) {
2040 tile->comp = 0;
2041 if (++tile->res == tile->maxNDecompLevels + 1) {
2042 tile->res = 0;
2043 }
2044 }
2045 }
2046 break;
2047 case 3: // precinct, component, resolution level, layer
2048 //~ this isn't correct -- see B.12.1.4
2049 if (++tile->layer == tile->nLayers) {
2050 tile->layer = 0;
2051 if (++tile->res == tile->maxNDecompLevels + 1) {
2052 tile->res = 0;
2053 if (++tile->comp == img.nComps) {
2054 tile->comp = 0;
2055 }
2056 }
2057 }
2058 break;
2059 case 4: // component, precinct, resolution level, layer
2060 //~ this isn't correct -- see B.12.1.5
2061 if (++tile->layer == tile->nLayers) {
2062 tile->layer = 0;
2063 if (++tile->res == tile->maxNDecompLevels + 1) {
2064 tile->res = 0;
2065 if (++tile->comp == img.nComps) {
2066 tile->comp = 0;
2067 }
2068 }
2069 }
2070 break;
2071 }
2072 }
2073
2074 return gTrue;
2075
2076 err:
2077 error(getPos(), "Error in JPX stream");
2078 return gFalse;
2079}
2080
2081GBool JPXStream::readCodeBlockData(JPXTileComp *tileComp,
2082 JPXResLevel *resLevel,
2083 JPXPrecinct *precinct,
2084 JPXSubband *subband,
2085 Guint res, Guint sb,
2086 JPXCodeBlock *cb) {
2087 JPXCoeff *coeff0, *coeff1, *coeff;
2088 Guint horiz, vert, diag, all, cx, xorBit;
2089 int horizSign, vertSign;
2090 Guint i, x, y0, y1, y2;
2091
2092 if (cb->arithDecoder) {
2093 cb->arithDecoder->restart(cb->dataLen);
2094 } else {
2095 cb->arithDecoder = new JArithmeticDecoder();
2096 cb->arithDecoder->setStream(str, cb->dataLen);
2097 cb->arithDecoder->start();
2098 cb->stats = new JArithmeticDecoderStats(jpxNContexts);
2099 cb->stats->setEntry(jpxContextSigProp, 4, 0);
2100 cb->stats->setEntry(jpxContextRunLength, 3, 0);
2101 cb->stats->setEntry(jpxContextUniform, 46, 0);
2102 }
2103
2104 for (i = 0; i < cb->nCodingPasses; ++i) {
2105 switch (cb->nextPass) {
2106
2107 //----- significance propagation pass
2108 case jpxPassSigProp:
2109 for (y0 = cb->y0, coeff0 = cb->coeffs;
2110 y0 < cb->y1;
2111 y0 += 4, coeff0 += 4 << tileComp->codeBlockW) {
2112 for (x = cb->x0, coeff1 = coeff0;
2113 x < cb->x1;
2114 ++x, ++coeff1) {
2115 for (y1 = 0, coeff = coeff1;
2116 y1 < 4 && y0+y1 < cb->y1;
2117 ++y1, coeff += tileComp->cbW) {
2118 if (!(coeff->flags & jpxCoeffSignificant)) {
2119 horiz = vert = diag = 0;
2120 horizSign = vertSign = 2;
2121 if (x > cb->x0) {
2122 if (coeff[-1].flags & jpxCoeffSignificant) {
2123 ++horiz;
2124 horizSign += (coeff[-1].flags & jpxCoeffSign) ? -1 : 1;
2125 }
2126 if (y0+y1 > cb->y0) {
2127 diag += (coeff[-(int)tileComp->cbW - 1].flags
2128 >> jpxCoeffSignificantB) & 1;
2129 }
2130 if (y0+y1 < cb->y1 - 1) {
2131 diag += (coeff[tileComp->cbW - 1].flags
2132 >> jpxCoeffSignificantB) & 1;
2133 }
2134 }
2135 if (x < cb->x1 - 1) {
2136 if (coeff[1].flags & jpxCoeffSignificant) {
2137 ++horiz;
2138 horizSign += (coeff[1].flags & jpxCoeffSign) ? -1 : 1;
2139 }
2140 if (y0+y1 > cb->y0) {
2141 diag += (coeff[-(int)tileComp->cbW + 1].flags
2142 >> jpxCoeffSignificantB) & 1;
2143 }
2144 if (y0+y1 < cb->y1 - 1) {
2145 diag += (coeff[tileComp->cbW + 1].flags
2146 >> jpxCoeffSignificantB) & 1;
2147 }
2148 }
2149 if (y0+y1 > cb->y0) {
2150 if (coeff[-(int)tileComp->cbW].flags & jpxCoeffSignificant) {
2151 ++vert;
2152 vertSign += (coeff[-(int)tileComp->cbW].flags & jpxCoeffSign)
2153 ? -1 : 1;
2154 }
2155 }
2156 if (y0+y1 < cb->y1 - 1) {
2157 if (coeff[tileComp->cbW].flags & jpxCoeffSignificant) {
2158 ++vert;
2159 vertSign += (coeff[tileComp->cbW].flags & jpxCoeffSign)
2160 ? -1 : 1;
2161 }
2162 }
2163 cx = sigPropContext[horiz][vert][diag][res == 0 ? 1 : sb];
2164 if (cx != 0) {
2165 if (cb->arithDecoder->decodeBit(cx, cb->stats)) {
2166 coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef;
2167 coeff->mag = (coeff->mag << 1) | 1;
2168 cx = signContext[horizSign][vertSign][0];
2169 xorBit = signContext[horizSign][vertSign][1];
2170 if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) {
2171 coeff->flags |= jpxCoeffSign;
2172 }
2173 }
2174 ++coeff->len;
2175 coeff->flags |= jpxCoeffTouched;
2176 }
2177 }
2178 }
2179 }
2180 }
2181 ++cb->nextPass;
2182 break;
2183
2184 //----- magnitude refinement pass
2185 case jpxPassMagRef:
2186 for (y0 = cb->y0, coeff0 = cb->coeffs;
2187 y0 < cb->y1;
2188 y0 += 4, coeff0 += 4 << tileComp->codeBlockW) {
2189 for (x = cb->x0, coeff1 = coeff0;
2190 x < cb->x1;
2191 ++x, ++coeff1) {
2192 for (y1 = 0, coeff = coeff1;
2193 y1 < 4 && y0+y1 < cb->y1;
2194 ++y1, coeff += tileComp->cbW) {
2195 if ((coeff->flags & jpxCoeffSignificant) &&
2196 !(coeff->flags & jpxCoeffTouched)) {
2197 if (coeff->flags & jpxCoeffFirstMagRef) {
2198 all = 0;
2199 if (x > cb->x0) {
2200 all += (coeff[-1].flags >> jpxCoeffSignificantB) & 1;
2201 if (y0+y1 > cb->y0) {
2202 all += (coeff[-(int)tileComp->cbW - 1].flags
2203 >> jpxCoeffSignificantB) & 1;
2204 }
2205 if (y0+y1 < cb->y1 - 1) {
2206 all += (coeff[tileComp->cbW - 1].flags
2207 >> jpxCoeffSignificantB) & 1;
2208 }
2209 }
2210 if (x < cb->x1 - 1) {
2211 all += (coeff[1].flags >> jpxCoeffSignificantB) & 1;
2212 if (y0+y1 > cb->y0) {
2213 all += (coeff[-(int)tileComp->cbW + 1].flags
2214 >> jpxCoeffSignificantB) & 1;
2215 }
2216 if (y0+y1 < cb->y1 - 1) {
2217 all += (coeff[tileComp->cbW + 1].flags
2218 >> jpxCoeffSignificantB) & 1;
2219 }
2220 }
2221 if (y0+y1 > cb->y0) {
2222 all += (coeff[-(int)tileComp->cbW].flags
2223 >> jpxCoeffSignificantB) & 1;
2224 }
2225 if (y0+y1 < cb->y1 - 1) {
2226 all += (coeff[tileComp->cbW].flags
2227 >> jpxCoeffSignificantB) & 1;
2228 }
2229 cx = all ? 15 : 14;
2230 } else {
2231 cx = 16;
2232 }
2233 coeff->mag = (coeff->mag << 1) |
2234 cb->arithDecoder->decodeBit(cx, cb->stats);
2235 ++coeff->len;
2236 coeff->flags |= jpxCoeffTouched;
2237 coeff->flags &= ~jpxCoeffFirstMagRef;
2238 }
2239 }
2240 }
2241 }
2242 ++cb->nextPass;
2243 break;
2244
2245 //----- cleanup pass
2246 case jpxPassCleanup:
2247 for (y0 = cb->y0, coeff0 = cb->coeffs;
2248 y0 < cb->y1;
2249 y0 += 4, coeff0 += 4 << tileComp->codeBlockW) {
2250 for (x = cb->x0, coeff1 = coeff0;
2251 x < cb->x1;
2252 ++x, ++coeff1) {
2253 y1 = 0;
2254 if (y0 + 3 < cb->y1 &&
2255 !(coeff1->flags & jpxCoeffTouched) &&
2256 !(coeff1[tileComp->cbW].flags & jpxCoeffTouched) &&
2257 !(coeff1[2 * tileComp->cbW].flags & jpxCoeffTouched) &&
2258 !(coeff1[3 * tileComp->cbW].flags & jpxCoeffTouched) &&
2259 (x == cb->x0 || y0 == cb->y0 ||
2260 !(coeff1[-(int)tileComp->cbW - 1].flags
2261 & jpxCoeffSignificant)) &&
2262 (y0 == cb->y0 ||
2263 !(coeff1[-(int)tileComp->cbW].flags
2264 & jpxCoeffSignificant)) &&
2265 (x == cb->x1 - 1 || y0 == cb->y0 ||
2266 !(coeff1[-(int)tileComp->cbW + 1].flags
2267 & jpxCoeffSignificant)) &&
2268 (x == cb->x0 ||
2269 (!(coeff1[-1].flags & jpxCoeffSignificant) &&
2270 !(coeff1[tileComp->cbW - 1].flags
2271 & jpxCoeffSignificant) &&
2272 !(coeff1[2 * tileComp->cbW - 1].flags
2273 & jpxCoeffSignificant) &&
2274 !(coeff1[3 * tileComp->cbW - 1].flags
2275 & jpxCoeffSignificant))) &&
2276 (x == cb->x1 - 1 ||
2277 (!(coeff1[1].flags & jpxCoeffSignificant) &&
2278 !(coeff1[tileComp->cbW + 1].flags
2279 & jpxCoeffSignificant) &&
2280 !(coeff1[2 * tileComp->cbW + 1].flags
2281 & jpxCoeffSignificant) &&
2282 !(coeff1[3 * tileComp->cbW + 1].flags
2283 & jpxCoeffSignificant))) &&
2284 (x == cb->x0 || y0+4 == cb->y1 ||
2285 !(coeff1[4 * tileComp->cbW - 1].flags & jpxCoeffSignificant)) &&
2286 (y0+4 == cb->y1 ||
2287 !(coeff1[4 * tileComp->cbW].flags & jpxCoeffSignificant)) &&
2288 (x == cb->x1 - 1 || y0+4 == cb->y1 ||
2289 !(coeff1[4 * tileComp->cbW + 1].flags
2290 & jpxCoeffSignificant))) {
2291 if (cb->arithDecoder->decodeBit(jpxContextRunLength, cb->stats)) {
2292 y1 = cb->arithDecoder->decodeBit(jpxContextUniform, cb->stats);
2293 y1 = (y1 << 1) |
2294 cb->arithDecoder->decodeBit(jpxContextUniform, cb->stats);
2295 for (y2 = 0, coeff = coeff1;
2296 y2 < y1;
2297 ++y2, coeff += tileComp->cbW) {
2298 ++coeff->len;
2299 }
2300 coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef;
2301 coeff->mag = (coeff->mag << 1) | 1;
2302 ++coeff->len;
2303 cx = signContext[2][2][0];
2304 xorBit = signContext[2][2][1];
2305 if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) {
2306 coeff->flags |= jpxCoeffSign;
2307 }
2308 ++y1;
2309 } else {
2310 for (y1 = 0, coeff = coeff1;
2311 y1 < 4;
2312 ++y1, coeff += tileComp->cbW) {
2313 ++coeff->len;
2314 }
2315 y1 = 4;
2316 }
2317 }
2318 for (coeff = &coeff1[y1 << tileComp->codeBlockW];
2319 y1 < 4 && y0 + y1 < cb->y1;
2320 ++y1, coeff += tileComp->cbW) {
2321 if (!(coeff->flags & jpxCoeffTouched)) {
2322 horiz = vert = diag = 0;
2323 horizSign = vertSign = 2;
2324 if (x > cb->x0) {
2325 if (coeff[-1].flags & jpxCoeffSignificant) {
2326 ++horiz;
2327 horizSign += (coeff[-1].flags & jpxCoeffSign) ? -1 : 1;
2328 }
2329 if (y0+y1 > cb->y0) {
2330 diag += (coeff[-(int)tileComp->cbW - 1].flags
2331 >> jpxCoeffSignificantB) & 1;
2332 }
2333 if (y0+y1 < cb->y1 - 1) {
2334 diag += (coeff[tileComp->cbW - 1].flags
2335 >> jpxCoeffSignificantB) & 1;
2336 }
2337 }
2338 if (x < cb->x1 - 1) {
2339 if (coeff[1].flags & jpxCoeffSignificant) {
2340 ++horiz;
2341 horizSign += (coeff[1].flags & jpxCoeffSign) ? -1 : 1;
2342 }
2343 if (y0+y1 > cb->y0) {
2344 diag += (coeff[-(int)tileComp->cbW + 1].flags
2345 >> jpxCoeffSignificantB) & 1;
2346 }
2347 if (y0+y1 < cb->y1 - 1) {
2348 diag += (coeff[tileComp->cbW + 1].flags
2349 >> jpxCoeffSignificantB) & 1;
2350 }
2351 }
2352 if (y0+y1 > cb->y0) {
2353 if (coeff[-(int)tileComp->cbW].flags & jpxCoeffSignificant) {
2354 ++vert;
2355 vertSign += (coeff[-(int)tileComp->cbW].flags & jpxCoeffSign)
2356 ? -1 : 1;
2357 }
2358 }
2359 if (y0+y1 < cb->y1 - 1) {
2360 if (coeff[tileComp->cbW].flags & jpxCoeffSignificant) {
2361 ++vert;
2362 vertSign += (coeff[tileComp->cbW].flags & jpxCoeffSign)
2363 ? -1 : 1;
2364 }
2365 }
2366 cx = sigPropContext[horiz][vert][diag][res == 0 ? 1 : sb];
2367 if (cb->arithDecoder->decodeBit(cx, cb->stats)) {
2368 coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef;
2369 coeff->mag = (coeff->mag << 1) | 1;
2370 cx = signContext[horizSign][vertSign][0];
2371 xorBit = signContext[horizSign][vertSign][1];
2372 if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) {
2373 coeff->flags |= jpxCoeffSign;
2374 }
2375 }
2376 ++coeff->len;
2377 } else {
2378 coeff->flags &= ~jpxCoeffTouched;
2379 }
2380 }
2381 }
2382 }
2383 cb->nextPass = jpxPassSigProp;
2384 break;
2385 }
2386 }
2387
2388 cb->arithDecoder->cleanup();
2389 return gTrue;
2390}
2391
2392// Inverse quantization, and wavelet transform (IDWT). This also does
2393// the initial shift to convert to fixed point format.
2394void JPXStream::inverseTransform(JPXTileComp *tileComp) {
2395 JPXResLevel *resLevel;
2396 JPXPrecinct *precinct;
2397 JPXSubband *subband;
2398 JPXCodeBlock *cb;
2399 JPXCoeff *coeff0, *coeff;
2400 Guint qStyle, guard, eps, shift;
2401 int shift2;
2402 double mu;
2403 int val;
2404 int *dataPtr;
2405 Guint nx0, ny0, nx1, ny1;
2406 Guint r, cbX, cbY, x, y;
2407
2408 //----- (NL)LL subband (resolution level 0)
2409
2410 resLevel = &tileComp->resLevels[0];
2411 precinct = &resLevel->precincts[0];
2412 subband = &precinct->subbands[0];
2413
2414 // i-quant parameters
2415 qStyle = tileComp->quantStyle & 0x1f;
2416 guard = (tileComp->quantStyle >> 5) & 7;
2417 if (qStyle == 0) {
2418 eps = (tileComp->quantSteps[0] >> 3) & 0x1f;
2419 shift = guard + eps - 1;
2420 mu = 0; // make gcc happy
2421 } else {
2422 shift = guard - 1 + tileComp->prec;
2423 mu = (double)(0x800 + (tileComp->quantSteps[0] & 0x7ff)) / 2048.0;
2424 }
2425 if (tileComp->transform == 0) {
2426 shift += fracBits;
2427 }
2428
2429 // copy (NL)LL into the upper-left corner of the data array, doing
2430 // the fixed point adjustment and dequantization along the way
2431 cb = subband->cbs;
2432 for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
2433 for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
2434 for (y = cb->y0, coeff0 = cb->coeffs;
2435 y < cb->y1;
2436 ++y, coeff0 += tileComp->cbW) {
2437 dataPtr = &tileComp->data[(y - subband->y0)
2438 * (tileComp->x1 - tileComp->x0)
2439 + (cb->x0 - subband->x0)];
2440 for (x = cb->x0, coeff = coeff0; x < cb->x1; ++x, ++coeff) {
2441 val = (int)coeff->mag;
2442 if (val != 0) {
2443 shift2 = shift - (cb->nZeroBitPlanes + coeff->len);
2444 if (shift2 > 0) {
2445 val = (val << shift2) + (1 << (shift2 - 1));
2446 } else {
2447 val >>= -shift2;
2448 }
2449 if (qStyle == 0) {
2450 if (tileComp->transform == 0) {
2451 val &= -1 << fracBits;
2452 }
2453 } else {
2454 val = (int)((double)val * mu);
2455 }
2456 if (coeff->flags & jpxCoeffSign) {
2457 val = -val;
2458 }
2459 }
2460 *dataPtr++ = val;
2461 }
2462 }
2463 ++cb;
2464 }
2465 }
2466
2467 //----- IDWT for each level
2468
2469 for (r = 1; r <= tileComp->nDecompLevels; ++r) {
2470 resLevel = &tileComp->resLevels[r];
2471
2472 // (n)LL is already in the upper-left corner of the
2473 // tile-component data array -- interleave with (n)HL/LH/HH
2474 // and inverse transform to get (n-1)LL, which will be stored
2475 // in the upper-left corner of the tile-component data array
2476 if (r == tileComp->nDecompLevels) {
2477 nx0 = tileComp->x0;
2478 ny0 = tileComp->y0;
2479 nx1 = tileComp->x1;
2480 ny1 = tileComp->y1;
2481 } else {
2482 nx0 = tileComp->resLevels[r+1].x0;
2483 ny0 = tileComp->resLevels[r+1].y0;
2484 nx1 = tileComp->resLevels[r+1].x1;
2485 ny1 = tileComp->resLevels[r+1].y1;
2486 }
2487 inverseTransformLevel(tileComp, r, resLevel, nx0, ny0, nx1, ny1);
2488 }
2489}
2490
2491// Do one level of the inverse transform:
2492// - take (n)LL from the tile-component data array
2493// - take (n)HL/LH/HH from <resLevel>
2494// - leave the resulting (n-1)LL in the tile-component data array
2495void JPXStream::inverseTransformLevel(JPXTileComp *tileComp,
2496 Guint r, JPXResLevel *resLevel,
2497 Guint nx0, Guint ny0,
2498 Guint nx1, Guint ny1) {
2499 JPXPrecinct *precinct;
2500 JPXSubband *subband;
2501 JPXCodeBlock *cb;
2502 JPXCoeff *coeff0, *coeff;
2503 Guint qStyle, guard, eps, shift, t;
2504 int shift2;
2505 double mu;
2506 int val;
2507 int *dataPtr;
2508 Guint xo, yo;
2509 Guint x, y, sb, cbX, cbY;
2510 int xx, yy;
2511
2512 //----- interleave
2513
2514 // spread out LL
2515 for (yy = resLevel->y1 - 1; yy >= (int)resLevel->y0; --yy) {
2516 for (xx = resLevel->x1 - 1; xx >= (int)resLevel->x0; --xx) {
2517 tileComp->data[(2 * yy - ny0) * (tileComp->x1 - tileComp->x0)
2518 + (2 * xx - nx0)] =
2519 tileComp->data[(yy - resLevel->y0) * (tileComp->x1 - tileComp->x0)
2520 + (xx - resLevel->x0)];
2521 }
2522 }
2523
2524 // i-quant parameters
2525 qStyle = tileComp->quantStyle & 0x1f;
2526 guard = (tileComp->quantStyle >> 5) & 7;
2527
2528 // interleave HL/LH/HH
2529 precinct = &resLevel->precincts[0];
2530 for (sb = 0; sb < 3; ++sb) {
2531
2532 // i-quant parameters
2533 if (qStyle == 0) {
2534 eps = (tileComp->quantSteps[3*r - 2 + sb] >> 3) & 0x1f;
2535 shift = guard + eps - 1;
2536 mu = 0; // make gcc happy
2537 } else {
2538 shift = guard + tileComp->prec;
2539 if (sb == 2) {
2540 ++shift;
2541 }
2542 t = tileComp->quantSteps[qStyle == 1 ? 0 : (3*r - 2 + sb)];
2543 mu = (double)(0x800 + (t & 0x7ff)) / 2048.0;
2544 }
2545 if (tileComp->transform == 0) {
2546 shift += fracBits;
2547 }
2548
2549 // copy the subband coefficients into the data array, doing the
2550 // fixed point adjustment and dequantization along the way
2551 xo = (sb & 1) ? 0 : 1;
2552 yo = (sb > 0) ? 1 : 0;
2553 subband = &precinct->subbands[sb];
2554 cb = subband->cbs;
2555 for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
2556 for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
2557 for (y = cb->y0, coeff0 = cb->coeffs;
2558 y < cb->y1;
2559 ++y, coeff0 += tileComp->cbW) {
2560 dataPtr = &tileComp->data[(2 * y + yo - ny0)
2561 * (tileComp->x1 - tileComp->x0)
2562 + (2 * cb->x0 + xo - nx0)];
2563 for (x = cb->x0, coeff = coeff0; x < cb->x1; ++x, ++coeff) {
2564 val = (int)coeff->mag;
2565 if (val != 0) {
2566 shift2 = shift - (cb->nZeroBitPlanes + coeff->len);
2567 if (shift2 > 0) {
2568 val = (val << shift2) + (1 << (shift2 - 1));
2569 } else {
2570 val >>= -shift2;
2571 }
2572 if (qStyle == 0) {
2573 if (tileComp->transform == 0) {
2574 val &= -1 << fracBits;
2575 }
2576 } else {
2577 val = (int)((double)val * mu);
2578 }
2579 if (coeff->flags & jpxCoeffSign) {
2580 val = -val;
2581 }
2582 }
2583 *dataPtr = val;
2584 dataPtr += 2;
2585 }
2586 }
2587 ++cb;
2588 }
2589 }
2590 }
2591
2592 //----- horizontal (row) transforms
2593 dataPtr = tileComp->data;
2594 for (y = 0; y < ny1 - ny0; ++y) {
2595 inverseTransform1D(tileComp, dataPtr, 1, nx0, nx1);
2596 dataPtr += tileComp->x1 - tileComp->x0;
2597 }
2598
2599 //----- vertical (column) transforms
2600 dataPtr = tileComp->data;
2601 for (x = 0; x < nx1 - nx0; ++x) {
2602 inverseTransform1D(tileComp, dataPtr,
2603 tileComp->x1 - tileComp->x0, ny0, ny1);
2604 ++dataPtr;
2605 }
2606}
2607
2608void JPXStream::inverseTransform1D(JPXTileComp *tileComp,
2609 int *data, Guint stride,
2610 Guint i0, Guint i1) {
2611 int *buf;
2612 Guint offset, end, i;
2613
2614 //----- special case for length = 1
2615 if (i1 - i0 == 1) {
2616 if (i0 & 1) {
2617 *data >>= 1;
2618 }
2619
2620 } else {
2621
2622 // choose an offset: this makes even buf[] indexes correspond to
2623 // odd values of i, and vice versa
2624 offset = 3 + (i0 & 1);
2625 end = offset + i1 - i0;
2626
2627 //----- gather
2628 buf = tileComp->buf;
2629 for (i = 0; i < i1 - i0; ++i) {
2630 buf[offset + i] = data[i * stride];
2631 }
2632
2633 //----- extend right
2634 buf[end] = buf[end - 2];
2635 if (i1 - i0 == 2) {
2636 buf[end+1] = buf[offset + 1];
2637 buf[end+2] = buf[offset];
2638 buf[end+3] = buf[offset + 1];
2639 } else {
2640 buf[end+1] = buf[end - 3];
2641 if (i1 - i0 == 3) {
2642 buf[end+2] = buf[offset + 1];
2643 buf[end+3] = buf[offset + 2];
2644 } else {
2645 buf[end+2] = buf[end - 4];
2646 if (i1 - i0 == 4) {
2647 buf[end+3] = buf[offset + 1];
2648 } else {
2649 buf[end+3] = buf[end - 5];
2650 }
2651 }
2652 }
2653
2654 //----- extend left
2655 buf[offset - 1] = buf[offset + 1];
2656 buf[offset - 2] = buf[offset + 2];
2657 buf[offset - 3] = buf[offset + 3];
2658 if (offset == 4) {
2659 buf[0] = buf[offset + 4];
2660 }
2661
2662 //----- 9-7 irreversible filter
2663
2664 if (tileComp->transform == 0) {
2665 // step 1 (even)
2666 for (i = 1; i <= end + 2; i += 2) {
2667 buf[i] = (int)(idwtKappa * buf[i]);
2668 }
2669 // step 2 (odd)
2670 for (i = 0; i <= end + 3; i += 2) {
2671 buf[i] = (int)(idwtIKappa * buf[i]);
2672 }
2673 // step 3 (even)
2674 for (i = 1; i <= end + 2; i += 2) {
2675 buf[i] = (int)(buf[i] - idwtDelta * (buf[i-1] + buf[i+1]));
2676 }
2677 // step 4 (odd)
2678 for (i = 2; i <= end + 1; i += 2) {
2679 buf[i] = (int)(buf[i] - idwtGamma * (buf[i-1] + buf[i+1]));
2680 }
2681 // step 5 (even)
2682 for (i = 3; i <= end; i += 2) {
2683 buf[i] = (int)(buf[i] - idwtBeta * (buf[i-1] + buf[i+1]));
2684 }
2685 // step 6 (odd)
2686 for (i = 4; i <= end - 1; i += 2) {
2687 buf[i] = (int)(buf[i] - idwtAlpha * (buf[i-1] + buf[i+1]));
2688 }
2689
2690 //----- 5-3 reversible filter
2691
2692 } else {
2693 // step 1 (even)
2694 for (i = 3; i <= end; i += 2) {
2695 buf[i] -= (buf[i-1] + buf[i+1] + 2) >> 2;
2696 }
2697 // step 2 (odd)
2698 for (i = 4; i < end; i += 2) {
2699 buf[i] += (buf[i-1] + buf[i+1]) >> 1;
2700 }
2701 }
2702
2703 //----- scatter
2704 for (i = 0; i < i1 - i0; ++i) {
2705 data[i * stride] = buf[offset + i];
2706 }
2707 }
2708}
2709
2710// Inverse multi-component transform and DC level shift. This also
2711// converts fixed point samples back to integers.
2712GBool JPXStream::inverseMultiCompAndDC(JPXTile *tile) {
2713 JPXTileComp *tileComp;
2714 int coeff, d0, d1, d2, t, minVal, maxVal, zeroVal;
2715 int *dataPtr;
2716 Guint j, comp, x, y;
2717
2718 //----- inverse multi-component transform
2719
2720 if (tile->multiComp == 1) {
2721 if (img.nComps < 3 ||
2722 tile->tileComps[0].hSep != tile->tileComps[1].hSep ||
2723 tile->tileComps[0].vSep != tile->tileComps[1].vSep ||
2724 tile->tileComps[1].hSep != tile->tileComps[2].hSep ||
2725 tile->tileComps[1].vSep != tile->tileComps[2].vSep) {
2726 return gFalse;
2727 }
2728
2729 // inverse irreversible multiple component transform
2730 if (tile->tileComps[0].transform == 0) {
2731 j = 0;
2732 for (y = 0; y < tile->tileComps[0].y1 - tile->tileComps[0].y0; ++y) {
2733 for (x = 0; x < tile->tileComps[0].x1 - tile->tileComps[0].x0; ++x) {
2734 d0 = tile->tileComps[0].data[j];
2735 d1 = tile->tileComps[1].data[j];
2736 d2 = tile->tileComps[2].data[j];
2737 tile->tileComps[0].data[j] = (int)(d0 + 1.402 * d2 + 0.5);
2738 tile->tileComps[1].data[j] =
2739 (int)(d0 - 0.34413 * d1 - 0.71414 * d2 + 0.5);
2740 tile->tileComps[2].data[j] = (int)(d0 + 1.772 * d1 + 0.5);
2741 ++j;
2742 }
2743 }
2744
2745 // inverse reversible multiple component transform
2746 } else {
2747 j = 0;
2748 for (y = 0; y < tile->tileComps[0].y1 - tile->tileComps[0].y0; ++y) {
2749 for (x = 0; x < tile->tileComps[0].x1 - tile->tileComps[0].x0; ++x) {
2750 d0 = tile->tileComps[0].data[j];
2751 d1 = tile->tileComps[1].data[j];
2752 d2 = tile->tileComps[2].data[j];
2753 tile->tileComps[1].data[j] = t = d0 - ((d2 + d1) >> 2);
2754 tile->tileComps[0].data[j] = d2 + t;
2755 tile->tileComps[2].data[j] = d1 + t;
2756 ++j;
2757 }
2758 }
2759 }
2760 }
2761
2762 //----- DC level shift
2763 for (comp = 0; comp < img.nComps; ++comp) {
2764 tileComp = &tile->tileComps[comp];
2765
2766 // signed: clip
2767 if (tileComp->sgned) {
2768 minVal = -(1 << (tileComp->prec - 1));
2769 maxVal = (1 << (tileComp->prec - 1)) - 1;
2770 dataPtr = tileComp->data;
2771 for (y = 0; y < tileComp->y1 - tileComp->y0; ++y) {
2772 for (x = 0; x < tileComp->x1 - tileComp->x0; ++x) {
2773 coeff = *dataPtr;
2774 if (tileComp->transform == 0) {
2775 coeff >>= fracBits;
2776 }
2777 if (coeff < minVal) {
2778 coeff = minVal;
2779 } else if (coeff > maxVal) {
2780 coeff = maxVal;
2781 }
2782 *dataPtr++ = coeff;
2783 }
2784 }
2785
2786 // unsigned: inverse DC level shift and clip
2787 } else {
2788 maxVal = (1 << tileComp->prec) - 1;
2789 zeroVal = 1 << (tileComp->prec - 1);
2790 dataPtr = tileComp->data;
2791 for (y = 0; y < tileComp->y1 - tileComp->y0; ++y) {
2792 for (x = 0; x < tileComp->x1 - tileComp->x0; ++x) {
2793 coeff = *dataPtr;
2794 if (tileComp->transform == 0) {
2795 coeff >>= fracBits;
2796 }
2797 coeff += zeroVal;
2798 if (coeff < 0) {
2799 coeff = 0;
2800 } else if (coeff > maxVal) {
2801 coeff = maxVal;
2802 }
2803 *dataPtr++ = coeff;
2804 }
2805 }
2806 }
2807 }
2808
2809 return gTrue;
2810}
2811
2812GBool JPXStream::readBoxHdr(Guint *boxType, Guint *boxLen, Guint *dataLen) {
2813 Guint len, lenH;
2814
2815 if (!readULong(&len) ||
2816 !readULong(boxType)) {
2817 return gFalse;
2818 }
2819 if (len == 1) {
2820 if (!readULong(&lenH) || !readULong(&len)) {
2821 return gFalse;
2822 }
2823 if (lenH) {
2824 error(getPos(), "JPX stream contains a box larger than 2^32 bytes");
2825 return gFalse;
2826 }
2827 *boxLen = len;
2828 *dataLen = len - 16;
2829 } else if (len == 0) {
2830 *boxLen = 0;
2831 *dataLen = 0;
2832 } else {
2833 *boxLen = len;
2834 *dataLen = len - 8;
2835 }
2836 return gTrue;
2837}
2838
2839int JPXStream::readMarkerHdr(int *segType, Guint *segLen) {
2840 int c;
2841
2842 do {
2843 do {
2844 if ((c = str->getChar()) == EOF) {
2845 return gFalse;
2846 }
2847 } while (c != 0xff);
2848 do {
2849 if ((c = str->getChar()) == EOF) {
2850 return gFalse;
2851 }
2852 } while (c == 0xff);
2853 } while (c == 0x00);
2854 *segType = c;
2855 if ((c >= 0x30 && c <= 0x3f) ||
2856 c == 0x4f || c == 0x92 || c == 0x93 || c == 0xd9) {
2857 *segLen = 0;
2858 return gTrue;
2859 }
2860 return readUWord(segLen);
2861}
2862
2863GBool JPXStream::readUByte(Guint *x) {
2864 int c0;
2865
2866 if ((c0 = str->getChar()) == EOF) {
2867 return gFalse;
2868 }
2869 *x = (Guint)c0;
2870 return gTrue;
2871}
2872
2873GBool JPXStream::readByte(int *x) {
2874 int c0;
2875
2876 if ((c0 = str->getChar()) == EOF) {
2877 return gFalse;
2878 }
2879 *x = c0;
2880 if (c0 & 0x80) {
2881 *x |= -1 - 0xff;
2882 }
2883 return gTrue;
2884}
2885
2886GBool JPXStream::readUWord(Guint *x) {
2887 int c0, c1;
2888
2889 if ((c0 = str->getChar()) == EOF ||
2890 (c1 = str->getChar()) == EOF) {
2891 return gFalse;
2892 }
2893 *x = (Guint)((c0 << 8) | c1);
2894 return gTrue;
2895}
2896
2897GBool JPXStream::readULong(Guint *x) {
2898 int c0, c1, c2, c3;
2899
2900 if ((c0 = str->getChar()) == EOF ||
2901 (c1 = str->getChar()) == EOF ||
2902 (c2 = str->getChar()) == EOF ||
2903 (c3 = str->getChar()) == EOF) {
2904 return gFalse;
2905 }
2906 *x = (Guint)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
2907 return gTrue;
2908}
2909
2910GBool JPXStream::readNBytes(int nBytes, GBool signd, int *x) {
2911 int y, c, i;
2912
2913 y = 0;
2914 for (i = 0; i < nBytes; ++i) {
2915 if ((c = str->getChar()) == EOF) {
2916 return gFalse;
2917 }
2918 y = (y << 8) + c;
2919 }
2920 if (signd) {
2921 if (y & (1 << (8 * nBytes - 1))) {
2922 y |= -1 << (8 * nBytes);
2923 }
2924 }
2925 *x = y;
2926 return gTrue;
2927}
2928
2929GBool JPXStream::readBits(int nBits, Guint *x) {
2930 int c;
2931
2932 while (bitBufLen < nBits) {
2933 if ((c = str->getChar()) == EOF) {
2934 return gFalse;
2935 }
2936 ++byteCount;
2937 if (bitBufSkip) {
2938 bitBuf = (bitBuf << 7) | (c & 0x7f);
2939 bitBufLen += 7;
2940 } else {
2941 bitBuf = (bitBuf << 8) | (c & 0xff);
2942 bitBufLen += 8;
2943 }
2944 bitBufSkip = c == 0xff;
2945 }
2946 *x = (bitBuf >> (bitBufLen - nBits)) & ((1 << nBits) - 1);
2947 bitBufLen -= nBits;
2948 return gTrue;
2949}
2950
2951void JPXStream::clearBitBuf() {
2952 bitBufLen = 0;
2953 bitBufSkip = gFalse;
2954 byteCount = 0;
2955}