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