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 JPXStream::JPXStream(Stream
*strA
):
187 havePalette
= gFalse
;
188 haveCompMap
= gFalse
;
189 haveChannelDefn
= gFalse
;
198 JPXStream::~JPXStream() {
200 JPXTileComp
*tileComp
;
201 JPXResLevel
*resLevel
;
202 JPXPrecinct
*precinct
;
205 Guint comp
, i
, k
, r
, pre
, sb
;
215 gfree(compMap
.pComp
);
217 if (haveChannelDefn
) {
218 gfree(channelDefn
.idx
);
219 gfree(channelDefn
.type
);
220 gfree(channelDefn
.assoc
);
224 for (i
= 0; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
225 tile
= &img
.tiles
[i
];
226 if (tile
->tileComps
) {
227 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
228 tileComp
= &tile
->tileComps
[comp
];
229 gfree(tileComp
->quantSteps
);
230 gfree(tileComp
->data
);
231 gfree(tileComp
->buf
);
232 if (tileComp
->resLevels
) {
233 for (r
= 0; r
<= tileComp
->nDecompLevels
; ++r
) {
234 resLevel
= &tileComp
->resLevels
[r
];
235 if (resLevel
->precincts
) {
236 for (pre
= 0; pre
< 1; ++pre
) {
237 precinct
= &resLevel
->precincts
[pre
];
238 if (precinct
->subbands
) {
239 for (sb
= 0; sb
< (r
== 0 ? 1 : 3); ++sb
) {
240 subband
= &precinct
->subbands
[sb
];
241 gfree(subband
->inclusion
);
242 gfree(subband
->zeroBitPlane
);
244 for (k
= 0; k
< subband
->nXCBs
* subband
->nYCBs
; ++k
) {
245 cb
= &subband
->cbs
[k
];
247 if (cb
->arithDecoder
) {
248 delete cb
->arithDecoder
;
257 gfree(precinct
->subbands
);
260 gfree(img
.tiles
[i
].tileComps
[comp
].resLevels
[r
].precincts
);
263 gfree(img
.tiles
[i
].tileComps
[comp
].resLevels
);
266 gfree(img
.tiles
[i
].tileComps
);
274 void JPXStream::reset() {
279 // readBoxes reported an error, so we go immediately to EOF
287 int JPXStream::getChar() {
290 if (readBufLen
< 8) {
293 if (readBufLen
== 8) {
296 } else if (readBufLen
> 8) {
297 c
= (readBuf
>> (readBufLen
- 8)) & 0xff;
299 } else if (readBufLen
== 0) {
302 c
= (readBuf
<< (8 - readBufLen
)) & 0xff;
308 int JPXStream::lookChar() {
311 if (readBufLen
< 8) {
314 if (readBufLen
== 8) {
316 } else if (readBufLen
> 8) {
317 c
= (readBuf
>> (readBufLen
- 8)) & 0xff;
318 } else if (readBufLen
== 0) {
321 c
= (readBuf
<< (8 - readBufLen
)) & 0xff;
326 void JPXStream::fillReadBuf() {
327 JPXTileComp
*tileComp
;
328 Guint tileIdx
, tx
, ty
;
332 if (curY
>= img
.ySize
) {
335 tileIdx
= ((curY
- img
.yTileOffset
) / img
.yTileSize
) * img
.nXTiles
336 + (curX
- img
.xTileOffset
) / img
.xTileSize
;
337 #if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid
338 tileComp
= &img
.tiles
[tileIdx
].tileComps
[curComp
];
340 tileComp
= &img
.tiles
[tileIdx
].tileComps
[havePalette
? 0 : curComp
];
342 tx
= jpxCeilDiv((curX
- img
.xTileOffset
) % img
.xTileSize
, tileComp
->hSep
);
343 ty
= jpxCeilDiv((curY
- img
.yTileOffset
) % img
.yTileSize
, tileComp
->vSep
);
344 pix
= (int)tileComp
->data
[ty
* (tileComp
->x1
- tileComp
->x0
) + tx
];
345 pixBits
= tileComp
->prec
;
346 #if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid
347 if (++curComp
== img
.nComps
) {
350 if (pix
>= 0 && pix
< palette
.nEntries
) {
351 pix
= palette
.c
[pix
* palette
.nComps
+ curComp
];
354 pixBits
= palette
.bpc
[curComp
];
356 if (++curComp
== (Guint
)(havePalette
? palette
.nComps
: img
.nComps
)) {
359 if (++curX
== img
.xSize
) {
365 readBuf
= (readBuf
<< 8) | (pix
& 0xff);
367 readBuf
= (readBuf
<< pixBits
) | (pix
& ((1 << pixBits
) - 1));
369 readBufLen
+= pixBits
;
370 } while (readBufLen
< 8);
373 GString
*JPXStream::getPSFilter(int psLevel
, char *indent
) {
377 GBool
JPXStream::isBinary(GBool last
) {
378 return str
->isBinary(gTrue
);
381 void JPXStream::getImageParams(int *bitsPerComponent
,
382 StreamColorSpaceMode
*csMode
) {
383 Guint boxType
, boxLen
, dataLen
, csEnum
;
384 Guint bpc1
, dummy
, i
;
385 int csMeth
, csPrec
, csPrec1
, dummy2
;
386 StreamColorSpaceMode csMode1
;
387 GBool haveBPC
, haveCSMode
;
389 csPrec
= 0; // make gcc happy
390 haveBPC
= haveCSMode
= gFalse
;
392 if (str
->lookChar() == 0xff) {
393 getImageParams2(bitsPerComponent
, csMode
);
395 while (readBoxHdr(&boxType
, &boxLen
, &dataLen
)) {
396 if (boxType
== 0x6a703268) { // JP2 header
398 } else if (boxType
== 0x69686472) { // image header
399 if (readULong(&dummy
) &&
406 *bitsPerComponent
= bpc1
+ 1;
409 } else if (boxType
== 0x636F6C72) { // color specification
410 if (readByte(&csMeth
) &&
411 readByte(&csPrec1
) &&
414 if (readULong(&csEnum
)) {
415 csMode1
= streamCSNone
;
416 if (csEnum
== jpxCSBiLevel
||
417 csEnum
== jpxCSGrayscale
) {
418 csMode1
= streamCSDeviceGray
;
419 } else if (csEnum
== jpxCSCMYK
) {
420 csMode1
= streamCSDeviceCMYK
;
421 } else if (csEnum
== jpxCSsRGB
||
422 csEnum
== jpxCSCISesRGB
||
423 csEnum
== jpxCSROMMRGB
) {
424 csMode1
= streamCSDeviceRGB
;
426 if (csMode1
!= streamCSNone
&&
427 (!haveCSMode
|| csPrec1
> csPrec
)) {
432 for (i
= 0; i
< dataLen
- 7; ++i
) {
437 for (i
= 0; i
< dataLen
- 3; ++i
) {
442 } else if (boxType
== 0x6A703263) { // codestream
443 if (!(haveBPC
&& haveCSMode
)) {
444 getImageParams2(bitsPerComponent
, csMode
);
448 for (i
= 0; i
< dataLen
; ++i
) {
457 // Get image parameters from the codestream.
458 void JPXStream::getImageParams2(int *bitsPerComponent
,
459 StreamColorSpaceMode
*csMode
) {
461 Guint segLen
, nComps1
, bpc1
, dummy
, i
;
463 while (readMarkerHdr(&segType
, &segLen
)) {
464 if (segType
== 0x51) { // SIZ - image and tile size
465 if (readUWord(&dummy
) &&
474 readUWord(&nComps1
) &&
476 *bitsPerComponent
= (bpc1
& 0x7f) + 1;
477 // if there's no color space info, take a guess
479 *csMode
= streamCSDeviceGray
;
480 } else if (nComps1
== 3) {
481 *csMode
= streamCSDeviceRGB
;
482 } else if (nComps1
== 4) {
483 *csMode
= streamCSDeviceCMYK
;
489 for (i
= 0; i
< segLen
- 2; ++i
) {
497 GBool
JPXStream::readBoxes() {
498 Guint boxType
, boxLen
, dataLen
;
499 Guint bpc1
, compression
, unknownColorspace
, ipr
;
504 // check for a naked JPEG 2000 codestream (without the JP2/JPX
505 // wrapper) -- this appears to be a violation of the PDF spec, but
507 if (str
->lookChar() == 0xff) {
508 error(getPos(), "Naked JPEG 2000 codestream, missing JP2/JPX wrapper");
511 bpc
= (Guint
*)gmallocn(nComps
, sizeof(Guint
));
512 for (i
= 0; i
< nComps
; ++i
) {
513 bpc
[i
] = img
.tiles
[0].tileComps
[i
].prec
;
515 width
= img
.xSize
- img
.xOffset
;
516 height
= img
.ySize
- img
.yOffset
;
520 while (readBoxHdr(&boxType
, &boxLen
, &dataLen
)) {
522 case 0x6a703268: // JP2 header
523 // this is a grouping box ('superbox') which has no real
524 // contents and doesn't appear to be used consistently, i.e.,
525 // some things which should be subboxes of the JP2 header box
526 // show up outside of it - so we simply ignore the JP2 header
529 case 0x69686472: // image header
530 if (!readULong(&height
) ||
531 !readULong(&width
) ||
532 !readUWord(&nComps
) ||
534 !readUByte(&compression
) ||
535 !readUByte(&unknownColorspace
) ||
537 error(getPos(), "Unexpected EOF in JPX stream");
540 if (compression
!= 7) {
541 error(getPos(), "Unknown compression type in JPX stream");
544 bpc
= (Guint
*)gmallocn(nComps
, sizeof(Guint
));
545 for (i
= 0; i
< nComps
; ++i
) {
550 case 0x62706363: // bits per component
552 error(getPos(), "Found bits per component box before image header box in JPX stream");
555 if (dataLen
!= nComps
) {
556 error(getPos(), "Invalid bits per component box in JPX stream");
559 for (i
= 0; i
< nComps
; ++i
) {
560 if (!readUByte(&bpc
[i
])) {
561 error(getPos(), "Unexpected EOF in JPX stream");
566 case 0x636F6C72: // color specification
567 if (!readColorSpecBox(dataLen
)) {
571 case 0x70636c72: // palette
572 if (!readUWord(&palette
.nEntries
) ||
573 !readUByte(&palette
.nComps
)) {
574 error(getPos(), "Unexpected EOF in JPX stream");
577 palette
.bpc
= (Guint
*)gmallocn(palette
.nComps
, sizeof(Guint
));
579 (int *)gmallocn(palette
.nEntries
* palette
.nComps
, sizeof(int));
580 for (i
= 0; i
< palette
.nComps
; ++i
) {
581 if (!readUByte(&palette
.bpc
[i
])) {
582 error(getPos(), "Unexpected EOF in JPX stream");
587 for (i
= 0; i
< palette
.nEntries
; ++i
) {
588 for (j
= 0; j
< palette
.nComps
; ++j
) {
589 if (!readNBytes(((palette
.bpc
[j
] & 0x7f) + 7) >> 3,
590 (palette
.bpc
[j
] & 0x80) ? gTrue
: gFalse
,
591 &palette
.c
[i
* palette
.nComps
+ j
])) {
592 error(getPos(), "Unexpected EOF in JPX stream");
599 case 0x636d6170: // component mapping
600 compMap
.nChannels
= dataLen
/ 4;
601 compMap
.comp
= (Guint
*)gmallocn(compMap
.nChannels
, sizeof(Guint
));
602 compMap
.type
= (Guint
*)gmallocn(compMap
.nChannels
, sizeof(Guint
));
603 compMap
.pComp
= (Guint
*)gmallocn(compMap
.nChannels
, sizeof(Guint
));
604 for (i
= 0; i
< compMap
.nChannels
; ++i
) {
605 if (!readUWord(&compMap
.comp
[i
]) ||
606 !readUByte(&compMap
.type
[i
]) ||
607 !readUByte(&compMap
.pComp
[i
])) {
608 error(getPos(), "Unexpected EOF in JPX stream");
614 case 0x63646566: // channel definition
615 if (!readUWord(&channelDefn
.nChannels
)) {
616 error(getPos(), "Unexpected EOF in JPX stream");
620 (Guint
*)gmallocn(channelDefn
.nChannels
, sizeof(Guint
));
622 (Guint
*)gmallocn(channelDefn
.nChannels
, sizeof(Guint
));
624 (Guint
*)gmallocn(channelDefn
.nChannels
, sizeof(Guint
));
625 for (i
= 0; i
< channelDefn
.nChannels
; ++i
) {
626 if (!readUWord(&channelDefn
.idx
[i
]) ||
627 !readUWord(&channelDefn
.type
[i
]) ||
628 !readUWord(&channelDefn
.assoc
[i
])) {
629 error(getPos(), "Unexpected EOF in JPX stream");
633 haveChannelDefn
= gTrue
;
635 case 0x6A703263: // contiguous codestream
637 error(getPos(), "JPX stream is missing the image header box");
640 error(getPos(), "JPX stream has no supported color spec");
642 if (!readCodestream(dataLen
)) {
647 for (i
= 0; i
< dataLen
; ++i
) {
648 if (str
->getChar() == EOF
) {
649 error(getPos(), "Unexpected EOF in JPX stream");
659 GBool
JPXStream::readColorSpecBox(Guint dataLen
) {
661 Guint csApprox
, csEnum
;
666 if (!readUByte(&newCS
.meth
) ||
667 !readByte(&newCS
.prec
) ||
668 !readUByte(&csApprox
)) {
671 switch (newCS
.meth
) {
672 case 1: // enumerated colorspace
673 if (!readULong(&csEnum
)) {
676 newCS
.enumerated
.type
= (JPXColorSpaceType
)csEnum
;
677 switch (newCS
.enumerated
.type
) {
703 if (dataLen
== 7 + 7*4) {
704 if (!readULong(&newCS
.enumerated
.cieLab
.rl
) ||
705 !readULong(&newCS
.enumerated
.cieLab
.ol
) ||
706 !readULong(&newCS
.enumerated
.cieLab
.ra
) ||
707 !readULong(&newCS
.enumerated
.cieLab
.oa
) ||
708 !readULong(&newCS
.enumerated
.cieLab
.rb
) ||
709 !readULong(&newCS
.enumerated
.cieLab
.ob
) ||
710 !readULong(&newCS
.enumerated
.cieLab
.il
)) {
713 } else if (dataLen
== 7) {
714 //~ this assumes the 8-bit case
715 newCS
.enumerated
.cieLab
.rl
= 100;
716 newCS
.enumerated
.cieLab
.ol
= 0;
717 newCS
.enumerated
.cieLab
.ra
= 255;
718 newCS
.enumerated
.cieLab
.oa
= 128;
719 newCS
.enumerated
.cieLab
.rb
= 255;
720 newCS
.enumerated
.cieLab
.ob
= 96;
721 newCS
.enumerated
.cieLab
.il
= 0x00443530;
737 // not allowed in PDF
758 case 2: // restricted ICC profile
759 case 3: // any ICC profile (JPX)
760 case 4: // vendor color (JPX)
761 for (i
= 0; i
< dataLen
- 3; ++i
) {
762 if (str
->getChar() == EOF
) {
769 if (ok
&& (!haveCS
|| newCS
.prec
> cs
.prec
)) {
777 error(getPos(), "Error in JPX color spec");
781 GBool
JPXStream::readCodestream(Guint len
) {
783 JPXTileComp
*tileComp
;
785 GBool haveSIZ
, haveCOD
, haveQCD
, haveSOT
;
786 Guint precinctSize
, style
;
787 Guint segLen
, capabilities
, comp
, i
, j
, r
;
790 haveSIZ
= haveCOD
= haveQCD
= haveSOT
= gFalse
;
792 if (!readMarkerHdr(&segType
, &segLen
)) {
793 error(getPos(), "Error in JPX codestream");
797 case 0x4f: // SOC - start of codestream
800 case 0x51: // SIZ - image and tile size
801 if (!readUWord(&capabilities
) ||
802 !readULong(&img
.xSize
) ||
803 !readULong(&img
.ySize
) ||
804 !readULong(&img
.xOffset
) ||
805 !readULong(&img
.yOffset
) ||
806 !readULong(&img
.xTileSize
) ||
807 !readULong(&img
.yTileSize
) ||
808 !readULong(&img
.xTileOffset
) ||
809 !readULong(&img
.yTileOffset
) ||
810 !readUWord(&img
.nComps
)) {
811 error(getPos(), "Error in JPX SIZ marker segment");
814 if (haveImgHdr
&& img
.nComps
!= nComps
) {
815 error(getPos(), "Different number of components in JPX SIZ marker segment");
818 img
.nXTiles
= (img
.xSize
- img
.xTileOffset
+ img
.xTileSize
- 1)
820 img
.nYTiles
= (img
.ySize
- img
.yTileOffset
+ img
.yTileSize
- 1)
822 // check for overflow before allocating memory
823 if (img
.nXTiles
<= 0 || img
.nYTiles
<= 0 ||
824 img
.nXTiles
>= INT_MAX
/ img
.nYTiles
) {
825 error(getPos(), "Bad tile count in JPX SIZ marker segment");
828 img
.tiles
= (JPXTile
*)gmallocn(img
.nXTiles
* img
.nYTiles
,
830 for (i
= 0; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
831 img
.tiles
[i
].tileComps
= (JPXTileComp
*)gmallocn(img
.nComps
,
832 sizeof(JPXTileComp
));
833 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
834 img
.tiles
[i
].tileComps
[comp
].quantSteps
= NULL
;
835 img
.tiles
[i
].tileComps
[comp
].data
= NULL
;
836 img
.tiles
[i
].tileComps
[comp
].buf
= NULL
;
837 img
.tiles
[i
].tileComps
[comp
].resLevels
= NULL
;
840 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
841 if (!readUByte(&img
.tiles
[0].tileComps
[comp
].prec
) ||
842 !readUByte(&img
.tiles
[0].tileComps
[comp
].hSep
) ||
843 !readUByte(&img
.tiles
[0].tileComps
[comp
].vSep
)) {
844 error(getPos(), "Error in JPX SIZ marker segment");
847 img
.tiles
[0].tileComps
[comp
].sgned
=
848 (img
.tiles
[0].tileComps
[comp
].prec
& 0x80) ? gTrue
: gFalse
;
849 img
.tiles
[0].tileComps
[comp
].prec
=
850 (img
.tiles
[0].tileComps
[comp
].prec
& 0x7f) + 1;
851 for (i
= 1; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
852 img
.tiles
[i
].tileComps
[comp
] = img
.tiles
[0].tileComps
[comp
];
857 case 0x52: // COD - coding style default
858 if (!readUByte(&img
.tiles
[0].tileComps
[0].style
) ||
859 !readUByte(&img
.tiles
[0].progOrder
) ||
860 !readUWord(&img
.tiles
[0].nLayers
) ||
861 !readUByte(&img
.tiles
[0].multiComp
) ||
862 !readUByte(&img
.tiles
[0].tileComps
[0].nDecompLevels
) ||
863 !readUByte(&img
.tiles
[0].tileComps
[0].codeBlockW
) ||
864 !readUByte(&img
.tiles
[0].tileComps
[0].codeBlockH
) ||
865 !readUByte(&img
.tiles
[0].tileComps
[0].codeBlockStyle
) ||
866 !readUByte(&img
.tiles
[0].tileComps
[0].transform
)) {
867 error(getPos(), "Error in JPX COD marker segment");
870 img
.tiles
[0].tileComps
[0].codeBlockW
+= 2;
871 img
.tiles
[0].tileComps
[0].codeBlockH
+= 2;
872 for (i
= 0; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
874 img
.tiles
[i
].progOrder
= img
.tiles
[0].progOrder
;
875 img
.tiles
[i
].nLayers
= img
.tiles
[0].nLayers
;
876 img
.tiles
[i
].multiComp
= img
.tiles
[0].multiComp
;
878 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
879 if (!(i
== 0 && comp
== 0)) {
880 img
.tiles
[i
].tileComps
[comp
].style
=
881 img
.tiles
[0].tileComps
[0].style
;
882 img
.tiles
[i
].tileComps
[comp
].nDecompLevels
=
883 img
.tiles
[0].tileComps
[0].nDecompLevels
;
884 img
.tiles
[i
].tileComps
[comp
].codeBlockW
=
885 img
.tiles
[0].tileComps
[0].codeBlockW
;
886 img
.tiles
[i
].tileComps
[comp
].codeBlockH
=
887 img
.tiles
[0].tileComps
[0].codeBlockH
;
888 img
.tiles
[i
].tileComps
[comp
].codeBlockStyle
=
889 img
.tiles
[0].tileComps
[0].codeBlockStyle
;
890 img
.tiles
[i
].tileComps
[comp
].transform
=
891 img
.tiles
[0].tileComps
[0].transform
;
893 img
.tiles
[i
].tileComps
[comp
].resLevels
=
894 (JPXResLevel
*)gmallocn(
895 (img
.tiles
[i
].tileComps
[comp
].nDecompLevels
+ 1),
896 sizeof(JPXResLevel
));
897 for (r
= 0; r
<= img
.tiles
[i
].tileComps
[comp
].nDecompLevels
; ++r
) {
898 img
.tiles
[i
].tileComps
[comp
].resLevels
[r
].precincts
= NULL
;
902 for (r
= 0; r
<= img
.tiles
[0].tileComps
[0].nDecompLevels
; ++r
) {
903 if (img
.tiles
[0].tileComps
[0].style
& 0x01) {
904 if (!readUByte(&precinctSize
)) {
905 error(getPos(), "Error in JPX COD marker segment");
908 img
.tiles
[0].tileComps
[0].resLevels
[r
].precinctWidth
=
910 img
.tiles
[0].tileComps
[0].resLevels
[r
].precinctHeight
=
911 (precinctSize
>> 4) & 0x0f;
913 img
.tiles
[0].tileComps
[0].resLevels
[r
].precinctWidth
= 15;
914 img
.tiles
[0].tileComps
[0].resLevels
[r
].precinctHeight
= 15;
917 for (i
= 0; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
918 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
919 if (!(i
== 0 && comp
== 0)) {
920 for (r
= 0; r
<= img
.tiles
[i
].tileComps
[comp
].nDecompLevels
; ++r
) {
921 img
.tiles
[i
].tileComps
[comp
].resLevels
[r
].precinctWidth
=
922 img
.tiles
[0].tileComps
[0].resLevels
[r
].precinctWidth
;
923 img
.tiles
[i
].tileComps
[comp
].resLevels
[r
].precinctHeight
=
924 img
.tiles
[0].tileComps
[0].resLevels
[r
].precinctHeight
;
931 case 0x53: // COC - coding style component
933 error(getPos(), "JPX COC marker segment before COD segment");
936 if ((img
.nComps
> 256 && !readUWord(&comp
)) ||
937 (img
.nComps
<= 256 && !readUByte(&comp
)) ||
938 comp
>= img
.nComps
||
939 !readUByte(&style
) ||
940 !readUByte(&img
.tiles
[0].tileComps
[comp
].nDecompLevels
) ||
941 !readUByte(&img
.tiles
[0].tileComps
[comp
].codeBlockW
) ||
942 !readUByte(&img
.tiles
[0].tileComps
[comp
].codeBlockH
) ||
943 !readUByte(&img
.tiles
[0].tileComps
[comp
].codeBlockStyle
) ||
944 !readUByte(&img
.tiles
[0].tileComps
[comp
].transform
)) {
945 error(getPos(), "Error in JPX COC marker segment");
948 img
.tiles
[0].tileComps
[comp
].style
=
949 (img
.tiles
[0].tileComps
[comp
].style
& ~1) | (style
& 1);
950 img
.tiles
[0].tileComps
[comp
].codeBlockW
+= 2;
951 img
.tiles
[0].tileComps
[comp
].codeBlockH
+= 2;
952 for (i
= 0; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
954 img
.tiles
[i
].tileComps
[comp
].style
=
955 img
.tiles
[0].tileComps
[comp
].style
;
956 img
.tiles
[i
].tileComps
[comp
].nDecompLevels
=
957 img
.tiles
[0].tileComps
[comp
].nDecompLevels
;
958 img
.tiles
[i
].tileComps
[comp
].codeBlockW
=
959 img
.tiles
[0].tileComps
[comp
].codeBlockW
;
960 img
.tiles
[i
].tileComps
[comp
].codeBlockH
=
961 img
.tiles
[0].tileComps
[comp
].codeBlockH
;
962 img
.tiles
[i
].tileComps
[comp
].codeBlockStyle
=
963 img
.tiles
[0].tileComps
[comp
].codeBlockStyle
;
964 img
.tiles
[i
].tileComps
[comp
].transform
=
965 img
.tiles
[0].tileComps
[comp
].transform
;
967 img
.tiles
[i
].tileComps
[comp
].resLevels
=
968 (JPXResLevel
*)greallocn(
969 img
.tiles
[i
].tileComps
[comp
].resLevels
,
970 (img
.tiles
[i
].tileComps
[comp
].nDecompLevels
+ 1),
971 sizeof(JPXResLevel
));
972 for (r
= 0; r
<= img
.tiles
[i
].tileComps
[comp
].nDecompLevels
; ++r
) {
973 img
.tiles
[i
].tileComps
[comp
].resLevels
[r
].precincts
= NULL
;
976 for (r
= 0; r
<= img
.tiles
[0].tileComps
[comp
].nDecompLevels
; ++r
) {
977 if (img
.tiles
[0].tileComps
[comp
].style
& 0x01) {
978 if (!readUByte(&precinctSize
)) {
979 error(getPos(), "Error in JPX COD marker segment");
982 img
.tiles
[0].tileComps
[comp
].resLevels
[r
].precinctWidth
=
984 img
.tiles
[0].tileComps
[comp
].resLevels
[r
].precinctHeight
=
985 (precinctSize
>> 4) & 0x0f;
987 img
.tiles
[0].tileComps
[comp
].resLevels
[r
].precinctWidth
= 15;
988 img
.tiles
[0].tileComps
[comp
].resLevels
[r
].precinctHeight
= 15;
991 for (i
= 1; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
992 for (r
= 0; r
<= img
.tiles
[i
].tileComps
[comp
].nDecompLevels
; ++r
) {
993 img
.tiles
[i
].tileComps
[comp
].resLevels
[r
].precinctWidth
=
994 img
.tiles
[0].tileComps
[comp
].resLevels
[r
].precinctWidth
;
995 img
.tiles
[i
].tileComps
[comp
].resLevels
[r
].precinctHeight
=
996 img
.tiles
[0].tileComps
[comp
].resLevels
[r
].precinctHeight
;
1000 case 0x5c: // QCD - quantization default
1001 if (!readUByte(&img
.tiles
[0].tileComps
[0].quantStyle
)) {
1002 error(getPos(), "Error in JPX QCD marker segment");
1005 if ((img
.tiles
[0].tileComps
[0].quantStyle
& 0x1f) == 0x00) {
1006 img
.tiles
[0].tileComps
[0].nQuantSteps
= segLen
- 3;
1007 img
.tiles
[0].tileComps
[0].quantSteps
=
1008 (Guint
*)greallocn(img
.tiles
[0].tileComps
[0].quantSteps
,
1009 img
.tiles
[0].tileComps
[0].nQuantSteps
,
1011 for (i
= 0; i
< img
.tiles
[0].tileComps
[0].nQuantSteps
; ++i
) {
1012 if (!readUByte(&img
.tiles
[0].tileComps
[0].quantSteps
[i
])) {
1013 error(getPos(), "Error in JPX QCD marker segment");
1017 } else if ((img
.tiles
[0].tileComps
[0].quantStyle
& 0x1f) == 0x01) {
1018 img
.tiles
[0].tileComps
[0].nQuantSteps
= 1;
1019 img
.tiles
[0].tileComps
[0].quantSteps
=
1020 (Guint
*)greallocn(img
.tiles
[0].tileComps
[0].quantSteps
,
1021 img
.tiles
[0].tileComps
[0].nQuantSteps
,
1023 if (!readUWord(&img
.tiles
[0].tileComps
[0].quantSteps
[0])) {
1024 error(getPos(), "Error in JPX QCD marker segment");
1027 } else if ((img
.tiles
[0].tileComps
[0].quantStyle
& 0x1f) == 0x02) {
1028 img
.tiles
[0].tileComps
[0].nQuantSteps
= (segLen
- 3) / 2;
1029 img
.tiles
[0].tileComps
[0].quantSteps
=
1030 (Guint
*)greallocn(img
.tiles
[0].tileComps
[0].quantSteps
,
1031 img
.tiles
[0].tileComps
[0].nQuantSteps
,
1033 for (i
= 0; i
< img
.tiles
[0].tileComps
[0].nQuantSteps
; ++i
) {
1034 if (!readUWord(&img
.tiles
[0].tileComps
[0].quantSteps
[i
])) {
1035 error(getPos(), "Error in JPX QCD marker segment");
1040 error(getPos(), "Error in JPX QCD marker segment");
1043 for (i
= 0; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
1044 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
1045 if (!(i
== 0 && comp
== 0)) {
1046 img
.tiles
[i
].tileComps
[comp
].quantStyle
=
1047 img
.tiles
[0].tileComps
[0].quantStyle
;
1048 img
.tiles
[i
].tileComps
[comp
].nQuantSteps
=
1049 img
.tiles
[0].tileComps
[0].nQuantSteps
;
1050 img
.tiles
[i
].tileComps
[comp
].quantSteps
=
1051 (Guint
*)greallocn(img
.tiles
[i
].tileComps
[comp
].quantSteps
,
1052 img
.tiles
[0].tileComps
[0].nQuantSteps
,
1054 for (j
= 0; j
< img
.tiles
[0].tileComps
[0].nQuantSteps
; ++j
) {
1055 img
.tiles
[i
].tileComps
[comp
].quantSteps
[j
] =
1056 img
.tiles
[0].tileComps
[0].quantSteps
[j
];
1063 case 0x5d: // QCC - quantization component
1065 error(getPos(), "JPX QCC marker segment before QCD segment");
1068 if ((img
.nComps
> 256 && !readUWord(&comp
)) ||
1069 (img
.nComps
<= 256 && !readUByte(&comp
)) ||
1070 comp
>= img
.nComps
||
1071 !readUByte(&img
.tiles
[0].tileComps
[comp
].quantStyle
)) {
1072 error(getPos(), "Error in JPX QCC marker segment");
1075 if ((img
.tiles
[0].tileComps
[comp
].quantStyle
& 0x1f) == 0x00) {
1076 img
.tiles
[0].tileComps
[comp
].nQuantSteps
=
1077 segLen
- (img
.nComps
> 256 ? 5 : 4);
1078 img
.tiles
[0].tileComps
[comp
].quantSteps
=
1079 (Guint
*)greallocn(img
.tiles
[0].tileComps
[comp
].quantSteps
,
1080 img
.tiles
[0].tileComps
[comp
].nQuantSteps
,
1082 for (i
= 0; i
< img
.tiles
[0].tileComps
[comp
].nQuantSteps
; ++i
) {
1083 if (!readUByte(&img
.tiles
[0].tileComps
[comp
].quantSteps
[i
])) {
1084 error(getPos(), "Error in JPX QCC marker segment");
1088 } else if ((img
.tiles
[0].tileComps
[comp
].quantStyle
& 0x1f) == 0x01) {
1089 img
.tiles
[0].tileComps
[comp
].nQuantSteps
= 1;
1090 img
.tiles
[0].tileComps
[comp
].quantSteps
=
1091 (Guint
*)greallocn(img
.tiles
[0].tileComps
[comp
].quantSteps
,
1092 img
.tiles
[0].tileComps
[comp
].nQuantSteps
,
1094 if (!readUWord(&img
.tiles
[0].tileComps
[comp
].quantSteps
[0])) {
1095 error(getPos(), "Error in JPX QCC marker segment");
1098 } else if ((img
.tiles
[0].tileComps
[comp
].quantStyle
& 0x1f) == 0x02) {
1099 img
.tiles
[0].tileComps
[comp
].nQuantSteps
=
1100 (segLen
- (img
.nComps
> 256 ? 5 : 4)) / 2;
1101 img
.tiles
[0].tileComps
[comp
].quantSteps
=
1102 (Guint
*)greallocn(img
.tiles
[0].tileComps
[comp
].quantSteps
,
1103 img
.tiles
[0].tileComps
[comp
].nQuantSteps
,
1105 for (i
= 0; i
< img
.tiles
[0].tileComps
[comp
].nQuantSteps
; ++i
) {
1106 if (!readUWord(&img
.tiles
[0].tileComps
[comp
].quantSteps
[i
])) {
1107 error(getPos(), "Error in JPX QCD marker segment");
1112 error(getPos(), "Error in JPX QCC marker segment");
1115 for (i
= 1; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
1116 img
.tiles
[i
].tileComps
[comp
].quantStyle
=
1117 img
.tiles
[0].tileComps
[comp
].quantStyle
;
1118 img
.tiles
[i
].tileComps
[comp
].nQuantSteps
=
1119 img
.tiles
[0].tileComps
[comp
].nQuantSteps
;
1120 img
.tiles
[i
].tileComps
[comp
].quantSteps
=
1121 (Guint
*)greallocn(img
.tiles
[i
].tileComps
[comp
].quantSteps
,
1122 img
.tiles
[0].tileComps
[comp
].nQuantSteps
,
1124 for (j
= 0; j
< img
.tiles
[0].tileComps
[comp
].nQuantSteps
; ++j
) {
1125 img
.tiles
[i
].tileComps
[comp
].quantSteps
[j
] =
1126 img
.tiles
[0].tileComps
[comp
].quantSteps
[j
];
1130 case 0x5e: // RGN - region of interest
1131 #if 1 //~ ROI is unimplemented
1132 fprintf(stderr
, "RGN\n");
1133 for (i
= 0; i
< segLen
- 2; ++i
) {
1134 if (str
->getChar() == EOF
) {
1135 error(getPos(), "Error in JPX PPM marker segment");
1140 if ((img
.nComps
> 256 && !readUWord(&comp
)) ||
1141 (img
.nComps
<= 256 && !readUByte(&comp
)) ||
1142 comp
>= img
.nComps
||
1143 !readUByte(&compInfo
[comp
].defROI
.style
) ||
1144 !readUByte(&compInfo
[comp
].defROI
.shift
)) {
1145 error(getPos(), "Error in JPX RGN marker segment");
1150 case 0x5f: // POC - progression order change
1151 #if 1 //~ progression order changes are unimplemented
1152 fprintf(stderr
, "POC\n");
1153 for (i
= 0; i
< segLen
- 2; ++i
) {
1154 if (str
->getChar() == EOF
) {
1155 error(getPos(), "Error in JPX PPM marker segment");
1160 nProgs
= (segLen
- 2) / (img
.nComps
> 256 ? 9 : 7);
1161 progs
= (JPXProgOrder
*)gmallocn(nProgs
, sizeof(JPXProgOrder
));
1162 for (i
= 0; i
< nProgs
; ++i
) {
1163 if (!readUByte(&progs
[i
].startRes
) ||
1164 !(img
.nComps
> 256 && readUWord(&progs
[i
].startComp
)) ||
1165 !(img
.nComps
<= 256 && readUByte(&progs
[i
].startComp
)) ||
1166 !readUWord(&progs
[i
].endLayer
) ||
1167 !readUByte(&progs
[i
].endRes
) ||
1168 !(img
.nComps
> 256 && readUWord(&progs
[i
].endComp
)) ||
1169 !(img
.nComps
<= 256 && readUByte(&progs
[i
].endComp
)) ||
1170 !readUByte(&progs
[i
].progOrder
)) {
1171 error(getPos(), "Error in JPX POC marker segment");
1177 case 0x60: // PPM - packed packet headers, main header
1178 #if 1 //~ packed packet headers are unimplemented
1179 fprintf(stderr
, "PPM\n");
1180 for (i
= 0; i
< segLen
- 2; ++i
) {
1181 if (str
->getChar() == EOF
) {
1182 error(getPos(), "Error in JPX PPM marker segment");
1188 case 0x55: // TLM - tile-part lengths
1190 for (i
= 0; i
< segLen
- 2; ++i
) {
1191 if (str
->getChar() == EOF
) {
1192 error(getPos(), "Error in JPX TLM marker segment");
1197 case 0x57: // PLM - packet length, main header
1199 for (i
= 0; i
< segLen
- 2; ++i
) {
1200 if (str
->getChar() == EOF
) {
1201 error(getPos(), "Error in JPX PLM marker segment");
1206 case 0x63: // CRG - component registration
1208 for (i
= 0; i
< segLen
- 2; ++i
) {
1209 if (str
->getChar() == EOF
) {
1210 error(getPos(), "Error in JPX CRG marker segment");
1215 case 0x64: // COM - comment
1217 for (i
= 0; i
< segLen
- 2; ++i
) {
1218 if (str
->getChar() == EOF
) {
1219 error(getPos(), "Error in JPX COM marker segment");
1224 case 0x90: // SOT - start of tile
1228 error(getPos(), "Unknown marker segment %02x in JPX stream", segType
);
1229 for (i
= 0; i
< segLen
- 2; ++i
) {
1230 if (str
->getChar() == EOF
) {
1239 error(getPos(), "Missing SIZ marker segment in JPX stream");
1243 error(getPos(), "Missing COD marker segment in JPX stream");
1247 error(getPos(), "Missing QCD marker segment in JPX stream");
1251 //----- read the tile-parts
1253 if (!readTilePart()) {
1256 if (!readMarkerHdr(&segType
, &segLen
)) {
1257 error(getPos(), "Error in JPX codestream");
1260 if (segType
!= 0x90) { // SOT - start of tile
1265 if (segType
!= 0xd9) { // EOC - end of codestream
1266 error(getPos(), "Missing EOC marker in JPX codestream");
1270 //----- finish decoding the image
1271 for (i
= 0; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
1272 tile
= &img
.tiles
[i
];
1273 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
1274 tileComp
= &tile
->tileComps
[comp
];
1275 inverseTransform(tileComp
);
1277 if (!inverseMultiCompAndDC(tile
)) {
1282 //~ can free memory below tileComps here, and also tileComp.buf
1287 GBool
JPXStream::readTilePart() {
1289 JPXTileComp
*tileComp
;
1290 JPXResLevel
*resLevel
;
1291 JPXPrecinct
*precinct
;
1292 JPXSubband
*subband
;
1295 Guint tileIdx
, tilePartLen
, tilePartIdx
, nTileParts
;
1296 GBool tilePartToEOC
;
1297 Guint precinctSize
, style
;
1298 Guint n
, nSBs
, nx
, ny
, sbx0
, sby0
, comp
, segLen
;
1299 Guint i
, j
, k
, cbX
, cbY
, r
, pre
, sb
, cbi
;
1302 // process the SOT marker segment
1303 if (!readUWord(&tileIdx
) ||
1304 !readULong(&tilePartLen
) ||
1305 !readUByte(&tilePartIdx
) ||
1306 !readUByte(&nTileParts
)) {
1307 error(getPos(), "Error in JPX SOT marker segment");
1311 if (tileIdx
>= img
.nXTiles
* img
.nYTiles
) {
1312 error(getPos(), "Weird tile index in JPX stream");
1316 tilePartToEOC
= tilePartLen
== 0;
1317 tilePartLen
-= 12; // subtract size of SOT segment
1321 if (!readMarkerHdr(&segType
, &segLen
)) {
1322 error(getPos(), "Error in JPX tile-part codestream");
1325 tilePartLen
-= 2 + segLen
;
1327 case 0x52: // COD - coding style default
1328 if (!readUByte(&img
.tiles
[tileIdx
].tileComps
[0].style
) ||
1329 !readUByte(&img
.tiles
[tileIdx
].progOrder
) ||
1330 !readUWord(&img
.tiles
[tileIdx
].nLayers
) ||
1331 !readUByte(&img
.tiles
[tileIdx
].multiComp
) ||
1332 !readUByte(&img
.tiles
[tileIdx
].tileComps
[0].nDecompLevels
) ||
1333 !readUByte(&img
.tiles
[tileIdx
].tileComps
[0].codeBlockW
) ||
1334 !readUByte(&img
.tiles
[tileIdx
].tileComps
[0].codeBlockH
) ||
1335 !readUByte(&img
.tiles
[tileIdx
].tileComps
[0].codeBlockStyle
) ||
1336 !readUByte(&img
.tiles
[tileIdx
].tileComps
[0].transform
)) {
1337 error(getPos(), "Error in JPX COD marker segment");
1340 img
.tiles
[tileIdx
].tileComps
[0].codeBlockW
+= 2;
1341 img
.tiles
[tileIdx
].tileComps
[0].codeBlockH
+= 2;
1342 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
1344 img
.tiles
[tileIdx
].tileComps
[comp
].style
=
1345 img
.tiles
[tileIdx
].tileComps
[0].style
;
1346 img
.tiles
[tileIdx
].tileComps
[comp
].nDecompLevels
=
1347 img
.tiles
[tileIdx
].tileComps
[0].nDecompLevels
;
1348 img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockW
=
1349 img
.tiles
[tileIdx
].tileComps
[0].codeBlockW
;
1350 img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockH
=
1351 img
.tiles
[tileIdx
].tileComps
[0].codeBlockH
;
1352 img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockStyle
=
1353 img
.tiles
[tileIdx
].tileComps
[0].codeBlockStyle
;
1354 img
.tiles
[tileIdx
].tileComps
[comp
].transform
=
1355 img
.tiles
[tileIdx
].tileComps
[0].transform
;
1357 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
=
1358 (JPXResLevel
*)greallocn(
1359 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
,
1360 (img
.tiles
[tileIdx
].tileComps
[comp
].nDecompLevels
+ 1),
1361 sizeof(JPXResLevel
));
1363 r
<= img
.tiles
[tileIdx
].tileComps
[comp
].nDecompLevels
;
1365 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
[r
].precincts
= NULL
;
1368 for (r
= 0; r
<= img
.tiles
[tileIdx
].tileComps
[0].nDecompLevels
; ++r
) {
1369 if (img
.tiles
[tileIdx
].tileComps
[0].style
& 0x01) {
1370 if (!readUByte(&precinctSize
)) {
1371 error(getPos(), "Error in JPX COD marker segment");
1374 img
.tiles
[tileIdx
].tileComps
[0].resLevels
[r
].precinctWidth
=
1375 precinctSize
& 0x0f;
1376 img
.tiles
[tileIdx
].tileComps
[0].resLevels
[r
].precinctHeight
=
1377 (precinctSize
>> 4) & 0x0f;
1379 img
.tiles
[tileIdx
].tileComps
[0].resLevels
[r
].precinctWidth
= 15;
1380 img
.tiles
[tileIdx
].tileComps
[0].resLevels
[r
].precinctHeight
= 15;
1383 for (comp
= 1; comp
< img
.nComps
; ++comp
) {
1385 r
<= img
.tiles
[tileIdx
].tileComps
[comp
].nDecompLevels
;
1387 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
[r
].precinctWidth
=
1388 img
.tiles
[tileIdx
].tileComps
[0].resLevels
[r
].precinctWidth
;
1389 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
[r
].precinctHeight
=
1390 img
.tiles
[tileIdx
].tileComps
[0].resLevels
[r
].precinctHeight
;
1394 case 0x53: // COC - coding style component
1395 if ((img
.nComps
> 256 && !readUWord(&comp
)) ||
1396 (img
.nComps
<= 256 && !readUByte(&comp
)) ||
1397 comp
>= img
.nComps
||
1398 !readUByte(&style
) ||
1399 !readUByte(&img
.tiles
[tileIdx
].tileComps
[comp
].nDecompLevels
) ||
1400 !readUByte(&img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockW
) ||
1401 !readUByte(&img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockH
) ||
1402 !readUByte(&img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockStyle
) ||
1403 !readUByte(&img
.tiles
[tileIdx
].tileComps
[comp
].transform
)) {
1404 error(getPos(), "Error in JPX COC marker segment");
1407 img
.tiles
[tileIdx
].tileComps
[comp
].style
=
1408 (img
.tiles
[tileIdx
].tileComps
[comp
].style
& ~1) | (style
& 1);
1409 img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockW
+= 2;
1410 img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockH
+= 2;
1411 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
=
1412 (JPXResLevel
*)greallocn(
1413 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
,
1414 (img
.tiles
[tileIdx
].tileComps
[comp
].nDecompLevels
+ 1),
1415 sizeof(JPXResLevel
));
1416 for (r
= 0; r
<= img
.tiles
[tileIdx
].tileComps
[comp
].nDecompLevels
; ++r
) {
1417 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
[r
].precincts
= NULL
;
1419 for (r
= 0; r
<= img
.tiles
[tileIdx
].tileComps
[comp
].nDecompLevels
; ++r
) {
1420 if (img
.tiles
[tileIdx
].tileComps
[comp
].style
& 0x01) {
1421 if (!readUByte(&precinctSize
)) {
1422 error(getPos(), "Error in JPX COD marker segment");
1425 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
[r
].precinctWidth
=
1426 precinctSize
& 0x0f;
1427 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
[r
].precinctHeight
=
1428 (precinctSize
>> 4) & 0x0f;
1430 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
[r
].precinctWidth
= 15;
1431 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
[r
].precinctHeight
= 15;
1435 case 0x5c: // QCD - quantization default
1436 if (!readUByte(&img
.tiles
[tileIdx
].tileComps
[0].quantStyle
)) {
1437 error(getPos(), "Error in JPX QCD marker segment");
1440 if ((img
.tiles
[tileIdx
].tileComps
[0].quantStyle
& 0x1f) == 0x00) {
1441 img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
=
1443 img
.tiles
[tileIdx
].tileComps
[0].quantSteps
=
1444 (Guint
*)greallocn(img
.tiles
[tileIdx
].tileComps
[0].quantSteps
,
1445 img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
,
1447 for (i
= 0; i
< img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
; ++i
) {
1448 if (!readUByte(&img
.tiles
[tileIdx
].tileComps
[0].quantSteps
[i
])) {
1449 error(getPos(), "Error in JPX QCD marker segment");
1453 } else if ((img
.tiles
[tileIdx
].tileComps
[0].quantStyle
& 0x1f) == 0x01) {
1454 img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
= 1;
1455 img
.tiles
[tileIdx
].tileComps
[0].quantSteps
=
1456 (Guint
*)greallocn(img
.tiles
[tileIdx
].tileComps
[0].quantSteps
,
1457 img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
,
1459 if (!readUWord(&img
.tiles
[tileIdx
].tileComps
[0].quantSteps
[0])) {
1460 error(getPos(), "Error in JPX QCD marker segment");
1463 } else if ((img
.tiles
[tileIdx
].tileComps
[0].quantStyle
& 0x1f) == 0x02) {
1464 img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
= (segLen
- 3) / 2;
1465 img
.tiles
[tileIdx
].tileComps
[0].quantSteps
=
1466 (Guint
*)greallocn(img
.tiles
[tileIdx
].tileComps
[0].quantSteps
,
1467 img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
,
1469 for (i
= 0; i
< img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
; ++i
) {
1470 if (!readUWord(&img
.tiles
[tileIdx
].tileComps
[0].quantSteps
[i
])) {
1471 error(getPos(), "Error in JPX QCD marker segment");
1476 error(getPos(), "Error in JPX QCD marker segment");
1479 for (comp
= 1; comp
< img
.nComps
; ++comp
) {
1480 img
.tiles
[tileIdx
].tileComps
[comp
].quantStyle
=
1481 img
.tiles
[tileIdx
].tileComps
[0].quantStyle
;
1482 img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
=
1483 img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
;
1484 img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
=
1485 (Guint
*)greallocn(img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
,
1486 img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
,
1488 for (j
= 0; j
< img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
; ++j
) {
1489 img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
[j
] =
1490 img
.tiles
[tileIdx
].tileComps
[0].quantSteps
[j
];
1494 case 0x5d: // QCC - quantization component
1495 if ((img
.nComps
> 256 && !readUWord(&comp
)) ||
1496 (img
.nComps
<= 256 && !readUByte(&comp
)) ||
1497 comp
>= img
.nComps
||
1498 !readUByte(&img
.tiles
[tileIdx
].tileComps
[comp
].quantStyle
)) {
1499 error(getPos(), "Error in JPX QCC marker segment");
1502 if ((img
.tiles
[tileIdx
].tileComps
[comp
].quantStyle
& 0x1f) == 0x00) {
1503 img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
=
1504 segLen
- (img
.nComps
> 256 ? 5 : 4);
1505 img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
=
1506 (Guint
*)greallocn(img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
,
1507 img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
,
1509 for (i
= 0; i
< img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
; ++i
) {
1510 if (!readUByte(&img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
[i
])) {
1511 error(getPos(), "Error in JPX QCC marker segment");
1515 } else if ((img
.tiles
[tileIdx
].tileComps
[comp
].quantStyle
& 0x1f)
1517 img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
= 1;
1518 img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
=
1519 (Guint
*)greallocn(img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
,
1520 img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
,
1522 if (!readUWord(&img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
[0])) {
1523 error(getPos(), "Error in JPX QCC marker segment");
1526 } else if ((img
.tiles
[tileIdx
].tileComps
[comp
].quantStyle
& 0x1f)
1528 img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
=
1529 (segLen
- (img
.nComps
> 256 ? 5 : 4)) / 2;
1530 img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
=
1531 (Guint
*)greallocn(img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
,
1532 img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
,
1534 for (i
= 0; i
< img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
; ++i
) {
1535 if (!readUWord(&img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
[i
])) {
1536 error(getPos(), "Error in JPX QCD marker segment");
1541 error(getPos(), "Error in JPX QCC marker segment");
1545 case 0x5e: // RGN - region of interest
1546 #if 1 //~ ROI is unimplemented
1547 fprintf(stderr
, "RGN\n");
1548 for (i
= 0; i
< segLen
- 2; ++i
) {
1549 if (str
->getChar() == EOF
) {
1550 error(getPos(), "Error in JPX PPM marker segment");
1555 if ((img
.nComps
> 256 && !readUWord(&comp
)) ||
1556 (img
.nComps
<= 256 && !readUByte(&comp
)) ||
1557 comp
>= img
.nComps
||
1558 !readUByte(&compInfo
[comp
].roi
.style
) ||
1559 !readUByte(&compInfo
[comp
].roi
.shift
)) {
1560 error(getPos(), "Error in JPX RGN marker segment");
1565 case 0x5f: // POC - progression order change
1566 #if 1 //~ progression order changes are unimplemented
1567 fprintf(stderr
, "POC\n");
1568 for (i
= 0; i
< segLen
- 2; ++i
) {
1569 if (str
->getChar() == EOF
) {
1570 error(getPos(), "Error in JPX PPM marker segment");
1575 nTileProgs
= (segLen
- 2) / (img
.nComps
> 256 ? 9 : 7);
1576 tileProgs
= (JPXProgOrder
*)gmallocn(nTileProgs
, sizeof(JPXProgOrder
));
1577 for (i
= 0; i
< nTileProgs
; ++i
) {
1578 if (!readUByte(&tileProgs
[i
].startRes
) ||
1579 !(img
.nComps
> 256 && readUWord(&tileProgs
[i
].startComp
)) ||
1580 !(img
.nComps
<= 256 && readUByte(&tileProgs
[i
].startComp
)) ||
1581 !readUWord(&tileProgs
[i
].endLayer
) ||
1582 !readUByte(&tileProgs
[i
].endRes
) ||
1583 !(img
.nComps
> 256 && readUWord(&tileProgs
[i
].endComp
)) ||
1584 !(img
.nComps
<= 256 && readUByte(&tileProgs
[i
].endComp
)) ||
1585 !readUByte(&tileProgs
[i
].progOrder
)) {
1586 error(getPos(), "Error in JPX POC marker segment");
1592 case 0x61: // PPT - packed packet headers, tile-part hdr
1593 #if 1 //~ packed packet headers are unimplemented
1594 fprintf(stderr
, "PPT\n");
1595 for (i
= 0; i
< segLen
- 2; ++i
) {
1596 if (str
->getChar() == EOF
) {
1597 error(getPos(), "Error in JPX PPT marker segment");
1602 case 0x58: // PLT - packet length, tile-part header
1604 for (i
= 0; i
< segLen
- 2; ++i
) {
1605 if (str
->getChar() == EOF
) {
1606 error(getPos(), "Error in JPX PLT marker segment");
1611 case 0x64: // COM - comment
1613 for (i
= 0; i
< segLen
- 2; ++i
) {
1614 if (str
->getChar() == EOF
) {
1615 error(getPos(), "Error in JPX COM marker segment");
1620 case 0x93: // SOD - start of data
1624 error(getPos(), "Unknown marker segment %02x in JPX tile-part stream",
1626 for (i
= 0; i
< segLen
- 2; ++i
) {
1627 if (str
->getChar() == EOF
) {
1635 //----- initialize the tile, precincts, and code-blocks
1636 if (tilePartIdx
== 0) {
1637 tile
= &img
.tiles
[tileIdx
];
1638 i
= tileIdx
/ img
.nXTiles
;
1639 j
= tileIdx
% img
.nXTiles
;
1640 if ((tile
->x0
= img
.xTileOffset
+ j
* img
.xTileSize
) < img
.xOffset
) {
1641 tile
->x0
= img
.xOffset
;
1643 if ((tile
->y0
= img
.yTileOffset
+ i
* img
.yTileSize
) < img
.yOffset
) {
1644 tile
->y0
= img
.yOffset
;
1646 if ((tile
->x1
= img
.xTileOffset
+ (j
+ 1) * img
.xTileSize
) > img
.xSize
) {
1647 tile
->x1
= img
.xSize
;
1649 if ((tile
->y1
= img
.yTileOffset
+ (i
+ 1) * img
.yTileSize
) > img
.ySize
) {
1650 tile
->y1
= img
.ySize
;
1656 tile
->maxNDecompLevels
= 0;
1657 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
1658 tileComp
= &tile
->tileComps
[comp
];
1659 if (tileComp
->nDecompLevels
> tile
->maxNDecompLevels
) {
1660 tile
->maxNDecompLevels
= tileComp
->nDecompLevels
;
1662 tileComp
->x0
= jpxCeilDiv(tile
->x0
, tileComp
->hSep
);
1663 tileComp
->y0
= jpxCeilDiv(tile
->y0
, tileComp
->hSep
);
1664 tileComp
->x1
= jpxCeilDiv(tile
->x1
, tileComp
->hSep
);
1665 tileComp
->y1
= jpxCeilDiv(tile
->y1
, tileComp
->hSep
);
1666 tileComp
->cbW
= 1 << tileComp
->codeBlockW
;
1667 tileComp
->cbH
= 1 << tileComp
->codeBlockH
;
1668 tileComp
->data
= (int *)gmallocn((tileComp
->x1
- tileComp
->x0
) *
1669 (tileComp
->y1
- tileComp
->y0
),
1671 if (tileComp
->x1
- tileComp
->x0
> tileComp
->y1
- tileComp
->y0
) {
1672 n
= tileComp
->x1
- tileComp
->x0
;
1674 n
= tileComp
->y1
- tileComp
->y0
;
1676 tileComp
->buf
= (int *)gmallocn(n
+ 8, sizeof(int));
1677 for (r
= 0; r
<= tileComp
->nDecompLevels
; ++r
) {
1678 resLevel
= &tileComp
->resLevels
[r
];
1679 k
= r
== 0 ? tileComp
->nDecompLevels
1680 : tileComp
->nDecompLevels
- r
+ 1;
1681 resLevel
->x0
= jpxCeilDivPow2(tileComp
->x0
, k
);
1682 resLevel
->y0
= jpxCeilDivPow2(tileComp
->y0
, k
);
1683 resLevel
->x1
= jpxCeilDivPow2(tileComp
->x1
, k
);
1684 resLevel
->y1
= jpxCeilDivPow2(tileComp
->y1
, k
);
1686 resLevel
->bx0
[0] = resLevel
->x0
;
1687 resLevel
->by0
[0] = resLevel
->y0
;
1688 resLevel
->bx1
[0] = resLevel
->x1
;
1689 resLevel
->by1
[0] = resLevel
->y1
;
1691 resLevel
->bx0
[0] = jpxCeilDivPow2(tileComp
->x0
- (1 << (k
-1)), k
);
1692 resLevel
->by0
[0] = resLevel
->y0
;
1693 resLevel
->bx1
[0] = jpxCeilDivPow2(tileComp
->x1
- (1 << (k
-1)), k
);
1694 resLevel
->by1
[0] = resLevel
->y1
;
1695 resLevel
->bx0
[1] = resLevel
->x0
;
1696 resLevel
->by0
[1] = jpxCeilDivPow2(tileComp
->y0
- (1 << (k
-1)), k
);
1697 resLevel
->bx1
[1] = resLevel
->x1
;
1698 resLevel
->by1
[1] = jpxCeilDivPow2(tileComp
->y1
- (1 << (k
-1)), k
);
1699 resLevel
->bx0
[2] = jpxCeilDivPow2(tileComp
->x0
- (1 << (k
-1)), k
);
1700 resLevel
->by0
[2] = jpxCeilDivPow2(tileComp
->y0
- (1 << (k
-1)), k
);
1701 resLevel
->bx1
[2] = jpxCeilDivPow2(tileComp
->x1
- (1 << (k
-1)), k
);
1702 resLevel
->by1
[2] = jpxCeilDivPow2(tileComp
->y1
- (1 << (k
-1)), k
);
1704 resLevel
->precincts
= (JPXPrecinct
*)gmallocn(1, sizeof(JPXPrecinct
));
1705 for (pre
= 0; pre
< 1; ++pre
) {
1706 precinct
= &resLevel
->precincts
[pre
];
1707 precinct
->x0
= resLevel
->x0
;
1708 precinct
->y0
= resLevel
->y0
;
1709 precinct
->x1
= resLevel
->x1
;
1710 precinct
->y1
= resLevel
->y1
;
1711 nSBs
= r
== 0 ? 1 : 3;
1712 precinct
->subbands
=
1713 (JPXSubband
*)gmallocn(nSBs
, sizeof(JPXSubband
));
1714 for (sb
= 0; sb
< nSBs
; ++sb
) {
1715 subband
= &precinct
->subbands
[sb
];
1716 subband
->x0
= resLevel
->bx0
[sb
];
1717 subband
->y0
= resLevel
->by0
[sb
];
1718 subband
->x1
= resLevel
->bx1
[sb
];
1719 subband
->y1
= resLevel
->by1
[sb
];
1720 subband
->nXCBs
= jpxCeilDivPow2(subband
->x1
,
1721 tileComp
->codeBlockW
)
1722 - jpxFloorDivPow2(subband
->x0
,
1723 tileComp
->codeBlockW
);
1724 subband
->nYCBs
= jpxCeilDivPow2(subband
->y1
,
1725 tileComp
->codeBlockH
)
1726 - jpxFloorDivPow2(subband
->y0
,
1727 tileComp
->codeBlockH
);
1728 n
= subband
->nXCBs
> subband
->nYCBs
? subband
->nXCBs
1730 for (subband
->maxTTLevel
= 0, --n
;
1732 ++subband
->maxTTLevel
, n
>>= 1) ;
1734 for (level
= subband
->maxTTLevel
; level
>= 0; --level
) {
1735 nx
= jpxCeilDivPow2(subband
->nXCBs
, level
);
1736 ny
= jpxCeilDivPow2(subband
->nYCBs
, level
);
1739 subband
->inclusion
=
1740 (JPXTagTreeNode
*)gmallocn(n
, sizeof(JPXTagTreeNode
));
1741 subband
->zeroBitPlane
=
1742 (JPXTagTreeNode
*)gmallocn(n
, sizeof(JPXTagTreeNode
));
1743 for (k
= 0; k
< n
; ++k
) {
1744 subband
->inclusion
[k
].finished
= gFalse
;
1745 subband
->inclusion
[k
].val
= 0;
1746 subband
->zeroBitPlane
[k
].finished
= gFalse
;
1747 subband
->zeroBitPlane
[k
].val
= 0;
1749 subband
->cbs
= (JPXCodeBlock
*)gmallocn(subband
->nXCBs
*
1751 sizeof(JPXCodeBlock
));
1752 sbx0
= jpxFloorDivPow2(subband
->x0
, tileComp
->codeBlockW
);
1753 sby0
= jpxFloorDivPow2(subband
->y0
, tileComp
->codeBlockH
);
1755 for (cbY
= 0; cbY
< subband
->nYCBs
; ++cbY
) {
1756 for (cbX
= 0; cbX
< subband
->nXCBs
; ++cbX
) {
1757 cb
->x0
= (sbx0
+ cbX
) << tileComp
->codeBlockW
;
1758 cb
->x1
= cb
->x0
+ tileComp
->cbW
;
1759 if (subband
->x0
> cb
->x0
) {
1760 cb
->x0
= subband
->x0
;
1762 if (subband
->x1
< cb
->x1
) {
1763 cb
->x1
= subband
->x1
;
1765 cb
->y0
= (sby0
+ cbY
) << tileComp
->codeBlockH
;
1766 cb
->y1
= cb
->y0
+ tileComp
->cbH
;
1767 if (subband
->y0
> cb
->y0
) {
1768 cb
->y0
= subband
->y0
;
1770 if (subband
->y1
< cb
->y1
) {
1771 cb
->y1
= subband
->y1
;
1775 cb
->nextPass
= jpxPassCleanup
;
1776 cb
->nZeroBitPlanes
= 0;
1778 (JPXCoeff
*)gmallocn((1 << (tileComp
->codeBlockW
1779 + tileComp
->codeBlockH
)),
1782 cbi
< (Guint
)(1 << (tileComp
->codeBlockW
1783 + tileComp
->codeBlockH
));
1785 cb
->coeffs
[cbi
].flags
= 0;
1786 cb
->coeffs
[cbi
].len
= 0;
1787 cb
->coeffs
[cbi
].mag
= 0;
1789 cb
->arithDecoder
= NULL
;
1800 return readTilePartData(tileIdx
, tilePartLen
, tilePartToEOC
);
1803 GBool
JPXStream::readTilePartData(Guint tileIdx
,
1804 Guint tilePartLen
, GBool tilePartToEOC
) {
1806 JPXTileComp
*tileComp
;
1807 JPXResLevel
*resLevel
;
1808 JPXPrecinct
*precinct
;
1809 JPXSubband
*subband
;
1812 Guint bits
, cbX
, cbY
, nx
, ny
, i
, j
, n
, sb
;
1815 tile
= &img
.tiles
[tileIdx
];
1817 // read all packets from this tile-part
1819 if (tilePartToEOC
) {
1820 //~ peek for an EOC marker
1821 } else if (tilePartLen
== 0) {
1825 tileComp
= &tile
->tileComps
[tile
->comp
];
1826 resLevel
= &tileComp
->resLevels
[tile
->res
];
1827 precinct
= &resLevel
->precincts
[tile
->precinct
];
1829 //----- packet header
1832 if (!readBits(1, &bits
)) {
1836 // packet is empty -- clear all code-block inclusion flags
1837 for (sb
= 0; sb
< (tile
->res
== 0 ? 1 : 3); ++sb
) {
1838 subband
= &precinct
->subbands
[sb
];
1839 for (cbY
= 0; cbY
< subband
->nYCBs
; ++cbY
) {
1840 for (cbX
= 0; cbX
< subband
->nXCBs
; ++cbX
) {
1841 cb
= &subband
->cbs
[cbY
* subband
->nXCBs
+ cbX
];
1842 cb
->included
= gFalse
;
1848 for (sb
= 0; sb
< (tile
->res
== 0 ? 1 : 3); ++sb
) {
1849 subband
= &precinct
->subbands
[sb
];
1850 for (cbY
= 0; cbY
< subband
->nYCBs
; ++cbY
) {
1851 for (cbX
= 0; cbX
< subband
->nXCBs
; ++cbX
) {
1852 cb
= &subband
->cbs
[cbY
* subband
->nXCBs
+ cbX
];
1854 // skip code-blocks with no coefficients
1855 if (cb
->x0
>= cb
->x1
|| cb
->y0
>= cb
->y1
) {
1856 cb
->included
= gFalse
;
1860 // code-block inclusion
1862 if (!readBits(1, &cb
->included
)) {
1868 for (level
= subband
->maxTTLevel
; level
>= 0; --level
) {
1869 nx
= jpxCeilDivPow2(subband
->nXCBs
, level
);
1870 ny
= jpxCeilDivPow2(subband
->nYCBs
, level
);
1871 j
= i
+ (cbY
>> level
) * nx
+ (cbX
>> level
);
1872 if (!subband
->inclusion
[j
].finished
&&
1873 !subband
->inclusion
[j
].val
) {
1874 subband
->inclusion
[j
].val
= ttVal
;
1876 ttVal
= subband
->inclusion
[j
].val
;
1878 while (!subband
->inclusion
[j
].finished
&&
1879 ttVal
<= tile
->layer
) {
1880 if (!readBits(1, &bits
)) {
1884 subband
->inclusion
[j
].finished
= gTrue
;
1889 subband
->inclusion
[j
].val
= ttVal
;
1890 if (ttVal
> tile
->layer
) {
1895 cb
->included
= level
< 0;
1900 // zero bit-plane count
1904 for (level
= subband
->maxTTLevel
; level
>= 0; --level
) {
1905 nx
= jpxCeilDivPow2(subband
->nXCBs
, level
);
1906 ny
= jpxCeilDivPow2(subband
->nYCBs
, level
);
1907 j
= i
+ (cbY
>> level
) * nx
+ (cbX
>> level
);
1908 if (!subband
->zeroBitPlane
[j
].finished
&&
1909 !subband
->zeroBitPlane
[j
].val
) {
1910 subband
->zeroBitPlane
[j
].val
= ttVal
;
1912 ttVal
= subband
->zeroBitPlane
[j
].val
;
1914 while (!subband
->zeroBitPlane
[j
].finished
) {
1915 if (!readBits(1, &bits
)) {
1919 subband
->zeroBitPlane
[j
].finished
= gTrue
;
1924 subband
->zeroBitPlane
[j
].val
= ttVal
;
1927 cb
->nZeroBitPlanes
= ttVal
;
1930 // number of coding passes
1931 if (!readBits(1, &bits
)) {
1935 cb
->nCodingPasses
= 1;
1937 if (!readBits(1, &bits
)) {
1941 cb
->nCodingPasses
= 2;
1943 if (!readBits(2, &bits
)) {
1947 cb
->nCodingPasses
= 3 + bits
;
1949 if (!readBits(5, &bits
)) {
1953 cb
->nCodingPasses
= 6 + bits
;
1955 if (!readBits(7, &bits
)) {
1958 cb
->nCodingPasses
= 37 + bits
;
1966 if (!readBits(1, &bits
)) {
1975 // length of compressed data
1976 //~ deal with multiple codeword segments
1977 for (n
= cb
->lBlock
, i
= cb
->nCodingPasses
>> 1;
1980 if (!readBits(n
, &cb
->dataLen
)) {
1988 tilePartLen
-= byteCount
;
1993 for (sb
= 0; sb
< (tile
->res
== 0 ? 1 : 3); ++sb
) {
1994 subband
= &precinct
->subbands
[sb
];
1995 for (cbY
= 0; cbY
< subband
->nYCBs
; ++cbY
) {
1996 for (cbX
= 0; cbX
< subband
->nXCBs
; ++cbX
) {
1997 cb
= &subband
->cbs
[cbY
* subband
->nXCBs
+ cbX
];
1999 if (!readCodeBlockData(tileComp
, resLevel
, precinct
, subband
,
2000 tile
->res
, sb
, cb
)) {
2003 tilePartLen
-= cb
->dataLen
;
2012 switch (tile
->progOrder
) {
2013 case 0: // layer, resolution level, component, precinct
2014 if (++tile
->comp
== img
.nComps
) {
2016 if (++tile
->res
== tile
->maxNDecompLevels
+ 1) {
2018 if (++tile
->layer
== tile
->nLayers
) {
2024 case 1: // resolution level, layer, component, precinct
2025 if (++tile
->comp
== img
.nComps
) {
2027 if (++tile
->layer
== tile
->nLayers
) {
2029 if (++tile
->res
== tile
->maxNDecompLevels
+ 1) {
2035 case 2: // resolution level, precinct, component, layer
2036 //~ this isn't correct -- see B.12.1.3
2037 if (++tile
->layer
== tile
->nLayers
) {
2039 if (++tile
->comp
== img
.nComps
) {
2041 if (++tile
->res
== tile
->maxNDecompLevels
+ 1) {
2047 case 3: // precinct, component, resolution level, layer
2048 //~ this isn't correct -- see B.12.1.4
2049 if (++tile
->layer
== tile
->nLayers
) {
2051 if (++tile
->res
== tile
->maxNDecompLevels
+ 1) {
2053 if (++tile
->comp
== img
.nComps
) {
2059 case 4: // component, precinct, resolution level, layer
2060 //~ this isn't correct -- see B.12.1.5
2061 if (++tile
->layer
== tile
->nLayers
) {
2063 if (++tile
->res
== tile
->maxNDecompLevels
+ 1) {
2065 if (++tile
->comp
== img
.nComps
) {
2077 error(getPos(), "Error in JPX stream");
2081 GBool
JPXStream::readCodeBlockData(JPXTileComp
*tileComp
,
2082 JPXResLevel
*resLevel
,
2083 JPXPrecinct
*precinct
,
2084 JPXSubband
*subband
,
2085 Guint res
, Guint sb
,
2087 JPXCoeff
*coeff0
, *coeff1
, *coeff
;
2088 Guint horiz
, vert
, diag
, all
, cx
, xorBit
;
2089 int horizSign
, vertSign
;
2090 Guint i
, x
, y0
, y1
, y2
;
2092 if (cb
->arithDecoder
) {
2093 cb
->arithDecoder
->restart(cb
->dataLen
);
2095 cb
->arithDecoder
= new JArithmeticDecoder();
2096 cb
->arithDecoder
->setStream(str
, cb
->dataLen
);
2097 cb
->arithDecoder
->start();
2098 cb
->stats
= new JArithmeticDecoderStats(jpxNContexts
);
2099 cb
->stats
->setEntry(jpxContextSigProp
, 4, 0);
2100 cb
->stats
->setEntry(jpxContextRunLength
, 3, 0);
2101 cb
->stats
->setEntry(jpxContextUniform
, 46, 0);
2104 for (i
= 0; i
< cb
->nCodingPasses
; ++i
) {
2105 switch (cb
->nextPass
) {
2107 //----- significance propagation pass
2108 case jpxPassSigProp
:
2109 for (y0
= cb
->y0
, coeff0
= cb
->coeffs
;
2111 y0
+= 4, coeff0
+= 4 << tileComp
->codeBlockW
) {
2112 for (x
= cb
->x0
, coeff1
= coeff0
;
2115 for (y1
= 0, coeff
= coeff1
;
2116 y1
< 4 && y0
+y1
< cb
->y1
;
2117 ++y1
, coeff
+= tileComp
->cbW
) {
2118 if (!(coeff
->flags
& jpxCoeffSignificant
)) {
2119 horiz
= vert
= diag
= 0;
2120 horizSign
= vertSign
= 2;
2122 if (coeff
[-1].flags
& jpxCoeffSignificant
) {
2124 horizSign
+= (coeff
[-1].flags
& jpxCoeffSign
) ? -1 : 1;
2126 if (y0
+y1
> cb
->y0
) {
2127 diag
+= (coeff
[-(int)tileComp
->cbW
- 1].flags
2128 >> jpxCoeffSignificantB
) & 1;
2130 if (y0
+y1
< cb
->y1
- 1) {
2131 diag
+= (coeff
[tileComp
->cbW
- 1].flags
2132 >> jpxCoeffSignificantB
) & 1;
2135 if (x
< cb
->x1
- 1) {
2136 if (coeff
[1].flags
& jpxCoeffSignificant
) {
2138 horizSign
+= (coeff
[1].flags
& jpxCoeffSign
) ? -1 : 1;
2140 if (y0
+y1
> cb
->y0
) {
2141 diag
+= (coeff
[-(int)tileComp
->cbW
+ 1].flags
2142 >> jpxCoeffSignificantB
) & 1;
2144 if (y0
+y1
< cb
->y1
- 1) {
2145 diag
+= (coeff
[tileComp
->cbW
+ 1].flags
2146 >> jpxCoeffSignificantB
) & 1;
2149 if (y0
+y1
> cb
->y0
) {
2150 if (coeff
[-(int)tileComp
->cbW
].flags
& jpxCoeffSignificant
) {
2152 vertSign
+= (coeff
[-(int)tileComp
->cbW
].flags
& jpxCoeffSign
)
2156 if (y0
+y1
< cb
->y1
- 1) {
2157 if (coeff
[tileComp
->cbW
].flags
& jpxCoeffSignificant
) {
2159 vertSign
+= (coeff
[tileComp
->cbW
].flags
& jpxCoeffSign
)
2163 cx
= sigPropContext
[horiz
][vert
][diag
][res
== 0 ? 1 : sb
];
2165 if (cb
->arithDecoder
->decodeBit(cx
, cb
->stats
)) {
2166 coeff
->flags
|= jpxCoeffSignificant
| jpxCoeffFirstMagRef
;
2167 coeff
->mag
= (coeff
->mag
<< 1) | 1;
2168 cx
= signContext
[horizSign
][vertSign
][0];
2169 xorBit
= signContext
[horizSign
][vertSign
][1];
2170 if (cb
->arithDecoder
->decodeBit(cx
, cb
->stats
) ^ xorBit
) {
2171 coeff
->flags
|= jpxCoeffSign
;
2175 coeff
->flags
|= jpxCoeffTouched
;
2184 //----- magnitude refinement pass
2186 for (y0
= cb
->y0
, coeff0
= cb
->coeffs
;
2188 y0
+= 4, coeff0
+= 4 << tileComp
->codeBlockW
) {
2189 for (x
= cb
->x0
, coeff1
= coeff0
;
2192 for (y1
= 0, coeff
= coeff1
;
2193 y1
< 4 && y0
+y1
< cb
->y1
;
2194 ++y1
, coeff
+= tileComp
->cbW
) {
2195 if ((coeff
->flags
& jpxCoeffSignificant
) &&
2196 !(coeff
->flags
& jpxCoeffTouched
)) {
2197 if (coeff
->flags
& jpxCoeffFirstMagRef
) {
2200 all
+= (coeff
[-1].flags
>> jpxCoeffSignificantB
) & 1;
2201 if (y0
+y1
> cb
->y0
) {
2202 all
+= (coeff
[-(int)tileComp
->cbW
- 1].flags
2203 >> jpxCoeffSignificantB
) & 1;
2205 if (y0
+y1
< cb
->y1
- 1) {
2206 all
+= (coeff
[tileComp
->cbW
- 1].flags
2207 >> jpxCoeffSignificantB
) & 1;
2210 if (x
< cb
->x1
- 1) {
2211 all
+= (coeff
[1].flags
>> jpxCoeffSignificantB
) & 1;
2212 if (y0
+y1
> cb
->y0
) {
2213 all
+= (coeff
[-(int)tileComp
->cbW
+ 1].flags
2214 >> jpxCoeffSignificantB
) & 1;
2216 if (y0
+y1
< cb
->y1
- 1) {
2217 all
+= (coeff
[tileComp
->cbW
+ 1].flags
2218 >> jpxCoeffSignificantB
) & 1;
2221 if (y0
+y1
> cb
->y0
) {
2222 all
+= (coeff
[-(int)tileComp
->cbW
].flags
2223 >> jpxCoeffSignificantB
) & 1;
2225 if (y0
+y1
< cb
->y1
- 1) {
2226 all
+= (coeff
[tileComp
->cbW
].flags
2227 >> jpxCoeffSignificantB
) & 1;
2233 coeff
->mag
= (coeff
->mag
<< 1) |
2234 cb
->arithDecoder
->decodeBit(cx
, cb
->stats
);
2236 coeff
->flags
|= jpxCoeffTouched
;
2237 coeff
->flags
&= ~jpxCoeffFirstMagRef
;
2245 //----- cleanup pass
2246 case jpxPassCleanup
:
2247 for (y0
= cb
->y0
, coeff0
= cb
->coeffs
;
2249 y0
+= 4, coeff0
+= 4 << tileComp
->codeBlockW
) {
2250 for (x
= cb
->x0
, coeff1
= coeff0
;
2254 if (y0
+ 3 < cb
->y1
&&
2255 !(coeff1
->flags
& jpxCoeffTouched
) &&
2256 !(coeff1
[tileComp
->cbW
].flags
& jpxCoeffTouched
) &&
2257 !(coeff1
[2 * tileComp
->cbW
].flags
& jpxCoeffTouched
) &&
2258 !(coeff1
[3 * tileComp
->cbW
].flags
& jpxCoeffTouched
) &&
2259 (x
== cb
->x0
|| y0
== cb
->y0
||
2260 !(coeff1
[-(int)tileComp
->cbW
- 1].flags
2261 & jpxCoeffSignificant
)) &&
2263 !(coeff1
[-(int)tileComp
->cbW
].flags
2264 & jpxCoeffSignificant
)) &&
2265 (x
== cb
->x1
- 1 || y0
== cb
->y0
||
2266 !(coeff1
[-(int)tileComp
->cbW
+ 1].flags
2267 & jpxCoeffSignificant
)) &&
2269 (!(coeff1
[-1].flags
& jpxCoeffSignificant
) &&
2270 !(coeff1
[tileComp
->cbW
- 1].flags
2271 & jpxCoeffSignificant
) &&
2272 !(coeff1
[2 * tileComp
->cbW
- 1].flags
2273 & jpxCoeffSignificant
) &&
2274 !(coeff1
[3 * tileComp
->cbW
- 1].flags
2275 & jpxCoeffSignificant
))) &&
2277 (!(coeff1
[1].flags
& jpxCoeffSignificant
) &&
2278 !(coeff1
[tileComp
->cbW
+ 1].flags
2279 & jpxCoeffSignificant
) &&
2280 !(coeff1
[2 * tileComp
->cbW
+ 1].flags
2281 & jpxCoeffSignificant
) &&
2282 !(coeff1
[3 * tileComp
->cbW
+ 1].flags
2283 & jpxCoeffSignificant
))) &&
2284 (x
== cb
->x0
|| y0
+4 == cb
->y1
||
2285 !(coeff1
[4 * tileComp
->cbW
- 1].flags
& jpxCoeffSignificant
)) &&
2287 !(coeff1
[4 * tileComp
->cbW
].flags
& jpxCoeffSignificant
)) &&
2288 (x
== cb
->x1
- 1 || y0
+4 == cb
->y1
||
2289 !(coeff1
[4 * tileComp
->cbW
+ 1].flags
2290 & jpxCoeffSignificant
))) {
2291 if (cb
->arithDecoder
->decodeBit(jpxContextRunLength
, cb
->stats
)) {
2292 y1
= cb
->arithDecoder
->decodeBit(jpxContextUniform
, cb
->stats
);
2294 cb
->arithDecoder
->decodeBit(jpxContextUniform
, cb
->stats
);
2295 for (y2
= 0, coeff
= coeff1
;
2297 ++y2
, coeff
+= tileComp
->cbW
) {
2300 coeff
->flags
|= jpxCoeffSignificant
| jpxCoeffFirstMagRef
;
2301 coeff
->mag
= (coeff
->mag
<< 1) | 1;
2303 cx
= signContext
[2][2][0];
2304 xorBit
= signContext
[2][2][1];
2305 if (cb
->arithDecoder
->decodeBit(cx
, cb
->stats
) ^ xorBit
) {
2306 coeff
->flags
|= jpxCoeffSign
;
2310 for (y1
= 0, coeff
= coeff1
;
2312 ++y1
, coeff
+= tileComp
->cbW
) {
2318 for (coeff
= &coeff1
[y1
<< tileComp
->codeBlockW
];
2319 y1
< 4 && y0
+ y1
< cb
->y1
;
2320 ++y1
, coeff
+= tileComp
->cbW
) {
2321 if (!(coeff
->flags
& jpxCoeffTouched
)) {
2322 horiz
= vert
= diag
= 0;
2323 horizSign
= vertSign
= 2;
2325 if (coeff
[-1].flags
& jpxCoeffSignificant
) {
2327 horizSign
+= (coeff
[-1].flags
& jpxCoeffSign
) ? -1 : 1;
2329 if (y0
+y1
> cb
->y0
) {
2330 diag
+= (coeff
[-(int)tileComp
->cbW
- 1].flags
2331 >> jpxCoeffSignificantB
) & 1;
2333 if (y0
+y1
< cb
->y1
- 1) {
2334 diag
+= (coeff
[tileComp
->cbW
- 1].flags
2335 >> jpxCoeffSignificantB
) & 1;
2338 if (x
< cb
->x1
- 1) {
2339 if (coeff
[1].flags
& jpxCoeffSignificant
) {
2341 horizSign
+= (coeff
[1].flags
& jpxCoeffSign
) ? -1 : 1;
2343 if (y0
+y1
> cb
->y0
) {
2344 diag
+= (coeff
[-(int)tileComp
->cbW
+ 1].flags
2345 >> jpxCoeffSignificantB
) & 1;
2347 if (y0
+y1
< cb
->y1
- 1) {
2348 diag
+= (coeff
[tileComp
->cbW
+ 1].flags
2349 >> jpxCoeffSignificantB
) & 1;
2352 if (y0
+y1
> cb
->y0
) {
2353 if (coeff
[-(int)tileComp
->cbW
].flags
& jpxCoeffSignificant
) {
2355 vertSign
+= (coeff
[-(int)tileComp
->cbW
].flags
& jpxCoeffSign
)
2359 if (y0
+y1
< cb
->y1
- 1) {
2360 if (coeff
[tileComp
->cbW
].flags
& jpxCoeffSignificant
) {
2362 vertSign
+= (coeff
[tileComp
->cbW
].flags
& jpxCoeffSign
)
2366 cx
= sigPropContext
[horiz
][vert
][diag
][res
== 0 ? 1 : sb
];
2367 if (cb
->arithDecoder
->decodeBit(cx
, cb
->stats
)) {
2368 coeff
->flags
|= jpxCoeffSignificant
| jpxCoeffFirstMagRef
;
2369 coeff
->mag
= (coeff
->mag
<< 1) | 1;
2370 cx
= signContext
[horizSign
][vertSign
][0];
2371 xorBit
= signContext
[horizSign
][vertSign
][1];
2372 if (cb
->arithDecoder
->decodeBit(cx
, cb
->stats
) ^ xorBit
) {
2373 coeff
->flags
|= jpxCoeffSign
;
2378 coeff
->flags
&= ~jpxCoeffTouched
;
2383 cb
->nextPass
= jpxPassSigProp
;
2388 cb
->arithDecoder
->cleanup();
2392 // Inverse quantization, and wavelet transform (IDWT). This also does
2393 // the initial shift to convert to fixed point format.
2394 void JPXStream::inverseTransform(JPXTileComp
*tileComp
) {
2395 JPXResLevel
*resLevel
;
2396 JPXPrecinct
*precinct
;
2397 JPXSubband
*subband
;
2399 JPXCoeff
*coeff0
, *coeff
;
2400 Guint qStyle
, guard
, eps
, shift
;
2405 Guint nx0
, ny0
, nx1
, ny1
;
2406 Guint r
, cbX
, cbY
, x
, y
;
2408 //----- (NL)LL subband (resolution level 0)
2410 resLevel
= &tileComp
->resLevels
[0];
2411 precinct
= &resLevel
->precincts
[0];
2412 subband
= &precinct
->subbands
[0];
2414 // i-quant parameters
2415 qStyle
= tileComp
->quantStyle
& 0x1f;
2416 guard
= (tileComp
->quantStyle
>> 5) & 7;
2418 eps
= (tileComp
->quantSteps
[0] >> 3) & 0x1f;
2419 shift
= guard
+ eps
- 1;
2420 mu
= 0; // make gcc happy
2422 shift
= guard
- 1 + tileComp
->prec
;
2423 mu
= (double)(0x800 + (tileComp
->quantSteps
[0] & 0x7ff)) / 2048.0;
2425 if (tileComp
->transform
== 0) {
2429 // copy (NL)LL into the upper-left corner of the data array, doing
2430 // the fixed point adjustment and dequantization along the way
2432 for (cbY
= 0; cbY
< subband
->nYCBs
; ++cbY
) {
2433 for (cbX
= 0; cbX
< subband
->nXCBs
; ++cbX
) {
2434 for (y
= cb
->y0
, coeff0
= cb
->coeffs
;
2436 ++y
, coeff0
+= tileComp
->cbW
) {
2437 dataPtr
= &tileComp
->data
[(y
- subband
->y0
)
2438 * (tileComp
->x1
- tileComp
->x0
)
2439 + (cb
->x0
- subband
->x0
)];
2440 for (x
= cb
->x0
, coeff
= coeff0
; x
< cb
->x1
; ++x
, ++coeff
) {
2441 val
= (int)coeff
->mag
;
2443 shift2
= shift
- (cb
->nZeroBitPlanes
+ coeff
->len
);
2445 val
= (val
<< shift2
) + (1 << (shift2
- 1));
2450 if (tileComp
->transform
== 0) {
2451 val
&= -1 << fracBits
;
2454 val
= (int)((double)val
* mu
);
2456 if (coeff
->flags
& jpxCoeffSign
) {
2467 //----- IDWT for each level
2469 for (r
= 1; r
<= tileComp
->nDecompLevels
; ++r
) {
2470 resLevel
= &tileComp
->resLevels
[r
];
2472 // (n)LL is already in the upper-left corner of the
2473 // tile-component data array -- interleave with (n)HL/LH/HH
2474 // and inverse transform to get (n-1)LL, which will be stored
2475 // in the upper-left corner of the tile-component data array
2476 if (r
== tileComp
->nDecompLevels
) {
2482 nx0
= tileComp
->resLevels
[r
+1].x0
;
2483 ny0
= tileComp
->resLevels
[r
+1].y0
;
2484 nx1
= tileComp
->resLevels
[r
+1].x1
;
2485 ny1
= tileComp
->resLevels
[r
+1].y1
;
2487 inverseTransformLevel(tileComp
, r
, resLevel
, nx0
, ny0
, nx1
, ny1
);
2491 // Do one level of the inverse transform:
2492 // - take (n)LL from the tile-component data array
2493 // - take (n)HL/LH/HH from <resLevel>
2494 // - leave the resulting (n-1)LL in the tile-component data array
2495 void JPXStream::inverseTransformLevel(JPXTileComp
*tileComp
,
2496 Guint r
, JPXResLevel
*resLevel
,
2497 Guint nx0
, Guint ny0
,
2498 Guint nx1
, Guint ny1
) {
2499 JPXPrecinct
*precinct
;
2500 JPXSubband
*subband
;
2502 JPXCoeff
*coeff0
, *coeff
;
2503 Guint qStyle
, guard
, eps
, shift
, t
;
2509 Guint x
, y
, sb
, cbX
, cbY
;
2515 for (yy
= resLevel
->y1
- 1; yy
>= (int)resLevel
->y0
; --yy
) {
2516 for (xx
= resLevel
->x1
- 1; xx
>= (int)resLevel
->x0
; --xx
) {
2517 tileComp
->data
[(2 * yy
- ny0
) * (tileComp
->x1
- tileComp
->x0
)
2519 tileComp
->data
[(yy
- resLevel
->y0
) * (tileComp
->x1
- tileComp
->x0
)
2520 + (xx
- resLevel
->x0
)];
2524 // i-quant parameters
2525 qStyle
= tileComp
->quantStyle
& 0x1f;
2526 guard
= (tileComp
->quantStyle
>> 5) & 7;
2528 // interleave HL/LH/HH
2529 precinct
= &resLevel
->precincts
[0];
2530 for (sb
= 0; sb
< 3; ++sb
) {
2532 // i-quant parameters
2534 eps
= (tileComp
->quantSteps
[3*r
- 2 + sb
] >> 3) & 0x1f;
2535 shift
= guard
+ eps
- 1;
2536 mu
= 0; // make gcc happy
2538 shift
= guard
+ tileComp
->prec
;
2542 t
= tileComp
->quantSteps
[qStyle
== 1 ? 0 : (3*r
- 2 + sb
)];
2543 mu
= (double)(0x800 + (t
& 0x7ff)) / 2048.0;
2545 if (tileComp
->transform
== 0) {
2549 // copy the subband coefficients into the data array, doing the
2550 // fixed point adjustment and dequantization along the way
2551 xo
= (sb
& 1) ? 0 : 1;
2552 yo
= (sb
> 0) ? 1 : 0;
2553 subband
= &precinct
->subbands
[sb
];
2555 for (cbY
= 0; cbY
< subband
->nYCBs
; ++cbY
) {
2556 for (cbX
= 0; cbX
< subband
->nXCBs
; ++cbX
) {
2557 for (y
= cb
->y0
, coeff0
= cb
->coeffs
;
2559 ++y
, coeff0
+= tileComp
->cbW
) {
2560 dataPtr
= &tileComp
->data
[(2 * y
+ yo
- ny0
)
2561 * (tileComp
->x1
- tileComp
->x0
)
2562 + (2 * cb
->x0
+ xo
- nx0
)];
2563 for (x
= cb
->x0
, coeff
= coeff0
; x
< cb
->x1
; ++x
, ++coeff
) {
2564 val
= (int)coeff
->mag
;
2566 shift2
= shift
- (cb
->nZeroBitPlanes
+ coeff
->len
);
2568 val
= (val
<< shift2
) + (1 << (shift2
- 1));
2573 if (tileComp
->transform
== 0) {
2574 val
&= -1 << fracBits
;
2577 val
= (int)((double)val
* mu
);
2579 if (coeff
->flags
& jpxCoeffSign
) {
2592 //----- horizontal (row) transforms
2593 dataPtr
= tileComp
->data
;
2594 for (y
= 0; y
< ny1
- ny0
; ++y
) {
2595 inverseTransform1D(tileComp
, dataPtr
, 1, nx0
, nx1
);
2596 dataPtr
+= tileComp
->x1
- tileComp
->x0
;
2599 //----- vertical (column) transforms
2600 dataPtr
= tileComp
->data
;
2601 for (x
= 0; x
< nx1
- nx0
; ++x
) {
2602 inverseTransform1D(tileComp
, dataPtr
,
2603 tileComp
->x1
- tileComp
->x0
, ny0
, ny1
);
2608 void JPXStream::inverseTransform1D(JPXTileComp
*tileComp
,
2609 int *data
, Guint stride
,
2610 Guint i0
, Guint i1
) {
2612 Guint offset
, end
, i
;
2614 //----- special case for length = 1
2622 // choose an offset: this makes even buf[] indexes correspond to
2623 // odd values of i, and vice versa
2624 offset
= 3 + (i0
& 1);
2625 end
= offset
+ i1
- i0
;
2628 buf
= tileComp
->buf
;
2629 for (i
= 0; i
< i1
- i0
; ++i
) {
2630 buf
[offset
+ i
] = data
[i
* stride
];
2633 //----- extend right
2634 buf
[end
] = buf
[end
- 2];
2636 buf
[end
+1] = buf
[offset
+ 1];
2637 buf
[end
+2] = buf
[offset
];
2638 buf
[end
+3] = buf
[offset
+ 1];
2640 buf
[end
+1] = buf
[end
- 3];
2642 buf
[end
+2] = buf
[offset
+ 1];
2643 buf
[end
+3] = buf
[offset
+ 2];
2645 buf
[end
+2] = buf
[end
- 4];
2647 buf
[end
+3] = buf
[offset
+ 1];
2649 buf
[end
+3] = buf
[end
- 5];
2655 buf
[offset
- 1] = buf
[offset
+ 1];
2656 buf
[offset
- 2] = buf
[offset
+ 2];
2657 buf
[offset
- 3] = buf
[offset
+ 3];
2659 buf
[0] = buf
[offset
+ 4];
2662 //----- 9-7 irreversible filter
2664 if (tileComp
->transform
== 0) {
2666 for (i
= 1; i
<= end
+ 2; i
+= 2) {
2667 buf
[i
] = (int)(idwtKappa
* buf
[i
]);
2670 for (i
= 0; i
<= end
+ 3; i
+= 2) {
2671 buf
[i
] = (int)(idwtIKappa
* buf
[i
]);
2674 for (i
= 1; i
<= end
+ 2; i
+= 2) {
2675 buf
[i
] = (int)(buf
[i
] - idwtDelta
* (buf
[i
-1] + buf
[i
+1]));
2678 for (i
= 2; i
<= end
+ 1; i
+= 2) {
2679 buf
[i
] = (int)(buf
[i
] - idwtGamma
* (buf
[i
-1] + buf
[i
+1]));
2682 for (i
= 3; i
<= end
; i
+= 2) {
2683 buf
[i
] = (int)(buf
[i
] - idwtBeta
* (buf
[i
-1] + buf
[i
+1]));
2686 for (i
= 4; i
<= end
- 1; i
+= 2) {
2687 buf
[i
] = (int)(buf
[i
] - idwtAlpha
* (buf
[i
-1] + buf
[i
+1]));
2690 //----- 5-3 reversible filter
2694 for (i
= 3; i
<= end
; i
+= 2) {
2695 buf
[i
] -= (buf
[i
-1] + buf
[i
+1] + 2) >> 2;
2698 for (i
= 4; i
< end
; i
+= 2) {
2699 buf
[i
] += (buf
[i
-1] + buf
[i
+1]) >> 1;
2704 for (i
= 0; i
< i1
- i0
; ++i
) {
2705 data
[i
* stride
] = buf
[offset
+ i
];
2710 // Inverse multi-component transform and DC level shift. This also
2711 // converts fixed point samples back to integers.
2712 GBool
JPXStream::inverseMultiCompAndDC(JPXTile
*tile
) {
2713 JPXTileComp
*tileComp
;
2714 int coeff
, d0
, d1
, d2
, t
, minVal
, maxVal
, zeroVal
;
2716 Guint j
, comp
, x
, y
;
2718 //----- inverse multi-component transform
2720 if (tile
->multiComp
== 1) {
2721 if (img
.nComps
< 3 ||
2722 tile
->tileComps
[0].hSep
!= tile
->tileComps
[1].hSep
||
2723 tile
->tileComps
[0].vSep
!= tile
->tileComps
[1].vSep
||
2724 tile
->tileComps
[1].hSep
!= tile
->tileComps
[2].hSep
||
2725 tile
->tileComps
[1].vSep
!= tile
->tileComps
[2].vSep
) {
2729 // inverse irreversible multiple component transform
2730 if (tile
->tileComps
[0].transform
== 0) {
2732 for (y
= 0; y
< tile
->tileComps
[0].y1
- tile
->tileComps
[0].y0
; ++y
) {
2733 for (x
= 0; x
< tile
->tileComps
[0].x1
- tile
->tileComps
[0].x0
; ++x
) {
2734 d0
= tile
->tileComps
[0].data
[j
];
2735 d1
= tile
->tileComps
[1].data
[j
];
2736 d2
= tile
->tileComps
[2].data
[j
];
2737 tile
->tileComps
[0].data
[j
] = (int)(d0
+ 1.402 * d2
+ 0.5);
2738 tile
->tileComps
[1].data
[j
] =
2739 (int)(d0
- 0.34413 * d1
- 0.71414 * d2
+ 0.5);
2740 tile
->tileComps
[2].data
[j
] = (int)(d0
+ 1.772 * d1
+ 0.5);
2745 // inverse reversible multiple component transform
2748 for (y
= 0; y
< tile
->tileComps
[0].y1
- tile
->tileComps
[0].y0
; ++y
) {
2749 for (x
= 0; x
< tile
->tileComps
[0].x1
- tile
->tileComps
[0].x0
; ++x
) {
2750 d0
= tile
->tileComps
[0].data
[j
];
2751 d1
= tile
->tileComps
[1].data
[j
];
2752 d2
= tile
->tileComps
[2].data
[j
];
2753 tile
->tileComps
[1].data
[j
] = t
= d0
- ((d2
+ d1
) >> 2);
2754 tile
->tileComps
[0].data
[j
] = d2
+ t
;
2755 tile
->tileComps
[2].data
[j
] = d1
+ t
;
2762 //----- DC level shift
2763 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
2764 tileComp
= &tile
->tileComps
[comp
];
2767 if (tileComp
->sgned
) {
2768 minVal
= -(1 << (tileComp
->prec
- 1));
2769 maxVal
= (1 << (tileComp
->prec
- 1)) - 1;
2770 dataPtr
= tileComp
->data
;
2771 for (y
= 0; y
< tileComp
->y1
- tileComp
->y0
; ++y
) {
2772 for (x
= 0; x
< tileComp
->x1
- tileComp
->x0
; ++x
) {
2774 if (tileComp
->transform
== 0) {
2777 if (coeff
< minVal
) {
2779 } else if (coeff
> maxVal
) {
2786 // unsigned: inverse DC level shift and clip
2788 maxVal
= (1 << tileComp
->prec
) - 1;
2789 zeroVal
= 1 << (tileComp
->prec
- 1);
2790 dataPtr
= tileComp
->data
;
2791 for (y
= 0; y
< tileComp
->y1
- tileComp
->y0
; ++y
) {
2792 for (x
= 0; x
< tileComp
->x1
- tileComp
->x0
; ++x
) {
2794 if (tileComp
->transform
== 0) {
2800 } else if (coeff
> maxVal
) {
2812 GBool
JPXStream::readBoxHdr(Guint
*boxType
, Guint
*boxLen
, Guint
*dataLen
) {
2815 if (!readULong(&len
) ||
2816 !readULong(boxType
)) {
2820 if (!readULong(&lenH
) || !readULong(&len
)) {
2824 error(getPos(), "JPX stream contains a box larger than 2^32 bytes");
2828 *dataLen
= len
- 16;
2829 } else if (len
== 0) {
2839 int JPXStream::readMarkerHdr(int *segType
, Guint
*segLen
) {
2844 if ((c
= str
->getChar()) == EOF
) {
2847 } while (c
!= 0xff);
2849 if ((c
= str
->getChar()) == EOF
) {
2852 } while (c
== 0xff);
2853 } while (c
== 0x00);
2855 if ((c
>= 0x30 && c
<= 0x3f) ||
2856 c
== 0x4f || c
== 0x92 || c
== 0x93 || c
== 0xd9) {
2860 return readUWord(segLen
);
2863 GBool
JPXStream::readUByte(Guint
*x
) {
2866 if ((c0
= str
->getChar()) == EOF
) {
2873 GBool
JPXStream::readByte(int *x
) {
2876 if ((c0
= str
->getChar()) == EOF
) {
2886 GBool
JPXStream::readUWord(Guint
*x
) {
2889 if ((c0
= str
->getChar()) == EOF
||
2890 (c1
= str
->getChar()) == EOF
) {
2893 *x
= (Guint
)((c0
<< 8) | c1
);
2897 GBool
JPXStream::readULong(Guint
*x
) {
2900 if ((c0
= str
->getChar()) == EOF
||
2901 (c1
= str
->getChar()) == EOF
||
2902 (c2
= str
->getChar()) == EOF
||
2903 (c3
= str
->getChar()) == EOF
) {
2906 *x
= (Guint
)((c0
<< 24) | (c1
<< 16) | (c2
<< 8) | c3
);
2910 GBool
JPXStream::readNBytes(int nBytes
, GBool signd
, int *x
) {
2914 for (i
= 0; i
< nBytes
; ++i
) {
2915 if ((c
= str
->getChar()) == EOF
) {
2921 if (y
& (1 << (8 * nBytes
- 1))) {
2922 y
|= -1 << (8 * nBytes
);
2929 GBool
JPXStream::readBits(int nBits
, Guint
*x
) {
2932 while (bitBufLen
< nBits
) {
2933 if ((c
= str
->getChar()) == EOF
) {
2938 bitBuf
= (bitBuf
<< 7) | (c
& 0x7f);
2941 bitBuf
= (bitBuf
<< 8) | (c
& 0xff);
2944 bitBufSkip
= c
== 0xff;
2946 *x
= (bitBuf
>> (bitBufLen
- nBits
)) & ((1 << nBits
) - 1);
2951 void JPXStream::clearBitBuf() {
2953 bitBufSkip
= gFalse
;