1 //========================================================================
5 // Copyright 2002-2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
18 #include "JArithmeticDecoder.h"
19 #include "JPXStream.h"
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,
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
43 //------------------------------------------------------------------------
45 // number of contexts for the arithmetic decoder
46 #define jpxNContexts 19
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
54 //------------------------------------------------------------------------
56 #define jpxPassSigProp 0
57 #define jpxPassMagRef 1
58 #define jpxPassCleanup 2
60 //------------------------------------------------------------------------
62 // arithmetic decoder context for the significance propagation and
64 // [horiz][vert][diag][subband]
65 // where subband = 0 for HL
68 static 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
116 // arithmetic decoder context and xor bit for the sign bit in the
117 // significance propagation pass:
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
122 static 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
150 //------------------------------------------------------------------------
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)
160 // number of bits to the right of the decimal point for the fixed
161 // point arithmetic used in the IDWT
164 //------------------------------------------------------------------------
167 #define jpxFloorDiv(x, y) ((x) / (y))
170 #define jpxFloorDivPow2(x, y) ((x) >> (y))
173 #define jpxCeilDiv(x, y) (((x) + (y) - 1) / (y))
176 #define jpxCeilDivPow2(x, y) (((x) + (1 << (y)) - 1) >> (y))
178 //------------------------------------------------------------------------
180 #if 1 //----- disable coverage tracking
184 #else //----- enable coverage tracking
199 JPXCover::JPXCover(int sizeA
) {
202 data
= (int *)gmallocn(size
, sizeof(int));
203 memset(data
, 0, size
* sizeof(int));
206 JPXCover::~JPXCover() {
209 printf("JPX coverage:\n");
210 for (i
= 0; i
<= used
; ++i
) {
211 printf(" %4d: %8d\n", i
, data
[i
]);
216 void JPXCover::incr(int idx
) {
225 JPXCover
jpxCover(150);
227 #define cover(idx) jpxCover.incr(idx)
229 #endif //----- coverage tracking
231 //------------------------------------------------------------------------
233 JPXStream::JPXStream(Stream
*strA
):
240 havePalette
= gFalse
;
241 haveCompMap
= gFalse
;
242 haveChannelDefn
= gFalse
;
251 JPXStream::~JPXStream() {
256 void JPXStream::reset() {
261 // readBoxes reported an error, so we go immediately to EOF
269 void JPXStream::close() {
271 JPXTileComp
*tileComp
;
272 JPXResLevel
*resLevel
;
273 JPXPrecinct
*precinct
;
276 Guint comp
, i
, k
, r
, pre
, sb
;
283 havePalette
= gFalse
;
288 gfree(compMap
.pComp
);
289 haveCompMap
= gFalse
;
291 if (haveChannelDefn
) {
292 gfree(channelDefn
.idx
);
293 gfree(channelDefn
.type
);
294 gfree(channelDefn
.assoc
);
295 haveChannelDefn
= gFalse
;
299 for (i
= 0; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
300 tile
= &img
.tiles
[i
];
301 if (tile
->tileComps
) {
302 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
303 tileComp
= &tile
->tileComps
[comp
];
304 gfree(tileComp
->quantSteps
);
305 gfree(tileComp
->data
);
306 gfree(tileComp
->buf
);
307 if (tileComp
->resLevels
) {
308 for (r
= 0; r
<= tileComp
->nDecompLevels
; ++r
) {
309 resLevel
= &tileComp
->resLevels
[r
];
310 if (resLevel
->precincts
) {
311 for (pre
= 0; pre
< 1; ++pre
) {
312 precinct
= &resLevel
->precincts
[pre
];
313 if (precinct
->subbands
) {
314 for (sb
= 0; sb
< (Guint
)(r
== 0 ? 1 : 3); ++sb
) {
315 subband
= &precinct
->subbands
[sb
];
316 gfree(subband
->inclusion
);
317 gfree(subband
->zeroBitPlane
);
319 for (k
= 0; k
< subband
->nXCBs
* subband
->nYCBs
; ++k
) {
320 cb
= &subband
->cbs
[k
];
322 if (cb
->arithDecoder
) {
323 delete cb
->arithDecoder
;
332 gfree(precinct
->subbands
);
335 gfree(img
.tiles
[i
].tileComps
[comp
].resLevels
[r
].precincts
);
338 gfree(img
.tiles
[i
].tileComps
[comp
].resLevels
);
341 gfree(img
.tiles
[i
].tileComps
);
347 FilterStream::close();
350 int JPXStream::getChar() {
353 if (readBufLen
< 8) {
356 if (readBufLen
== 8) {
359 } else if (readBufLen
> 8) {
360 c
= (readBuf
>> (readBufLen
- 8)) & 0xff;
362 } else if (readBufLen
== 0) {
365 c
= (readBuf
<< (8 - readBufLen
)) & 0xff;
371 int JPXStream::lookChar() {
374 if (readBufLen
< 8) {
377 if (readBufLen
== 8) {
379 } else if (readBufLen
> 8) {
380 c
= (readBuf
>> (readBufLen
- 8)) & 0xff;
381 } else if (readBufLen
== 0) {
384 c
= (readBuf
<< (8 - readBufLen
)) & 0xff;
389 void JPXStream::fillReadBuf() {
390 JPXTileComp
*tileComp
;
391 Guint tileIdx
, tx
, ty
;
395 if (curY
>= img
.ySize
) {
398 tileIdx
= ((curY
- img
.yTileOffset
) / img
.yTileSize
) * img
.nXTiles
399 + (curX
- img
.xTileOffset
) / img
.xTileSize
;
400 #if 1 //~ ignore the palette, assume the PDF ColorSpace xObject is valid
401 tileComp
= &img
.tiles
[tileIdx
].tileComps
[curComp
];
403 tileComp
= &img
.tiles
[tileIdx
].tileComps
[havePalette
? 0 : curComp
];
405 tx
= jpxCeilDiv((curX
- img
.xTileOffset
) % img
.xTileSize
, tileComp
->hSep
);
406 ty
= jpxCeilDiv((curY
- img
.yTileOffset
) % img
.yTileSize
, tileComp
->vSep
);
407 pix
= (int)tileComp
->data
[ty
* (tileComp
->x1
- tileComp
->x0
) + tx
];
408 pixBits
= tileComp
->prec
;
409 #if 1 //~ ignore the palette, assume the PDF ColorSpace xObject is valid
410 if (++curComp
== img
.nComps
) {
413 if (pix
>= 0 && pix
< palette
.nEntries
) {
414 pix
= palette
.c
[pix
* palette
.nComps
+ curComp
];
417 pixBits
= palette
.bpc
[curComp
];
419 if (++curComp
== (Guint
)(havePalette
? palette
.nComps
: img
.nComps
)) {
422 if (++curX
== img
.xSize
) {
428 readBuf
= (readBuf
<< 8) | (pix
& 0xff);
430 readBuf
= (readBuf
<< pixBits
) | (pix
& ((1 << pixBits
) - 1));
432 readBufLen
+= pixBits
;
433 } while (readBufLen
< 8);
436 GString
*JPXStream::getPSFilter(int psLevel
, char *indent
) {
440 GBool
JPXStream::isBinary(GBool last
) {
441 return str
->isBinary(gTrue
);
444 void JPXStream::getImageParams(int *bitsPerComponent
,
445 StreamColorSpaceMode
*csMode
) {
446 Guint boxType
, boxLen
, dataLen
, csEnum
;
447 Guint bpc1
, dummy
, i
;
448 int csMeth
, csPrec
, csPrec1
, dummy2
;
449 StreamColorSpaceMode csMode1
;
450 GBool haveBPC
, haveCSMode
;
452 csPrec
= 0; // make gcc happy
453 haveBPC
= haveCSMode
= gFalse
;
455 if (str
->lookChar() == 0xff) {
456 getImageParams2(bitsPerComponent
, csMode
);
458 while (readBoxHdr(&boxType
, &boxLen
, &dataLen
)) {
459 if (boxType
== 0x6a703268) { // JP2 header
462 } else if (boxType
== 0x69686472) { // image header
464 if (readULong(&dummy
) &&
471 *bitsPerComponent
= bpc1
+ 1;
474 } else if (boxType
== 0x636F6C72) { // color specification
476 if (readByte(&csMeth
) &&
477 readByte(&csPrec1
) &&
480 if (readULong(&csEnum
)) {
481 csMode1
= streamCSNone
;
482 if (csEnum
== jpxCSBiLevel
||
483 csEnum
== jpxCSGrayscale
) {
484 csMode1
= streamCSDeviceGray
;
485 } else if (csEnum
== jpxCSCMYK
) {
486 csMode1
= streamCSDeviceCMYK
;
487 } else if (csEnum
== jpxCSsRGB
||
488 csEnum
== jpxCSCISesRGB
||
489 csEnum
== jpxCSROMMRGB
) {
490 csMode1
= streamCSDeviceRGB
;
492 if (csMode1
!= streamCSNone
&&
493 (!haveCSMode
|| csPrec1
> csPrec
)) {
498 for (i
= 0; i
< dataLen
- 7; ++i
) {
503 for (i
= 0; i
< dataLen
- 3; ++i
) {
508 } else if (boxType
== 0x6A703263) { // codestream
510 if (!(haveBPC
&& haveCSMode
)) {
511 getImageParams2(bitsPerComponent
, csMode
);
516 for (i
= 0; i
< dataLen
; ++i
) {
525 // Get image parameters from the codestream.
526 void JPXStream::getImageParams2(int *bitsPerComponent
,
527 StreamColorSpaceMode
*csMode
) {
529 Guint segLen
, nComps1
, bpc1
, dummy
, i
;
531 while (readMarkerHdr(&segType
, &segLen
)) {
532 if (segType
== 0x51) { // SIZ - image and tile size
534 if (readUWord(&dummy
) &&
543 readUWord(&nComps1
) &&
545 *bitsPerComponent
= (bpc1
& 0x7f) + 1;
546 // if there's no color space info, take a guess
548 *csMode
= streamCSDeviceGray
;
549 } else if (nComps1
== 3) {
550 *csMode
= streamCSDeviceRGB
;
551 } else if (nComps1
== 4) {
552 *csMode
= streamCSDeviceCMYK
;
559 for (i
= 0; i
< segLen
- 2; ++i
) {
567 GBool
JPXStream::readBoxes() {
568 Guint boxType
, boxLen
, dataLen
;
569 Guint bpc1
, compression
, unknownColorspace
, ipr
;
574 // check for a naked JPEG 2000 codestream (without the JP2/JPX
575 // wrapper) -- this appears to be a violation of the PDF spec, but
577 if (str
->lookChar() == 0xff) {
579 error(getPos(), "Naked JPEG 2000 codestream, missing JP2/JPX wrapper");
582 bpc
= (Guint
*)gmallocn(nComps
, sizeof(Guint
));
583 for (i
= 0; i
< nComps
; ++i
) {
584 bpc
[i
] = img
.tiles
[0].tileComps
[i
].prec
;
586 width
= img
.xSize
- img
.xOffset
;
587 height
= img
.ySize
- img
.yOffset
;
591 while (readBoxHdr(&boxType
, &boxLen
, &dataLen
)) {
593 case 0x6a703268: // JP2 header
594 // this is a grouping box ('superbox') which has no real
595 // contents and doesn't appear to be used consistently, i.e.,
596 // some things which should be subboxes of the JP2 header box
597 // show up outside of it - so we simply ignore the JP2 header
601 case 0x69686472: // image header
603 if (!readULong(&height
) ||
604 !readULong(&width
) ||
605 !readUWord(&nComps
) ||
607 !readUByte(&compression
) ||
608 !readUByte(&unknownColorspace
) ||
610 error(getPos(), "Unexpected EOF in JPX stream");
613 if (compression
!= 7) {
614 error(getPos(), "Unknown compression type in JPX stream");
617 bpc
= (Guint
*)gmallocn(nComps
, sizeof(Guint
));
618 for (i
= 0; i
< nComps
; ++i
) {
623 case 0x62706363: // bits per component
626 error(getPos(), "Found bits per component box before image header box in JPX stream");
629 if (dataLen
!= nComps
) {
630 error(getPos(), "Invalid bits per component box in JPX stream");
633 for (i
= 0; i
< nComps
; ++i
) {
634 if (!readUByte(&bpc
[i
])) {
635 error(getPos(), "Unexpected EOF in JPX stream");
640 case 0x636F6C72: // color specification
642 if (!readColorSpecBox(dataLen
)) {
646 case 0x70636c72: // palette
648 if (!readUWord(&palette
.nEntries
) ||
649 !readUByte(&palette
.nComps
)) {
650 error(getPos(), "Unexpected EOF in JPX stream");
653 palette
.bpc
= (Guint
*)gmallocn(palette
.nComps
, sizeof(Guint
));
655 (int *)gmallocn(palette
.nEntries
* palette
.nComps
, sizeof(int));
656 for (i
= 0; i
< palette
.nComps
; ++i
) {
657 if (!readUByte(&palette
.bpc
[i
])) {
658 error(getPos(), "Unexpected EOF in JPX stream");
663 for (i
= 0; i
< palette
.nEntries
; ++i
) {
664 for (j
= 0; j
< palette
.nComps
; ++j
) {
665 if (!readNBytes(((palette
.bpc
[j
] & 0x7f) + 7) >> 3,
666 (palette
.bpc
[j
] & 0x80) ? gTrue
: gFalse
,
667 &palette
.c
[i
* palette
.nComps
+ j
])) {
668 error(getPos(), "Unexpected EOF in JPX stream");
675 case 0x636d6170: // component mapping
677 compMap
.nChannels
= dataLen
/ 4;
678 compMap
.comp
= (Guint
*)gmallocn(compMap
.nChannels
, sizeof(Guint
));
679 compMap
.type
= (Guint
*)gmallocn(compMap
.nChannels
, sizeof(Guint
));
680 compMap
.pComp
= (Guint
*)gmallocn(compMap
.nChannels
, sizeof(Guint
));
681 for (i
= 0; i
< compMap
.nChannels
; ++i
) {
682 if (!readUWord(&compMap
.comp
[i
]) ||
683 !readUByte(&compMap
.type
[i
]) ||
684 !readUByte(&compMap
.pComp
[i
])) {
685 error(getPos(), "Unexpected EOF in JPX stream");
691 case 0x63646566: // channel definition
693 if (!readUWord(&channelDefn
.nChannels
)) {
694 error(getPos(), "Unexpected EOF in JPX stream");
698 (Guint
*)gmallocn(channelDefn
.nChannels
, sizeof(Guint
));
700 (Guint
*)gmallocn(channelDefn
.nChannels
, sizeof(Guint
));
702 (Guint
*)gmallocn(channelDefn
.nChannels
, sizeof(Guint
));
703 for (i
= 0; i
< channelDefn
.nChannels
; ++i
) {
704 if (!readUWord(&channelDefn
.idx
[i
]) ||
705 !readUWord(&channelDefn
.type
[i
]) ||
706 !readUWord(&channelDefn
.assoc
[i
])) {
707 error(getPos(), "Unexpected EOF in JPX stream");
711 haveChannelDefn
= gTrue
;
713 case 0x6A703263: // contiguous codestream
716 error(getPos(), "JPX stream is missing the image header box");
719 error(getPos(), "JPX stream has no supported color spec");
721 if (!readCodestream(dataLen
)) {
727 for (i
= 0; i
< dataLen
; ++i
) {
728 if (str
->getChar() == EOF
) {
729 error(getPos(), "Unexpected EOF in JPX stream");
739 GBool
JPXStream::readColorSpecBox(Guint dataLen
) {
741 Guint csApprox
, csEnum
;
746 if (!readUByte(&newCS
.meth
) ||
747 !readByte(&newCS
.prec
) ||
748 !readUByte(&csApprox
)) {
751 switch (newCS
.meth
) {
752 case 1: // enumerated colorspace
754 if (!readULong(&csEnum
)) {
757 newCS
.enumerated
.type
= (JPXColorSpaceType
)csEnum
;
758 switch (newCS
.enumerated
.type
) {
784 if (dataLen
== 7 + 7*4) {
785 if (!readULong(&newCS
.enumerated
.cieLab
.rl
) ||
786 !readULong(&newCS
.enumerated
.cieLab
.ol
) ||
787 !readULong(&newCS
.enumerated
.cieLab
.ra
) ||
788 !readULong(&newCS
.enumerated
.cieLab
.oa
) ||
789 !readULong(&newCS
.enumerated
.cieLab
.rb
) ||
790 !readULong(&newCS
.enumerated
.cieLab
.ob
) ||
791 !readULong(&newCS
.enumerated
.cieLab
.il
)) {
794 } else if (dataLen
== 7) {
795 //~ this assumes the 8-bit case
797 newCS
.enumerated
.cieLab
.rl
= 100;
798 newCS
.enumerated
.cieLab
.ol
= 0;
799 newCS
.enumerated
.cieLab
.ra
= 255;
800 newCS
.enumerated
.cieLab
.oa
= 128;
801 newCS
.enumerated
.cieLab
.rb
= 255;
802 newCS
.enumerated
.cieLab
.ob
= 96;
803 newCS
.enumerated
.cieLab
.il
= 0x00443530;
819 // not allowed in PDF
840 case 2: // restricted ICC profile
841 case 3: // any ICC profile (JPX)
842 case 4: // vendor color (JPX)
844 for (i
= 0; i
< dataLen
- 3; ++i
) {
845 if (str
->getChar() == EOF
) {
852 if (ok
&& (!haveCS
|| newCS
.prec
> cs
.prec
)) {
860 error(getPos(), "Error in JPX color spec");
864 GBool
JPXStream::readCodestream(Guint len
) {
866 JPXTileComp
*tileComp
;
868 GBool haveSIZ
, haveCOD
, haveQCD
, haveSOT
;
869 Guint precinctSize
, style
;
870 Guint segLen
, capabilities
, comp
, i
, j
, r
;
873 haveSIZ
= haveCOD
= haveQCD
= haveSOT
= gFalse
;
875 if (!readMarkerHdr(&segType
, &segLen
)) {
876 error(getPos(), "Error in JPX codestream");
880 case 0x4f: // SOC - start of codestream
884 case 0x51: // SIZ - image and tile size
886 if (!readUWord(&capabilities
) ||
887 !readULong(&img
.xSize
) ||
888 !readULong(&img
.ySize
) ||
889 !readULong(&img
.xOffset
) ||
890 !readULong(&img
.yOffset
) ||
891 !readULong(&img
.xTileSize
) ||
892 !readULong(&img
.yTileSize
) ||
893 !readULong(&img
.xTileOffset
) ||
894 !readULong(&img
.yTileOffset
) ||
895 !readUWord(&img
.nComps
)) {
896 error(getPos(), "Error in JPX SIZ marker segment");
899 if (haveImgHdr
&& img
.nComps
!= nComps
) {
900 error(getPos(), "Different number of components in JPX SIZ marker segment");
903 img
.nXTiles
= (img
.xSize
- img
.xTileOffset
+ img
.xTileSize
- 1)
905 img
.nYTiles
= (img
.ySize
- img
.yTileOffset
+ img
.yTileSize
- 1)
907 // check for overflow before allocating memory
908 if (img
.nXTiles
<= 0 || img
.nYTiles
<= 0 ||
909 img
.nXTiles
>= INT_MAX
/ img
.nYTiles
) {
910 error(getPos(), "Bad tile count in JPX SIZ marker segment");
913 img
.tiles
= (JPXTile
*)gmallocn(img
.nXTiles
* img
.nYTiles
,
915 for (i
= 0; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
916 img
.tiles
[i
].tileComps
= (JPXTileComp
*)gmallocn(img
.nComps
,
917 sizeof(JPXTileComp
));
918 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
919 img
.tiles
[i
].tileComps
[comp
].quantSteps
= NULL
;
920 img
.tiles
[i
].tileComps
[comp
].data
= NULL
;
921 img
.tiles
[i
].tileComps
[comp
].buf
= NULL
;
922 img
.tiles
[i
].tileComps
[comp
].resLevels
= NULL
;
925 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
926 if (!readUByte(&img
.tiles
[0].tileComps
[comp
].prec
) ||
927 !readUByte(&img
.tiles
[0].tileComps
[comp
].hSep
) ||
928 !readUByte(&img
.tiles
[0].tileComps
[comp
].vSep
)) {
929 error(getPos(), "Error in JPX SIZ marker segment");
932 img
.tiles
[0].tileComps
[comp
].sgned
=
933 (img
.tiles
[0].tileComps
[comp
].prec
& 0x80) ? gTrue
: gFalse
;
934 img
.tiles
[0].tileComps
[comp
].prec
=
935 (img
.tiles
[0].tileComps
[comp
].prec
& 0x7f) + 1;
936 for (i
= 1; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
937 img
.tiles
[i
].tileComps
[comp
] = img
.tiles
[0].tileComps
[comp
];
942 case 0x52: // COD - coding style default
944 if (!readUByte(&img
.tiles
[0].tileComps
[0].style
) ||
945 !readUByte(&img
.tiles
[0].progOrder
) ||
946 !readUWord(&img
.tiles
[0].nLayers
) ||
947 !readUByte(&img
.tiles
[0].multiComp
) ||
948 !readUByte(&img
.tiles
[0].tileComps
[0].nDecompLevels
) ||
949 !readUByte(&img
.tiles
[0].tileComps
[0].codeBlockW
) ||
950 !readUByte(&img
.tiles
[0].tileComps
[0].codeBlockH
) ||
951 !readUByte(&img
.tiles
[0].tileComps
[0].codeBlockStyle
) ||
952 !readUByte(&img
.tiles
[0].tileComps
[0].transform
)) {
953 error(getPos(), "Error in JPX COD marker segment");
956 img
.tiles
[0].tileComps
[0].codeBlockW
+= 2;
957 img
.tiles
[0].tileComps
[0].codeBlockH
+= 2;
958 for (i
= 0; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
960 img
.tiles
[i
].progOrder
= img
.tiles
[0].progOrder
;
961 img
.tiles
[i
].nLayers
= img
.tiles
[0].nLayers
;
962 img
.tiles
[i
].multiComp
= img
.tiles
[0].multiComp
;
964 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
965 if (!(i
== 0 && comp
== 0)) {
966 img
.tiles
[i
].tileComps
[comp
].style
=
967 img
.tiles
[0].tileComps
[0].style
;
968 img
.tiles
[i
].tileComps
[comp
].nDecompLevels
=
969 img
.tiles
[0].tileComps
[0].nDecompLevels
;
970 img
.tiles
[i
].tileComps
[comp
].codeBlockW
=
971 img
.tiles
[0].tileComps
[0].codeBlockW
;
972 img
.tiles
[i
].tileComps
[comp
].codeBlockH
=
973 img
.tiles
[0].tileComps
[0].codeBlockH
;
974 img
.tiles
[i
].tileComps
[comp
].codeBlockStyle
=
975 img
.tiles
[0].tileComps
[0].codeBlockStyle
;
976 img
.tiles
[i
].tileComps
[comp
].transform
=
977 img
.tiles
[0].tileComps
[0].transform
;
979 img
.tiles
[i
].tileComps
[comp
].resLevels
=
980 (JPXResLevel
*)gmallocn(
981 (img
.tiles
[i
].tileComps
[comp
].nDecompLevels
+ 1),
982 sizeof(JPXResLevel
));
983 for (r
= 0; r
<= img
.tiles
[i
].tileComps
[comp
].nDecompLevels
; ++r
) {
984 img
.tiles
[i
].tileComps
[comp
].resLevels
[r
].precincts
= NULL
;
988 for (r
= 0; r
<= img
.tiles
[0].tileComps
[0].nDecompLevels
; ++r
) {
989 if (img
.tiles
[0].tileComps
[0].style
& 0x01) {
991 if (!readUByte(&precinctSize
)) {
992 error(getPos(), "Error in JPX COD marker segment");
995 img
.tiles
[0].tileComps
[0].resLevels
[r
].precinctWidth
=
997 img
.tiles
[0].tileComps
[0].resLevels
[r
].precinctHeight
=
998 (precinctSize
>> 4) & 0x0f;
1000 img
.tiles
[0].tileComps
[0].resLevels
[r
].precinctWidth
= 15;
1001 img
.tiles
[0].tileComps
[0].resLevels
[r
].precinctHeight
= 15;
1004 for (i
= 0; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
1005 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
1006 if (!(i
== 0 && comp
== 0)) {
1007 for (r
= 0; r
<= img
.tiles
[i
].tileComps
[comp
].nDecompLevels
; ++r
) {
1008 img
.tiles
[i
].tileComps
[comp
].resLevels
[r
].precinctWidth
=
1009 img
.tiles
[0].tileComps
[0].resLevels
[r
].precinctWidth
;
1010 img
.tiles
[i
].tileComps
[comp
].resLevels
[r
].precinctHeight
=
1011 img
.tiles
[0].tileComps
[0].resLevels
[r
].precinctHeight
;
1018 case 0x53: // COC - coding style component
1021 error(getPos(), "JPX COC marker segment before COD segment");
1024 if ((img
.nComps
> 256 && !readUWord(&comp
)) ||
1025 (img
.nComps
<= 256 && !readUByte(&comp
)) ||
1026 comp
>= img
.nComps
||
1027 !readUByte(&style
) ||
1028 !readUByte(&img
.tiles
[0].tileComps
[comp
].nDecompLevels
) ||
1029 !readUByte(&img
.tiles
[0].tileComps
[comp
].codeBlockW
) ||
1030 !readUByte(&img
.tiles
[0].tileComps
[comp
].codeBlockH
) ||
1031 !readUByte(&img
.tiles
[0].tileComps
[comp
].codeBlockStyle
) ||
1032 !readUByte(&img
.tiles
[0].tileComps
[comp
].transform
)) {
1033 error(getPos(), "Error in JPX COC marker segment");
1036 img
.tiles
[0].tileComps
[comp
].style
=
1037 (img
.tiles
[0].tileComps
[comp
].style
& ~1) | (style
& 1);
1038 img
.tiles
[0].tileComps
[comp
].codeBlockW
+= 2;
1039 img
.tiles
[0].tileComps
[comp
].codeBlockH
+= 2;
1040 for (i
= 0; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
1042 img
.tiles
[i
].tileComps
[comp
].style
=
1043 img
.tiles
[0].tileComps
[comp
].style
;
1044 img
.tiles
[i
].tileComps
[comp
].nDecompLevels
=
1045 img
.tiles
[0].tileComps
[comp
].nDecompLevels
;
1046 img
.tiles
[i
].tileComps
[comp
].codeBlockW
=
1047 img
.tiles
[0].tileComps
[comp
].codeBlockW
;
1048 img
.tiles
[i
].tileComps
[comp
].codeBlockH
=
1049 img
.tiles
[0].tileComps
[comp
].codeBlockH
;
1050 img
.tiles
[i
].tileComps
[comp
].codeBlockStyle
=
1051 img
.tiles
[0].tileComps
[comp
].codeBlockStyle
;
1052 img
.tiles
[i
].tileComps
[comp
].transform
=
1053 img
.tiles
[0].tileComps
[comp
].transform
;
1055 img
.tiles
[i
].tileComps
[comp
].resLevels
=
1056 (JPXResLevel
*)greallocn(
1057 img
.tiles
[i
].tileComps
[comp
].resLevels
,
1058 (img
.tiles
[i
].tileComps
[comp
].nDecompLevels
+ 1),
1059 sizeof(JPXResLevel
));
1060 for (r
= 0; r
<= img
.tiles
[i
].tileComps
[comp
].nDecompLevels
; ++r
) {
1061 img
.tiles
[i
].tileComps
[comp
].resLevels
[r
].precincts
= NULL
;
1064 for (r
= 0; r
<= img
.tiles
[0].tileComps
[comp
].nDecompLevels
; ++r
) {
1065 if (img
.tiles
[0].tileComps
[comp
].style
& 0x01) {
1066 if (!readUByte(&precinctSize
)) {
1067 error(getPos(), "Error in JPX COD marker segment");
1070 img
.tiles
[0].tileComps
[comp
].resLevels
[r
].precinctWidth
=
1071 precinctSize
& 0x0f;
1072 img
.tiles
[0].tileComps
[comp
].resLevels
[r
].precinctHeight
=
1073 (precinctSize
>> 4) & 0x0f;
1075 img
.tiles
[0].tileComps
[comp
].resLevels
[r
].precinctWidth
= 15;
1076 img
.tiles
[0].tileComps
[comp
].resLevels
[r
].precinctHeight
= 15;
1079 for (i
= 1; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
1080 for (r
= 0; r
<= img
.tiles
[i
].tileComps
[comp
].nDecompLevels
; ++r
) {
1081 img
.tiles
[i
].tileComps
[comp
].resLevels
[r
].precinctWidth
=
1082 img
.tiles
[0].tileComps
[comp
].resLevels
[r
].precinctWidth
;
1083 img
.tiles
[i
].tileComps
[comp
].resLevels
[r
].precinctHeight
=
1084 img
.tiles
[0].tileComps
[comp
].resLevels
[r
].precinctHeight
;
1088 case 0x5c: // QCD - quantization default
1090 if (!readUByte(&img
.tiles
[0].tileComps
[0].quantStyle
)) {
1091 error(getPos(), "Error in JPX QCD marker segment");
1094 if ((img
.tiles
[0].tileComps
[0].quantStyle
& 0x1f) == 0x00) {
1095 img
.tiles
[0].tileComps
[0].nQuantSteps
= segLen
- 3;
1096 img
.tiles
[0].tileComps
[0].quantSteps
=
1097 (Guint
*)greallocn(img
.tiles
[0].tileComps
[0].quantSteps
,
1098 img
.tiles
[0].tileComps
[0].nQuantSteps
,
1100 for (i
= 0; i
< img
.tiles
[0].tileComps
[0].nQuantSteps
; ++i
) {
1101 if (!readUByte(&img
.tiles
[0].tileComps
[0].quantSteps
[i
])) {
1102 error(getPos(), "Error in JPX QCD marker segment");
1106 } else if ((img
.tiles
[0].tileComps
[0].quantStyle
& 0x1f) == 0x01) {
1107 img
.tiles
[0].tileComps
[0].nQuantSteps
= 1;
1108 img
.tiles
[0].tileComps
[0].quantSteps
=
1109 (Guint
*)greallocn(img
.tiles
[0].tileComps
[0].quantSteps
,
1110 img
.tiles
[0].tileComps
[0].nQuantSteps
,
1112 if (!readUWord(&img
.tiles
[0].tileComps
[0].quantSteps
[0])) {
1113 error(getPos(), "Error in JPX QCD marker segment");
1116 } else if ((img
.tiles
[0].tileComps
[0].quantStyle
& 0x1f) == 0x02) {
1117 img
.tiles
[0].tileComps
[0].nQuantSteps
= (segLen
- 3) / 2;
1118 img
.tiles
[0].tileComps
[0].quantSteps
=
1119 (Guint
*)greallocn(img
.tiles
[0].tileComps
[0].quantSteps
,
1120 img
.tiles
[0].tileComps
[0].nQuantSteps
,
1122 for (i
= 0; i
< img
.tiles
[0].tileComps
[0].nQuantSteps
; ++i
) {
1123 if (!readUWord(&img
.tiles
[0].tileComps
[0].quantSteps
[i
])) {
1124 error(getPos(), "Error in JPX QCD marker segment");
1129 error(getPos(), "Error in JPX QCD marker segment");
1132 for (i
= 0; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
1133 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
1134 if (!(i
== 0 && comp
== 0)) {
1135 img
.tiles
[i
].tileComps
[comp
].quantStyle
=
1136 img
.tiles
[0].tileComps
[0].quantStyle
;
1137 img
.tiles
[i
].tileComps
[comp
].nQuantSteps
=
1138 img
.tiles
[0].tileComps
[0].nQuantSteps
;
1139 img
.tiles
[i
].tileComps
[comp
].quantSteps
=
1140 (Guint
*)greallocn(img
.tiles
[i
].tileComps
[comp
].quantSteps
,
1141 img
.tiles
[0].tileComps
[0].nQuantSteps
,
1143 for (j
= 0; j
< img
.tiles
[0].tileComps
[0].nQuantSteps
; ++j
) {
1144 img
.tiles
[i
].tileComps
[comp
].quantSteps
[j
] =
1145 img
.tiles
[0].tileComps
[0].quantSteps
[j
];
1152 case 0x5d: // QCC - quantization component
1155 error(getPos(), "JPX QCC marker segment before QCD segment");
1158 if ((img
.nComps
> 256 && !readUWord(&comp
)) ||
1159 (img
.nComps
<= 256 && !readUByte(&comp
)) ||
1160 comp
>= img
.nComps
||
1161 !readUByte(&img
.tiles
[0].tileComps
[comp
].quantStyle
)) {
1162 error(getPos(), "Error in JPX QCC marker segment");
1165 if ((img
.tiles
[0].tileComps
[comp
].quantStyle
& 0x1f) == 0x00) {
1166 img
.tiles
[0].tileComps
[comp
].nQuantSteps
=
1167 segLen
- (img
.nComps
> 256 ? 5 : 4);
1168 img
.tiles
[0].tileComps
[comp
].quantSteps
=
1169 (Guint
*)greallocn(img
.tiles
[0].tileComps
[comp
].quantSteps
,
1170 img
.tiles
[0].tileComps
[comp
].nQuantSteps
,
1172 for (i
= 0; i
< img
.tiles
[0].tileComps
[comp
].nQuantSteps
; ++i
) {
1173 if (!readUByte(&img
.tiles
[0].tileComps
[comp
].quantSteps
[i
])) {
1174 error(getPos(), "Error in JPX QCC marker segment");
1178 } else if ((img
.tiles
[0].tileComps
[comp
].quantStyle
& 0x1f) == 0x01) {
1179 img
.tiles
[0].tileComps
[comp
].nQuantSteps
= 1;
1180 img
.tiles
[0].tileComps
[comp
].quantSteps
=
1181 (Guint
*)greallocn(img
.tiles
[0].tileComps
[comp
].quantSteps
,
1182 img
.tiles
[0].tileComps
[comp
].nQuantSteps
,
1184 if (!readUWord(&img
.tiles
[0].tileComps
[comp
].quantSteps
[0])) {
1185 error(getPos(), "Error in JPX QCC marker segment");
1188 } else if ((img
.tiles
[0].tileComps
[comp
].quantStyle
& 0x1f) == 0x02) {
1189 img
.tiles
[0].tileComps
[comp
].nQuantSteps
=
1190 (segLen
- (img
.nComps
> 256 ? 5 : 4)) / 2;
1191 img
.tiles
[0].tileComps
[comp
].quantSteps
=
1192 (Guint
*)greallocn(img
.tiles
[0].tileComps
[comp
].quantSteps
,
1193 img
.tiles
[0].tileComps
[comp
].nQuantSteps
,
1195 for (i
= 0; i
< img
.tiles
[0].tileComps
[comp
].nQuantSteps
; ++i
) {
1196 if (!readUWord(&img
.tiles
[0].tileComps
[comp
].quantSteps
[i
])) {
1197 error(getPos(), "Error in JPX QCD marker segment");
1202 error(getPos(), "Error in JPX QCC marker segment");
1205 for (i
= 1; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
1206 img
.tiles
[i
].tileComps
[comp
].quantStyle
=
1207 img
.tiles
[0].tileComps
[comp
].quantStyle
;
1208 img
.tiles
[i
].tileComps
[comp
].nQuantSteps
=
1209 img
.tiles
[0].tileComps
[comp
].nQuantSteps
;
1210 img
.tiles
[i
].tileComps
[comp
].quantSteps
=
1211 (Guint
*)greallocn(img
.tiles
[i
].tileComps
[comp
].quantSteps
,
1212 img
.tiles
[0].tileComps
[comp
].nQuantSteps
,
1214 for (j
= 0; j
< img
.tiles
[0].tileComps
[comp
].nQuantSteps
; ++j
) {
1215 img
.tiles
[i
].tileComps
[comp
].quantSteps
[j
] =
1216 img
.tiles
[0].tileComps
[comp
].quantSteps
[j
];
1220 case 0x5e: // RGN - region of interest
1222 #if 1 //~ ROI is unimplemented
1223 fprintf(stderr
, "RGN\n");
1224 for (i
= 0; i
< segLen
- 2; ++i
) {
1225 if (str
->getChar() == EOF
) {
1226 error(getPos(), "Error in JPX PPM marker segment");
1231 if ((img
.nComps
> 256 && !readUWord(&comp
)) ||
1232 (img
.nComps
<= 256 && !readUByte(&comp
)) ||
1233 comp
>= img
.nComps
||
1234 !readUByte(&compInfo
[comp
].defROI
.style
) ||
1235 !readUByte(&compInfo
[comp
].defROI
.shift
)) {
1236 error(getPos(), "Error in JPX RGN marker segment");
1241 case 0x5f: // POC - progression order change
1243 #if 1 //~ progression order changes are unimplemented
1244 fprintf(stderr
, "POC\n");
1245 for (i
= 0; i
< segLen
- 2; ++i
) {
1246 if (str
->getChar() == EOF
) {
1247 error(getPos(), "Error in JPX PPM marker segment");
1252 nProgs
= (segLen
- 2) / (img
.nComps
> 256 ? 9 : 7);
1253 progs
= (JPXProgOrder
*)gmallocn(nProgs
, sizeof(JPXProgOrder
));
1254 for (i
= 0; i
< nProgs
; ++i
) {
1255 if (!readUByte(&progs
[i
].startRes
) ||
1256 !(img
.nComps
> 256 && readUWord(&progs
[i
].startComp
)) ||
1257 !(img
.nComps
<= 256 && readUByte(&progs
[i
].startComp
)) ||
1258 !readUWord(&progs
[i
].endLayer
) ||
1259 !readUByte(&progs
[i
].endRes
) ||
1260 !(img
.nComps
> 256 && readUWord(&progs
[i
].endComp
)) ||
1261 !(img
.nComps
<= 256 && readUByte(&progs
[i
].endComp
)) ||
1262 !readUByte(&progs
[i
].progOrder
)) {
1263 error(getPos(), "Error in JPX POC marker segment");
1269 case 0x60: // PPM - packed packet headers, main header
1271 #if 1 //~ packed packet headers are unimplemented
1272 fprintf(stderr
, "PPM\n");
1273 for (i
= 0; i
< segLen
- 2; ++i
) {
1274 if (str
->getChar() == EOF
) {
1275 error(getPos(), "Error in JPX PPM marker segment");
1281 case 0x55: // TLM - tile-part lengths
1284 for (i
= 0; i
< segLen
- 2; ++i
) {
1285 if (str
->getChar() == EOF
) {
1286 error(getPos(), "Error in JPX TLM marker segment");
1291 case 0x57: // PLM - packet length, main header
1294 for (i
= 0; i
< segLen
- 2; ++i
) {
1295 if (str
->getChar() == EOF
) {
1296 error(getPos(), "Error in JPX PLM marker segment");
1301 case 0x63: // CRG - component registration
1304 for (i
= 0; i
< segLen
- 2; ++i
) {
1305 if (str
->getChar() == EOF
) {
1306 error(getPos(), "Error in JPX CRG marker segment");
1311 case 0x64: // COM - comment
1314 for (i
= 0; i
< segLen
- 2; ++i
) {
1315 if (str
->getChar() == EOF
) {
1316 error(getPos(), "Error in JPX COM marker segment");
1321 case 0x90: // SOT - start of tile
1327 error(getPos(), "Unknown marker segment %02x in JPX stream", segType
);
1328 for (i
= 0; i
< segLen
- 2; ++i
) {
1329 if (str
->getChar() == EOF
) {
1338 error(getPos(), "Missing SIZ marker segment in JPX stream");
1342 error(getPos(), "Missing COD marker segment in JPX stream");
1346 error(getPos(), "Missing QCD marker segment in JPX stream");
1350 //----- read the tile-parts
1352 if (!readTilePart()) {
1355 if (!readMarkerHdr(&segType
, &segLen
)) {
1356 error(getPos(), "Error in JPX codestream");
1359 if (segType
!= 0x90) { // SOT - start of tile
1364 if (segType
!= 0xd9) { // EOC - end of codestream
1365 error(getPos(), "Missing EOC marker in JPX codestream");
1369 //----- finish decoding the image
1370 for (i
= 0; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
1371 tile
= &img
.tiles
[i
];
1372 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
1373 tileComp
= &tile
->tileComps
[comp
];
1374 inverseTransform(tileComp
);
1376 if (!inverseMultiCompAndDC(tile
)) {
1381 //~ can free memory below tileComps here, and also tileComp.buf
1386 GBool
JPXStream::readTilePart() {
1388 JPXTileComp
*tileComp
;
1389 JPXResLevel
*resLevel
;
1390 JPXPrecinct
*precinct
;
1391 JPXSubband
*subband
;
1394 Guint tileIdx
, tilePartLen
, tilePartIdx
, nTileParts
;
1395 GBool tilePartToEOC
;
1396 Guint precinctSize
, style
;
1397 Guint n
, nSBs
, nx
, ny
, sbx0
, sby0
, comp
, segLen
;
1398 Guint i
, j
, k
, cbX
, cbY
, r
, pre
, sb
, cbi
;
1401 // process the SOT marker segment
1402 if (!readUWord(&tileIdx
) ||
1403 !readULong(&tilePartLen
) ||
1404 !readUByte(&tilePartIdx
) ||
1405 !readUByte(&nTileParts
)) {
1406 error(getPos(), "Error in JPX SOT marker segment");
1410 if (tileIdx
>= img
.nXTiles
* img
.nYTiles
) {
1411 error(getPos(), "Weird tile index in JPX stream");
1415 tilePartToEOC
= tilePartLen
== 0;
1416 tilePartLen
-= 12; // subtract size of SOT segment
1420 if (!readMarkerHdr(&segType
, &segLen
)) {
1421 error(getPos(), "Error in JPX tile-part codestream");
1424 tilePartLen
-= 2 + segLen
;
1426 case 0x52: // COD - coding style default
1428 if (!readUByte(&img
.tiles
[tileIdx
].tileComps
[0].style
) ||
1429 !readUByte(&img
.tiles
[tileIdx
].progOrder
) ||
1430 !readUWord(&img
.tiles
[tileIdx
].nLayers
) ||
1431 !readUByte(&img
.tiles
[tileIdx
].multiComp
) ||
1432 !readUByte(&img
.tiles
[tileIdx
].tileComps
[0].nDecompLevels
) ||
1433 !readUByte(&img
.tiles
[tileIdx
].tileComps
[0].codeBlockW
) ||
1434 !readUByte(&img
.tiles
[tileIdx
].tileComps
[0].codeBlockH
) ||
1435 !readUByte(&img
.tiles
[tileIdx
].tileComps
[0].codeBlockStyle
) ||
1436 !readUByte(&img
.tiles
[tileIdx
].tileComps
[0].transform
)) {
1437 error(getPos(), "Error in JPX COD marker segment");
1440 img
.tiles
[tileIdx
].tileComps
[0].codeBlockW
+= 2;
1441 img
.tiles
[tileIdx
].tileComps
[0].codeBlockH
+= 2;
1442 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
1444 img
.tiles
[tileIdx
].tileComps
[comp
].style
=
1445 img
.tiles
[tileIdx
].tileComps
[0].style
;
1446 img
.tiles
[tileIdx
].tileComps
[comp
].nDecompLevels
=
1447 img
.tiles
[tileIdx
].tileComps
[0].nDecompLevels
;
1448 img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockW
=
1449 img
.tiles
[tileIdx
].tileComps
[0].codeBlockW
;
1450 img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockH
=
1451 img
.tiles
[tileIdx
].tileComps
[0].codeBlockH
;
1452 img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockStyle
=
1453 img
.tiles
[tileIdx
].tileComps
[0].codeBlockStyle
;
1454 img
.tiles
[tileIdx
].tileComps
[comp
].transform
=
1455 img
.tiles
[tileIdx
].tileComps
[0].transform
;
1457 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
=
1458 (JPXResLevel
*)greallocn(
1459 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
,
1460 (img
.tiles
[tileIdx
].tileComps
[comp
].nDecompLevels
+ 1),
1461 sizeof(JPXResLevel
));
1463 r
<= img
.tiles
[tileIdx
].tileComps
[comp
].nDecompLevels
;
1465 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
[r
].precincts
= NULL
;
1468 for (r
= 0; r
<= img
.tiles
[tileIdx
].tileComps
[0].nDecompLevels
; ++r
) {
1469 if (img
.tiles
[tileIdx
].tileComps
[0].style
& 0x01) {
1470 if (!readUByte(&precinctSize
)) {
1471 error(getPos(), "Error in JPX COD marker segment");
1474 img
.tiles
[tileIdx
].tileComps
[0].resLevels
[r
].precinctWidth
=
1475 precinctSize
& 0x0f;
1476 img
.tiles
[tileIdx
].tileComps
[0].resLevels
[r
].precinctHeight
=
1477 (precinctSize
>> 4) & 0x0f;
1479 img
.tiles
[tileIdx
].tileComps
[0].resLevels
[r
].precinctWidth
= 15;
1480 img
.tiles
[tileIdx
].tileComps
[0].resLevels
[r
].precinctHeight
= 15;
1483 for (comp
= 1; comp
< img
.nComps
; ++comp
) {
1485 r
<= img
.tiles
[tileIdx
].tileComps
[comp
].nDecompLevels
;
1487 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
[r
].precinctWidth
=
1488 img
.tiles
[tileIdx
].tileComps
[0].resLevels
[r
].precinctWidth
;
1489 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
[r
].precinctHeight
=
1490 img
.tiles
[tileIdx
].tileComps
[0].resLevels
[r
].precinctHeight
;
1494 case 0x53: // COC - coding style component
1496 if ((img
.nComps
> 256 && !readUWord(&comp
)) ||
1497 (img
.nComps
<= 256 && !readUByte(&comp
)) ||
1498 comp
>= img
.nComps
||
1499 !readUByte(&style
) ||
1500 !readUByte(&img
.tiles
[tileIdx
].tileComps
[comp
].nDecompLevels
) ||
1501 !readUByte(&img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockW
) ||
1502 !readUByte(&img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockH
) ||
1503 !readUByte(&img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockStyle
) ||
1504 !readUByte(&img
.tiles
[tileIdx
].tileComps
[comp
].transform
)) {
1505 error(getPos(), "Error in JPX COC marker segment");
1508 img
.tiles
[tileIdx
].tileComps
[comp
].style
=
1509 (img
.tiles
[tileIdx
].tileComps
[comp
].style
& ~1) | (style
& 1);
1510 img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockW
+= 2;
1511 img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockH
+= 2;
1512 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
=
1513 (JPXResLevel
*)greallocn(
1514 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
,
1515 (img
.tiles
[tileIdx
].tileComps
[comp
].nDecompLevels
+ 1),
1516 sizeof(JPXResLevel
));
1517 for (r
= 0; r
<= img
.tiles
[tileIdx
].tileComps
[comp
].nDecompLevels
; ++r
) {
1518 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
[r
].precincts
= NULL
;
1520 for (r
= 0; r
<= img
.tiles
[tileIdx
].tileComps
[comp
].nDecompLevels
; ++r
) {
1521 if (img
.tiles
[tileIdx
].tileComps
[comp
].style
& 0x01) {
1522 if (!readUByte(&precinctSize
)) {
1523 error(getPos(), "Error in JPX COD marker segment");
1526 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
[r
].precinctWidth
=
1527 precinctSize
& 0x0f;
1528 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
[r
].precinctHeight
=
1529 (precinctSize
>> 4) & 0x0f;
1531 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
[r
].precinctWidth
= 15;
1532 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
[r
].precinctHeight
= 15;
1536 case 0x5c: // QCD - quantization default
1538 if (!readUByte(&img
.tiles
[tileIdx
].tileComps
[0].quantStyle
)) {
1539 error(getPos(), "Error in JPX QCD marker segment");
1542 if ((img
.tiles
[tileIdx
].tileComps
[0].quantStyle
& 0x1f) == 0x00) {
1543 img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
=
1545 img
.tiles
[tileIdx
].tileComps
[0].quantSteps
=
1546 (Guint
*)greallocn(img
.tiles
[tileIdx
].tileComps
[0].quantSteps
,
1547 img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
,
1549 for (i
= 0; i
< img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
; ++i
) {
1550 if (!readUByte(&img
.tiles
[tileIdx
].tileComps
[0].quantSteps
[i
])) {
1551 error(getPos(), "Error in JPX QCD marker segment");
1555 } else if ((img
.tiles
[tileIdx
].tileComps
[0].quantStyle
& 0x1f) == 0x01) {
1556 img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
= 1;
1557 img
.tiles
[tileIdx
].tileComps
[0].quantSteps
=
1558 (Guint
*)greallocn(img
.tiles
[tileIdx
].tileComps
[0].quantSteps
,
1559 img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
,
1561 if (!readUWord(&img
.tiles
[tileIdx
].tileComps
[0].quantSteps
[0])) {
1562 error(getPos(), "Error in JPX QCD marker segment");
1565 } else if ((img
.tiles
[tileIdx
].tileComps
[0].quantStyle
& 0x1f) == 0x02) {
1566 img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
= (segLen
- 3) / 2;
1567 img
.tiles
[tileIdx
].tileComps
[0].quantSteps
=
1568 (Guint
*)greallocn(img
.tiles
[tileIdx
].tileComps
[0].quantSteps
,
1569 img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
,
1571 for (i
= 0; i
< img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
; ++i
) {
1572 if (!readUWord(&img
.tiles
[tileIdx
].tileComps
[0].quantSteps
[i
])) {
1573 error(getPos(), "Error in JPX QCD marker segment");
1578 error(getPos(), "Error in JPX QCD marker segment");
1581 for (comp
= 1; comp
< img
.nComps
; ++comp
) {
1582 img
.tiles
[tileIdx
].tileComps
[comp
].quantStyle
=
1583 img
.tiles
[tileIdx
].tileComps
[0].quantStyle
;
1584 img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
=
1585 img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
;
1586 img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
=
1587 (Guint
*)greallocn(img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
,
1588 img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
,
1590 for (j
= 0; j
< img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
; ++j
) {
1591 img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
[j
] =
1592 img
.tiles
[tileIdx
].tileComps
[0].quantSteps
[j
];
1596 case 0x5d: // QCC - quantization component
1598 if ((img
.nComps
> 256 && !readUWord(&comp
)) ||
1599 (img
.nComps
<= 256 && !readUByte(&comp
)) ||
1600 comp
>= img
.nComps
||
1601 !readUByte(&img
.tiles
[tileIdx
].tileComps
[comp
].quantStyle
)) {
1602 error(getPos(), "Error in JPX QCC marker segment");
1605 if ((img
.tiles
[tileIdx
].tileComps
[comp
].quantStyle
& 0x1f) == 0x00) {
1606 img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
=
1607 segLen
- (img
.nComps
> 256 ? 5 : 4);
1608 img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
=
1609 (Guint
*)greallocn(img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
,
1610 img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
,
1612 for (i
= 0; i
< img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
; ++i
) {
1613 if (!readUByte(&img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
[i
])) {
1614 error(getPos(), "Error in JPX QCC marker segment");
1618 } else if ((img
.tiles
[tileIdx
].tileComps
[comp
].quantStyle
& 0x1f)
1620 img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
= 1;
1621 img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
=
1622 (Guint
*)greallocn(img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
,
1623 img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
,
1625 if (!readUWord(&img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
[0])) {
1626 error(getPos(), "Error in JPX QCC marker segment");
1629 } else if ((img
.tiles
[tileIdx
].tileComps
[comp
].quantStyle
& 0x1f)
1631 img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
=
1632 (segLen
- (img
.nComps
> 256 ? 5 : 4)) / 2;
1633 img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
=
1634 (Guint
*)greallocn(img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
,
1635 img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
,
1637 for (i
= 0; i
< img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
; ++i
) {
1638 if (!readUWord(&img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
[i
])) {
1639 error(getPos(), "Error in JPX QCD marker segment");
1644 error(getPos(), "Error in JPX QCC marker segment");
1648 case 0x5e: // RGN - region of interest
1650 #if 1 //~ ROI is unimplemented
1651 fprintf(stderr
, "RGN\n");
1652 for (i
= 0; i
< segLen
- 2; ++i
) {
1653 if (str
->getChar() == EOF
) {
1654 error(getPos(), "Error in JPX PPM marker segment");
1659 if ((img
.nComps
> 256 && !readUWord(&comp
)) ||
1660 (img
.nComps
<= 256 && !readUByte(&comp
)) ||
1661 comp
>= img
.nComps
||
1662 !readUByte(&compInfo
[comp
].roi
.style
) ||
1663 !readUByte(&compInfo
[comp
].roi
.shift
)) {
1664 error(getPos(), "Error in JPX RGN marker segment");
1669 case 0x5f: // POC - progression order change
1671 #if 1 //~ progression order changes are unimplemented
1672 fprintf(stderr
, "POC\n");
1673 for (i
= 0; i
< segLen
- 2; ++i
) {
1674 if (str
->getChar() == EOF
) {
1675 error(getPos(), "Error in JPX PPM marker segment");
1680 nTileProgs
= (segLen
- 2) / (img
.nComps
> 256 ? 9 : 7);
1681 tileProgs
= (JPXProgOrder
*)gmallocn(nTileProgs
, sizeof(JPXProgOrder
));
1682 for (i
= 0; i
< nTileProgs
; ++i
) {
1683 if (!readUByte(&tileProgs
[i
].startRes
) ||
1684 !(img
.nComps
> 256 && readUWord(&tileProgs
[i
].startComp
)) ||
1685 !(img
.nComps
<= 256 && readUByte(&tileProgs
[i
].startComp
)) ||
1686 !readUWord(&tileProgs
[i
].endLayer
) ||
1687 !readUByte(&tileProgs
[i
].endRes
) ||
1688 !(img
.nComps
> 256 && readUWord(&tileProgs
[i
].endComp
)) ||
1689 !(img
.nComps
<= 256 && readUByte(&tileProgs
[i
].endComp
)) ||
1690 !readUByte(&tileProgs
[i
].progOrder
)) {
1691 error(getPos(), "Error in JPX POC marker segment");
1697 case 0x61: // PPT - packed packet headers, tile-part hdr
1699 #if 1 //~ packed packet headers are unimplemented
1700 fprintf(stderr
, "PPT\n");
1701 for (i
= 0; i
< segLen
- 2; ++i
) {
1702 if (str
->getChar() == EOF
) {
1703 error(getPos(), "Error in JPX PPT marker segment");
1708 case 0x58: // PLT - packet length, tile-part header
1711 for (i
= 0; i
< segLen
- 2; ++i
) {
1712 if (str
->getChar() == EOF
) {
1713 error(getPos(), "Error in JPX PLT marker segment");
1718 case 0x64: // COM - comment
1721 for (i
= 0; i
< segLen
- 2; ++i
) {
1722 if (str
->getChar() == EOF
) {
1723 error(getPos(), "Error in JPX COM marker segment");
1728 case 0x93: // SOD - start of data
1734 error(getPos(), "Unknown marker segment %02x in JPX tile-part stream",
1736 for (i
= 0; i
< segLen
- 2; ++i
) {
1737 if (str
->getChar() == EOF
) {
1745 //----- initialize the tile, precincts, and code-blocks
1746 if (tilePartIdx
== 0) {
1747 tile
= &img
.tiles
[tileIdx
];
1748 i
= tileIdx
/ img
.nXTiles
;
1749 j
= tileIdx
% img
.nXTiles
;
1750 if ((tile
->x0
= img
.xTileOffset
+ j
* img
.xTileSize
) < img
.xOffset
) {
1751 tile
->x0
= img
.xOffset
;
1753 if ((tile
->y0
= img
.yTileOffset
+ i
* img
.yTileSize
) < img
.yOffset
) {
1754 tile
->y0
= img
.yOffset
;
1756 if ((tile
->x1
= img
.xTileOffset
+ (j
+ 1) * img
.xTileSize
) > img
.xSize
) {
1757 tile
->x1
= img
.xSize
;
1759 if ((tile
->y1
= img
.yTileOffset
+ (i
+ 1) * img
.yTileSize
) > img
.ySize
) {
1760 tile
->y1
= img
.ySize
;
1766 tile
->maxNDecompLevels
= 0;
1767 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
1768 tileComp
= &tile
->tileComps
[comp
];
1769 if (tileComp
->nDecompLevels
> tile
->maxNDecompLevels
) {
1770 tile
->maxNDecompLevels
= tileComp
->nDecompLevels
;
1772 tileComp
->x0
= jpxCeilDiv(tile
->x0
, tileComp
->hSep
);
1773 tileComp
->y0
= jpxCeilDiv(tile
->y0
, tileComp
->hSep
);
1774 tileComp
->x1
= jpxCeilDiv(tile
->x1
, tileComp
->hSep
);
1775 tileComp
->y1
= jpxCeilDiv(tile
->y1
, tileComp
->hSep
);
1776 tileComp
->cbW
= 1 << tileComp
->codeBlockW
;
1777 tileComp
->cbH
= 1 << tileComp
->codeBlockH
;
1778 tileComp
->data
= (int *)gmallocn((tileComp
->x1
- tileComp
->x0
) *
1779 (tileComp
->y1
- tileComp
->y0
),
1781 if (tileComp
->x1
- tileComp
->x0
> tileComp
->y1
- tileComp
->y0
) {
1782 n
= tileComp
->x1
- tileComp
->x0
;
1784 n
= tileComp
->y1
- tileComp
->y0
;
1786 tileComp
->buf
= (int *)gmallocn(n
+ 8, sizeof(int));
1787 for (r
= 0; r
<= tileComp
->nDecompLevels
; ++r
) {
1788 resLevel
= &tileComp
->resLevels
[r
];
1789 k
= r
== 0 ? tileComp
->nDecompLevels
1790 : tileComp
->nDecompLevels
- r
+ 1;
1791 resLevel
->x0
= jpxCeilDivPow2(tileComp
->x0
, k
);
1792 resLevel
->y0
= jpxCeilDivPow2(tileComp
->y0
, k
);
1793 resLevel
->x1
= jpxCeilDivPow2(tileComp
->x1
, k
);
1794 resLevel
->y1
= jpxCeilDivPow2(tileComp
->y1
, k
);
1796 resLevel
->bx0
[0] = resLevel
->x0
;
1797 resLevel
->by0
[0] = resLevel
->y0
;
1798 resLevel
->bx1
[0] = resLevel
->x1
;
1799 resLevel
->by1
[0] = resLevel
->y1
;
1801 resLevel
->bx0
[0] = jpxCeilDivPow2(tileComp
->x0
- (1 << (k
-1)), k
);
1802 resLevel
->by0
[0] = resLevel
->y0
;
1803 resLevel
->bx1
[0] = jpxCeilDivPow2(tileComp
->x1
- (1 << (k
-1)), k
);
1804 resLevel
->by1
[0] = resLevel
->y1
;
1805 resLevel
->bx0
[1] = resLevel
->x0
;
1806 resLevel
->by0
[1] = jpxCeilDivPow2(tileComp
->y0
- (1 << (k
-1)), k
);
1807 resLevel
->bx1
[1] = resLevel
->x1
;
1808 resLevel
->by1
[1] = jpxCeilDivPow2(tileComp
->y1
- (1 << (k
-1)), k
);
1809 resLevel
->bx0
[2] = jpxCeilDivPow2(tileComp
->x0
- (1 << (k
-1)), k
);
1810 resLevel
->by0
[2] = jpxCeilDivPow2(tileComp
->y0
- (1 << (k
-1)), k
);
1811 resLevel
->bx1
[2] = jpxCeilDivPow2(tileComp
->x1
- (1 << (k
-1)), k
);
1812 resLevel
->by1
[2] = jpxCeilDivPow2(tileComp
->y1
- (1 << (k
-1)), k
);
1814 resLevel
->precincts
= (JPXPrecinct
*)gmallocn(1, sizeof(JPXPrecinct
));
1815 for (pre
= 0; pre
< 1; ++pre
) {
1816 precinct
= &resLevel
->precincts
[pre
];
1817 precinct
->x0
= resLevel
->x0
;
1818 precinct
->y0
= resLevel
->y0
;
1819 precinct
->x1
= resLevel
->x1
;
1820 precinct
->y1
= resLevel
->y1
;
1821 nSBs
= r
== 0 ? 1 : 3;
1822 precinct
->subbands
=
1823 (JPXSubband
*)gmallocn(nSBs
, sizeof(JPXSubband
));
1824 for (sb
= 0; sb
< nSBs
; ++sb
) {
1825 subband
= &precinct
->subbands
[sb
];
1826 subband
->x0
= resLevel
->bx0
[sb
];
1827 subband
->y0
= resLevel
->by0
[sb
];
1828 subband
->x1
= resLevel
->bx1
[sb
];
1829 subband
->y1
= resLevel
->by1
[sb
];
1830 subband
->nXCBs
= jpxCeilDivPow2(subband
->x1
,
1831 tileComp
->codeBlockW
)
1832 - jpxFloorDivPow2(subband
->x0
,
1833 tileComp
->codeBlockW
);
1834 subband
->nYCBs
= jpxCeilDivPow2(subband
->y1
,
1835 tileComp
->codeBlockH
)
1836 - jpxFloorDivPow2(subband
->y0
,
1837 tileComp
->codeBlockH
);
1838 n
= subband
->nXCBs
> subband
->nYCBs
? subband
->nXCBs
1840 for (subband
->maxTTLevel
= 0, --n
;
1842 ++subband
->maxTTLevel
, n
>>= 1) ;
1844 for (level
= subband
->maxTTLevel
; level
>= 0; --level
) {
1845 nx
= jpxCeilDivPow2(subband
->nXCBs
, level
);
1846 ny
= jpxCeilDivPow2(subband
->nYCBs
, level
);
1849 subband
->inclusion
=
1850 (JPXTagTreeNode
*)gmallocn(n
, sizeof(JPXTagTreeNode
));
1851 subband
->zeroBitPlane
=
1852 (JPXTagTreeNode
*)gmallocn(n
, sizeof(JPXTagTreeNode
));
1853 for (k
= 0; k
< n
; ++k
) {
1854 subband
->inclusion
[k
].finished
= gFalse
;
1855 subband
->inclusion
[k
].val
= 0;
1856 subband
->zeroBitPlane
[k
].finished
= gFalse
;
1857 subband
->zeroBitPlane
[k
].val
= 0;
1859 subband
->cbs
= (JPXCodeBlock
*)gmallocn(subband
->nXCBs
*
1861 sizeof(JPXCodeBlock
));
1862 sbx0
= jpxFloorDivPow2(subband
->x0
, tileComp
->codeBlockW
);
1863 sby0
= jpxFloorDivPow2(subband
->y0
, tileComp
->codeBlockH
);
1865 for (cbY
= 0; cbY
< subband
->nYCBs
; ++cbY
) {
1866 for (cbX
= 0; cbX
< subband
->nXCBs
; ++cbX
) {
1867 cb
->x0
= (sbx0
+ cbX
) << tileComp
->codeBlockW
;
1868 cb
->x1
= cb
->x0
+ tileComp
->cbW
;
1869 if (subband
->x0
> cb
->x0
) {
1870 cb
->x0
= subband
->x0
;
1872 if (subband
->x1
< cb
->x1
) {
1873 cb
->x1
= subband
->x1
;
1875 cb
->y0
= (sby0
+ cbY
) << tileComp
->codeBlockH
;
1876 cb
->y1
= cb
->y0
+ tileComp
->cbH
;
1877 if (subband
->y0
> cb
->y0
) {
1878 cb
->y0
= subband
->y0
;
1880 if (subband
->y1
< cb
->y1
) {
1881 cb
->y1
= subband
->y1
;
1885 cb
->nextPass
= jpxPassCleanup
;
1886 cb
->nZeroBitPlanes
= 0;
1888 (JPXCoeff
*)gmallocn((1 << (tileComp
->codeBlockW
1889 + tileComp
->codeBlockH
)),
1892 cbi
< (Guint
)(1 << (tileComp
->codeBlockW
1893 + tileComp
->codeBlockH
));
1895 cb
->coeffs
[cbi
].flags
= 0;
1896 cb
->coeffs
[cbi
].len
= 0;
1897 cb
->coeffs
[cbi
].mag
= 0;
1899 cb
->arithDecoder
= NULL
;
1910 return readTilePartData(tileIdx
, tilePartLen
, tilePartToEOC
);
1913 GBool
JPXStream::readTilePartData(Guint tileIdx
,
1914 Guint tilePartLen
, GBool tilePartToEOC
) {
1916 JPXTileComp
*tileComp
;
1917 JPXResLevel
*resLevel
;
1918 JPXPrecinct
*precinct
;
1919 JPXSubband
*subband
;
1922 Guint bits
, cbX
, cbY
, nx
, ny
, i
, j
, n
, sb
;
1925 tile
= &img
.tiles
[tileIdx
];
1927 // read all packets from this tile-part
1929 if (tilePartToEOC
) {
1930 //~ peek for an EOC marker
1932 } else if (tilePartLen
== 0) {
1936 tileComp
= &tile
->tileComps
[tile
->comp
];
1937 resLevel
= &tileComp
->resLevels
[tile
->res
];
1938 precinct
= &resLevel
->precincts
[tile
->precinct
];
1940 //----- packet header
1943 startBitBuf(tilePartLen
);
1946 if (!readBits(1, &bits
)) {
1950 // packet is empty -- clear all code-block inclusion flags
1952 for (sb
= 0; sb
< (Guint
)(tile
->res
== 0 ? 1 : 3); ++sb
) {
1953 subband
= &precinct
->subbands
[sb
];
1954 for (cbY
= 0; cbY
< subband
->nYCBs
; ++cbY
) {
1955 for (cbX
= 0; cbX
< subband
->nXCBs
; ++cbX
) {
1956 cb
= &subband
->cbs
[cbY
* subband
->nXCBs
+ cbX
];
1957 cb
->included
= gFalse
;
1963 for (sb
= 0; sb
< (Guint
)(tile
->res
== 0 ? 1 : 3); ++sb
) {
1964 subband
= &precinct
->subbands
[sb
];
1965 for (cbY
= 0; cbY
< subband
->nYCBs
; ++cbY
) {
1966 for (cbX
= 0; cbX
< subband
->nXCBs
; ++cbX
) {
1967 cb
= &subband
->cbs
[cbY
* subband
->nXCBs
+ cbX
];
1969 // skip code-blocks with no coefficients
1970 if (cb
->x0
>= cb
->x1
|| cb
->y0
>= cb
->y1
) {
1972 cb
->included
= gFalse
;
1976 // code-block inclusion
1979 if (!readBits(1, &cb
->included
)) {
1986 for (level
= subband
->maxTTLevel
; level
>= 0; --level
) {
1987 nx
= jpxCeilDivPow2(subband
->nXCBs
, level
);
1988 ny
= jpxCeilDivPow2(subband
->nYCBs
, level
);
1989 j
= i
+ (cbY
>> level
) * nx
+ (cbX
>> level
);
1990 if (!subband
->inclusion
[j
].finished
&&
1991 !subband
->inclusion
[j
].val
) {
1992 subband
->inclusion
[j
].val
= ttVal
;
1994 ttVal
= subband
->inclusion
[j
].val
;
1996 while (!subband
->inclusion
[j
].finished
&&
1997 ttVal
<= tile
->layer
) {
1998 if (!readBits(1, &bits
)) {
2002 subband
->inclusion
[j
].finished
= gTrue
;
2007 subband
->inclusion
[j
].val
= ttVal
;
2008 if (ttVal
> tile
->layer
) {
2013 cb
->included
= level
< 0;
2019 // zero bit-plane count
2024 for (level
= subband
->maxTTLevel
; level
>= 0; --level
) {
2025 nx
= jpxCeilDivPow2(subband
->nXCBs
, level
);
2026 ny
= jpxCeilDivPow2(subband
->nYCBs
, level
);
2027 j
= i
+ (cbY
>> level
) * nx
+ (cbX
>> level
);
2028 if (!subband
->zeroBitPlane
[j
].finished
&&
2029 !subband
->zeroBitPlane
[j
].val
) {
2030 subband
->zeroBitPlane
[j
].val
= ttVal
;
2032 ttVal
= subband
->zeroBitPlane
[j
].val
;
2034 while (!subband
->zeroBitPlane
[j
].finished
) {
2035 if (!readBits(1, &bits
)) {
2039 subband
->zeroBitPlane
[j
].finished
= gTrue
;
2044 subband
->zeroBitPlane
[j
].val
= ttVal
;
2047 cb
->nZeroBitPlanes
= ttVal
;
2050 // number of coding passes
2051 if (!readBits(1, &bits
)) {
2056 cb
->nCodingPasses
= 1;
2058 if (!readBits(1, &bits
)) {
2063 cb
->nCodingPasses
= 2;
2066 if (!readBits(2, &bits
)) {
2071 cb
->nCodingPasses
= 3 + bits
;
2074 if (!readBits(5, &bits
)) {
2079 cb
->nCodingPasses
= 6 + bits
;
2082 if (!readBits(7, &bits
)) {
2085 cb
->nCodingPasses
= 37 + bits
;
2093 if (!readBits(1, &bits
)) {
2102 // length of compressed data
2103 //~ deal with multiple codeword segments
2104 for (n
= cb
->lBlock
, i
= cb
->nCodingPasses
>> 1;
2107 if (!readBits(n
, &cb
->dataLen
)) {
2115 tilePartLen
= finishBitBuf();
2119 for (sb
= 0; sb
< (Guint
)(tile
->res
== 0 ? 1 : 3); ++sb
) {
2120 subband
= &precinct
->subbands
[sb
];
2121 for (cbY
= 0; cbY
< subband
->nYCBs
; ++cbY
) {
2122 for (cbX
= 0; cbX
< subband
->nXCBs
; ++cbX
) {
2123 cb
= &subband
->cbs
[cbY
* subband
->nXCBs
+ cbX
];
2125 if (!readCodeBlockData(tileComp
, resLevel
, precinct
, subband
,
2126 tile
->res
, sb
, cb
)) {
2129 tilePartLen
-= cb
->dataLen
;
2138 switch (tile
->progOrder
) {
2139 case 0: // layer, resolution level, component, precinct
2141 if (++tile
->comp
== img
.nComps
) {
2143 if (++tile
->res
== tile
->maxNDecompLevels
+ 1) {
2145 if (++tile
->layer
== tile
->nLayers
) {
2151 case 1: // resolution level, layer, component, precinct
2153 if (++tile
->comp
== img
.nComps
) {
2155 if (++tile
->layer
== tile
->nLayers
) {
2157 if (++tile
->res
== tile
->maxNDecompLevels
+ 1) {
2163 case 2: // resolution level, precinct, component, layer
2164 //~ this isn't correct -- see B.12.1.3
2166 if (++tile
->layer
== tile
->nLayers
) {
2168 if (++tile
->comp
== img
.nComps
) {
2170 if (++tile
->res
== tile
->maxNDecompLevels
+ 1) {
2176 case 3: // precinct, component, resolution level, layer
2177 //~ this isn't correct -- see B.12.1.4
2179 if (++tile
->layer
== tile
->nLayers
) {
2181 if (++tile
->res
== tile
->maxNDecompLevels
+ 1) {
2183 if (++tile
->comp
== img
.nComps
) {
2189 case 4: // component, precinct, resolution level, layer
2190 //~ this isn't correct -- see B.12.1.5
2192 if (++tile
->layer
== tile
->nLayers
) {
2194 if (++tile
->res
== tile
->maxNDecompLevels
+ 1) {
2196 if (++tile
->comp
== img
.nComps
) {
2208 error(getPos(), "Error in JPX stream");
2212 GBool
JPXStream::readCodeBlockData(JPXTileComp
*tileComp
,
2213 JPXResLevel
*resLevel
,
2214 JPXPrecinct
*precinct
,
2215 JPXSubband
*subband
,
2216 Guint res
, Guint sb
,
2218 JPXCoeff
*coeff0
, *coeff1
, *coeff
;
2219 Guint horiz
, vert
, diag
, all
, cx
, xorBit
;
2220 int horizSign
, vertSign
;
2221 Guint i
, x
, y0
, y1
, y2
;
2223 if (cb
->arithDecoder
) {
2225 cb
->arithDecoder
->restart(cb
->dataLen
);
2228 cb
->arithDecoder
= new JArithmeticDecoder();
2229 cb
->arithDecoder
->setStream(str
, cb
->dataLen
);
2230 cb
->arithDecoder
->start();
2231 cb
->stats
= new JArithmeticDecoderStats(jpxNContexts
);
2232 cb
->stats
->setEntry(jpxContextSigProp
, 4, 0);
2233 cb
->stats
->setEntry(jpxContextRunLength
, 3, 0);
2234 cb
->stats
->setEntry(jpxContextUniform
, 46, 0);
2237 for (i
= 0; i
< cb
->nCodingPasses
; ++i
) {
2238 switch (cb
->nextPass
) {
2240 //----- significance propagation pass
2241 case jpxPassSigProp
:
2243 for (y0
= cb
->y0
, coeff0
= cb
->coeffs
;
2245 y0
+= 4, coeff0
+= 4 << tileComp
->codeBlockW
) {
2246 for (x
= cb
->x0
, coeff1
= coeff0
;
2249 for (y1
= 0, coeff
= coeff1
;
2250 y1
< 4 && y0
+y1
< cb
->y1
;
2251 ++y1
, coeff
+= tileComp
->cbW
) {
2252 if (!(coeff
->flags
& jpxCoeffSignificant
)) {
2253 horiz
= vert
= diag
= 0;
2254 horizSign
= vertSign
= 2;
2256 if (coeff
[-1].flags
& jpxCoeffSignificant
) {
2258 horizSign
+= (coeff
[-1].flags
& jpxCoeffSign
) ? -1 : 1;
2260 if (y0
+y1
> cb
->y0
) {
2261 diag
+= (coeff
[-(int)tileComp
->cbW
- 1].flags
2262 >> jpxCoeffSignificantB
) & 1;
2264 if (y0
+y1
< cb
->y1
- 1) {
2265 diag
+= (coeff
[tileComp
->cbW
- 1].flags
2266 >> jpxCoeffSignificantB
) & 1;
2269 if (x
< cb
->x1
- 1) {
2270 if (coeff
[1].flags
& jpxCoeffSignificant
) {
2272 horizSign
+= (coeff
[1].flags
& jpxCoeffSign
) ? -1 : 1;
2274 if (y0
+y1
> cb
->y0
) {
2275 diag
+= (coeff
[-(int)tileComp
->cbW
+ 1].flags
2276 >> jpxCoeffSignificantB
) & 1;
2278 if (y0
+y1
< cb
->y1
- 1) {
2279 diag
+= (coeff
[tileComp
->cbW
+ 1].flags
2280 >> jpxCoeffSignificantB
) & 1;
2283 if (y0
+y1
> cb
->y0
) {
2284 if (coeff
[-(int)tileComp
->cbW
].flags
& jpxCoeffSignificant
) {
2286 vertSign
+= (coeff
[-(int)tileComp
->cbW
].flags
& jpxCoeffSign
)
2290 if (y0
+y1
< cb
->y1
- 1) {
2291 if (coeff
[tileComp
->cbW
].flags
& jpxCoeffSignificant
) {
2293 vertSign
+= (coeff
[tileComp
->cbW
].flags
& jpxCoeffSign
)
2297 cx
= sigPropContext
[horiz
][vert
][diag
][res
== 0 ? 1 : sb
];
2299 if (cb
->arithDecoder
->decodeBit(cx
, cb
->stats
)) {
2300 coeff
->flags
|= jpxCoeffSignificant
| jpxCoeffFirstMagRef
;
2301 coeff
->mag
= (coeff
->mag
<< 1) | 1;
2302 cx
= signContext
[horizSign
][vertSign
][0];
2303 xorBit
= signContext
[horizSign
][vertSign
][1];
2304 if (cb
->arithDecoder
->decodeBit(cx
, cb
->stats
) ^ xorBit
) {
2305 coeff
->flags
|= jpxCoeffSign
;
2309 coeff
->flags
|= jpxCoeffTouched
;
2318 //----- magnitude refinement pass
2321 for (y0
= cb
->y0
, coeff0
= cb
->coeffs
;
2323 y0
+= 4, coeff0
+= 4 << tileComp
->codeBlockW
) {
2324 for (x
= cb
->x0
, coeff1
= coeff0
;
2327 for (y1
= 0, coeff
= coeff1
;
2328 y1
< 4 && y0
+y1
< cb
->y1
;
2329 ++y1
, coeff
+= tileComp
->cbW
) {
2330 if ((coeff
->flags
& jpxCoeffSignificant
) &&
2331 !(coeff
->flags
& jpxCoeffTouched
)) {
2332 if (coeff
->flags
& jpxCoeffFirstMagRef
) {
2335 all
+= (coeff
[-1].flags
>> jpxCoeffSignificantB
) & 1;
2336 if (y0
+y1
> cb
->y0
) {
2337 all
+= (coeff
[-(int)tileComp
->cbW
- 1].flags
2338 >> jpxCoeffSignificantB
) & 1;
2340 if (y0
+y1
< cb
->y1
- 1) {
2341 all
+= (coeff
[tileComp
->cbW
- 1].flags
2342 >> jpxCoeffSignificantB
) & 1;
2345 if (x
< cb
->x1
- 1) {
2346 all
+= (coeff
[1].flags
>> jpxCoeffSignificantB
) & 1;
2347 if (y0
+y1
> cb
->y0
) {
2348 all
+= (coeff
[-(int)tileComp
->cbW
+ 1].flags
2349 >> jpxCoeffSignificantB
) & 1;
2351 if (y0
+y1
< cb
->y1
- 1) {
2352 all
+= (coeff
[tileComp
->cbW
+ 1].flags
2353 >> jpxCoeffSignificantB
) & 1;
2356 if (y0
+y1
> cb
->y0
) {
2357 all
+= (coeff
[-(int)tileComp
->cbW
].flags
2358 >> jpxCoeffSignificantB
) & 1;
2360 if (y0
+y1
< cb
->y1
- 1) {
2361 all
+= (coeff
[tileComp
->cbW
].flags
2362 >> jpxCoeffSignificantB
) & 1;
2368 coeff
->mag
= (coeff
->mag
<< 1) |
2369 cb
->arithDecoder
->decodeBit(cx
, cb
->stats
);
2371 coeff
->flags
|= jpxCoeffTouched
;
2372 coeff
->flags
&= ~jpxCoeffFirstMagRef
;
2380 //----- cleanup pass
2381 case jpxPassCleanup
:
2383 for (y0
= cb
->y0
, coeff0
= cb
->coeffs
;
2385 y0
+= 4, coeff0
+= 4 << tileComp
->codeBlockW
) {
2386 for (x
= cb
->x0
, coeff1
= coeff0
;
2390 if (y0
+ 3 < cb
->y1
&&
2391 !(coeff1
->flags
& jpxCoeffTouched
) &&
2392 !(coeff1
[tileComp
->cbW
].flags
& jpxCoeffTouched
) &&
2393 !(coeff1
[2 * tileComp
->cbW
].flags
& jpxCoeffTouched
) &&
2394 !(coeff1
[3 * tileComp
->cbW
].flags
& jpxCoeffTouched
) &&
2395 (x
== cb
->x0
|| y0
== cb
->y0
||
2396 !(coeff1
[-(int)tileComp
->cbW
- 1].flags
2397 & jpxCoeffSignificant
)) &&
2399 !(coeff1
[-(int)tileComp
->cbW
].flags
2400 & jpxCoeffSignificant
)) &&
2401 (x
== cb
->x1
- 1 || y0
== cb
->y0
||
2402 !(coeff1
[-(int)tileComp
->cbW
+ 1].flags
2403 & jpxCoeffSignificant
)) &&
2405 (!(coeff1
[-1].flags
& jpxCoeffSignificant
) &&
2406 !(coeff1
[tileComp
->cbW
- 1].flags
2407 & jpxCoeffSignificant
) &&
2408 !(coeff1
[2 * tileComp
->cbW
- 1].flags
2409 & jpxCoeffSignificant
) &&
2410 !(coeff1
[3 * tileComp
->cbW
- 1].flags
2411 & jpxCoeffSignificant
))) &&
2413 (!(coeff1
[1].flags
& jpxCoeffSignificant
) &&
2414 !(coeff1
[tileComp
->cbW
+ 1].flags
2415 & jpxCoeffSignificant
) &&
2416 !(coeff1
[2 * tileComp
->cbW
+ 1].flags
2417 & jpxCoeffSignificant
) &&
2418 !(coeff1
[3 * tileComp
->cbW
+ 1].flags
2419 & jpxCoeffSignificant
))) &&
2420 (x
== cb
->x0
|| y0
+4 == cb
->y1
||
2421 !(coeff1
[4 * tileComp
->cbW
- 1].flags
& jpxCoeffSignificant
)) &&
2423 !(coeff1
[4 * tileComp
->cbW
].flags
& jpxCoeffSignificant
)) &&
2424 (x
== cb
->x1
- 1 || y0
+4 == cb
->y1
||
2425 !(coeff1
[4 * tileComp
->cbW
+ 1].flags
2426 & jpxCoeffSignificant
))) {
2427 if (cb
->arithDecoder
->decodeBit(jpxContextRunLength
, cb
->stats
)) {
2428 y1
= cb
->arithDecoder
->decodeBit(jpxContextUniform
, cb
->stats
);
2430 cb
->arithDecoder
->decodeBit(jpxContextUniform
, cb
->stats
);
2431 for (y2
= 0, coeff
= coeff1
;
2433 ++y2
, coeff
+= tileComp
->cbW
) {
2436 coeff
->flags
|= jpxCoeffSignificant
| jpxCoeffFirstMagRef
;
2437 coeff
->mag
= (coeff
->mag
<< 1) | 1;
2439 cx
= signContext
[2][2][0];
2440 xorBit
= signContext
[2][2][1];
2441 if (cb
->arithDecoder
->decodeBit(cx
, cb
->stats
) ^ xorBit
) {
2442 coeff
->flags
|= jpxCoeffSign
;
2446 for (y1
= 0, coeff
= coeff1
;
2448 ++y1
, coeff
+= tileComp
->cbW
) {
2454 for (coeff
= &coeff1
[y1
<< tileComp
->codeBlockW
];
2455 y1
< 4 && y0
+ y1
< cb
->y1
;
2456 ++y1
, coeff
+= tileComp
->cbW
) {
2457 if (!(coeff
->flags
& jpxCoeffTouched
)) {
2458 horiz
= vert
= diag
= 0;
2459 horizSign
= vertSign
= 2;
2461 if (coeff
[-1].flags
& jpxCoeffSignificant
) {
2463 horizSign
+= (coeff
[-1].flags
& jpxCoeffSign
) ? -1 : 1;
2465 if (y0
+y1
> cb
->y0
) {
2466 diag
+= (coeff
[-(int)tileComp
->cbW
- 1].flags
2467 >> jpxCoeffSignificantB
) & 1;
2469 if (y0
+y1
< cb
->y1
- 1) {
2470 diag
+= (coeff
[tileComp
->cbW
- 1].flags
2471 >> jpxCoeffSignificantB
) & 1;
2474 if (x
< cb
->x1
- 1) {
2475 if (coeff
[1].flags
& jpxCoeffSignificant
) {
2477 horizSign
+= (coeff
[1].flags
& jpxCoeffSign
) ? -1 : 1;
2479 if (y0
+y1
> cb
->y0
) {
2480 diag
+= (coeff
[-(int)tileComp
->cbW
+ 1].flags
2481 >> jpxCoeffSignificantB
) & 1;
2483 if (y0
+y1
< cb
->y1
- 1) {
2484 diag
+= (coeff
[tileComp
->cbW
+ 1].flags
2485 >> jpxCoeffSignificantB
) & 1;
2488 if (y0
+y1
> cb
->y0
) {
2489 if (coeff
[-(int)tileComp
->cbW
].flags
& jpxCoeffSignificant
) {
2491 vertSign
+= (coeff
[-(int)tileComp
->cbW
].flags
& jpxCoeffSign
)
2495 if (y0
+y1
< cb
->y1
- 1) {
2496 if (coeff
[tileComp
->cbW
].flags
& jpxCoeffSignificant
) {
2498 vertSign
+= (coeff
[tileComp
->cbW
].flags
& jpxCoeffSign
)
2502 cx
= sigPropContext
[horiz
][vert
][diag
][res
== 0 ? 1 : sb
];
2503 if (cb
->arithDecoder
->decodeBit(cx
, cb
->stats
)) {
2504 coeff
->flags
|= jpxCoeffSignificant
| jpxCoeffFirstMagRef
;
2505 coeff
->mag
= (coeff
->mag
<< 1) | 1;
2506 cx
= signContext
[horizSign
][vertSign
][0];
2507 xorBit
= signContext
[horizSign
][vertSign
][1];
2508 if (cb
->arithDecoder
->decodeBit(cx
, cb
->stats
) ^ xorBit
) {
2509 coeff
->flags
|= jpxCoeffSign
;
2514 coeff
->flags
&= ~jpxCoeffTouched
;
2519 cb
->nextPass
= jpxPassSigProp
;
2524 cb
->arithDecoder
->cleanup();
2528 // Inverse quantization, and wavelet transform (IDWT). This also does
2529 // the initial shift to convert to fixed point format.
2530 void JPXStream::inverseTransform(JPXTileComp
*tileComp
) {
2531 JPXResLevel
*resLevel
;
2532 JPXPrecinct
*precinct
;
2533 JPXSubband
*subband
;
2535 JPXCoeff
*coeff0
, *coeff
;
2536 Guint qStyle
, guard
, eps
, shift
;
2541 Guint nx0
, ny0
, nx1
, ny1
;
2542 Guint r
, cbX
, cbY
, x
, y
;
2546 //----- (NL)LL subband (resolution level 0)
2548 resLevel
= &tileComp
->resLevels
[0];
2549 precinct
= &resLevel
->precincts
[0];
2550 subband
= &precinct
->subbands
[0];
2552 // i-quant parameters
2553 qStyle
= tileComp
->quantStyle
& 0x1f;
2554 guard
= (tileComp
->quantStyle
>> 5) & 7;
2557 eps
= (tileComp
->quantSteps
[0] >> 3) & 0x1f;
2558 shift
= guard
+ eps
- 1;
2559 mu
= 0; // make gcc happy
2562 shift
= guard
- 1 + tileComp
->prec
;
2563 mu
= (double)(0x800 + (tileComp
->quantSteps
[0] & 0x7ff)) / 2048.0;
2565 if (tileComp
->transform
== 0) {
2570 // copy (NL)LL into the upper-left corner of the data array, doing
2571 // the fixed point adjustment and dequantization along the way
2573 for (cbY
= 0; cbY
< subband
->nYCBs
; ++cbY
) {
2574 for (cbX
= 0; cbX
< subband
->nXCBs
; ++cbX
) {
2575 for (y
= cb
->y0
, coeff0
= cb
->coeffs
;
2577 ++y
, coeff0
+= tileComp
->cbW
) {
2578 dataPtr
= &tileComp
->data
[(y
- subband
->y0
)
2579 * (tileComp
->x1
- tileComp
->x0
)
2580 + (cb
->x0
- subband
->x0
)];
2581 for (x
= cb
->x0
, coeff
= coeff0
; x
< cb
->x1
; ++x
, ++coeff
) {
2582 val
= (int)coeff
->mag
;
2584 shift2
= shift
- (cb
->nZeroBitPlanes
+ coeff
->len
);
2587 val
= (val
<< shift2
) + (1 << (shift2
- 1));
2594 if (tileComp
->transform
== 0) {
2596 val
&= -1 << fracBits
;
2600 val
= (int)((double)val
* mu
);
2602 if (coeff
->flags
& jpxCoeffSign
) {
2614 //----- IDWT for each level
2616 for (r
= 1; r
<= tileComp
->nDecompLevels
; ++r
) {
2617 resLevel
= &tileComp
->resLevels
[r
];
2619 // (n)LL is already in the upper-left corner of the
2620 // tile-component data array -- interleave with (n)HL/LH/HH
2621 // and inverse transform to get (n-1)LL, which will be stored
2622 // in the upper-left corner of the tile-component data array
2623 if (r
== tileComp
->nDecompLevels
) {
2631 nx0
= tileComp
->resLevels
[r
+1].x0
;
2632 ny0
= tileComp
->resLevels
[r
+1].y0
;
2633 nx1
= tileComp
->resLevels
[r
+1].x1
;
2634 ny1
= tileComp
->resLevels
[r
+1].y1
;
2636 inverseTransformLevel(tileComp
, r
, resLevel
, nx0
, ny0
, nx1
, ny1
);
2640 // Do one level of the inverse transform:
2641 // - take (n)LL from the tile-component data array
2642 // - take (n)HL/LH/HH from <resLevel>
2643 // - leave the resulting (n-1)LL in the tile-component data array
2644 void JPXStream::inverseTransformLevel(JPXTileComp
*tileComp
,
2645 Guint r
, JPXResLevel
*resLevel
,
2646 Guint nx0
, Guint ny0
,
2647 Guint nx1
, Guint ny1
) {
2648 JPXPrecinct
*precinct
;
2649 JPXSubband
*subband
;
2651 JPXCoeff
*coeff0
, *coeff
;
2652 Guint qStyle
, guard
, eps
, shift
, t
;
2658 Guint x
, y
, sb
, cbX
, cbY
;
2664 for (yy
= resLevel
->y1
- 1; yy
>= (int)resLevel
->y0
; --yy
) {
2665 for (xx
= resLevel
->x1
- 1; xx
>= (int)resLevel
->x0
; --xx
) {
2666 tileComp
->data
[(2 * yy
- ny0
) * (tileComp
->x1
- tileComp
->x0
)
2668 tileComp
->data
[(yy
- resLevel
->y0
) * (tileComp
->x1
- tileComp
->x0
)
2669 + (xx
- resLevel
->x0
)];
2673 // i-quant parameters
2674 qStyle
= tileComp
->quantStyle
& 0x1f;
2675 guard
= (tileComp
->quantStyle
>> 5) & 7;
2677 // interleave HL/LH/HH
2678 precinct
= &resLevel
->precincts
[0];
2679 for (sb
= 0; sb
< 3; ++sb
) {
2681 // i-quant parameters
2684 eps
= (tileComp
->quantSteps
[3*r
- 2 + sb
] >> 3) & 0x1f;
2685 shift
= guard
+ eps
- 1;
2686 mu
= 0; // make gcc happy
2689 shift
= guard
+ tileComp
->prec
;
2694 t
= tileComp
->quantSteps
[qStyle
== 1 ? 0 : (3*r
- 2 + sb
)];
2695 mu
= (double)(0x800 + (t
& 0x7ff)) / 2048.0;
2697 if (tileComp
->transform
== 0) {
2702 // copy the subband coefficients into the data array, doing the
2703 // fixed point adjustment and dequantization along the way
2704 xo
= (sb
& 1) ? 0 : 1;
2705 yo
= (sb
> 0) ? 1 : 0;
2706 subband
= &precinct
->subbands
[sb
];
2708 for (cbY
= 0; cbY
< subband
->nYCBs
; ++cbY
) {
2709 for (cbX
= 0; cbX
< subband
->nXCBs
; ++cbX
) {
2710 for (y
= cb
->y0
, coeff0
= cb
->coeffs
;
2712 ++y
, coeff0
+= tileComp
->cbW
) {
2713 dataPtr
= &tileComp
->data
[(2 * y
+ yo
- ny0
)
2714 * (tileComp
->x1
- tileComp
->x0
)
2715 + (2 * cb
->x0
+ xo
- nx0
)];
2716 for (x
= cb
->x0
, coeff
= coeff0
; x
< cb
->x1
; ++x
, ++coeff
) {
2717 val
= (int)coeff
->mag
;
2719 shift2
= shift
- (cb
->nZeroBitPlanes
+ coeff
->len
);
2722 val
= (val
<< shift2
) + (1 << (shift2
- 1));
2729 if (tileComp
->transform
== 0) {
2730 val
&= -1 << fracBits
;
2734 val
= (int)((double)val
* mu
);
2736 if (coeff
->flags
& jpxCoeffSign
) {
2750 //----- horizontal (row) transforms
2751 dataPtr
= tileComp
->data
;
2752 for (y
= 0; y
< ny1
- ny0
; ++y
) {
2753 inverseTransform1D(tileComp
, dataPtr
, 1, nx0
, nx1
);
2754 dataPtr
+= tileComp
->x1
- tileComp
->x0
;
2757 //----- vertical (column) transforms
2758 dataPtr
= tileComp
->data
;
2759 for (x
= 0; x
< nx1
- nx0
; ++x
) {
2760 inverseTransform1D(tileComp
, dataPtr
,
2761 tileComp
->x1
- tileComp
->x0
, ny0
, ny1
);
2766 void JPXStream::inverseTransform1D(JPXTileComp
*tileComp
,
2767 int *data
, Guint stride
,
2768 Guint i0
, Guint i1
) {
2770 Guint offset
, end
, i
;
2772 //----- special case for length = 1
2783 // choose an offset: this makes even buf[] indexes correspond to
2784 // odd values of i, and vice versa
2785 offset
= 3 + (i0
& 1);
2786 end
= offset
+ i1
- i0
;
2789 buf
= tileComp
->buf
;
2790 for (i
= 0; i
< i1
- i0
; ++i
) {
2791 buf
[offset
+ i
] = data
[i
* stride
];
2794 //----- extend right
2795 buf
[end
] = buf
[end
- 2];
2798 buf
[end
+1] = buf
[offset
+ 1];
2799 buf
[end
+2] = buf
[offset
];
2800 buf
[end
+3] = buf
[offset
+ 1];
2803 buf
[end
+1] = buf
[end
- 3];
2806 buf
[end
+2] = buf
[offset
+ 1];
2807 buf
[end
+3] = buf
[offset
+ 2];
2810 buf
[end
+2] = buf
[end
- 4];
2813 buf
[end
+3] = buf
[offset
+ 1];
2816 buf
[end
+3] = buf
[end
- 5];
2822 buf
[offset
- 1] = buf
[offset
+ 1];
2823 buf
[offset
- 2] = buf
[offset
+ 2];
2824 buf
[offset
- 3] = buf
[offset
+ 3];
2827 buf
[0] = buf
[offset
+ 4];
2830 //----- 9-7 irreversible filter
2832 if (tileComp
->transform
== 0) {
2835 for (i
= 1; i
<= end
+ 2; i
+= 2) {
2836 buf
[i
] = (int)(idwtKappa
* buf
[i
]);
2839 for (i
= 0; i
<= end
+ 3; i
+= 2) {
2840 buf
[i
] = (int)(idwtIKappa
* buf
[i
]);
2843 for (i
= 1; i
<= end
+ 2; i
+= 2) {
2844 buf
[i
] = (int)(buf
[i
] - idwtDelta
* (buf
[i
-1] + buf
[i
+1]));
2847 for (i
= 2; i
<= end
+ 1; i
+= 2) {
2848 buf
[i
] = (int)(buf
[i
] - idwtGamma
* (buf
[i
-1] + buf
[i
+1]));
2851 for (i
= 3; i
<= end
; i
+= 2) {
2852 buf
[i
] = (int)(buf
[i
] - idwtBeta
* (buf
[i
-1] + buf
[i
+1]));
2855 for (i
= 4; i
<= end
- 1; i
+= 2) {
2856 buf
[i
] = (int)(buf
[i
] - idwtAlpha
* (buf
[i
-1] + buf
[i
+1]));
2859 //----- 5-3 reversible filter
2864 for (i
= 3; i
<= end
; i
+= 2) {
2865 buf
[i
] -= (buf
[i
-1] + buf
[i
+1] + 2) >> 2;
2868 for (i
= 4; i
< end
; i
+= 2) {
2869 buf
[i
] += (buf
[i
-1] + buf
[i
+1]) >> 1;
2874 for (i
= 0; i
< i1
- i0
; ++i
) {
2875 data
[i
* stride
] = buf
[offset
+ i
];
2880 // Inverse multi-component transform and DC level shift. This also
2881 // converts fixed point samples back to integers.
2882 GBool
JPXStream::inverseMultiCompAndDC(JPXTile
*tile
) {
2883 JPXTileComp
*tileComp
;
2884 int coeff
, d0
, d1
, d2
, t
, minVal
, maxVal
, zeroVal
;
2886 Guint j
, comp
, x
, y
;
2888 //----- inverse multi-component transform
2890 if (tile
->multiComp
== 1) {
2892 if (img
.nComps
< 3 ||
2893 tile
->tileComps
[0].hSep
!= tile
->tileComps
[1].hSep
||
2894 tile
->tileComps
[0].vSep
!= tile
->tileComps
[1].vSep
||
2895 tile
->tileComps
[1].hSep
!= tile
->tileComps
[2].hSep
||
2896 tile
->tileComps
[1].vSep
!= tile
->tileComps
[2].vSep
) {
2900 // inverse irreversible multiple component transform
2901 if (tile
->tileComps
[0].transform
== 0) {
2904 for (y
= 0; y
< tile
->tileComps
[0].y1
- tile
->tileComps
[0].y0
; ++y
) {
2905 for (x
= 0; x
< tile
->tileComps
[0].x1
- tile
->tileComps
[0].x0
; ++x
) {
2906 d0
= tile
->tileComps
[0].data
[j
];
2907 d1
= tile
->tileComps
[1].data
[j
];
2908 d2
= tile
->tileComps
[2].data
[j
];
2909 tile
->tileComps
[0].data
[j
] = (int)(d0
+ 1.402 * d2
+ 0.5);
2910 tile
->tileComps
[1].data
[j
] =
2911 (int)(d0
- 0.34413 * d1
- 0.71414 * d2
+ 0.5);
2912 tile
->tileComps
[2].data
[j
] = (int)(d0
+ 1.772 * d1
+ 0.5);
2917 // inverse reversible multiple component transform
2921 for (y
= 0; y
< tile
->tileComps
[0].y1
- tile
->tileComps
[0].y0
; ++y
) {
2922 for (x
= 0; x
< tile
->tileComps
[0].x1
- tile
->tileComps
[0].x0
; ++x
) {
2923 d0
= tile
->tileComps
[0].data
[j
];
2924 d1
= tile
->tileComps
[1].data
[j
];
2925 d2
= tile
->tileComps
[2].data
[j
];
2926 tile
->tileComps
[1].data
[j
] = t
= d0
- ((d2
+ d1
) >> 2);
2927 tile
->tileComps
[0].data
[j
] = d2
+ t
;
2928 tile
->tileComps
[2].data
[j
] = d1
+ t
;
2935 //----- DC level shift
2936 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
2937 tileComp
= &tile
->tileComps
[comp
];
2940 if (tileComp
->sgned
) {
2942 minVal
= -(1 << (tileComp
->prec
- 1));
2943 maxVal
= (1 << (tileComp
->prec
- 1)) - 1;
2944 dataPtr
= tileComp
->data
;
2945 for (y
= 0; y
< tileComp
->y1
- tileComp
->y0
; ++y
) {
2946 for (x
= 0; x
< tileComp
->x1
- tileComp
->x0
; ++x
) {
2948 if (tileComp
->transform
== 0) {
2952 if (coeff
< minVal
) {
2955 } else if (coeff
> maxVal
) {
2963 // unsigned: inverse DC level shift and clip
2966 maxVal
= (1 << tileComp
->prec
) - 1;
2967 zeroVal
= 1 << (tileComp
->prec
- 1);
2968 dataPtr
= tileComp
->data
;
2969 for (y
= 0; y
< tileComp
->y1
- tileComp
->y0
; ++y
) {
2970 for (x
= 0; x
< tileComp
->x1
- tileComp
->x0
; ++x
) {
2972 if (tileComp
->transform
== 0) {
2980 } else if (coeff
> maxVal
) {
2993 GBool
JPXStream::readBoxHdr(Guint
*boxType
, Guint
*boxLen
, Guint
*dataLen
) {
2996 if (!readULong(&len
) ||
2997 !readULong(boxType
)) {
3001 if (!readULong(&lenH
) || !readULong(&len
)) {
3005 error(getPos(), "JPX stream contains a box larger than 2^32 bytes");
3009 *dataLen
= len
- 16;
3010 } else if (len
== 0) {
3020 int JPXStream::readMarkerHdr(int *segType
, Guint
*segLen
) {
3025 if ((c
= str
->getChar()) == EOF
) {
3028 } while (c
!= 0xff);
3030 if ((c
= str
->getChar()) == EOF
) {
3033 } while (c
== 0xff);
3034 } while (c
== 0x00);
3036 if ((c
>= 0x30 && c
<= 0x3f) ||
3037 c
== 0x4f || c
== 0x92 || c
== 0x93 || c
== 0xd9) {
3041 return readUWord(segLen
);
3044 GBool
JPXStream::readUByte(Guint
*x
) {
3047 if ((c0
= str
->getChar()) == EOF
) {
3054 GBool
JPXStream::readByte(int *x
) {
3057 if ((c0
= str
->getChar()) == EOF
) {
3067 GBool
JPXStream::readUWord(Guint
*x
) {
3070 if ((c0
= str
->getChar()) == EOF
||
3071 (c1
= str
->getChar()) == EOF
) {
3074 *x
= (Guint
)((c0
<< 8) | c1
);
3078 GBool
JPXStream::readULong(Guint
*x
) {
3081 if ((c0
= str
->getChar()) == EOF
||
3082 (c1
= str
->getChar()) == EOF
||
3083 (c2
= str
->getChar()) == EOF
||
3084 (c3
= str
->getChar()) == EOF
) {
3087 *x
= (Guint
)((c0
<< 24) | (c1
<< 16) | (c2
<< 8) | c3
);
3091 GBool
JPXStream::readNBytes(int nBytes
, GBool signd
, int *x
) {
3095 for (i
= 0; i
< nBytes
; ++i
) {
3096 if ((c
= str
->getChar()) == EOF
) {
3102 if (y
& (1 << (8 * nBytes
- 1))) {
3103 y
|= -1 << (8 * nBytes
);
3110 GBool
JPXStream::readBits(int nBits
, Guint
*x
) {
3113 while (bitBufLen
< nBits
) {
3114 if (byteCount
== 0 || (c
= str
->getChar()) == EOF
) {
3119 bitBuf
= (bitBuf
<< 7) | (c
& 0x7f);
3122 bitBuf
= (bitBuf
<< 8) | (c
& 0xff);
3125 bitBufSkip
= c
== 0xff;
3127 *x
= (bitBuf
>> (bitBufLen
- nBits
)) & ((1 << nBits
) - 1);
3132 void JPXStream::startBitBuf(Guint byteCountA
) {
3134 bitBufSkip
= gFalse
;
3135 byteCount
= byteCountA
;
3138 Guint
JPXStream::finishBitBuf() {