1 //========================================================================
5 // Copyright 2002-2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
17 #include "JArithmeticDecoder.h"
18 #include "JPXStream.h"
23 // - progression order changes
24 // - packed packet headers
25 // - support for palettes, channel maps, etc.
26 // - make sure all needed JP2/JPX subboxes are parsed (readBoxes)
27 // - can we assume that QCC segments must come after the QCD segment?
28 // - skip EPH markers (readTilePartData)
29 // - handle tilePartToEOC in readTilePartData
30 // - deal with multiple codeword segments (readTilePartData,
32 // - progression orders 2, 3, and 4
33 // - in coefficient decoding (readCodeBlockData):
34 // - termination pattern: terminate after every coding pass
35 // - error resilience segmentation symbol
36 // - selective arithmetic coding bypass
37 // - vertically causal context formation
38 // - coeffs longer than 31 bits (should just ignore the extra bits?)
39 // - handle boxes larger than 2^32 bytes
40 // - the fixed-point arithmetic won't handle 16-bit pixels
42 //------------------------------------------------------------------------
44 // number of contexts for the arithmetic decoder
45 #define jpxNContexts 19
47 #define jpxContextSigProp 0 // 0 - 8: significance prop and cleanup
48 #define jpxContextSign 9 // 9 - 13: sign
49 #define jpxContextMagRef 14 // 14 -16: magnitude refinement
50 #define jpxContextRunLength 17 // cleanup: run length
51 #define jpxContextUniform 18 // cleanup: first signif coeff
53 //------------------------------------------------------------------------
55 #define jpxPassSigProp 0
56 #define jpxPassMagRef 1
57 #define jpxPassCleanup 2
59 //------------------------------------------------------------------------
61 // arithmetic decoder context for the significance propagation and
63 // [horiz][vert][diag][subband]
64 // where subband = 0 for HL
67 static Guint sigPropContext[3][3][5][3] = {
68 {{{ 0, 0, 0 }, // horiz=0, vert=0, diag=0
69 { 1, 1, 3 }, // horiz=0, vert=0, diag=1
70 { 2, 2, 6 }, // horiz=0, vert=0, diag=2
71 { 2, 2, 8 }, // horiz=0, vert=0, diag=3
72 { 2, 2, 8 }}, // horiz=0, vert=0, diag=4
73 {{ 5, 3, 1 }, // horiz=0, vert=1, diag=0
74 { 6, 3, 4 }, // horiz=0, vert=1, diag=1
75 { 6, 3, 7 }, // horiz=0, vert=1, diag=2
76 { 6, 3, 8 }, // horiz=0, vert=1, diag=3
77 { 6, 3, 8 }}, // horiz=0, vert=1, diag=4
78 {{ 8, 4, 2 }, // horiz=0, vert=2, diag=0
79 { 8, 4, 5 }, // horiz=0, vert=2, diag=1
80 { 8, 4, 7 }, // horiz=0, vert=2, diag=2
81 { 8, 4, 8 }, // horiz=0, vert=2, diag=3
82 { 8, 4, 8 }}}, // horiz=0, vert=2, diag=4
83 {{{ 3, 5, 1 }, // horiz=1, vert=0, diag=0
84 { 3, 6, 4 }, // horiz=1, vert=0, diag=1
85 { 3, 6, 7 }, // horiz=1, vert=0, diag=2
86 { 3, 6, 8 }, // horiz=1, vert=0, diag=3
87 { 3, 6, 8 }}, // horiz=1, vert=0, diag=4
88 {{ 7, 7, 2 }, // horiz=1, vert=1, diag=0
89 { 7, 7, 5 }, // horiz=1, vert=1, diag=1
90 { 7, 7, 7 }, // horiz=1, vert=1, diag=2
91 { 7, 7, 8 }, // horiz=1, vert=1, diag=3
92 { 7, 7, 8 }}, // horiz=1, vert=1, diag=4
93 {{ 8, 7, 2 }, // horiz=1, vert=2, diag=0
94 { 8, 7, 5 }, // horiz=1, vert=2, diag=1
95 { 8, 7, 7 }, // horiz=1, vert=2, diag=2
96 { 8, 7, 8 }, // horiz=1, vert=2, diag=3
97 { 8, 7, 8 }}}, // horiz=1, vert=2, diag=4
98 {{{ 4, 8, 2 }, // horiz=2, vert=0, diag=0
99 { 4, 8, 5 }, // horiz=2, vert=0, diag=1
100 { 4, 8, 7 }, // horiz=2, vert=0, diag=2
101 { 4, 8, 8 }, // horiz=2, vert=0, diag=3
102 { 4, 8, 8 }}, // horiz=2, vert=0, diag=4
103 {{ 7, 8, 2 }, // horiz=2, vert=1, diag=0
104 { 7, 8, 5 }, // horiz=2, vert=1, diag=1
105 { 7, 8, 7 }, // horiz=2, vert=1, diag=2
106 { 7, 8, 8 }, // horiz=2, vert=1, diag=3
107 { 7, 8, 8 }}, // horiz=2, vert=1, diag=4
108 {{ 8, 8, 2 }, // horiz=2, vert=2, diag=0
109 { 8, 8, 5 }, // horiz=2, vert=2, diag=1
110 { 8, 8, 7 }, // horiz=2, vert=2, diag=2
111 { 8, 8, 8 }, // horiz=2, vert=2, diag=3
112 { 8, 8, 8 }}} // horiz=2, vert=2, diag=4
115 // arithmetic decoder context and xor bit for the sign bit in the
116 // significance propagation pass:
118 // where horiz/vert are offset by 2 (i.e., range is -2 .. 2)
119 // and k = 0 for the context
120 // = 1 for the xor bit
121 static Guint signContext[5][5][2] = {
122 {{ 13, 1 }, // horiz=-2, vert=-2
123 { 13, 1 }, // horiz=-2, vert=-1
124 { 12, 1 }, // horiz=-2, vert= 0
125 { 11, 1 }, // horiz=-2, vert=+1
126 { 11, 1 }}, // horiz=-2, vert=+2
127 {{ 13, 1 }, // horiz=-1, vert=-2
128 { 13, 1 }, // horiz=-1, vert=-1
129 { 12, 1 }, // horiz=-1, vert= 0
130 { 11, 1 }, // horiz=-1, vert=+1
131 { 11, 1 }}, // horiz=-1, vert=+2
132 {{ 10, 1 }, // horiz= 0, vert=-2
133 { 10, 1 }, // horiz= 0, vert=-1
134 { 9, 0 }, // horiz= 0, vert= 0
135 { 10, 0 }, // horiz= 0, vert=+1
136 { 10, 0 }}, // horiz= 0, vert=+2
137 {{ 11, 0 }, // horiz=+1, vert=-2
138 { 11, 0 }, // horiz=+1, vert=-1
139 { 12, 0 }, // horiz=+1, vert= 0
140 { 13, 0 }, // horiz=+1, vert=+1
141 { 13, 0 }}, // horiz=+1, vert=+2
142 {{ 11, 0 }, // horiz=+2, vert=-2
143 { 11, 0 }, // horiz=+2, vert=-1
144 { 12, 0 }, // horiz=+2, vert= 0
145 { 13, 0 }, // horiz=+2, vert=+1
146 { 13, 0 }}, // horiz=+2, vert=+2
149 //------------------------------------------------------------------------
151 // constants used in the IDWT
152 #define idwtAlpha -1.586134342059924
153 #define idwtBeta -0.052980118572961
154 #define idwtGamma 0.882911075530934
155 #define idwtDelta 0.443506852043971
156 #define idwtKappa 1.230174104914001
157 #define idwtIKappa (1.0 / idwtKappa)
159 // number of bits to the right of the decimal point for the fixed
160 // point arithmetic used in the IDWT
163 //------------------------------------------------------------------------
166 #define jpxFloorDiv(x, y) ((x) / (y))
169 #define jpxFloorDivPow2(x, y) ((x) >> (y))
172 #define jpxCeilDiv(x, y) (((x) + (y) - 1) / (y))
175 #define jpxCeilDivPow2(x, y) (((x) + (1 << (y)) - 1) >> (y))
177 //------------------------------------------------------------------------
179 JPXStream::JPXStream(Stream *strA):
186 havePalette = gFalse;
187 haveCompMap = gFalse;
188 haveChannelDefn = gFalse;
197 JPXStream::~JPXStream() {
199 JPXTileComp *tileComp;
200 JPXResLevel *resLevel;
201 JPXPrecinct *precinct;
204 Guint comp, i, k, r, pre, sb;
214 gfree(compMap.pComp);
216 if (haveChannelDefn) {
217 gfree(channelDefn.idx);
218 gfree(channelDefn.type);
219 gfree(channelDefn.assoc);
223 for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
224 tile = &img.tiles[i];
225 if (tile->tileComps) {
226 for (comp = 0; comp < img.nComps; ++comp) {
227 tileComp = &tile->tileComps[comp];
228 gfree(tileComp->quantSteps);
229 gfree(tileComp->data);
230 gfree(tileComp->buf);
231 if (tileComp->resLevels) {
232 for (r = 0; r <= tileComp->nDecompLevels; ++r) {
233 resLevel = &tileComp->resLevels[r];
234 if (resLevel->precincts) {
235 for (pre = 0; pre < 1; ++pre) {
236 precinct = &resLevel->precincts[pre];
237 if (precinct->subbands) {
238 for (sb = 0; sb < (r == 0 ? 1 : 3); ++sb) {
239 subband = &precinct->subbands[sb];
240 gfree(subband->inclusion);
241 gfree(subband->zeroBitPlane);
243 for (k = 0; k < subband->nXCBs * subband->nYCBs; ++k) {
244 cb = &subband->cbs[k];
253 gfree(precinct->subbands);
256 gfree(img.tiles[i].tileComps[comp].resLevels[r].precincts);
259 gfree(img.tiles[i].tileComps[comp].resLevels);
262 gfree(img.tiles[i].tileComps);
270 void JPXStream::reset() {
275 // readBoxes reported an error, so we go immediately to EOF
283 int JPXStream::getChar() {
286 if (readBufLen < 8) {
289 if (readBufLen == 8) {
292 } else if (readBufLen > 8) {
293 c = (readBuf >> (readBufLen - 8)) & 0xff;
295 } else if (readBufLen == 0) {
298 c = (readBuf << (8 - readBufLen)) & 0xff;
304 int JPXStream::lookChar() {
307 if (readBufLen < 8) {
310 if (readBufLen == 8) {
312 } else if (readBufLen > 8) {
313 c = (readBuf >> (readBufLen - 8)) & 0xff;
314 } else if (readBufLen == 0) {
317 c = (readBuf << (8 - readBufLen)) & 0xff;
322 void JPXStream::fillReadBuf() {
323 JPXTileComp *tileComp;
324 Guint tileIdx, tx, ty;
328 if (curY >= img.ySize) {
331 tileIdx = ((curY - img.yTileOffset) / img.yTileSize) * img.nXTiles
332 + (curX - img.xTileOffset) / img.xTileSize;
333 #if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid
334 tileComp = &img.tiles[tileIdx].tileComps[curComp];
336 tileComp = &img.tiles[tileIdx].tileComps[havePalette ? 0 : curComp];
338 tx = jpxCeilDiv((curX - img.xTileOffset) % img.xTileSize, tileComp->hSep);
339 ty = jpxCeilDiv((curY - img.yTileOffset) % img.yTileSize, tileComp->vSep);
340 pix = (int)tileComp->data[ty * (tileComp->x1 - tileComp->x0) + tx];
341 pixBits = tileComp->prec;
342 #if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid
343 if (++curComp == img.nComps) {
346 if (pix >= 0 && pix < palette.nEntries) {
347 pix = palette.c[pix * palette.nComps + curComp];
350 pixBits = palette.bpc[curComp];
352 if (++curComp == (Guint)(havePalette ? palette.nComps : img.nComps)) {
355 if (++curX == img.xSize) {
361 readBuf = (readBuf << 8) | (pix & 0xff);
363 readBuf = (readBuf << pixBits) | (pix & ((1 << pixBits) - 1));
365 readBufLen += pixBits;
366 } while (readBufLen < 8);
369 GString *JPXStream::getPSFilter(int psLevel, char *indent) {
373 GBool JPXStream::isBinary(GBool last) {
374 return str->isBinary(gTrue);
377 GBool JPXStream::readBoxes() {
378 Guint boxType, boxLen, dataLen;
379 Guint bpc1, compression, unknownColorspace, ipr;
384 // check for a naked JPEG 2000 codestream (without the JP2/JPX
385 // wrapper) -- this appears to be a violation of the PDF spec, but
387 if (str->lookChar() == 0xff) {
388 error(getPos(), "Naked JPEG 2000 codestream, missing JP2/JPX wrapper");
391 bpc = (Guint *)gmalloc(nComps * sizeof(Guint));
392 for (i = 0; i < nComps; ++i) {
393 bpc[i] = img.tiles[0].tileComps[i].prec;
395 width = img.xSize - img.xOffset;
396 height = img.ySize - img.yOffset;
400 while (readBoxHdr(&boxType, &boxLen, &dataLen)) {
402 case 0x6a703268: // JP2 header
403 // this is a grouping box ('superbox') which has no real
404 // contents and doesn't appear to be used consistently, i.e.,
405 // some things which should be subboxes of the JP2 header box
406 // show up outside of it - so we simply ignore the JP2 header
409 case 0x69686472: // image header
410 if (!readULong(&height) ||
411 !readULong(&width) ||
412 !readUWord(&nComps) ||
414 !readUByte(&compression) ||
415 !readUByte(&unknownColorspace) ||
417 error(getPos(), "Unexpected EOF in JPX stream");
420 if (compression != 7) {
421 error(getPos(), "Unknown compression type in JPX stream");
424 bpc = (Guint *)gmalloc(nComps * sizeof(Guint));
425 for (i = 0; i < nComps; ++i) {
430 case 0x62706363: // bits per component
432 error(getPos(), "Found bits per component box before image header box in JPX stream");
435 if (dataLen != nComps) {
436 error(getPos(), "Invalid bits per component box in JPX stream");
439 for (i = 0; i < nComps; ++i) {
440 if (!readUByte(&bpc[i])) {
441 error(getPos(), "Unexpected EOF in JPX stream");
446 case 0x636F6C72: // color specification
447 if (!readColorSpecBox(dataLen)) {
451 case 0x70636c72: // palette
452 if (!readUWord(&palette.nEntries) ||
453 !readUByte(&palette.nComps)) {
454 error(getPos(), "Unexpected EOF in JPX stream");
457 palette.bpc = (Guint *)gmalloc(palette.nComps * sizeof(Guint));
459 (int *)gmalloc(palette.nEntries * palette.nComps * sizeof(int));
460 for (i = 0; i < palette.nComps; ++i) {
461 if (!readUByte(&palette.bpc[i])) {
462 error(getPos(), "Unexpected EOF in JPX stream");
467 for (i = 0; i < palette.nEntries; ++i) {
468 for (j = 0; j < palette.nComps; ++j) {
469 if (!readNBytes(((palette.bpc[j] & 0x7f) + 7) >> 3,
470 (palette.bpc[j] & 0x80) ? gTrue : gFalse,
471 &palette.c[i * palette.nComps + j])) {
472 error(getPos(), "Unexpected EOF in JPX stream");
479 case 0x636d6170: // component mapping
480 compMap.nChannels = dataLen / 4;
481 compMap.comp = (Guint *)gmalloc(compMap.nChannels * sizeof(Guint));
482 compMap.type = (Guint *)gmalloc(compMap.nChannels * sizeof(Guint));
483 compMap.pComp = (Guint *)gmalloc(compMap.nChannels * sizeof(Guint));
484 for (i = 0; i < compMap.nChannels; ++i) {
485 if (!readUWord(&compMap.comp[i]) ||
486 !readUByte(&compMap.type[i]) ||
487 !readUByte(&compMap.pComp[i])) {
488 error(getPos(), "Unexpected EOF in JPX stream");
494 case 0x63646566: // channel definition
495 if (!readUWord(&channelDefn.nChannels)) {
496 error(getPos(), "Unexpected EOF in JPX stream");
500 (Guint *)gmalloc(channelDefn.nChannels * sizeof(Guint));
502 (Guint *)gmalloc(channelDefn.nChannels * sizeof(Guint));
504 (Guint *)gmalloc(channelDefn.nChannels * sizeof(Guint));
505 for (i = 0; i < channelDefn.nChannels; ++i) {
506 if (!readUWord(&channelDefn.idx[i]) ||
507 !readUWord(&channelDefn.type[i]) ||
508 !readUWord(&channelDefn.assoc[i])) {
509 error(getPos(), "Unexpected EOF in JPX stream");
513 haveChannelDefn = gTrue;
515 case 0x6A703263: // contiguous codestream
517 error(getPos(), "JPX stream is missing the image header box");
521 error(getPos(), "JPX stream has no supported color spec");
524 if (!readCodestream(dataLen)) {
529 for (i = 0; i < dataLen; ++i) {
530 if (str->getChar() == EOF) {
531 error(getPos(), "Unexpected EOF in JPX stream");
541 GBool JPXStream::readColorSpecBox(Guint dataLen) {
543 Guint csApprox, csEnum;
548 if (!readUByte(&newCS.meth) ||
549 !readByte(&newCS.prec) ||
550 !readUByte(&csApprox)) {
553 switch (newCS.meth) {
554 case 1: // enumerated colorspace
555 if (!readULong(&csEnum)) {
558 newCS.enumerated.type = (JPXColorSpaceType)csEnum;
559 switch (newCS.enumerated.type) {
585 if (dataLen == 3 + 7*4) {
586 if (!readULong(&newCS.enumerated.cieLab.rl) ||
587 !readULong(&newCS.enumerated.cieLab.ol) ||
588 !readULong(&newCS.enumerated.cieLab.ra) ||
589 !readULong(&newCS.enumerated.cieLab.oa) ||
590 !readULong(&newCS.enumerated.cieLab.rb) ||
591 !readULong(&newCS.enumerated.cieLab.ob) ||
592 !readULong(&newCS.enumerated.cieLab.il)) {
595 } else if (dataLen == 3) {
596 //~ this assumes the 8-bit case
597 newCS.enumerated.cieLab.rl = 100;
598 newCS.enumerated.cieLab.ol = 0;
599 newCS.enumerated.cieLab.ra = 255;
600 newCS.enumerated.cieLab.oa = 128;
601 newCS.enumerated.cieLab.rb = 255;
602 newCS.enumerated.cieLab.ob = 96;
603 newCS.enumerated.cieLab.il = 0x00443530;
619 // not allowed in PDF
640 case 2: // restricted ICC profile
641 case 3: // any ICC profile (JPX)
642 case 4: // vendor color (JPX)
643 for (i = 0; i < dataLen - 3; ++i) {
644 if (str->getChar() == EOF) {
651 if (ok && (!haveCS || newCS.prec > cs.prec)) {
659 error(getPos(), "Error in JPX color spec");
663 GBool JPXStream::readCodestream(Guint len) {
665 JPXTileComp *tileComp;
667 GBool haveSIZ, haveCOD, haveQCD, haveSOT;
668 Guint precinctSize, style;
669 Guint segLen, capabilities, comp, i, j, r;
672 haveSIZ = haveCOD = haveQCD = haveSOT = gFalse;
674 if (!readMarkerHdr(&segType, &segLen)) {
675 error(getPos(), "Error in JPX codestream");
679 case 0x4f: // SOC - start of codestream
682 case 0x51: // SIZ - image and tile size
683 if (!readUWord(&capabilities) ||
684 !readULong(&img.xSize) ||
685 !readULong(&img.ySize) ||
686 !readULong(&img.xOffset) ||
687 !readULong(&img.yOffset) ||
688 !readULong(&img.xTileSize) ||
689 !readULong(&img.yTileSize) ||
690 !readULong(&img.xTileOffset) ||
691 !readULong(&img.yTileOffset) ||
692 !readUWord(&img.nComps)) {
693 error(getPos(), "Error in JPX SIZ marker segment");
696 if (haveImgHdr && img.nComps != nComps) {
697 error(getPos(), "Different number of components in JPX SIZ marker segment");
700 img.nXTiles = (img.xSize - img.xTileOffset + img.xTileSize - 1)
702 img.nYTiles = (img.ySize - img.yTileOffset + img.yTileSize - 1)
704 img.tiles = (JPXTile *)gmalloc(img.nXTiles * img.nYTiles *
706 for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
707 img.tiles[i].tileComps = (JPXTileComp *)gmalloc(img.nComps *
708 sizeof(JPXTileComp));
709 for (comp = 0; comp < img.nComps; ++comp) {
710 img.tiles[i].tileComps[comp].quantSteps = NULL;
711 img.tiles[i].tileComps[comp].data = NULL;
712 img.tiles[i].tileComps[comp].buf = NULL;
713 img.tiles[i].tileComps[comp].resLevels = NULL;
716 for (comp = 0; comp < img.nComps; ++comp) {
717 if (!readUByte(&img.tiles[0].tileComps[comp].prec) ||
718 !readUByte(&img.tiles[0].tileComps[comp].hSep) ||
719 !readUByte(&img.tiles[0].tileComps[comp].vSep)) {
720 error(getPos(), "Error in JPX SIZ marker segment");
723 img.tiles[0].tileComps[comp].sgned =
724 (img.tiles[0].tileComps[comp].prec & 0x80) ? gTrue : gFalse;
725 img.tiles[0].tileComps[comp].prec =
726 (img.tiles[0].tileComps[comp].prec & 0x7f) + 1;
727 for (i = 1; i < img.nXTiles * img.nYTiles; ++i) {
728 img.tiles[i].tileComps[comp] = img.tiles[0].tileComps[comp];
733 case 0x52: // COD - coding style default
734 if (!readUByte(&img.tiles[0].tileComps[0].style) ||
735 !readUByte(&img.tiles[0].progOrder) ||
736 !readUWord(&img.tiles[0].nLayers) ||
737 !readUByte(&img.tiles[0].multiComp) ||
738 !readUByte(&img.tiles[0].tileComps[0].nDecompLevels) ||
739 !readUByte(&img.tiles[0].tileComps[0].codeBlockW) ||
740 !readUByte(&img.tiles[0].tileComps[0].codeBlockH) ||
741 !readUByte(&img.tiles[0].tileComps[0].codeBlockStyle) ||
742 !readUByte(&img.tiles[0].tileComps[0].transform)) {
743 error(getPos(), "Error in JPX COD marker segment");
746 img.tiles[0].tileComps[0].codeBlockW += 2;
747 img.tiles[0].tileComps[0].codeBlockH += 2;
748 for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
750 img.tiles[i].progOrder = img.tiles[0].progOrder;
751 img.tiles[i].nLayers = img.tiles[0].nLayers;
752 img.tiles[i].multiComp = img.tiles[0].multiComp;
754 for (comp = 0; comp < img.nComps; ++comp) {
755 if (!(i == 0 && comp == 0)) {
756 img.tiles[i].tileComps[comp].style =
757 img.tiles[0].tileComps[0].style;
758 img.tiles[i].tileComps[comp].nDecompLevels =
759 img.tiles[0].tileComps[0].nDecompLevels;
760 img.tiles[i].tileComps[comp].codeBlockW =
761 img.tiles[0].tileComps[0].codeBlockW;
762 img.tiles[i].tileComps[comp].codeBlockH =
763 img.tiles[0].tileComps[0].codeBlockH;
764 img.tiles[i].tileComps[comp].codeBlockStyle =
765 img.tiles[0].tileComps[0].codeBlockStyle;
766 img.tiles[i].tileComps[comp].transform =
767 img.tiles[0].tileComps[0].transform;
769 img.tiles[i].tileComps[comp].resLevels =
770 (JPXResLevel *)gmalloc(
771 (img.tiles[i].tileComps[comp].nDecompLevels + 1) *
772 sizeof(JPXResLevel));
773 for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) {
774 img.tiles[i].tileComps[comp].resLevels[r].precincts = NULL;
778 for (r = 0; r <= img.tiles[0].tileComps[0].nDecompLevels; ++r) {
779 if (img.tiles[0].tileComps[0].style & 0x01) {
780 if (!readUByte(&precinctSize)) {
781 error(getPos(), "Error in JPX COD marker segment");
784 img.tiles[0].tileComps[0].resLevels[r].precinctWidth =
786 img.tiles[0].tileComps[0].resLevels[r].precinctHeight =
787 (precinctSize >> 4) & 0x0f;
789 img.tiles[0].tileComps[0].resLevels[r].precinctWidth = 15;
790 img.tiles[0].tileComps[0].resLevels[r].precinctHeight = 15;
793 for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
794 for (comp = 0; comp < img.nComps; ++comp) {
795 if (!(i == 0 && comp == 0)) {
796 for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) {
797 img.tiles[i].tileComps[comp].resLevels[r].precinctWidth =
798 img.tiles[0].tileComps[0].resLevels[r].precinctWidth;
799 img.tiles[i].tileComps[comp].resLevels[r].precinctHeight =
800 img.tiles[0].tileComps[0].resLevels[r].precinctHeight;
807 case 0x53: // COC - coding style component
809 error(getPos(), "JPX COC marker segment before COD segment");
812 if ((img.nComps > 256 && !readUWord(&comp)) ||
813 (img.nComps <= 256 && !readUByte(&comp)) ||
814 comp >= img.nComps ||
815 !readUByte(&style) ||
816 !readUByte(&img.tiles[0].tileComps[comp].nDecompLevels) ||
817 !readUByte(&img.tiles[0].tileComps[comp].codeBlockW) ||
818 !readUByte(&img.tiles[0].tileComps[comp].codeBlockH) ||
819 !readUByte(&img.tiles[0].tileComps[comp].codeBlockStyle) ||
820 !readUByte(&img.tiles[0].tileComps[comp].transform)) {
821 error(getPos(), "Error in JPX COC marker segment");
824 img.tiles[0].tileComps[comp].style =
825 (img.tiles[0].tileComps[comp].style & ~1) | (style & 1);
826 img.tiles[0].tileComps[comp].codeBlockW += 2;
827 img.tiles[0].tileComps[comp].codeBlockH += 2;
828 for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
830 img.tiles[i].tileComps[comp].style =
831 img.tiles[0].tileComps[comp].style;
832 img.tiles[i].tileComps[comp].nDecompLevels =
833 img.tiles[0].tileComps[comp].nDecompLevels;
834 img.tiles[i].tileComps[comp].codeBlockW =
835 img.tiles[0].tileComps[comp].codeBlockW;
836 img.tiles[i].tileComps[comp].codeBlockH =
837 img.tiles[0].tileComps[comp].codeBlockH;
838 img.tiles[i].tileComps[comp].codeBlockStyle =
839 img.tiles[0].tileComps[comp].codeBlockStyle;
840 img.tiles[i].tileComps[comp].transform =
841 img.tiles[0].tileComps[comp].transform;
843 img.tiles[i].tileComps[comp].resLevels =
844 (JPXResLevel *)grealloc(
845 img.tiles[i].tileComps[comp].resLevels,
846 (img.tiles[i].tileComps[comp].nDecompLevels + 1) *
847 sizeof(JPXResLevel));
848 for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) {
849 img.tiles[i].tileComps[comp].resLevels[r].precincts = NULL;
852 for (r = 0; r <= img.tiles[0].tileComps[comp].nDecompLevels; ++r) {
853 if (img.tiles[0].tileComps[comp].style & 0x01) {
854 if (!readUByte(&precinctSize)) {
855 error(getPos(), "Error in JPX COD marker segment");
858 img.tiles[0].tileComps[comp].resLevels[r].precinctWidth =
860 img.tiles[0].tileComps[comp].resLevels[r].precinctHeight =
861 (precinctSize >> 4) & 0x0f;
863 img.tiles[0].tileComps[comp].resLevels[r].precinctWidth = 15;
864 img.tiles[0].tileComps[comp].resLevels[r].precinctHeight = 15;
867 for (i = 1; i < img.nXTiles * img.nYTiles; ++i) {
868 for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) {
869 img.tiles[i].tileComps[comp].resLevels[r].precinctWidth =
870 img.tiles[0].tileComps[comp].resLevels[r].precinctWidth;
871 img.tiles[i].tileComps[comp].resLevels[r].precinctHeight =
872 img.tiles[0].tileComps[comp].resLevels[r].precinctHeight;
876 case 0x5c: // QCD - quantization default
877 if (!readUByte(&img.tiles[0].tileComps[0].quantStyle)) {
878 error(getPos(), "Error in JPX QCD marker segment");
881 if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x00) {
882 img.tiles[0].tileComps[0].nQuantSteps = segLen - 3;
883 img.tiles[0].tileComps[0].quantSteps =
884 (Guint *)grealloc(img.tiles[0].tileComps[0].quantSteps,
885 img.tiles[0].tileComps[0].nQuantSteps *
887 for (i = 0; i < img.tiles[0].tileComps[0].nQuantSteps; ++i) {
888 if (!readUByte(&img.tiles[0].tileComps[0].quantSteps[i])) {
889 error(getPos(), "Error in JPX QCD marker segment");
893 } else if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x01) {
894 img.tiles[0].tileComps[0].nQuantSteps = 1;
895 img.tiles[0].tileComps[0].quantSteps =
896 (Guint *)grealloc(img.tiles[0].tileComps[0].quantSteps,
897 img.tiles[0].tileComps[0].nQuantSteps *
899 if (!readUWord(&img.tiles[0].tileComps[0].quantSteps[0])) {
900 error(getPos(), "Error in JPX QCD marker segment");
903 } else if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x02) {
904 img.tiles[0].tileComps[0].nQuantSteps = (segLen - 3) / 2;
905 img.tiles[0].tileComps[0].quantSteps =
906 (Guint *)grealloc(img.tiles[0].tileComps[0].quantSteps,
907 img.tiles[0].tileComps[0].nQuantSteps *
909 for (i = 0; i < img.tiles[0].tileComps[0].nQuantSteps; ++i) {
910 if (!readUWord(&img.tiles[0].tileComps[0].quantSteps[i])) {
911 error(getPos(), "Error in JPX QCD marker segment");
916 error(getPos(), "Error in JPX QCD marker segment");
919 for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
920 for (comp = 0; comp < img.nComps; ++comp) {
921 if (!(i == 0 && comp == 0)) {
922 img.tiles[i].tileComps[comp].quantStyle =
923 img.tiles[0].tileComps[0].quantStyle;
924 img.tiles[i].tileComps[comp].nQuantSteps =
925 img.tiles[0].tileComps[0].nQuantSteps;
926 img.tiles[i].tileComps[comp].quantSteps =
927 (Guint *)grealloc(img.tiles[i].tileComps[comp].quantSteps,
928 img.tiles[0].tileComps[0].nQuantSteps *
930 for (j = 0; j < img.tiles[0].tileComps[0].nQuantSteps; ++j) {
931 img.tiles[i].tileComps[comp].quantSteps[j] =
932 img.tiles[0].tileComps[0].quantSteps[j];
939 case 0x5d: // QCC - quantization component
941 error(getPos(), "JPX QCC marker segment before QCD segment");
944 if ((img.nComps > 256 && !readUWord(&comp)) ||
945 (img.nComps <= 256 && !readUByte(&comp)) ||
946 comp >= img.nComps ||
947 !readUByte(&img.tiles[0].tileComps[comp].quantStyle)) {
948 error(getPos(), "Error in JPX QCC marker segment");
951 if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x00) {
952 img.tiles[0].tileComps[comp].nQuantSteps =
953 segLen - (img.nComps > 256 ? 5 : 4);
954 img.tiles[0].tileComps[comp].quantSteps =
955 (Guint *)grealloc(img.tiles[0].tileComps[comp].quantSteps,
956 img.tiles[0].tileComps[comp].nQuantSteps *
958 for (i = 0; i < img.tiles[0].tileComps[comp].nQuantSteps; ++i) {
959 if (!readUByte(&img.tiles[0].tileComps[comp].quantSteps[i])) {
960 error(getPos(), "Error in JPX QCC marker segment");
964 } else if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x01) {
965 img.tiles[0].tileComps[comp].nQuantSteps = 1;
966 img.tiles[0].tileComps[comp].quantSteps =
967 (Guint *)grealloc(img.tiles[0].tileComps[comp].quantSteps,
968 img.tiles[0].tileComps[comp].nQuantSteps *
970 if (!readUWord(&img.tiles[0].tileComps[comp].quantSteps[0])) {
971 error(getPos(), "Error in JPX QCC marker segment");
974 } else if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x02) {
975 img.tiles[0].tileComps[comp].nQuantSteps =
976 (segLen - (img.nComps > 256 ? 5 : 4)) / 2;
977 img.tiles[0].tileComps[comp].quantSteps =
978 (Guint *)grealloc(img.tiles[0].tileComps[comp].quantSteps,
979 img.tiles[0].tileComps[comp].nQuantSteps *
981 for (i = 0; i < img.tiles[0].tileComps[comp].nQuantSteps; ++i) {
982 if (!readUWord(&img.tiles[0].tileComps[comp].quantSteps[i])) {
983 error(getPos(), "Error in JPX QCD marker segment");
988 error(getPos(), "Error in JPX QCC marker segment");
991 for (i = 1; i < img.nXTiles * img.nYTiles; ++i) {
992 img.tiles[i].tileComps[comp].quantStyle =
993 img.tiles[0].tileComps[comp].quantStyle;
994 img.tiles[i].tileComps[comp].nQuantSteps =
995 img.tiles[0].tileComps[comp].nQuantSteps;
996 img.tiles[i].tileComps[comp].quantSteps =
997 (Guint *)grealloc(img.tiles[i].tileComps[comp].quantSteps,
998 img.tiles[0].tileComps[comp].nQuantSteps *
1000 for (j = 0; j < img.tiles[0].tileComps[comp].nQuantSteps; ++j) {
1001 img.tiles[i].tileComps[comp].quantSteps[j] =
1002 img.tiles[0].tileComps[comp].quantSteps[j];
1006 case 0x5e: // RGN - region of interest
1007 #if 1 //~ ROI is unimplemented
1008 fprintf(stderr, "RGN\n");
1009 for (i = 0; i < segLen - 2; ++i) {
1010 if (str->getChar() == EOF) {
1011 error(getPos(), "Error in JPX PPM marker segment");
1016 if ((img.nComps > 256 && !readUWord(&comp)) ||
1017 (img.nComps <= 256 && !readUByte(&comp)) ||
1018 comp >= img.nComps ||
1019 !readUByte(&compInfo[comp].defROI.style) ||
1020 !readUByte(&compInfo[comp].defROI.shift)) {
1021 error(getPos(), "Error in JPX RGN marker segment");
1026 case 0x5f: // POC - progression order change
1027 #if 1 //~ progression order changes are unimplemented
1028 fprintf(stderr, "POC\n");
1029 for (i = 0; i < segLen - 2; ++i) {
1030 if (str->getChar() == EOF) {
1031 error(getPos(), "Error in JPX PPM marker segment");
1036 nProgs = (segLen - 2) / (img.nComps > 256 ? 9 : 7);
1037 progs = (JPXProgOrder *)gmalloc(nProgs * sizeof(JPXProgOrder));
1038 for (i = 0; i < nProgs; ++i) {
1039 if (!readUByte(&progs[i].startRes) ||
1040 !(img.nComps > 256 && readUWord(&progs[i].startComp)) ||
1041 !(img.nComps <= 256 && readUByte(&progs[i].startComp)) ||
1042 !readUWord(&progs[i].endLayer) ||
1043 !readUByte(&progs[i].endRes) ||
1044 !(img.nComps > 256 && readUWord(&progs[i].endComp)) ||
1045 !(img.nComps <= 256 && readUByte(&progs[i].endComp)) ||
1046 !readUByte(&progs[i].progOrder)) {
1047 error(getPos(), "Error in JPX POC marker segment");
1053 case 0x60: // PPM - packed packet headers, main header
1054 #if 1 //~ packed packet headers are unimplemented
1055 fprintf(stderr, "PPM\n");
1056 for (i = 0; i < segLen - 2; ++i) {
1057 if (str->getChar() == EOF) {
1058 error(getPos(), "Error in JPX PPM marker segment");
1064 case 0x55: // TLM - tile-part lengths
1066 for (i = 0; i < segLen - 2; ++i) {
1067 if (str->getChar() == EOF) {
1068 error(getPos(), "Error in JPX TLM marker segment");
1073 case 0x57: // PLM - packet length, main header
1075 for (i = 0; i < segLen - 2; ++i) {
1076 if (str->getChar() == EOF) {
1077 error(getPos(), "Error in JPX PLM marker segment");
1082 case 0x63: // CRG - component registration
1084 for (i = 0; i < segLen - 2; ++i) {
1085 if (str->getChar() == EOF) {
1086 error(getPos(), "Error in JPX CRG marker segment");
1091 case 0x64: // COM - comment
1093 for (i = 0; i < segLen - 2; ++i) {
1094 if (str->getChar() == EOF) {
1095 error(getPos(), "Error in JPX COM marker segment");
1100 case 0x90: // SOT - start of tile
1104 error(getPos(), "Unknown marker segment %02x in JPX stream", segType);
1105 for (i = 0; i < segLen - 2; ++i) {
1106 if (str->getChar() == EOF) {
1115 error(getPos(), "Missing SIZ marker segment in JPX stream");
1119 error(getPos(), "Missing COD marker segment in JPX stream");
1123 error(getPos(), "Missing QCD marker segment in JPX stream");
1127 //----- read the tile-parts
1129 if (!readTilePart()) {
1132 if (!readMarkerHdr(&segType, &segLen)) {
1133 error(getPos(), "Error in JPX codestream");
1136 if (segType != 0x90) { // SOT - start of tile
1141 if (segType != 0xd9) { // EOC - end of codestream
1142 error(getPos(), "Missing EOC marker in JPX codestream");
1146 //----- finish decoding the image
1147 for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
1148 tile = &img.tiles[i];
1149 for (comp = 0; comp < img.nComps; ++comp) {
1150 tileComp = &tile->tileComps[comp];
1151 inverseTransform(tileComp);
1153 if (!inverseMultiCompAndDC(tile)) {
1158 //~ can free memory below tileComps here, and also tileComp.buf
1163 GBool JPXStream::readTilePart() {
1165 JPXTileComp *tileComp;
1166 JPXResLevel *resLevel;
1167 JPXPrecinct *precinct;
1168 JPXSubband *subband;
1171 Guint tileIdx, tilePartLen, tilePartIdx, nTileParts;
1172 GBool tilePartToEOC;
1173 Guint precinctSize, style;
1174 Guint n, nSBs, nx, ny, sbx0, sby0, comp, segLen;
1175 Guint i, j, k, cbX, cbY, r, pre, sb, cbi;
1178 // process the SOT marker segment
1179 if (!readUWord(&tileIdx) ||
1180 !readULong(&tilePartLen) ||
1181 !readUByte(&tilePartIdx) ||
1182 !readUByte(&nTileParts)) {
1183 error(getPos(), "Error in JPX SOT marker segment");
1187 if (tileIdx >= img.nXTiles * img.nYTiles) {
1188 error(getPos(), "Weird tile index in JPX stream");
1192 tilePartToEOC = tilePartLen == 0;
1193 tilePartLen -= 12; // subtract size of SOT segment
1197 if (!readMarkerHdr(&segType, &segLen)) {
1198 error(getPos(), "Error in JPX tile-part codestream");
1201 tilePartLen -= 2 + segLen;
1203 case 0x52: // COD - coding style default
1204 if (!readUByte(&img.tiles[tileIdx].tileComps[0].style) ||
1205 !readUByte(&img.tiles[tileIdx].progOrder) ||
1206 !readUWord(&img.tiles[tileIdx].nLayers) ||
1207 !readUByte(&img.tiles[tileIdx].multiComp) ||
1208 !readUByte(&img.tiles[tileIdx].tileComps[0].nDecompLevels) ||
1209 !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockW) ||
1210 !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockH) ||
1211 !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockStyle) ||
1212 !readUByte(&img.tiles[tileIdx].tileComps[0].transform)) {
1213 error(getPos(), "Error in JPX COD marker segment");
1216 img.tiles[tileIdx].tileComps[0].codeBlockW += 2;
1217 img.tiles[tileIdx].tileComps[0].codeBlockH += 2;
1218 for (comp = 0; comp < img.nComps; ++comp) {
1220 img.tiles[tileIdx].tileComps[comp].style =
1221 img.tiles[tileIdx].tileComps[0].style;
1222 img.tiles[tileIdx].tileComps[comp].nDecompLevels =
1223 img.tiles[tileIdx].tileComps[0].nDecompLevels;
1224 img.tiles[tileIdx].tileComps[comp].codeBlockW =
1225 img.tiles[tileIdx].tileComps[0].codeBlockW;
1226 img.tiles[tileIdx].tileComps[comp].codeBlockH =
1227 img.tiles[tileIdx].tileComps[0].codeBlockH;
1228 img.tiles[tileIdx].tileComps[comp].codeBlockStyle =
1229 img.tiles[tileIdx].tileComps[0].codeBlockStyle;
1230 img.tiles[tileIdx].tileComps[comp].transform =
1231 img.tiles[tileIdx].tileComps[0].transform;
1233 img.tiles[tileIdx].tileComps[comp].resLevels =
1234 (JPXResLevel *)grealloc(
1235 img.tiles[tileIdx].tileComps[comp].resLevels,
1236 (img.tiles[tileIdx].tileComps[comp].nDecompLevels + 1) *
1237 sizeof(JPXResLevel));
1239 r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels;
1241 img.tiles[tileIdx].tileComps[comp].resLevels[r].precincts = NULL;
1244 for (r = 0; r <= img.tiles[tileIdx].tileComps[0].nDecompLevels; ++r) {
1245 if (img.tiles[tileIdx].tileComps[0].style & 0x01) {
1246 if (!readUByte(&precinctSize)) {
1247 error(getPos(), "Error in JPX COD marker segment");
1250 img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth =
1251 precinctSize & 0x0f;
1252 img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight =
1253 (precinctSize >> 4) & 0x0f;
1255 img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth = 15;
1256 img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight = 15;
1259 for (comp = 1; comp < img.nComps; ++comp) {
1261 r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels;
1263 img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth =
1264 img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth;
1265 img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight =
1266 img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight;
1270 case 0x53: // COC - coding style component
1271 if ((img.nComps > 256 && !readUWord(&comp)) ||
1272 (img.nComps <= 256 && !readUByte(&comp)) ||
1273 comp >= img.nComps ||
1274 !readUByte(&style) ||
1275 !readUByte(&img.tiles[tileIdx].tileComps[comp].nDecompLevels) ||
1276 !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockW) ||
1277 !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockH) ||
1278 !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockStyle) ||
1279 !readUByte(&img.tiles[tileIdx].tileComps[comp].transform)) {
1280 error(getPos(), "Error in JPX COC marker segment");
1283 img.tiles[tileIdx].tileComps[comp].style =
1284 (img.tiles[tileIdx].tileComps[comp].style & ~1) | (style & 1);
1285 img.tiles[tileIdx].tileComps[comp].codeBlockW += 2;
1286 img.tiles[tileIdx].tileComps[comp].codeBlockH += 2;
1287 img.tiles[tileIdx].tileComps[comp].resLevels =
1288 (JPXResLevel *)grealloc(
1289 img.tiles[tileIdx].tileComps[comp].resLevels,
1290 (img.tiles[tileIdx].tileComps[comp].nDecompLevels + 1) *
1291 sizeof(JPXResLevel));
1292 for (r = 0; r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; ++r) {
1293 img.tiles[tileIdx].tileComps[comp].resLevels[r].precincts = NULL;
1295 for (r = 0; r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; ++r) {
1296 if (img.tiles[tileIdx].tileComps[comp].style & 0x01) {
1297 if (!readUByte(&precinctSize)) {
1298 error(getPos(), "Error in JPX COD marker segment");
1301 img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth =
1302 precinctSize & 0x0f;
1303 img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight =
1304 (precinctSize >> 4) & 0x0f;
1306 img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth = 15;
1307 img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight = 15;
1311 case 0x5c: // QCD - quantization default
1312 if (!readUByte(&img.tiles[tileIdx].tileComps[0].quantStyle)) {
1313 error(getPos(), "Error in JPX QCD marker segment");
1316 if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x00) {
1317 img.tiles[tileIdx].tileComps[0].nQuantSteps =
1319 img.tiles[tileIdx].tileComps[0].quantSteps =
1320 (Guint *)grealloc(img.tiles[tileIdx].tileComps[0].quantSteps,
1321 img.tiles[tileIdx].tileComps[0].nQuantSteps *
1323 for (i = 0; i < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++i) {
1324 if (!readUByte(&img.tiles[tileIdx].tileComps[0].quantSteps[i])) {
1325 error(getPos(), "Error in JPX QCD marker segment");
1329 } else if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x01) {
1330 img.tiles[tileIdx].tileComps[0].nQuantSteps = 1;
1331 img.tiles[tileIdx].tileComps[0].quantSteps =
1332 (Guint *)grealloc(img.tiles[tileIdx].tileComps[0].quantSteps,
1333 img.tiles[tileIdx].tileComps[0].nQuantSteps *
1335 if (!readUWord(&img.tiles[tileIdx].tileComps[0].quantSteps[0])) {
1336 error(getPos(), "Error in JPX QCD marker segment");
1339 } else if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x02) {
1340 img.tiles[tileIdx].tileComps[0].nQuantSteps = (segLen - 3) / 2;
1341 img.tiles[tileIdx].tileComps[0].quantSteps =
1342 (Guint *)grealloc(img.tiles[tileIdx].tileComps[0].quantSteps,
1343 img.tiles[tileIdx].tileComps[0].nQuantSteps *
1345 for (i = 0; i < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++i) {
1346 if (!readUWord(&img.tiles[tileIdx].tileComps[0].quantSteps[i])) {
1347 error(getPos(), "Error in JPX QCD marker segment");
1352 error(getPos(), "Error in JPX QCD marker segment");
1355 for (comp = 1; comp < img.nComps; ++comp) {
1356 img.tiles[tileIdx].tileComps[comp].quantStyle =
1357 img.tiles[tileIdx].tileComps[0].quantStyle;
1358 img.tiles[tileIdx].tileComps[comp].nQuantSteps =
1359 img.tiles[tileIdx].tileComps[0].nQuantSteps;
1360 img.tiles[tileIdx].tileComps[comp].quantSteps =
1361 (Guint *)grealloc(img.tiles[tileIdx].tileComps[comp].quantSteps,
1362 img.tiles[tileIdx].tileComps[0].nQuantSteps *
1364 for (j = 0; j < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++j) {
1365 img.tiles[tileIdx].tileComps[comp].quantSteps[j] =
1366 img.tiles[tileIdx].tileComps[0].quantSteps[j];
1370 case 0x5d: // QCC - quantization component
1371 if ((img.nComps > 256 && !readUWord(&comp)) ||
1372 (img.nComps <= 256 && !readUByte(&comp)) ||
1373 comp >= img.nComps ||
1374 !readUByte(&img.tiles[tileIdx].tileComps[comp].quantStyle)) {
1375 error(getPos(), "Error in JPX QCC marker segment");
1378 if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f) == 0x00) {
1379 img.tiles[tileIdx].tileComps[comp].nQuantSteps =
1380 segLen - (img.nComps > 256 ? 5 : 4);
1381 img.tiles[tileIdx].tileComps[comp].quantSteps =
1382 (Guint *)grealloc(img.tiles[tileIdx].tileComps[comp].quantSteps,
1383 img.tiles[tileIdx].tileComps[comp].nQuantSteps *
1385 for (i = 0; i < img.tiles[tileIdx].tileComps[comp].nQuantSteps; ++i) {
1386 if (!readUByte(&img.tiles[tileIdx].tileComps[comp].quantSteps[i])) {
1387 error(getPos(), "Error in JPX QCC marker segment");
1391 } else if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f)
1393 img.tiles[tileIdx].tileComps[comp].nQuantSteps = 1;
1394 img.tiles[tileIdx].tileComps[comp].quantSteps =
1395 (Guint *)grealloc(img.tiles[tileIdx].tileComps[comp].quantSteps,
1396 img.tiles[tileIdx].tileComps[comp].nQuantSteps *
1398 if (!readUWord(&img.tiles[tileIdx].tileComps[comp].quantSteps[0])) {
1399 error(getPos(), "Error in JPX QCC marker segment");
1402 } else if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f)
1404 img.tiles[tileIdx].tileComps[comp].nQuantSteps =
1405 (segLen - (img.nComps > 256 ? 5 : 4)) / 2;
1406 img.tiles[tileIdx].tileComps[comp].quantSteps =
1407 (Guint *)grealloc(img.tiles[tileIdx].tileComps[comp].quantSteps,
1408 img.tiles[tileIdx].tileComps[comp].nQuantSteps *
1410 for (i = 0; i < img.tiles[tileIdx].tileComps[comp].nQuantSteps; ++i) {
1411 if (!readUWord(&img.tiles[tileIdx].tileComps[comp].quantSteps[i])) {
1412 error(getPos(), "Error in JPX QCD marker segment");
1417 error(getPos(), "Error in JPX QCC marker segment");
1421 case 0x5e: // RGN - region of interest
1422 #if 1 //~ ROI is unimplemented
1423 fprintf(stderr, "RGN\n");
1424 for (i = 0; i < segLen - 2; ++i) {
1425 if (str->getChar() == EOF) {
1426 error(getPos(), "Error in JPX PPM marker segment");
1431 if ((img.nComps > 256 && !readUWord(&comp)) ||
1432 (img.nComps <= 256 && !readUByte(&comp)) ||
1433 comp >= img.nComps ||
1434 !readUByte(&compInfo[comp].roi.style) ||
1435 !readUByte(&compInfo[comp].roi.shift)) {
1436 error(getPos(), "Error in JPX RGN marker segment");
1441 case 0x5f: // POC - progression order change
1442 #if 1 //~ progression order changes are unimplemented
1443 fprintf(stderr, "POC\n");
1444 for (i = 0; i < segLen - 2; ++i) {
1445 if (str->getChar() == EOF) {
1446 error(getPos(), "Error in JPX PPM marker segment");
1451 nTileProgs = (segLen - 2) / (img.nComps > 256 ? 9 : 7);
1452 tileProgs = (JPXProgOrder *)gmalloc(nTileProgs * sizeof(JPXProgOrder));
1453 for (i = 0; i < nTileProgs; ++i) {
1454 if (!readUByte(&tileProgs[i].startRes) ||
1455 !(img.nComps > 256 && readUWord(&tileProgs[i].startComp)) ||
1456 !(img.nComps <= 256 && readUByte(&tileProgs[i].startComp)) ||
1457 !readUWord(&tileProgs[i].endLayer) ||
1458 !readUByte(&tileProgs[i].endRes) ||
1459 !(img.nComps > 256 && readUWord(&tileProgs[i].endComp)) ||
1460 !(img.nComps <= 256 && readUByte(&tileProgs[i].endComp)) ||
1461 !readUByte(&tileProgs[i].progOrder)) {
1462 error(getPos(), "Error in JPX POC marker segment");
1468 case 0x61: // PPT - packed packet headers, tile-part hdr
1469 #if 1 //~ packed packet headers are unimplemented
1470 fprintf(stderr, "PPT\n");
1471 for (i = 0; i < segLen - 2; ++i) {
1472 if (str->getChar() == EOF) {
1473 error(getPos(), "Error in JPX PPT marker segment");
1478 case 0x58: // PLT - packet length, tile-part header
1480 for (i = 0; i < segLen - 2; ++i) {
1481 if (str->getChar() == EOF) {
1482 error(getPos(), "Error in JPX PLT marker segment");
1487 case 0x64: // COM - comment
1489 for (i = 0; i < segLen - 2; ++i) {
1490 if (str->getChar() == EOF) {
1491 error(getPos(), "Error in JPX COM marker segment");
1496 case 0x93: // SOD - start of data
1500 error(getPos(), "Unknown marker segment %02x in JPX tile-part stream",
1502 for (i = 0; i < segLen - 2; ++i) {
1503 if (str->getChar() == EOF) {
1511 //----- initialize the tile, precincts, and code-blocks
1512 if (tilePartIdx == 0) {
1513 tile = &img.tiles[tileIdx];
1514 i = tileIdx / img.nXTiles;
1515 j = tileIdx % img.nXTiles;
1516 if ((tile->x0 = img.xTileOffset + j * img.xTileSize) < img.xOffset) {
1517 tile->x0 = img.xOffset;
1519 if ((tile->y0 = img.yTileOffset + i * img.yTileSize) < img.yOffset) {
1520 tile->y0 = img.yOffset;
1522 if ((tile->x1 = img.xTileOffset + (j + 1) * img.xTileSize) > img.xSize) {
1523 tile->x1 = img.xSize;
1525 if ((tile->y1 = img.yTileOffset + (i + 1) * img.yTileSize) > img.ySize) {
1526 tile->y1 = img.ySize;
1532 tile->maxNDecompLevels = 0;
1533 for (comp = 0; comp < img.nComps; ++comp) {
1534 tileComp = &tile->tileComps[comp];
1535 if (tileComp->nDecompLevels > tile->maxNDecompLevels) {
1536 tile->maxNDecompLevels = tileComp->nDecompLevels;
1538 tileComp->x0 = jpxCeilDiv(tile->x0, tileComp->hSep);
1539 tileComp->y0 = jpxCeilDiv(tile->y0, tileComp->hSep);
1540 tileComp->x1 = jpxCeilDiv(tile->x1, tileComp->hSep);
1541 tileComp->y1 = jpxCeilDiv(tile->y1, tileComp->hSep);
1542 tileComp->cbW = 1 << tileComp->codeBlockW;
1543 tileComp->cbH = 1 << tileComp->codeBlockH;
1544 tileComp->data = (int *)gmalloc((tileComp->x1 - tileComp->x0) *
1545 (tileComp->y1 - tileComp->y0) *
1547 if (tileComp->x1 - tileComp->x0 > tileComp->y1 - tileComp->y0) {
1548 n = tileComp->x1 - tileComp->x0;
1550 n = tileComp->y1 - tileComp->y0;
1552 tileComp->buf = (int *)gmalloc((n + 8) * sizeof(int));
1553 for (r = 0; r <= tileComp->nDecompLevels; ++r) {
1554 resLevel = &tileComp->resLevels[r];
1555 k = r == 0 ? tileComp->nDecompLevels
1556 : tileComp->nDecompLevels - r + 1;
1557 resLevel->x0 = jpxCeilDivPow2(tileComp->x0, k);
1558 resLevel->y0 = jpxCeilDivPow2(tileComp->y0, k);
1559 resLevel->x1 = jpxCeilDivPow2(tileComp->x1, k);
1560 resLevel->y1 = jpxCeilDivPow2(tileComp->y1, k);
1562 resLevel->bx0[0] = resLevel->x0;
1563 resLevel->by0[0] = resLevel->y0;
1564 resLevel->bx1[0] = resLevel->x1;
1565 resLevel->by1[0] = resLevel->y1;
1567 resLevel->bx0[0] = jpxCeilDivPow2(tileComp->x0 - (1 << (k-1)), k);
1568 resLevel->by0[0] = resLevel->y0;
1569 resLevel->bx1[0] = jpxCeilDivPow2(tileComp->x1 - (1 << (k-1)), k);
1570 resLevel->by1[0] = resLevel->y1;
1571 resLevel->bx0[1] = resLevel->x0;
1572 resLevel->by0[1] = jpxCeilDivPow2(tileComp->y0 - (1 << (k-1)), k);
1573 resLevel->bx1[1] = resLevel->x1;
1574 resLevel->by1[1] = jpxCeilDivPow2(tileComp->y1 - (1 << (k-1)), k);
1575 resLevel->bx0[2] = jpxCeilDivPow2(tileComp->x0 - (1 << (k-1)), k);
1576 resLevel->by0[2] = jpxCeilDivPow2(tileComp->y0 - (1 << (k-1)), k);
1577 resLevel->bx1[2] = jpxCeilDivPow2(tileComp->x1 - (1 << (k-1)), k);
1578 resLevel->by1[2] = jpxCeilDivPow2(tileComp->y1 - (1 << (k-1)), k);
1580 resLevel->precincts = (JPXPrecinct *)gmalloc(1 * sizeof(JPXPrecinct));
1581 for (pre = 0; pre < 1; ++pre) {
1582 precinct = &resLevel->precincts[pre];
1583 precinct->x0 = resLevel->x0;
1584 precinct->y0 = resLevel->y0;
1585 precinct->x1 = resLevel->x1;
1586 precinct->y1 = resLevel->y1;
1587 nSBs = r == 0 ? 1 : 3;
1588 precinct->subbands =
1589 (JPXSubband *)gmalloc(nSBs * sizeof(JPXSubband));
1590 for (sb = 0; sb < nSBs; ++sb) {
1591 subband = &precinct->subbands[sb];
1592 subband->x0 = resLevel->bx0[sb];
1593 subband->y0 = resLevel->by0[sb];
1594 subband->x1 = resLevel->bx1[sb];
1595 subband->y1 = resLevel->by1[sb];
1596 subband->nXCBs = jpxCeilDivPow2(subband->x1,
1597 tileComp->codeBlockW)
1598 - jpxFloorDivPow2(subband->x0,
1599 tileComp->codeBlockW);
1600 subband->nYCBs = jpxCeilDivPow2(subband->y1,
1601 tileComp->codeBlockH)
1602 - jpxFloorDivPow2(subband->y0,
1603 tileComp->codeBlockH);
1604 n = subband->nXCBs > subband->nYCBs ? subband->nXCBs
1606 for (subband->maxTTLevel = 0, --n;
1608 ++subband->maxTTLevel, n >>= 1) ;
1610 for (level = subband->maxTTLevel; level >= 0; --level) {
1611 nx = jpxCeilDivPow2(subband->nXCBs, level);
1612 ny = jpxCeilDivPow2(subband->nYCBs, level);
1615 subband->inclusion =
1616 (JPXTagTreeNode *)gmalloc(n * sizeof(JPXTagTreeNode));
1617 subband->zeroBitPlane =
1618 (JPXTagTreeNode *)gmalloc(n * sizeof(JPXTagTreeNode));
1619 for (k = 0; k < n; ++k) {
1620 subband->inclusion[k].finished = gFalse;
1621 subband->inclusion[k].val = 0;
1622 subband->zeroBitPlane[k].finished = gFalse;
1623 subband->zeroBitPlane[k].val = 0;
1625 subband->cbs = (JPXCodeBlock *)gmalloc(subband->nXCBs *
1627 sizeof(JPXCodeBlock));
1628 sbx0 = jpxFloorDivPow2(subband->x0, tileComp->codeBlockW);
1629 sby0 = jpxFloorDivPow2(subband->y0, tileComp->codeBlockH);
1631 for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
1632 for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
1633 cb->x0 = (sbx0 + cbX) << tileComp->codeBlockW;
1634 cb->x1 = cb->x0 + tileComp->cbW;
1635 if (subband->x0 > cb->x0) {
1636 cb->x0 = subband->x0;
1638 if (subband->x1 < cb->x1) {
1639 cb->x1 = subband->x1;
1641 cb->y0 = (sby0 + cbY) << tileComp->codeBlockH;
1642 cb->y1 = cb->y0 + tileComp->cbH;
1643 if (subband->y0 > cb->y0) {
1644 cb->y0 = subband->y0;
1646 if (subband->y1 < cb->y1) {
1647 cb->y1 = subband->y1;
1651 cb->nextPass = jpxPassCleanup;
1652 cb->nZeroBitPlanes = 0;
1654 (JPXCoeff *)gmalloc((1 << (tileComp->codeBlockW
1655 + tileComp->codeBlockH))
1656 * sizeof(JPXCoeff));
1658 cbi < (Guint)(1 << (tileComp->codeBlockW
1659 + tileComp->codeBlockH));
1661 cb->coeffs[cbi].flags = 0;
1662 cb->coeffs[cbi].len = 0;
1663 cb->coeffs[cbi].mag = 0;
1665 cb->stats = new JArithmeticDecoderStats(jpxNContexts);
1666 cb->stats->setEntry(jpxContextSigProp, 4, 0);
1667 cb->stats->setEntry(jpxContextRunLength, 3, 0);
1668 cb->stats->setEntry(jpxContextUniform, 46, 0);
1678 return readTilePartData(tileIdx, tilePartLen, tilePartToEOC);
1681 GBool JPXStream::readTilePartData(Guint tileIdx,
1682 Guint tilePartLen, GBool tilePartToEOC) {
1684 JPXTileComp *tileComp;
1685 JPXResLevel *resLevel;
1686 JPXPrecinct *precinct;
1687 JPXSubband *subband;
1690 Guint bits, cbX, cbY, nx, ny, i, j, n, sb;
1693 tile = &img.tiles[tileIdx];
1695 // read all packets from this tile-part
1697 if (tilePartToEOC) {
1698 //~ peek for an EOC marker
1699 } else if (tilePartLen == 0) {
1703 tileComp = &tile->tileComps[tile->comp];
1704 resLevel = &tileComp->resLevels[tile->res];
1705 precinct = &resLevel->precincts[tile->precinct];
1707 //----- packet header
1710 if (!readBits(1, &bits)) {
1714 // packet is empty -- clear all code-block inclusion flags
1715 for (sb = 0; sb < (tile->res == 0 ? 1 : 3); ++sb) {
1716 subband = &precinct->subbands[sb];
1717 for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
1718 for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
1719 cb = &subband->cbs[cbY * subband->nXCBs + cbX];
1720 cb->included = gFalse;
1726 for (sb = 0; sb < (tile->res == 0 ? 1 : 3); ++sb) {
1727 subband = &precinct->subbands[sb];
1728 for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
1729 for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
1730 cb = &subband->cbs[cbY * subband->nXCBs + cbX];
1732 // skip code-blocks with no coefficients
1733 if (cb->x0 >= cb->x1 || cb->y0 >= cb->y1) {
1734 cb->included = gFalse;
1738 // code-block inclusion
1740 if (!readBits(1, &cb->included)) {
1746 for (level = subband->maxTTLevel; level >= 0; --level) {
1747 nx = jpxCeilDivPow2(subband->nXCBs, level);
1748 ny = jpxCeilDivPow2(subband->nYCBs, level);
1749 j = i + (cbY >> level) * nx + (cbX >> level);
1750 if (!subband->inclusion[j].finished &&
1751 !subband->inclusion[j].val) {
1752 subband->inclusion[j].val = ttVal;
1754 ttVal = subband->inclusion[j].val;
1756 while (!subband->inclusion[j].finished &&
1757 ttVal <= tile->layer) {
1758 if (!readBits(1, &bits)) {
1762 subband->inclusion[j].finished = gTrue;
1767 subband->inclusion[j].val = ttVal;
1768 if (ttVal > tile->layer) {
1773 cb->included = level < 0;
1778 // zero bit-plane count
1782 for (level = subband->maxTTLevel; level >= 0; --level) {
1783 nx = jpxCeilDivPow2(subband->nXCBs, level);
1784 ny = jpxCeilDivPow2(subband->nYCBs, level);
1785 j = i + (cbY >> level) * nx + (cbX >> level);
1786 if (!subband->zeroBitPlane[j].finished &&
1787 !subband->zeroBitPlane[j].val) {
1788 subband->zeroBitPlane[j].val = ttVal;
1790 ttVal = subband->zeroBitPlane[j].val;
1792 while (!subband->zeroBitPlane[j].finished) {
1793 if (!readBits(1, &bits)) {
1797 subband->zeroBitPlane[j].finished = gTrue;
1802 subband->zeroBitPlane[j].val = ttVal;
1805 cb->nZeroBitPlanes = ttVal;
1808 // number of coding passes
1809 if (!readBits(1, &bits)) {
1813 cb->nCodingPasses = 1;
1815 if (!readBits(1, &bits)) {
1819 cb->nCodingPasses = 2;
1821 if (!readBits(2, &bits)) {
1825 cb->nCodingPasses = 3 + bits;
1827 if (!readBits(5, &bits)) {
1831 cb->nCodingPasses = 6 + bits;
1833 if (!readBits(7, &bits)) {
1836 cb->nCodingPasses = 37 + bits;
1844 if (!readBits(1, &bits)) {
1853 // length of compressed data
1854 //~ deal with multiple codeword segments
1855 for (n = cb->lBlock, i = cb->nCodingPasses >> 1;
1858 if (!readBits(n, &cb->dataLen)) {
1866 tilePartLen -= byteCount;
1871 for (sb = 0; sb < (tile->res == 0 ? 1 : 3); ++sb) {
1872 subband = &precinct->subbands[sb];
1873 for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
1874 for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
1875 cb = &subband->cbs[cbY * subband->nXCBs + cbX];
1877 if (!readCodeBlockData(tileComp, resLevel, precinct, subband,
1878 tile->res, sb, cb)) {
1881 tilePartLen -= cb->dataLen;
1890 switch (tile->progOrder) {
1891 case 0: // layer, resolution level, component, precinct
1892 if (++tile->comp == img.nComps) {
1894 if (++tile->res == tile->maxNDecompLevels + 1) {
1896 if (++tile->layer == tile->nLayers) {
1902 case 1: // resolution level, layer, component, precinct
1903 if (++tile->comp == img.nComps) {
1905 if (++tile->layer == tile->nLayers) {
1907 if (++tile->res == tile->maxNDecompLevels + 1) {
1913 case 2: // resolution level, precinct, component, layer
1914 //~ this isn't correct -- see B.12.1.3
1915 if (++tile->layer == tile->nLayers) {
1917 if (++tile->comp == img.nComps) {
1919 if (++tile->res == tile->maxNDecompLevels + 1) {
1925 case 3: // precinct, component, resolution level, layer
1926 //~ this isn't correct -- see B.12.1.4
1927 if (++tile->layer == tile->nLayers) {
1929 if (++tile->res == tile->maxNDecompLevels + 1) {
1931 if (++tile->comp == img.nComps) {
1937 case 4: // component, precinct, resolution level, layer
1938 //~ this isn't correct -- see B.12.1.5
1939 if (++tile->layer == tile->nLayers) {
1941 if (++tile->res == tile->maxNDecompLevels + 1) {
1943 if (++tile->comp == img.nComps) {
1955 error(getPos(), "Error in JPX stream");
1959 GBool JPXStream::readCodeBlockData(JPXTileComp *tileComp,
1960 JPXResLevel *resLevel,
1961 JPXPrecinct *precinct,
1962 JPXSubband *subband,
1963 Guint res, Guint sb,
1965 JPXCoeff *coeff0, *coeff1, *coeff;
1966 JArithmeticDecoder *arithDecoder;
1967 Guint horiz, vert, diag, all, cx, xorBit;
1968 int horizSign, vertSign;
1969 Guint i, x, y0, y1, y2;
1971 arithDecoder = new JArithmeticDecoder();
1972 arithDecoder->setStream(str, cb->dataLen);
1973 arithDecoder->start();
1975 for (i = 0; i < cb->nCodingPasses; ++i) {
1976 switch (cb->nextPass) {
1978 //----- significance propagation pass
1979 case jpxPassSigProp:
1980 for (y0 = cb->y0, coeff0 = cb->coeffs;
1982 y0 += 4, coeff0 += 4 << tileComp->codeBlockW) {
1983 for (x = cb->x0, coeff1 = coeff0;
1986 for (y1 = 0, coeff = coeff1;
1987 y1 < 4 && y0+y1 < cb->y1;
1988 ++y1, coeff += tileComp->cbW) {
1989 if (!(coeff->flags & jpxCoeffSignificant)) {
1990 horiz = vert = diag = 0;
1991 horizSign = vertSign = 2;
1993 if (coeff[-1].flags & jpxCoeffSignificant) {
1995 horizSign += (coeff[-1].flags & jpxCoeffSign) ? -1 : 1;
1997 if (y0+y1 > cb->y0) {
1998 diag += (coeff[-tileComp->cbW - 1].flags
1999 >> jpxCoeffSignificantB) & 1;
2001 if (y0+y1 < cb->y1 - 1) {
2002 diag += (coeff[tileComp->cbW - 1].flags
2003 >> jpxCoeffSignificantB) & 1;
2006 if (x < cb->x1 - 1) {
2007 if (coeff[1].flags & jpxCoeffSignificant) {
2009 horizSign += (coeff[1].flags & jpxCoeffSign) ? -1 : 1;
2011 if (y0+y1 > cb->y0) {
2012 diag += (coeff[-tileComp->cbW + 1].flags
2013 >> jpxCoeffSignificantB) & 1;
2015 if (y0+y1 < cb->y1 - 1) {
2016 diag += (coeff[tileComp->cbW + 1].flags
2017 >> jpxCoeffSignificantB) & 1;
2020 if (y0+y1 > cb->y0) {
2021 if (coeff[-tileComp->cbW].flags & jpxCoeffSignificant) {
2023 vertSign += (coeff[-tileComp->cbW].flags & jpxCoeffSign)
2027 if (y0+y1 < cb->y1 - 1) {
2028 if (coeff[tileComp->cbW].flags & jpxCoeffSignificant) {
2030 vertSign += (coeff[tileComp->cbW].flags & jpxCoeffSign)
2034 cx = sigPropContext[horiz][vert][diag][res == 0 ? 1 : sb];
2036 if (arithDecoder->decodeBit(cx, cb->stats)) {
2037 coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef;
2038 coeff->mag = (coeff->mag << 1) | 1;
2039 cx = signContext[horizSign][vertSign][0];
2040 xorBit = signContext[horizSign][vertSign][1];
2041 if (arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) {
2042 coeff->flags |= jpxCoeffSign;
2046 coeff->flags |= jpxCoeffTouched;
2055 //----- magnitude refinement pass
2057 for (y0 = cb->y0, coeff0 = cb->coeffs;
2059 y0 += 4, coeff0 += 4 << tileComp->codeBlockW) {
2060 for (x = cb->x0, coeff1 = coeff0;
2063 for (y1 = 0, coeff = coeff1;
2064 y1 < 4 && y0+y1 < cb->y1;
2065 ++y1, coeff += tileComp->cbW) {
2066 if ((coeff->flags & jpxCoeffSignificant) &&
2067 !(coeff->flags & jpxCoeffTouched)) {
2068 if (coeff->flags & jpxCoeffFirstMagRef) {
2071 all += (coeff[-1].flags >> jpxCoeffSignificantB) & 1;
2072 if (y0+y1 > cb->y0) {
2073 all += (coeff[-tileComp->cbW - 1].flags
2074 >> jpxCoeffSignificantB) & 1;
2076 if (y0+y1 < cb->y1 - 1) {
2077 all += (coeff[tileComp->cbW - 1].flags
2078 >> jpxCoeffSignificantB) & 1;
2081 if (x < cb->x1 - 1) {
2082 all += (coeff[1].flags >> jpxCoeffSignificantB) & 1;
2083 if (y0+y1 > cb->y0) {
2084 all += (coeff[-tileComp->cbW + 1].flags
2085 >> jpxCoeffSignificantB) & 1;
2087 if (y0+y1 < cb->y1 - 1) {
2088 all += (coeff[tileComp->cbW + 1].flags
2089 >> jpxCoeffSignificantB) & 1;
2092 if (y0+y1 > cb->y0) {
2093 all += (coeff[-tileComp->cbW].flags
2094 >> jpxCoeffSignificantB) & 1;
2096 if (y0+y1 < cb->y1 - 1) {
2097 all += (coeff[tileComp->cbW].flags
2098 >> jpxCoeffSignificantB) & 1;
2104 coeff->mag = (coeff->mag << 1) |
2105 arithDecoder->decodeBit(cx, cb->stats);
2107 coeff->flags |= jpxCoeffTouched;
2108 coeff->flags &= ~jpxCoeffFirstMagRef;
2116 //----- cleanup pass
2117 case jpxPassCleanup:
2118 for (y0 = cb->y0, coeff0 = cb->coeffs;
2120 y0 += 4, coeff0 += 4 << tileComp->codeBlockW) {
2121 for (x = cb->x0, coeff1 = coeff0;
2125 if (y0 + 3 < cb->y1 &&
2126 !(coeff1->flags & jpxCoeffTouched) &&
2127 !(coeff1[tileComp->cbW].flags & jpxCoeffTouched) &&
2128 !(coeff1[2 * tileComp->cbW].flags & jpxCoeffTouched) &&
2129 !(coeff1[3 * tileComp->cbW].flags & jpxCoeffTouched) &&
2130 (x == cb->x0 || y0 == cb->y0 ||
2131 !(coeff1[-tileComp->cbW - 1].flags
2132 & jpxCoeffSignificant)) &&
2134 !(coeff1[-tileComp->cbW].flags & jpxCoeffSignificant)) &&
2135 (x == cb->x1 - 1 || y0 == cb->y0 ||
2136 !(coeff1[-tileComp->cbW + 1].flags & jpxCoeffSignificant)) &&
2138 (!(coeff1[-1].flags & jpxCoeffSignificant) &&
2139 !(coeff1[tileComp->cbW - 1].flags
2140 & jpxCoeffSignificant) &&
2141 !(coeff1[2 * tileComp->cbW - 1].flags
2142 & jpxCoeffSignificant) &&
2143 !(coeff1[3 * tileComp->cbW - 1].flags
2144 & jpxCoeffSignificant))) &&
2146 (!(coeff1[1].flags & jpxCoeffSignificant) &&
2147 !(coeff1[tileComp->cbW + 1].flags
2148 & jpxCoeffSignificant) &&
2149 !(coeff1[2 * tileComp->cbW + 1].flags
2150 & jpxCoeffSignificant) &&
2151 !(coeff1[3 * tileComp->cbW + 1].flags
2152 & jpxCoeffSignificant))) &&
2153 (x == cb->x0 || y0+4 == cb->y1 ||
2154 !(coeff1[4 * tileComp->cbW - 1].flags & jpxCoeffSignificant)) &&
2156 !(coeff1[4 * tileComp->cbW].flags & jpxCoeffSignificant)) &&
2157 (x == cb->x1 - 1 || y0+4 == cb->y1 ||
2158 !(coeff1[4 * tileComp->cbW + 1].flags
2159 & jpxCoeffSignificant))) {
2160 if (arithDecoder->decodeBit(jpxContextRunLength, cb->stats)) {
2161 y1 = arithDecoder->decodeBit(jpxContextUniform, cb->stats);
2163 arithDecoder->decodeBit(jpxContextUniform, cb->stats);
2164 for (y2 = 0, coeff = coeff1;
2166 ++y2, coeff += tileComp->cbW) {
2169 coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef;
2170 coeff->mag = (coeff->mag << 1) | 1;
2172 cx = signContext[2][2][0];
2173 xorBit = signContext[2][2][1];
2174 if (arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) {
2175 coeff->flags |= jpxCoeffSign;
2179 for (y1 = 0, coeff = coeff1;
2181 ++y1, coeff += tileComp->cbW) {
2187 for (coeff = &coeff1[y1 << tileComp->codeBlockW];
2188 y1 < 4 && y0 + y1 < cb->y1;
2189 ++y1, coeff += tileComp->cbW) {
2190 if (!(coeff->flags & jpxCoeffTouched)) {
2191 horiz = vert = diag = 0;
2192 horizSign = vertSign = 2;
2194 if (coeff[-1].flags & jpxCoeffSignificant) {
2196 horizSign += (coeff[-1].flags & jpxCoeffSign) ? -1 : 1;
2198 if (y0+y1 > cb->y0) {
2199 diag += (coeff[-tileComp->cbW - 1].flags
2200 >> jpxCoeffSignificantB) & 1;
2202 if (y0+y1 < cb->y1 - 1) {
2203 diag += (coeff[tileComp->cbW - 1].flags
2204 >> jpxCoeffSignificantB) & 1;
2207 if (x < cb->x1 - 1) {
2208 if (coeff[1].flags & jpxCoeffSignificant) {
2210 horizSign += (coeff[1].flags & jpxCoeffSign) ? -1 : 1;
2212 if (y0+y1 > cb->y0) {
2213 diag += (coeff[-tileComp->cbW + 1].flags
2214 >> jpxCoeffSignificantB) & 1;
2216 if (y0+y1 < cb->y1 - 1) {
2217 diag += (coeff[tileComp->cbW + 1].flags
2218 >> jpxCoeffSignificantB) & 1;
2221 if (y0+y1 > cb->y0) {
2222 if (coeff[-tileComp->cbW].flags & jpxCoeffSignificant) {
2224 vertSign += (coeff[-tileComp->cbW].flags & jpxCoeffSign)
2228 if (y0+y1 < cb->y1 - 1) {
2229 if (coeff[tileComp->cbW].flags & jpxCoeffSignificant) {
2231 vertSign += (coeff[tileComp->cbW].flags & jpxCoeffSign)
2235 cx = sigPropContext[horiz][vert][diag][res == 0 ? 1 : sb];
2236 if (arithDecoder->decodeBit(cx, cb->stats)) {
2237 coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef;
2238 coeff->mag = (coeff->mag << 1) | 1;
2239 cx = signContext[horizSign][vertSign][0];
2240 xorBit = signContext[horizSign][vertSign][1];
2241 if (arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) {
2242 coeff->flags |= jpxCoeffSign;
2247 coeff->flags &= ~jpxCoeffTouched;
2252 cb->nextPass = jpxPassSigProp;
2257 delete arithDecoder;
2261 // Inverse quantization, and wavelet transform (IDWT). This also does
2262 // the initial shift to convert to fixed point format.
2263 void JPXStream::inverseTransform(JPXTileComp *tileComp) {
2264 JPXResLevel *resLevel;
2265 JPXPrecinct *precinct;
2266 JPXSubband *subband;
2268 JPXCoeff *coeff0, *coeff;
2269 Guint qStyle, guard, eps, shift, shift2;
2273 Guint nx0, ny0, nx1, ny1;
2274 Guint r, cbX, cbY, x, y;
2276 //----- (NL)LL subband (resolution level 0)
2278 resLevel = &tileComp->resLevels[0];
2279 precinct = &resLevel->precincts[0];
2280 subband = &precinct->subbands[0];
2282 // i-quant parameters
2283 qStyle = tileComp->quantStyle & 0x1f;
2284 guard = (tileComp->quantStyle >> 5) & 7;
2286 eps = (tileComp->quantSteps[0] >> 3) & 0x1f;
2287 shift = guard + eps - 1;
2288 mu = 0; // make gcc happy
2290 shift = guard - 1 + tileComp->prec;
2291 mu = (double)(0x800 + (tileComp->quantSteps[0] & 0x7ff)) / 2048.0;
2293 if (tileComp->transform == 0) {
2297 // copy (NL)LL into the upper-left corner of the data array, doing
2298 // the fixed point adjustment and dequantization along the way
2300 for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
2301 for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
2302 for (y = cb->y0, coeff0 = cb->coeffs;
2304 ++y, coeff0 += tileComp->cbW) {
2305 dataPtr = &tileComp->data[(y - subband->y0)
2306 * (tileComp->x1 - tileComp->x0)
2307 + (cb->x0 - subband->x0)];
2308 for (x = cb->x0, coeff = coeff0; x < cb->x1; ++x, ++coeff) {
2309 val = (int)coeff->mag;
2311 shift2 = shift - (cb->nZeroBitPlanes + coeff->len);
2313 val = (val << shift2) + (1 << (shift2 - 1));
2318 if (tileComp->transform == 0) {
2319 val &= -1 << fracBits;
2322 val = (int)((double)val * mu);
2324 if (coeff->flags & jpxCoeffSign) {
2335 //----- IDWT for each level
2337 for (r = 1; r <= tileComp->nDecompLevels; ++r) {
2338 resLevel = &tileComp->resLevels[r];
2340 // (n)LL is already in the upper-left corner of the
2341 // tile-component data array -- interleave with (n)HL/LH/HH
2342 // and inverse transform to get (n-1)LL, which will be stored
2343 // in the upper-left corner of the tile-component data array
2344 if (r == tileComp->nDecompLevels) {
2350 nx0 = tileComp->resLevels[r+1].x0;
2351 ny0 = tileComp->resLevels[r+1].y0;
2352 nx1 = tileComp->resLevels[r+1].x1;
2353 ny1 = tileComp->resLevels[r+1].y1;
2355 inverseTransformLevel(tileComp, r, resLevel, nx0, ny0, nx1, ny1);
2359 // Do one level of the inverse transform:
2360 // - take (n)LL from the tile-component data array
2361 // - take (n)HL/LH/HH from <resLevel>
2362 // - leave the resulting (n-1)LL in the tile-component data array
2363 void JPXStream::inverseTransformLevel(JPXTileComp *tileComp,
2364 Guint r, JPXResLevel *resLevel,
2365 Guint nx0, Guint ny0,
2366 Guint nx1, Guint ny1) {
2367 JPXPrecinct *precinct;
2368 JPXSubband *subband;
2370 JPXCoeff *coeff0, *coeff;
2371 Guint qStyle, guard, eps, shift, shift2, t;
2376 Guint x, y, sb, cbX, cbY;
2382 for (yy = resLevel->y1 - 1; yy >= (int)resLevel->y0; --yy) {
2383 for (xx = resLevel->x1 - 1; xx >= (int)resLevel->x0; --xx) {
2384 tileComp->data[(2 * yy - ny0) * (tileComp->x1 - tileComp->x0)
2386 tileComp->data[(yy - resLevel->y0) * (tileComp->x1 - tileComp->x0)
2387 + (xx - resLevel->x0)];
2391 // i-quant parameters
2392 qStyle = tileComp->quantStyle & 0x1f;
2393 guard = (tileComp->quantStyle >> 5) & 7;
2395 // interleave HL/LH/HH
2396 precinct = &resLevel->precincts[0];
2397 for (sb = 0; sb < 3; ++sb) {
2399 // i-quant parameters
2401 eps = (tileComp->quantSteps[3*r - 2 + sb] >> 3) & 0x1f;
2402 shift = guard + eps - 1;
2403 mu = 0; // make gcc happy
2405 shift = guard + tileComp->prec;
2409 t = tileComp->quantSteps[qStyle == 1 ? 0 : (3*r - 2 + sb)];
2410 mu = (double)(0x800 + (t & 0x7ff)) / 2048.0;
2412 if (tileComp->transform == 0) {
2416 // copy the subband coefficients into the data array, doing the
2417 // fixed point adjustment and dequantization along the way
2418 xo = (sb & 1) ? 0 : 1;
2419 yo = (sb > 0) ? 1 : 0;
2420 subband = &precinct->subbands[sb];
2422 for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
2423 for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
2424 for (y = cb->y0, coeff0 = cb->coeffs;
2426 ++y, coeff0 += tileComp->cbW) {
2427 dataPtr = &tileComp->data[(2 * y + yo - ny0)
2428 * (tileComp->x1 - tileComp->x0)
2429 + (2 * cb->x0 + xo - nx0)];
2430 for (x = cb->x0, coeff = coeff0; x < cb->x1; ++x, ++coeff) {
2431 val = (int)coeff->mag;
2433 shift2 = shift - (cb->nZeroBitPlanes + coeff->len);
2435 val = (val << shift2) + (1 << (shift2 - 1));
2440 if (tileComp->transform == 0) {
2441 val &= -1 << fracBits;
2444 val = (int)((double)val * mu);
2446 if (coeff->flags & jpxCoeffSign) {
2459 //----- horizontal (row) transforms
2460 dataPtr = tileComp->data;
2461 for (y = 0; y < ny1 - ny0; ++y) {
2462 inverseTransform1D(tileComp, dataPtr, 1, nx0, nx1);
2463 dataPtr += tileComp->x1 - tileComp->x0;
2466 //----- vertical (column) transforms
2467 dataPtr = tileComp->data;
2468 for (x = 0; x < nx1 - nx0; ++x) {
2469 inverseTransform1D(tileComp, dataPtr,
2470 tileComp->x1 - tileComp->x0, ny0, ny1);
2475 void JPXStream::inverseTransform1D(JPXTileComp *tileComp,
2476 int *data, Guint stride,
2477 Guint i0, Guint i1) {
2479 Guint offset, end, i;
2481 //----- special case for length = 1
2489 // choose an offset: this makes even buf[] indexes correspond to
2490 // odd values of i, and vice versa
2491 offset = 3 + (i0 & 1);
2492 end = offset + i1 - i0;
2495 buf = tileComp->buf;
2496 for (i = 0; i < i1 - i0; ++i) {
2497 buf[offset + i] = data[i * stride];
2500 //----- extend right
2501 buf[end] = buf[end - 2];
2503 buf[end+1] = buf[offset + 1];
2504 buf[end+2] = buf[offset];
2505 buf[end+3] = buf[offset + 1];
2507 buf[end+1] = buf[end - 3];
2509 buf[end+2] = buf[offset + 1];
2510 buf[end+3] = buf[offset + 2];
2512 buf[end+2] = buf[end - 4];
2514 buf[end+3] = buf[offset + 1];
2516 buf[end+3] = buf[end - 5];
2522 buf[offset - 1] = buf[offset + 1];
2523 buf[offset - 2] = buf[offset + 2];
2524 buf[offset - 3] = buf[offset + 3];
2526 buf[0] = buf[offset + 4];
2529 //----- 9-7 irreversible filter
2531 if (tileComp->transform == 0) {
2533 for (i = 1; i <= end + 2; i += 2) {
2534 buf[i] = (int)(idwtKappa * buf[i]);
2537 for (i = 0; i <= end + 3; i += 2) {
2538 buf[i] = (int)(idwtIKappa * buf[i]);
2541 for (i = 1; i <= end + 2; i += 2) {
2542 buf[i] = (int)(buf[i] - idwtDelta * (buf[i-1] + buf[i+1]));
2545 for (i = 2; i <= end + 1; i += 2) {
2546 buf[i] = (int)(buf[i] - idwtGamma * (buf[i-1] + buf[i+1]));
2549 for (i = 3; i <= end; i += 2) {
2550 buf[i] = (int)(buf[i] - idwtBeta * (buf[i-1] + buf[i+1]));
2553 for (i = 4; i <= end - 1; i += 2) {
2554 buf[i] = (int)(buf[i] - idwtAlpha * (buf[i-1] + buf[i+1]));
2557 //----- 5-3 reversible filter
2561 for (i = 3; i <= end; i += 2) {
2562 buf[i] -= (buf[i-1] + buf[i+1] + 2) >> 2;
2565 for (i = 4; i < end; i += 2) {
2566 buf[i] += (buf[i-1] + buf[i+1]) >> 1;
2571 for (i = 0; i < i1 - i0; ++i) {
2572 data[i * stride] = buf[offset + i];
2577 // Inverse multi-component transform and DC level shift. This also
2578 // converts fixed point samples back to integers.
2579 GBool JPXStream::inverseMultiCompAndDC(JPXTile *tile) {
2580 JPXTileComp *tileComp;
2581 int coeff, d0, d1, d2, minVal, maxVal, zeroVal;
2583 Guint j, comp, x, y;
2585 //----- inverse multi-component transform
2587 if (tile->multiComp == 1) {
2588 if (img.nComps < 3 ||
2589 tile->tileComps[0].hSep != tile->tileComps[1].hSep ||
2590 tile->tileComps[0].vSep != tile->tileComps[1].vSep ||
2591 tile->tileComps[1].hSep != tile->tileComps[2].hSep ||
2592 tile->tileComps[1].vSep != tile->tileComps[2].vSep) {
2596 // inverse irreversible multiple component transform
2597 if (tile->tileComps[0].transform == 0) {
2599 for (y = 0; y < tile->tileComps[0].y1 - tile->tileComps[0].y0; ++y) {
2600 for (x = 0; x < tile->tileComps[0].x1 - tile->tileComps[0].x0; ++x) {
2601 d0 = tile->tileComps[0].data[j];
2602 d1 = tile->tileComps[1].data[j];
2603 d2 = tile->tileComps[2].data[j];
2604 tile->tileComps[0].data[j] = (int)(d0 + 1.402 * d2 + 0.5);
2605 tile->tileComps[1].data[j] =
2606 (int)(d0 - 0.34413 * d1 - 0.71414 * d2 + 0.5);
2607 tile->tileComps[2].data[j] = (int)(d0 + 1.772 * d1 + 0.5);
2612 // inverse reversible multiple component transform
2615 for (y = 0; y < tile->tileComps[0].y1 - tile->tileComps[0].y0; ++y) {
2616 for (x = 0; x < tile->tileComps[0].x1 - tile->tileComps[0].x0; ++x) {
2617 d0 = tile->tileComps[0].data[j];
2618 d1 = tile->tileComps[1].data[j];
2619 d2 = tile->tileComps[2].data[j];
2620 tile->tileComps[0].data[j] = d0 - ((d2 + d1) >> 2);
2621 tile->tileComps[1].data[j] = d2 - d1;
2622 tile->tileComps[2].data[j] = d0 - d1;
2629 //----- DC level shift
2630 for (comp = 0; comp < img.nComps; ++comp) {
2631 tileComp = &tile->tileComps[comp];
2634 if (tileComp->sgned) {
2635 minVal = -(1 << (tileComp->prec - 1));
2636 maxVal = (1 << (tileComp->prec - 1)) - 1;
2637 dataPtr = tileComp->data;
2638 for (y = 0; y < tileComp->y1 - tileComp->y0; ++y) {
2639 for (x = 0; x < tileComp->x1 - tileComp->x0; ++x) {
2641 if (tileComp->transform == 0) {
2644 if (coeff < minVal) {
2646 } else if (coeff > maxVal) {
2653 // unsigned: inverse DC level shift and clip
2655 maxVal = (1 << tileComp->prec) - 1;
2656 zeroVal = 1 << (tileComp->prec - 1);
2657 dataPtr = tileComp->data;
2658 for (y = 0; y < tileComp->y1 - tileComp->y0; ++y) {
2659 for (x = 0; x < tileComp->x1 - tileComp->x0; ++x) {
2661 if (tileComp->transform == 0) {
2667 } else if (coeff > maxVal) {
2679 GBool JPXStream::readBoxHdr(Guint *boxType, Guint *boxLen, Guint *dataLen) {
2682 if (!readULong(&len) ||
2683 !readULong(boxType)) {
2687 if (!readULong(&lenH) || !readULong(&len)) {
2691 error(getPos(), "JPX stream contains a box larger than 2^32 bytes");
2695 *dataLen = len - 16;
2696 } else if (len == 0) {
2706 int JPXStream::readMarkerHdr(int *segType, Guint *segLen) {
2711 if ((c = str->getChar()) == EOF) {
2714 } while (c != 0xff);
2716 if ((c = str->getChar()) == EOF) {
2719 } while (c == 0xff);
2720 } while (c == 0x00);
2722 if ((c >= 0x30 && c <= 0x3f) ||
2723 c == 0x4f || c == 0x92 || c == 0x93 || c == 0xd9) {
2727 return readUWord(segLen);
2730 GBool JPXStream::readUByte(Guint *x) {
2733 if ((c0 = str->getChar()) == EOF) {
2740 GBool JPXStream::readByte(int *x) {
2743 if ((c0 = str->getChar()) == EOF) {
2753 GBool JPXStream::readUWord(Guint *x) {
2756 if ((c0 = str->getChar()) == EOF ||
2757 (c1 = str->getChar()) == EOF) {
2760 *x = (Guint)((c0 << 8) | c1);
2764 GBool JPXStream::readULong(Guint *x) {
2767 if ((c0 = str->getChar()) == EOF ||
2768 (c1 = str->getChar()) == EOF ||
2769 (c2 = str->getChar()) == EOF ||
2770 (c3 = str->getChar()) == EOF) {
2773 *x = (Guint)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
2777 GBool JPXStream::readNBytes(int nBytes, GBool signd, int *x) {
2781 for (i = 0; i < nBytes; ++i) {
2782 if ((c = str->getChar()) == EOF) {
2788 if (y & (1 << (8 * nBytes - 1))) {
2789 y |= -1 << (8 * nBytes);
2796 GBool JPXStream::readBits(int nBits, Guint *x) {
2799 while (bitBufLen < nBits) {
2800 if ((c = str->getChar()) == EOF) {
2805 bitBuf = (bitBuf << 7) | (c & 0x7f);
2808 bitBuf = (bitBuf << 8) | (c & 0xff);
2811 bitBufSkip = c == 0xff;
2813 *x = (bitBuf >> (bitBufLen - nBits)) & ((1 << nBits) - 1);
2818 void JPXStream::clearBitBuf() {
2820 bitBufSkip = gFalse;