1 //========================================================================
5 // Copyright 2002-2003 Glyph & Cog, LLC
7 //========================================================================
9 //========================================================================
11 // Modified under the Poppler project - http://poppler.freedesktop.org
13 // All changes made under the Poppler project to this file are licensed
14 // under GPL version 2 or later
16 // Copyright (C) 2008, 2012 Albert Astals Cid <aacid@kde.org>
17 // Copyright (C) 2012 Thomas Freitag <Thomas.Freitag@alfa.de>
18 // Copyright (C) 2012 Even Rouault <even.rouault@mines-paris.org>
20 // To see a description of the changes please see the Changelog file that
21 // came with your tarball or type make ChangeLog if you are building from git
23 //========================================================================
27 #ifdef USE_GCC_PRAGMAS
28 #pragma implementation
34 #include "JArithmeticDecoder.h"
35 #include "JPXStream.h"
40 // - progression order changes
41 // - packed packet headers
42 // - support for palettes, channel maps, etc.
43 // - make sure all needed JP2/JPX subboxes are parsed (readBoxes)
44 // - can we assume that QCC segments must come after the QCD segment?
45 // - handle tilePartToEOC in readTilePartData
46 // - progression orders 2, 3, and 4
47 // - in coefficient decoding (readCodeBlockData):
48 // - selective arithmetic coding bypass
49 // (this also affects reading the cb->dataLen array)
50 // - coeffs longer than 31 bits (should just ignore the extra bits?)
51 // - handle boxes larger than 2^32 bytes
52 // - the fixed-point arithmetic won't handle 16-bit pixels
54 //------------------------------------------------------------------------
56 // number of contexts for the arithmetic decoder
57 #define jpxNContexts 19
59 #define jpxContextSigProp 0 // 0 - 8: significance prop and cleanup
60 #define jpxContextSign 9 // 9 - 13: sign
61 #define jpxContextMagRef 14 // 14 -16: magnitude refinement
62 #define jpxContextRunLength 17 // cleanup: run length
63 #define jpxContextUniform 18 // cleanup: first signif coeff
65 //------------------------------------------------------------------------
67 #define jpxPassSigProp 0
68 #define jpxPassMagRef 1
69 #define jpxPassCleanup 2
71 //------------------------------------------------------------------------
73 // arithmetic decoder context for the significance propagation and
75 // [horiz][vert][diag][subband]
76 // where subband = 0 for HL
79 static const Guint sigPropContext
[3][3][5][3] = {
80 {{{ 0, 0, 0 }, // horiz=0, vert=0, diag=0
81 { 1, 1, 3 }, // horiz=0, vert=0, diag=1
82 { 2, 2, 6 }, // horiz=0, vert=0, diag=2
83 { 2, 2, 8 }, // horiz=0, vert=0, diag=3
84 { 2, 2, 8 }}, // horiz=0, vert=0, diag=4
85 {{ 5, 3, 1 }, // horiz=0, vert=1, diag=0
86 { 6, 3, 4 }, // horiz=0, vert=1, diag=1
87 { 6, 3, 7 }, // horiz=0, vert=1, diag=2
88 { 6, 3, 8 }, // horiz=0, vert=1, diag=3
89 { 6, 3, 8 }}, // horiz=0, vert=1, diag=4
90 {{ 8, 4, 2 }, // horiz=0, vert=2, diag=0
91 { 8, 4, 5 }, // horiz=0, vert=2, diag=1
92 { 8, 4, 7 }, // horiz=0, vert=2, diag=2
93 { 8, 4, 8 }, // horiz=0, vert=2, diag=3
94 { 8, 4, 8 }}}, // horiz=0, vert=2, diag=4
95 {{{ 3, 5, 1 }, // horiz=1, vert=0, diag=0
96 { 3, 6, 4 }, // horiz=1, vert=0, diag=1
97 { 3, 6, 7 }, // horiz=1, vert=0, diag=2
98 { 3, 6, 8 }, // horiz=1, vert=0, diag=3
99 { 3, 6, 8 }}, // horiz=1, vert=0, diag=4
100 {{ 7, 7, 2 }, // horiz=1, vert=1, diag=0
101 { 7, 7, 5 }, // horiz=1, vert=1, diag=1
102 { 7, 7, 7 }, // horiz=1, vert=1, diag=2
103 { 7, 7, 8 }, // horiz=1, vert=1, diag=3
104 { 7, 7, 8 }}, // horiz=1, vert=1, diag=4
105 {{ 8, 7, 2 }, // horiz=1, vert=2, diag=0
106 { 8, 7, 5 }, // horiz=1, vert=2, diag=1
107 { 8, 7, 7 }, // horiz=1, vert=2, diag=2
108 { 8, 7, 8 }, // horiz=1, vert=2, diag=3
109 { 8, 7, 8 }}}, // horiz=1, vert=2, diag=4
110 {{{ 4, 8, 2 }, // horiz=2, vert=0, diag=0
111 { 4, 8, 5 }, // horiz=2, vert=0, diag=1
112 { 4, 8, 7 }, // horiz=2, vert=0, diag=2
113 { 4, 8, 8 }, // horiz=2, vert=0, diag=3
114 { 4, 8, 8 }}, // horiz=2, vert=0, diag=4
115 {{ 7, 8, 2 }, // horiz=2, vert=1, diag=0
116 { 7, 8, 5 }, // horiz=2, vert=1, diag=1
117 { 7, 8, 7 }, // horiz=2, vert=1, diag=2
118 { 7, 8, 8 }, // horiz=2, vert=1, diag=3
119 { 7, 8, 8 }}, // horiz=2, vert=1, diag=4
120 {{ 8, 8, 2 }, // horiz=2, vert=2, diag=0
121 { 8, 8, 5 }, // horiz=2, vert=2, diag=1
122 { 8, 8, 7 }, // horiz=2, vert=2, diag=2
123 { 8, 8, 8 }, // horiz=2, vert=2, diag=3
124 { 8, 8, 8 }}} // horiz=2, vert=2, diag=4
127 // arithmetic decoder context and xor bit for the sign bit in the
128 // significance propagation pass:
130 // where horiz/vert are offset by 2 (i.e., range is -2 .. 2)
131 // and k = 0 for the context
132 // = 1 for the xor bit
133 static const Guint signContext
[5][5][2] = {
134 {{ 13, 1 }, // horiz=-2, vert=-2
135 { 13, 1 }, // horiz=-2, vert=-1
136 { 12, 1 }, // horiz=-2, vert= 0
137 { 11, 1 }, // horiz=-2, vert=+1
138 { 11, 1 }}, // horiz=-2, vert=+2
139 {{ 13, 1 }, // horiz=-1, vert=-2
140 { 13, 1 }, // horiz=-1, vert=-1
141 { 12, 1 }, // horiz=-1, vert= 0
142 { 11, 1 }, // horiz=-1, vert=+1
143 { 11, 1 }}, // horiz=-1, vert=+2
144 {{ 10, 1 }, // horiz= 0, vert=-2
145 { 10, 1 }, // horiz= 0, vert=-1
146 { 9, 0 }, // horiz= 0, vert= 0
147 { 10, 0 }, // horiz= 0, vert=+1
148 { 10, 0 }}, // horiz= 0, vert=+2
149 {{ 11, 0 }, // horiz=+1, vert=-2
150 { 11, 0 }, // horiz=+1, vert=-1
151 { 12, 0 }, // horiz=+1, vert= 0
152 { 13, 0 }, // horiz=+1, vert=+1
153 { 13, 0 }}, // horiz=+1, vert=+2
154 {{ 11, 0 }, // horiz=+2, vert=-2
155 { 11, 0 }, // horiz=+2, vert=-1
156 { 12, 0 }, // horiz=+2, vert= 0
157 { 13, 0 }, // horiz=+2, vert=+1
158 { 13, 0 }}, // horiz=+2, vert=+2
161 //------------------------------------------------------------------------
163 // constants used in the IDWT
164 #define idwtAlpha -1.586134342059924
165 #define idwtBeta -0.052980118572961
166 #define idwtGamma 0.882911075530934
167 #define idwtDelta 0.443506852043971
168 #define idwtKappa 1.230174104914001
169 #define idwtIKappa (1.0 / idwtKappa)
171 // number of bits to the right of the decimal point for the fixed
172 // point arithmetic used in the IDWT
175 //------------------------------------------------------------------------
178 #define jpxFloorDiv(x, y) ((x) / (y))
181 #define jpxFloorDivPow2(x, y) ((x) >> (y))
184 #define jpxCeilDiv(x, y) (((x) + (y) - 1) / (y))
187 #define jpxCeilDivPow2(x, y) (((x) + (1 << (y)) - 1) >> (y))
189 //------------------------------------------------------------------------
191 #if 1 //----- disable coverage tracking
195 #else //----- enable coverage tracking
210 JPXCover::JPXCover(int sizeA
) {
213 data
= (int *)gmallocn(size
, sizeof(int));
214 memset(data
, 0, size
* sizeof(int));
217 JPXCover::~JPXCover() {
220 printf("JPX coverage:\n");
221 for (i
= 0; i
<= used
; ++i
) {
222 printf(" %4d: %8d\n", i
, data
[i
]);
227 void JPXCover::incr(int idx
) {
236 JPXCover
jpxCover(150);
238 #define cover(idx) jpxCover.incr(idx)
240 #endif //----- coverage tracking
242 //------------------------------------------------------------------------
244 JPXStream::JPXStream(Stream
*strA
):
247 bufStr
= new BufStream(str
, 2);
253 havePalette
= gFalse
;
254 haveCompMap
= gFalse
;
255 haveChannelDefn
= gFalse
;
268 JPXStream::~JPXStream() {
273 void JPXStream::reset() {
278 // readBoxes reported an error, so we go immediately to EOF
286 void JPXStream::close() {
288 JPXTileComp
*tileComp
;
289 JPXResLevel
*resLevel
;
290 JPXPrecinct
*precinct
;
293 Guint comp
, i
, k
, r
, pre
, sb
;
300 havePalette
= gFalse
;
305 gfree(compMap
.pComp
);
306 haveCompMap
= gFalse
;
308 if (haveChannelDefn
) {
309 gfree(channelDefn
.idx
);
310 gfree(channelDefn
.type
);
311 gfree(channelDefn
.assoc
);
312 haveChannelDefn
= gFalse
;
316 for (i
= 0; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
317 tile
= &img
.tiles
[i
];
318 if (tile
->tileComps
) {
319 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
320 tileComp
= &tile
->tileComps
[comp
];
321 gfree(tileComp
->quantSteps
);
322 gfree(tileComp
->data
);
323 gfree(tileComp
->buf
);
324 if (tileComp
->resLevels
) {
325 for (r
= 0; r
<= tileComp
->nDecompLevels
; ++r
) {
326 resLevel
= &tileComp
->resLevels
[r
];
327 if (resLevel
->precincts
) {
328 for (pre
= 0; pre
< 1; ++pre
) {
329 precinct
= &resLevel
->precincts
[pre
];
330 if (precinct
->subbands
) {
331 for (sb
= 0; sb
< (Guint
)(r
== 0 ? 1 : 3); ++sb
) {
332 subband
= &precinct
->subbands
[sb
];
333 gfree(subband
->inclusion
);
334 gfree(subband
->zeroBitPlane
);
336 for (k
= 0; k
< subband
->nXCBs
* subband
->nYCBs
; ++k
) {
337 cb
= &subband
->cbs
[k
];
340 if (cb
->arithDecoder
) {
341 delete cb
->arithDecoder
;
350 gfree(precinct
->subbands
);
353 gfree(img
.tiles
[i
].tileComps
[comp
].resLevels
[r
].precincts
);
356 gfree(img
.tiles
[i
].tileComps
[comp
].resLevels
);
359 gfree(img
.tiles
[i
].tileComps
);
368 int JPXStream::getChar() {
371 if (readBufLen
< 8) {
374 if (readBufLen
== 8) {
377 } else if (readBufLen
> 8) {
378 c
= (readBuf
>> (readBufLen
- 8)) & 0xff;
380 } else if (readBufLen
== 0) {
383 c
= (readBuf
<< (8 - readBufLen
)) & 0xff;
389 int JPXStream::lookChar() {
392 if (readBufLen
< 8) {
395 if (readBufLen
== 8) {
397 } else if (readBufLen
> 8) {
398 c
= (readBuf
>> (readBufLen
- 8)) & 0xff;
399 } else if (readBufLen
== 0) {
402 c
= (readBuf
<< (8 - readBufLen
)) & 0xff;
407 void JPXStream::fillReadBuf() {
408 JPXTileComp
*tileComp
;
409 Guint tileIdx
, tx
, ty
;
413 if (curY
>= img
.ySize
) {
416 tileIdx
= ((curY
- img
.yTileOffset
) / img
.yTileSize
) * img
.nXTiles
417 + (curX
- img
.xTileOffset
) / img
.xTileSize
;
418 #if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid
419 if (img
.tiles
== NULL
|| tileIdx
>= img
.nXTiles
* img
.nYTiles
|| img
.tiles
[tileIdx
].tileComps
== NULL
) {
420 error(errSyntaxError
, getPos(), "Unexpected tileIdx in fillReadBuf in JPX stream");
423 tileComp
= &img
.tiles
[tileIdx
].tileComps
[curComp
];
425 tileComp
= &img
.tiles
[tileIdx
].tileComps
[havePalette
? 0 : curComp
];
427 tx
= jpxCeilDiv((curX
- img
.xTileOffset
) % img
.xTileSize
, tileComp
->hSep
);
428 ty
= jpxCeilDiv((curY
- img
.yTileOffset
) % img
.yTileSize
, tileComp
->vSep
);
429 if (unlikely(ty
>= (tileComp
->y1
- tileComp
->y0
))) {
430 error(errSyntaxError
, getPos(), "Unexpected ty in fillReadBuf in JPX stream");
433 if (unlikely(tx
>= (tileComp
->x1
- tileComp
->x0
))) {
434 error(errSyntaxError
, getPos(), "Unexpected tx in fillReadBuf in JPX stream");
437 pix
= (int)tileComp
->data
[ty
* (tileComp
->x1
- tileComp
->x0
) + tx
];
438 pixBits
= tileComp
->prec
;
439 #if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid
440 if (++curComp
== img
.nComps
) {
443 if (pix
>= 0 && pix
< palette
.nEntries
) {
444 pix
= palette
.c
[pix
* palette
.nComps
+ curComp
];
448 pixBits
= palette
.bpc
[curComp
];
450 if (++curComp
== (Guint
)(havePalette
? palette
.nComps
: img
.nComps
)) {
453 if (++curX
== img
.xSize
) {
463 readBuf
= (readBuf
<< 8) | (pix
& 0xff);
465 readBuf
= (readBuf
<< pixBits
) | (pix
& ((1 << pixBits
) - 1));
467 readBufLen
+= pixBits
;
468 } while (readBufLen
< 8);
471 GooString
*JPXStream::getPSFilter(int psLevel
, const char *indent
) {
475 GBool
JPXStream::isBinary(GBool last
) {
476 return str
->isBinary(gTrue
);
479 void JPXStream::getImageParams(int *bitsPerComponent
,
480 StreamColorSpaceMode
*csMode
) {
481 Guint boxType
, boxLen
, dataLen
, csEnum
;
482 Guint bpc1
, dummy
, i
;
483 int csMeth
, csPrec
, csPrec1
, dummy2
;
484 StreamColorSpaceMode csMode1
;
485 GBool haveBPC
, haveCSMode
;
487 csPrec
= 0; // make gcc happy
488 haveBPC
= haveCSMode
= gFalse
;
490 if (bufStr
->lookChar() == 0xff) {
491 getImageParams2(bitsPerComponent
, csMode
);
493 while (readBoxHdr(&boxType
, &boxLen
, &dataLen
)) {
494 if (boxType
== 0x6a703268) { // JP2 header
497 } else if (boxType
== 0x69686472) { // image header
499 if (readULong(&dummy
) &&
506 *bitsPerComponent
= bpc1
+ 1;
509 } else if (boxType
== 0x636F6C72) { // color specification
511 if (readByte(&csMeth
) &&
512 readByte(&csPrec1
) &&
515 if (readULong(&csEnum
)) {
516 csMode1
= streamCSNone
;
517 if (csEnum
== jpxCSBiLevel
||
518 csEnum
== jpxCSGrayscale
) {
519 csMode1
= streamCSDeviceGray
;
520 } else if (csEnum
== jpxCSCMYK
) {
521 csMode1
= streamCSDeviceCMYK
;
522 } else if (csEnum
== jpxCSsRGB
||
523 csEnum
== jpxCSCISesRGB
||
524 csEnum
== jpxCSROMMRGB
) {
525 csMode1
= streamCSDeviceRGB
;
527 if (csMode1
!= streamCSNone
&&
528 (!haveCSMode
|| csPrec1
> csPrec
)) {
534 for (i
= 0; i
< dataLen
- 7; ++i
) {
535 if (bufStr
->getChar() == EOF
)
542 for (i
= 0; i
< dataLen
- 3; ++i
) {
543 if (bufStr
->getChar() == EOF
)
549 } else if (boxType
== 0x6A703263) { // codestream
551 if (!(haveBPC
&& haveCSMode
)) {
552 getImageParams2(bitsPerComponent
, csMode
);
557 for (i
= 0; i
< dataLen
; ++i
) {
558 if (unlikely(bufStr
->getChar() == EOF
)) {
559 error(errSyntaxError
, getPos(), "Unexpected EOF in getImageParams in JPX stream");
569 // Get image parameters from the codestream.
570 void JPXStream::getImageParams2(int *bitsPerComponent
,
571 StreamColorSpaceMode
*csMode
) {
573 Guint segLen
, nComps1
, bpc1
, dummy
, i
;
575 while (readMarkerHdr(&segType
, &segLen
)) {
576 if (segType
== 0x51) { // SIZ - image and tile size
578 if (readUWord(&dummy
) &&
587 readUWord(&nComps1
) &&
589 *bitsPerComponent
= (bpc1
& 0x7f) + 1;
590 // if there's no color space info, take a guess
592 *csMode
= streamCSDeviceGray
;
593 } else if (nComps1
== 3) {
594 *csMode
= streamCSDeviceRGB
;
595 } else if (nComps1
== 4) {
596 *csMode
= streamCSDeviceCMYK
;
603 for (i
= 0; i
< segLen
- 2; ++i
) {
611 GBool
JPXStream::readBoxes() {
612 Guint boxType
, boxLen
, dataLen
;
613 Guint bpc1
, compression
, unknownColorspace
, ipr
;
618 // initialize in case there is a parse error
619 img
.xSize
= img
.ySize
= 0;
620 img
.xOffset
= img
.yOffset
= 0;
621 img
.xTileSize
= img
.yTileSize
= 0;
622 img
.xTileOffset
= img
.yTileOffset
= 0;
625 // check for a naked JPEG 2000 codestream (without the JP2/JPX
626 // wrapper) -- this appears to be a violation of the PDF spec, but
628 if (bufStr
->lookChar() == 0xff) {
630 error(errSyntaxWarning
, getPos(),
631 "Naked JPEG 2000 codestream, missing JP2/JPX wrapper");
632 if (!readCodestream(0)) {
636 bpc
= (Guint
*)gmallocn(nComps
, sizeof(Guint
));
637 for (i
= 0; i
< nComps
; ++i
) {
638 bpc
[i
] = img
.tiles
[0].tileComps
[i
].prec
;
640 width
= img
.xSize
- img
.xOffset
;
641 height
= img
.ySize
- img
.yOffset
;
645 while (readBoxHdr(&boxType
, &boxLen
, &dataLen
)) {
647 case 0x6a703268: // JP2 header
648 // this is a grouping box ('superbox') which has no real
649 // contents and doesn't appear to be used consistently, i.e.,
650 // some things which should be subboxes of the JP2 header box
651 // show up outside of it - so we simply ignore the JP2 header
655 case 0x69686472: // image header
657 if (!readULong(&height
) ||
658 !readULong(&width
) ||
659 !readUWord(&nComps
) ||
661 !readUByte(&compression
) ||
662 !readUByte(&unknownColorspace
) ||
664 error(errSyntaxError
, getPos(), "Unexpected EOF in JPX stream");
667 if (compression
!= 7) {
668 error(errSyntaxError
, getPos(),
669 "Unknown compression type in JPX stream");
672 bpc
= (Guint
*)gmallocn(nComps
, sizeof(Guint
));
673 for (i
= 0; i
< nComps
; ++i
) {
678 case 0x62706363: // bits per component
681 error(errSyntaxError
, getPos(),
682 "Found bits per component box before image header box in JPX stream");
685 if (dataLen
!= nComps
) {
686 error(errSyntaxError
, getPos(),
687 "Invalid bits per component box in JPX stream");
690 for (i
= 0; i
< nComps
; ++i
) {
691 if (!readUByte(&bpc
[i
])) {
692 error(errSyntaxError
, getPos(), "Unexpected EOF in JPX stream");
697 case 0x636F6C72: // color specification
699 if (!readColorSpecBox(dataLen
)) {
703 case 0x70636c72: // palette
705 if (!readUWord(&palette
.nEntries
) ||
706 !readUByte(&palette
.nComps
)) {
707 error(errSyntaxError
, getPos(), "Unexpected EOF in JPX stream");
710 palette
.bpc
= (Guint
*)gmallocn(palette
.nComps
, sizeof(Guint
));
712 (int *)gmallocn(palette
.nEntries
* palette
.nComps
, sizeof(int));
713 for (i
= 0; i
< palette
.nComps
; ++i
) {
714 if (!readUByte(&palette
.bpc
[i
])) {
715 error(errSyntaxError
, getPos(), "Unexpected EOF in JPX stream");
720 for (i
= 0; i
< palette
.nEntries
; ++i
) {
721 for (j
= 0; j
< palette
.nComps
; ++j
) {
722 if (!readNBytes(((palette
.bpc
[j
] & 0x7f) + 7) >> 3,
723 (palette
.bpc
[j
] & 0x80) ? gTrue
: gFalse
,
724 &palette
.c
[i
* palette
.nComps
+ j
])) {
725 error(errSyntaxError
, getPos(), "Unexpected EOF in JPX stream");
732 case 0x636d6170: // component mapping
734 compMap
.nChannels
= dataLen
/ 4;
735 compMap
.comp
= (Guint
*)gmallocn(compMap
.nChannels
, sizeof(Guint
));
736 compMap
.type
= (Guint
*)gmallocn(compMap
.nChannels
, sizeof(Guint
));
737 compMap
.pComp
= (Guint
*)gmallocn(compMap
.nChannels
, sizeof(Guint
));
738 for (i
= 0; i
< compMap
.nChannels
; ++i
) {
739 if (!readUWord(&compMap
.comp
[i
]) ||
740 !readUByte(&compMap
.type
[i
]) ||
741 !readUByte(&compMap
.pComp
[i
])) {
742 error(errSyntaxError
, getPos(), "Unexpected EOF in JPX stream");
748 case 0x63646566: // channel definition
750 if (!readUWord(&channelDefn
.nChannels
)) {
751 error(errSyntaxError
, getPos(), "Unexpected EOF in JPX stream");
755 (Guint
*)gmallocn(channelDefn
.nChannels
, sizeof(Guint
));
757 (Guint
*)gmallocn(channelDefn
.nChannels
, sizeof(Guint
));
759 (Guint
*)gmallocn(channelDefn
.nChannels
, sizeof(Guint
));
760 for (i
= 0; i
< channelDefn
.nChannels
; ++i
) {
761 if (!readUWord(&channelDefn
.idx
[i
]) ||
762 !readUWord(&channelDefn
.type
[i
]) ||
763 !readUWord(&channelDefn
.assoc
[i
])) {
764 error(errSyntaxError
, getPos(), "Unexpected EOF in JPX stream");
768 haveChannelDefn
= gTrue
;
770 case 0x6A703263: // contiguous codestream
773 error(errSyntaxError
, getPos(),
774 "JPX stream is missing the image header box");
777 error(errSyntaxError
, getPos(),
778 "JPX stream has no supported color spec");
780 if (!readCodestream(dataLen
)) {
786 for (i
= 0; i
< dataLen
; ++i
) {
787 if (bufStr
->getChar() == EOF
) {
788 error(errSyntaxError
, getPos(), "Unexpected EOF in JPX stream");
798 GBool
JPXStream::readColorSpecBox(Guint dataLen
) {
800 Guint csApprox
, csEnum
;
805 if (!readUByte(&newCS
.meth
) ||
806 !readByte(&newCS
.prec
) ||
807 !readUByte(&csApprox
)) {
810 switch (newCS
.meth
) {
811 case 1: // enumerated colorspace
813 if (!readULong(&csEnum
)) {
816 newCS
.enumerated
.type
= (JPXColorSpaceType
)csEnum
;
817 switch (newCS
.enumerated
.type
) {
843 if (dataLen
== 7 + 7*4) {
844 if (!readULong(&newCS
.enumerated
.cieLab
.rl
) ||
845 !readULong(&newCS
.enumerated
.cieLab
.ol
) ||
846 !readULong(&newCS
.enumerated
.cieLab
.ra
) ||
847 !readULong(&newCS
.enumerated
.cieLab
.oa
) ||
848 !readULong(&newCS
.enumerated
.cieLab
.rb
) ||
849 !readULong(&newCS
.enumerated
.cieLab
.ob
) ||
850 !readULong(&newCS
.enumerated
.cieLab
.il
)) {
853 } else if (dataLen
== 7) {
854 //~ this assumes the 8-bit case
856 newCS
.enumerated
.cieLab
.rl
= 100;
857 newCS
.enumerated
.cieLab
.ol
= 0;
858 newCS
.enumerated
.cieLab
.ra
= 255;
859 newCS
.enumerated
.cieLab
.oa
= 128;
860 newCS
.enumerated
.cieLab
.rb
= 255;
861 newCS
.enumerated
.cieLab
.ob
= 96;
862 newCS
.enumerated
.cieLab
.il
= 0x00443530;
878 // not allowed in PDF
899 case 2: // restricted ICC profile
900 case 3: // any ICC profile (JPX)
901 case 4: // vendor color (JPX)
903 for (i
= 0; i
< dataLen
- 3; ++i
) {
904 if (bufStr
->getChar() == EOF
) {
911 if (ok
&& (!haveCS
|| newCS
.prec
> cs
.prec
)) {
919 error(errSyntaxError
, getPos(), "Error in JPX color spec");
923 GBool
JPXStream::readCodestream(Guint len
) {
925 JPXTileComp
*tileComp
;
927 GBool haveSIZ
, haveCOD
, haveQCD
, haveSOT
;
928 Guint precinctSize
, style
, nDecompLevels
;
929 Guint segLen
, capabilities
, comp
, i
, j
, r
;
932 haveSIZ
= haveCOD
= haveQCD
= haveSOT
= gFalse
;
934 if (!readMarkerHdr(&segType
, &segLen
)) {
935 error(errSyntaxError
, getPos(), "Error in JPX codestream");
939 case 0x4f: // SOC - start of codestream
943 case 0x51: // SIZ - image and tile size
946 error(errSyntaxError
, getPos(),
947 "Duplicate SIZ marker segment in JPX stream");
950 if (!readUWord(&capabilities
) ||
951 !readULong(&img
.xSize
) ||
952 !readULong(&img
.ySize
) ||
953 !readULong(&img
.xOffset
) ||
954 !readULong(&img
.yOffset
) ||
955 !readULong(&img
.xTileSize
) ||
956 !readULong(&img
.yTileSize
) ||
957 !readULong(&img
.xTileOffset
) ||
958 !readULong(&img
.yTileOffset
) ||
959 !readUWord(&img
.nComps
)) {
960 error(errSyntaxError
, getPos(), "Error in JPX SIZ marker segment");
963 if (haveImgHdr
&& img
.nComps
!= nComps
) {
964 error(errSyntaxError
, getPos(),
965 "Different number of components in JPX SIZ marker segment");
968 if (img
.xSize
== 0 || img
.ySize
== 0 ||
969 img
.xOffset
>= img
.xSize
|| img
.yOffset
>= img
.ySize
||
970 img
.xTileSize
== 0 || img
.yTileSize
== 0 ||
971 img
.xTileOffset
> img
.xOffset
||
972 img
.yTileOffset
> img
.yOffset
||
973 img
.xTileSize
+ img
.xTileOffset
<= img
.xOffset
||
974 img
.yTileSize
+ img
.yTileOffset
<= img
.yOffset
) {
975 error(errSyntaxError
, getPos(), "Error in JPX SIZ marker segment");
978 img
.nXTiles
= (img
.xSize
- img
.xTileOffset
+ img
.xTileSize
- 1)
980 img
.nYTiles
= (img
.ySize
- img
.yTileOffset
+ img
.yTileSize
- 1)
982 // check for overflow before allocating memory
983 if (img
.nXTiles
<= 0 || img
.nYTiles
<= 0 ||
984 img
.nXTiles
>= 65535 / img
.nYTiles
) {
985 error(errSyntaxError
, getPos(),
986 "Bad tile count in JPX SIZ marker segment");
989 img
.tiles
= (JPXTile
*)gmallocn(img
.nXTiles
* img
.nYTiles
,
991 for (i
= 0; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
992 img
.tiles
[i
].init
= gFalse
;
993 img
.tiles
[i
].tileComps
= (JPXTileComp
*)gmallocn(img
.nComps
,
994 sizeof(JPXTileComp
));
995 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
996 img
.tiles
[i
].tileComps
[comp
].quantSteps
= NULL
;
997 img
.tiles
[i
].tileComps
[comp
].data
= NULL
;
998 img
.tiles
[i
].tileComps
[comp
].buf
= NULL
;
999 img
.tiles
[i
].tileComps
[comp
].resLevels
= NULL
;
1002 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
1003 if (!readUByte(&img
.tiles
[0].tileComps
[comp
].prec
) ||
1004 !readUByte(&img
.tiles
[0].tileComps
[comp
].hSep
) ||
1005 !readUByte(&img
.tiles
[0].tileComps
[comp
].vSep
)) {
1006 error(errSyntaxError
, getPos(), "Error in JPX SIZ marker segment");
1009 if (img
.tiles
[0].tileComps
[comp
].hSep
== 0 ||
1010 img
.tiles
[0].tileComps
[comp
].vSep
== 0) {
1011 error(errSyntaxError
, getPos(), "Error in JPX SIZ marker segment");
1014 img
.tiles
[0].tileComps
[comp
].sgned
=
1015 (img
.tiles
[0].tileComps
[comp
].prec
& 0x80) ? gTrue
: gFalse
;
1016 img
.tiles
[0].tileComps
[comp
].prec
=
1017 (img
.tiles
[0].tileComps
[comp
].prec
& 0x7f) + 1;
1018 for (i
= 1; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
1019 img
.tiles
[i
].tileComps
[comp
] = img
.tiles
[0].tileComps
[comp
];
1024 case 0x52: // COD - coding style default
1027 error(errSyntaxError
, getPos(),
1028 "JPX COD marker segment before SIZ segment");
1031 if (img
.tiles
== NULL
|| img
.nXTiles
* img
.nYTiles
== 0 || img
.tiles
[0].tileComps
== NULL
) {
1032 error(errSyntaxError
, getPos(), "Error in JPX COD marker segment");
1035 if (!readUByte(&img
.tiles
[0].tileComps
[0].style
) ||
1036 !readUByte(&img
.tiles
[0].progOrder
) ||
1037 !readUWord(&img
.tiles
[0].nLayers
) ||
1038 !readUByte(&img
.tiles
[0].multiComp
) ||
1039 !readUByte(&nDecompLevels
) ||
1040 !readUByte(&img
.tiles
[0].tileComps
[0].codeBlockW
) ||
1041 !readUByte(&img
.tiles
[0].tileComps
[0].codeBlockH
) ||
1042 !readUByte(&img
.tiles
[0].tileComps
[0].codeBlockStyle
) ||
1043 !readUByte(&img
.tiles
[0].tileComps
[0].transform
)) {
1044 error(errSyntaxError
, getPos(), "Error in JPX COD marker segment");
1047 if (nDecompLevels
> 32 ||
1048 img
.tiles
[0].tileComps
[0].codeBlockW
> 8 ||
1049 img
.tiles
[0].tileComps
[0].codeBlockH
> 8) {
1050 error(errSyntaxError
, getPos(), "Error in JPX COD marker segment");
1053 img
.tiles
[0].tileComps
[0].nDecompLevels
= nDecompLevels
;
1054 img
.tiles
[0].tileComps
[0].codeBlockW
+= 2;
1055 img
.tiles
[0].tileComps
[0].codeBlockH
+= 2;
1056 for (i
= 0; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
1058 img
.tiles
[i
].progOrder
= img
.tiles
[0].progOrder
;
1059 img
.tiles
[i
].nLayers
= img
.tiles
[0].nLayers
;
1060 img
.tiles
[i
].multiComp
= img
.tiles
[0].multiComp
;
1062 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
1063 if (!(i
== 0 && comp
== 0)) {
1064 img
.tiles
[i
].tileComps
[comp
].style
=
1065 img
.tiles
[0].tileComps
[0].style
;
1066 img
.tiles
[i
].tileComps
[comp
].nDecompLevels
=
1067 img
.tiles
[0].tileComps
[0].nDecompLevels
;
1068 img
.tiles
[i
].tileComps
[comp
].codeBlockW
=
1069 img
.tiles
[0].tileComps
[0].codeBlockW
;
1070 img
.tiles
[i
].tileComps
[comp
].codeBlockH
=
1071 img
.tiles
[0].tileComps
[0].codeBlockH
;
1072 img
.tiles
[i
].tileComps
[comp
].codeBlockStyle
=
1073 img
.tiles
[0].tileComps
[0].codeBlockStyle
;
1074 img
.tiles
[i
].tileComps
[comp
].transform
=
1075 img
.tiles
[0].tileComps
[0].transform
;
1077 img
.tiles
[i
].tileComps
[comp
].resLevels
=
1078 (JPXResLevel
*)gmallocn_checkoverflow(
1079 (img
.tiles
[i
].tileComps
[comp
].nDecompLevels
+ 1),
1080 sizeof(JPXResLevel
));
1081 if (img
.tiles
[i
].tileComps
[comp
].resLevels
== NULL
) {
1082 error(errSyntaxError
, getPos(), "Error in JPX COD marker segment");
1085 for (r
= 0; r
<= img
.tiles
[i
].tileComps
[comp
].nDecompLevels
; ++r
) {
1086 img
.tiles
[i
].tileComps
[comp
].resLevels
[r
].precincts
= NULL
;
1090 for (r
= 0; r
<= img
.tiles
[0].tileComps
[0].nDecompLevels
; ++r
) {
1091 if (img
.tiles
[0].tileComps
[0].style
& 0x01) {
1093 if (!readUByte(&precinctSize
)) {
1094 error(errSyntaxError
, getPos(), "Error in JPX COD marker segment");
1097 img
.tiles
[0].tileComps
[0].resLevels
[r
].precinctWidth
=
1098 precinctSize
& 0x0f;
1099 img
.tiles
[0].tileComps
[0].resLevels
[r
].precinctHeight
=
1100 (precinctSize
>> 4) & 0x0f;
1102 img
.tiles
[0].tileComps
[0].resLevels
[r
].precinctWidth
= 15;
1103 img
.tiles
[0].tileComps
[0].resLevels
[r
].precinctHeight
= 15;
1106 for (i
= 0; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
1107 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
1108 if (!(i
== 0 && comp
== 0)) {
1109 for (r
= 0; r
<= img
.tiles
[i
].tileComps
[comp
].nDecompLevels
; ++r
) {
1110 img
.tiles
[i
].tileComps
[comp
].resLevels
[r
].precinctWidth
=
1111 img
.tiles
[0].tileComps
[0].resLevels
[r
].precinctWidth
;
1112 img
.tiles
[i
].tileComps
[comp
].resLevels
[r
].precinctHeight
=
1113 img
.tiles
[0].tileComps
[0].resLevels
[r
].precinctHeight
;
1120 case 0x53: // COC - coding style component
1123 error(errSyntaxError
, getPos(),
1124 "JPX COC marker segment before COD segment");
1127 if ((img
.nComps
> 256 && !readUWord(&comp
)) ||
1128 (img
.nComps
<= 256 && !readUByte(&comp
)) ||
1129 comp
>= img
.nComps
||
1130 !readUByte(&style
) ||
1131 !readUByte(&nDecompLevels
) ||
1132 !readUByte(&img
.tiles
[0].tileComps
[comp
].codeBlockW
) ||
1133 !readUByte(&img
.tiles
[0].tileComps
[comp
].codeBlockH
) ||
1134 !readUByte(&img
.tiles
[0].tileComps
[comp
].codeBlockStyle
) ||
1135 !readUByte(&img
.tiles
[0].tileComps
[comp
].transform
)) {
1136 error(errSyntaxError
, getPos(), "Error in JPX COC marker segment");
1139 if (nDecompLevels
> 32 ||
1140 img
.tiles
[0].tileComps
[comp
].codeBlockW
> 8 ||
1141 img
.tiles
[0].tileComps
[comp
].codeBlockH
> 8) {
1142 error(errSyntaxError
, getPos(), "Error in JPX COC marker segment");
1145 img
.tiles
[0].tileComps
[comp
].nDecompLevels
= nDecompLevels
;
1146 img
.tiles
[0].tileComps
[comp
].style
=
1147 (img
.tiles
[0].tileComps
[comp
].style
& ~1) | (style
& 1);
1148 img
.tiles
[0].tileComps
[comp
].codeBlockW
+= 2;
1149 img
.tiles
[0].tileComps
[comp
].codeBlockH
+= 2;
1150 for (i
= 0; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
1152 img
.tiles
[i
].tileComps
[comp
].style
=
1153 img
.tiles
[0].tileComps
[comp
].style
;
1154 img
.tiles
[i
].tileComps
[comp
].nDecompLevels
=
1155 img
.tiles
[0].tileComps
[comp
].nDecompLevels
;
1156 img
.tiles
[i
].tileComps
[comp
].codeBlockW
=
1157 img
.tiles
[0].tileComps
[comp
].codeBlockW
;
1158 img
.tiles
[i
].tileComps
[comp
].codeBlockH
=
1159 img
.tiles
[0].tileComps
[comp
].codeBlockH
;
1160 img
.tiles
[i
].tileComps
[comp
].codeBlockStyle
=
1161 img
.tiles
[0].tileComps
[comp
].codeBlockStyle
;
1162 img
.tiles
[i
].tileComps
[comp
].transform
=
1163 img
.tiles
[0].tileComps
[comp
].transform
;
1165 img
.tiles
[i
].tileComps
[comp
].resLevels
=
1166 (JPXResLevel
*)greallocn(
1167 img
.tiles
[i
].tileComps
[comp
].resLevels
,
1168 (img
.tiles
[i
].tileComps
[comp
].nDecompLevels
+ 1),
1169 sizeof(JPXResLevel
));
1170 for (r
= 0; r
<= img
.tiles
[i
].tileComps
[comp
].nDecompLevels
; ++r
) {
1171 img
.tiles
[i
].tileComps
[comp
].resLevels
[r
].precincts
= NULL
;
1174 for (r
= 0; r
<= img
.tiles
[0].tileComps
[comp
].nDecompLevels
; ++r
) {
1175 if (img
.tiles
[0].tileComps
[comp
].style
& 0x01) {
1176 if (!readUByte(&precinctSize
)) {
1177 error(errSyntaxError
, getPos(), "Error in JPX COD marker segment");
1180 img
.tiles
[0].tileComps
[comp
].resLevels
[r
].precinctWidth
=
1181 precinctSize
& 0x0f;
1182 img
.tiles
[0].tileComps
[comp
].resLevels
[r
].precinctHeight
=
1183 (precinctSize
>> 4) & 0x0f;
1185 img
.tiles
[0].tileComps
[comp
].resLevels
[r
].precinctWidth
= 15;
1186 img
.tiles
[0].tileComps
[comp
].resLevels
[r
].precinctHeight
= 15;
1189 for (i
= 1; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
1190 for (r
= 0; r
<= img
.tiles
[i
].tileComps
[comp
].nDecompLevels
; ++r
) {
1191 img
.tiles
[i
].tileComps
[comp
].resLevels
[r
].precinctWidth
=
1192 img
.tiles
[0].tileComps
[comp
].resLevels
[r
].precinctWidth
;
1193 img
.tiles
[i
].tileComps
[comp
].resLevels
[r
].precinctHeight
=
1194 img
.tiles
[0].tileComps
[comp
].resLevels
[r
].precinctHeight
;
1198 case 0x5c: // QCD - quantization default
1201 error(errSyntaxError
, getPos(),
1202 "JPX QCD marker segment before SIZ segment");
1205 if (!readUByte(&img
.tiles
[0].tileComps
[0].quantStyle
)) {
1206 error(errSyntaxError
, getPos(), "Error in JPX QCD marker segment");
1209 if ((img
.tiles
[0].tileComps
[0].quantStyle
& 0x1f) == 0x00) {
1211 error(errSyntaxError
, getPos(), "Error in JPX QCD marker segment");
1214 img
.tiles
[0].tileComps
[0].nQuantSteps
= segLen
- 3;
1215 img
.tiles
[0].tileComps
[0].quantSteps
=
1216 (Guint
*)greallocn(img
.tiles
[0].tileComps
[0].quantSteps
,
1217 img
.tiles
[0].tileComps
[0].nQuantSteps
,
1219 for (i
= 0; i
< img
.tiles
[0].tileComps
[0].nQuantSteps
; ++i
) {
1220 if (!readUByte(&img
.tiles
[0].tileComps
[0].quantSteps
[i
])) {
1221 error(errSyntaxError
, getPos(), "Error in JPX QCD marker segment");
1225 } else if ((img
.tiles
[0].tileComps
[0].quantStyle
& 0x1f) == 0x01) {
1226 img
.tiles
[0].tileComps
[0].nQuantSteps
= 1;
1227 img
.tiles
[0].tileComps
[0].quantSteps
=
1228 (Guint
*)greallocn(img
.tiles
[0].tileComps
[0].quantSteps
,
1229 img
.tiles
[0].tileComps
[0].nQuantSteps
,
1231 if (!readUWord(&img
.tiles
[0].tileComps
[0].quantSteps
[0])) {
1232 error(errSyntaxError
, getPos(), "Error in JPX QCD marker segment");
1235 } else if ((img
.tiles
[0].tileComps
[0].quantStyle
& 0x1f) == 0x02) {
1237 error(errSyntaxError
, getPos(), "Error in JPX QCD marker segment");
1240 img
.tiles
[0].tileComps
[0].nQuantSteps
= (segLen
- 3) / 2;
1241 img
.tiles
[0].tileComps
[0].quantSteps
=
1242 (Guint
*)greallocn(img
.tiles
[0].tileComps
[0].quantSteps
,
1243 img
.tiles
[0].tileComps
[0].nQuantSteps
,
1245 for (i
= 0; i
< img
.tiles
[0].tileComps
[0].nQuantSteps
; ++i
) {
1246 if (!readUWord(&img
.tiles
[0].tileComps
[0].quantSteps
[i
])) {
1247 error(errSyntaxError
, getPos(), "Error in JPX QCD marker segment");
1252 error(errSyntaxError
, getPos(), "Error in JPX QCD marker segment");
1255 for (i
= 0; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
1256 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
1257 if (!(i
== 0 && comp
== 0)) {
1258 img
.tiles
[i
].tileComps
[comp
].quantStyle
=
1259 img
.tiles
[0].tileComps
[0].quantStyle
;
1260 img
.tiles
[i
].tileComps
[comp
].nQuantSteps
=
1261 img
.tiles
[0].tileComps
[0].nQuantSteps
;
1262 img
.tiles
[i
].tileComps
[comp
].quantSteps
=
1263 (Guint
*)greallocn(img
.tiles
[i
].tileComps
[comp
].quantSteps
,
1264 img
.tiles
[0].tileComps
[0].nQuantSteps
,
1266 for (j
= 0; j
< img
.tiles
[0].tileComps
[0].nQuantSteps
; ++j
) {
1267 img
.tiles
[i
].tileComps
[comp
].quantSteps
[j
] =
1268 img
.tiles
[0].tileComps
[0].quantSteps
[j
];
1275 case 0x5d: // QCC - quantization component
1278 error(errSyntaxError
, getPos(),
1279 "JPX QCC marker segment before QCD segment");
1282 if ((img
.nComps
> 256 && !readUWord(&comp
)) ||
1283 (img
.nComps
<= 256 && !readUByte(&comp
)) ||
1284 comp
>= img
.nComps
||
1285 !readUByte(&img
.tiles
[0].tileComps
[comp
].quantStyle
)) {
1286 error(errSyntaxError
, getPos(), "Error in JPX QCC marker segment");
1289 if ((img
.tiles
[0].tileComps
[comp
].quantStyle
& 0x1f) == 0x00) {
1290 if (segLen
<= (img
.nComps
> 256 ? 5U : 4U)) {
1291 error(errSyntaxError
, getPos(), "Error in JPX QCC marker segment");
1294 img
.tiles
[0].tileComps
[comp
].nQuantSteps
=
1295 segLen
- (img
.nComps
> 256 ? 5 : 4);
1296 img
.tiles
[0].tileComps
[comp
].quantSteps
=
1297 (Guint
*)greallocn(img
.tiles
[0].tileComps
[comp
].quantSteps
,
1298 img
.tiles
[0].tileComps
[comp
].nQuantSteps
,
1300 for (i
= 0; i
< img
.tiles
[0].tileComps
[comp
].nQuantSteps
; ++i
) {
1301 if (!readUByte(&img
.tiles
[0].tileComps
[comp
].quantSteps
[i
])) {
1302 error(errSyntaxError
, getPos(), "Error in JPX QCC marker segment");
1306 } else if ((img
.tiles
[0].tileComps
[comp
].quantStyle
& 0x1f) == 0x01) {
1307 img
.tiles
[0].tileComps
[comp
].nQuantSteps
= 1;
1308 img
.tiles
[0].tileComps
[comp
].quantSteps
=
1309 (Guint
*)greallocn(img
.tiles
[0].tileComps
[comp
].quantSteps
,
1310 img
.tiles
[0].tileComps
[comp
].nQuantSteps
,
1312 if (!readUWord(&img
.tiles
[0].tileComps
[comp
].quantSteps
[0])) {
1313 error(errSyntaxError
, getPos(), "Error in JPX QCC marker segment");
1316 } else if ((img
.tiles
[0].tileComps
[comp
].quantStyle
& 0x1f) == 0x02) {
1317 if (segLen
< (img
.nComps
> 256 ? 5U : 4U) + 2) {
1318 error(errSyntaxError
, getPos(), "Error in JPX QCC marker segment");
1321 img
.tiles
[0].tileComps
[comp
].nQuantSteps
=
1322 (segLen
- (img
.nComps
> 256 ? 5 : 4)) / 2;
1323 img
.tiles
[0].tileComps
[comp
].quantSteps
=
1324 (Guint
*)greallocn(img
.tiles
[0].tileComps
[comp
].quantSteps
,
1325 img
.tiles
[0].tileComps
[comp
].nQuantSteps
,
1327 for (i
= 0; i
< img
.tiles
[0].tileComps
[comp
].nQuantSteps
; ++i
) {
1328 if (!readUWord(&img
.tiles
[0].tileComps
[comp
].quantSteps
[i
])) {
1329 error(errSyntaxError
, getPos(), "Error in JPX QCD marker segment");
1334 error(errSyntaxError
, getPos(), "Error in JPX QCC marker segment");
1337 for (i
= 1; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
1338 img
.tiles
[i
].tileComps
[comp
].quantStyle
=
1339 img
.tiles
[0].tileComps
[comp
].quantStyle
;
1340 img
.tiles
[i
].tileComps
[comp
].nQuantSteps
=
1341 img
.tiles
[0].tileComps
[comp
].nQuantSteps
;
1342 img
.tiles
[i
].tileComps
[comp
].quantSteps
=
1343 (Guint
*)greallocn(img
.tiles
[i
].tileComps
[comp
].quantSteps
,
1344 img
.tiles
[0].tileComps
[comp
].nQuantSteps
,
1346 for (j
= 0; j
< img
.tiles
[0].tileComps
[comp
].nQuantSteps
; ++j
) {
1347 img
.tiles
[i
].tileComps
[comp
].quantSteps
[j
] =
1348 img
.tiles
[0].tileComps
[comp
].quantSteps
[j
];
1352 case 0x5e: // RGN - region of interest
1354 #if 1 //~ ROI is unimplemented
1355 error(errUnimplemented
, -1, "got a JPX RGN segment");
1356 for (i
= 0; i
< segLen
- 2; ++i
) {
1357 if (bufStr
->getChar() == EOF
) {
1358 error(errSyntaxError
, getPos(), "Error in JPX RGN marker segment");
1363 if ((img
.nComps
> 256 && !readUWord(&comp
)) ||
1364 (img
.nComps
<= 256 && !readUByte(&comp
)) ||
1365 comp
>= img
.nComps
||
1366 !readUByte(&compInfo
[comp
].defROI
.style
) ||
1367 !readUByte(&compInfo
[comp
].defROI
.shift
)) {
1368 error(errSyntaxError
, getPos(), "Error in JPX RGN marker segment");
1373 case 0x5f: // POC - progression order change
1375 #if 1 //~ progression order changes are unimplemented
1376 error(errUnimplemented
, -1, "got a JPX POC segment");
1377 for (i
= 0; i
< segLen
- 2; ++i
) {
1378 if (bufStr
->getChar() == EOF
) {
1379 error(errSyntaxError
, getPos(), "Error in JPX POC marker segment");
1384 nProgs
= (segLen
- 2) / (img
.nComps
> 256 ? 9 : 7);
1385 progs
= (JPXProgOrder
*)gmallocn(nProgs
, sizeof(JPXProgOrder
));
1386 for (i
= 0; i
< nProgs
; ++i
) {
1387 if (!readUByte(&progs
[i
].startRes
) ||
1388 !(img
.nComps
> 256 && readUWord(&progs
[i
].startComp
)) ||
1389 !(img
.nComps
<= 256 && readUByte(&progs
[i
].startComp
)) ||
1390 !readUWord(&progs
[i
].endLayer
) ||
1391 !readUByte(&progs
[i
].endRes
) ||
1392 !(img
.nComps
> 256 && readUWord(&progs
[i
].endComp
)) ||
1393 !(img
.nComps
<= 256 && readUByte(&progs
[i
].endComp
)) ||
1394 !readUByte(&progs
[i
].progOrder
)) {
1395 error(errSyntaxError
, getPos(), "Error in JPX POC marker segment");
1401 case 0x60: // PPM - packed packet headers, main header
1403 #if 1 //~ packed packet headers are unimplemented
1404 error(errUnimplemented
, -1, "Got a JPX PPM segment");
1405 for (i
= 0; i
< segLen
- 2; ++i
) {
1406 if (bufStr
->getChar() == EOF
) {
1407 error(errSyntaxError
, getPos(), "Error in JPX PPM marker segment");
1413 case 0x55: // TLM - tile-part lengths
1416 for (i
= 0; i
< segLen
- 2; ++i
) {
1417 if (bufStr
->getChar() == EOF
) {
1418 error(errSyntaxError
, getPos(), "Error in JPX TLM marker segment");
1423 case 0x57: // PLM - packet length, main header
1426 for (i
= 0; i
< segLen
- 2; ++i
) {
1427 if (bufStr
->getChar() == EOF
) {
1428 error(errSyntaxError
, getPos(), "Error in JPX PLM marker segment");
1433 case 0x63: // CRG - component registration
1436 for (i
= 0; i
< segLen
- 2; ++i
) {
1437 if (bufStr
->getChar() == EOF
) {
1438 error(errSyntaxError
, getPos(), "Error in JPX CRG marker segment");
1443 case 0x64: // COM - comment
1446 for (i
= 0; i
< segLen
- 2; ++i
) {
1447 if (bufStr
->getChar() == EOF
) {
1448 error(errSyntaxError
, getPos(), "Error in JPX COM marker segment");
1453 case 0x90: // SOT - start of tile
1459 error(errSyntaxError
, getPos(),
1460 "Unknown marker segment {0:02x} in JPX stream", segType
);
1461 for (i
= 0; i
< segLen
- 2; ++i
) {
1462 if (bufStr
->getChar() == EOF
) {
1471 error(errSyntaxError
, getPos(),
1472 "Missing SIZ marker segment in JPX stream");
1476 error(errSyntaxError
, getPos(),
1477 "Missing COD marker segment in JPX stream");
1481 error(errSyntaxError
, getPos(),
1482 "Missing QCD marker segment in JPX stream");
1486 //----- read the tile-parts
1488 if (!readTilePart()) {
1491 if (!readMarkerHdr(&segType
, &segLen
)) {
1492 error(errSyntaxError
, getPos(), "Error in JPX codestream");
1495 if (segType
!= 0x90) { // SOT - start of tile
1500 if (segType
!= 0xd9) { // EOC - end of codestream
1501 error(errSyntaxError
, getPos(), "Missing EOC marker in JPX codestream");
1505 //----- finish decoding the image
1506 for (i
= 0; i
< img
.nXTiles
* img
.nYTiles
; ++i
) {
1507 tile
= &img
.tiles
[i
];
1509 error(errSyntaxError
, getPos(), "Uninitialized tile in JPX codestream");
1512 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
1513 tileComp
= &tile
->tileComps
[comp
];
1514 inverseTransform(tileComp
);
1516 if (!inverseMultiCompAndDC(tile
)) {
1521 //~ can free memory below tileComps here, and also tileComp.buf
1526 GBool
JPXStream::readTilePart() {
1528 JPXTileComp
*tileComp
;
1529 JPXResLevel
*resLevel
;
1530 JPXPrecinct
*precinct
;
1531 JPXSubband
*subband
;
1535 Guint tileIdx
, tilePartLen
, tilePartIdx
, nTileParts
;
1536 GBool tilePartToEOC
;
1537 Guint precinctSize
, style
, nDecompLevels
;
1538 Guint n
, nSBs
, nx
, ny
, sbx0
, sby0
, comp
, segLen
;
1539 Guint i
, j
, k
, cbX
, cbY
, r
, pre
, sb
, cbi
, cbj
;
1542 // process the SOT marker segment
1543 if (!readUWord(&tileIdx
) ||
1544 !readULong(&tilePartLen
) ||
1545 !readUByte(&tilePartIdx
) ||
1546 !readUByte(&nTileParts
)) {
1547 error(errSyntaxError
, getPos(), "Error in JPX SOT marker segment");
1551 if (tileIdx
>= img
.nXTiles
* img
.nYTiles
||
1552 (tilePartIdx
> 0 && !img
.tiles
[tileIdx
].init
)) {
1553 error(errSyntaxError
, getPos(), "Weird tile index in JPX stream");
1557 tilePartToEOC
= tilePartLen
== 0;
1558 tilePartLen
-= 12; // subtract size of SOT segment
1562 if (!readMarkerHdr(&segType
, &segLen
)) {
1563 error(errSyntaxError
, getPos(), "Error in JPX tile-part codestream");
1566 tilePartLen
-= 2 + segLen
;
1568 case 0x52: // COD - coding style default
1570 if (!readUByte(&img
.tiles
[tileIdx
].tileComps
[0].style
) ||
1571 !readUByte(&img
.tiles
[tileIdx
].progOrder
) ||
1572 !readUWord(&img
.tiles
[tileIdx
].nLayers
) ||
1573 !readUByte(&img
.tiles
[tileIdx
].multiComp
) ||
1574 !readUByte(&nDecompLevels
) ||
1575 !readUByte(&img
.tiles
[tileIdx
].tileComps
[0].codeBlockW
) ||
1576 !readUByte(&img
.tiles
[tileIdx
].tileComps
[0].codeBlockH
) ||
1577 !readUByte(&img
.tiles
[tileIdx
].tileComps
[0].codeBlockStyle
) ||
1578 !readUByte(&img
.tiles
[tileIdx
].tileComps
[0].transform
)) {
1579 error(errSyntaxError
, getPos(), "Error in JPX COD marker segment");
1582 if (nDecompLevels
> 32 ||
1583 img
.tiles
[tileIdx
].tileComps
[0].codeBlockW
> 8 ||
1584 img
.tiles
[tileIdx
].tileComps
[0].codeBlockH
> 8) {
1585 error(errSyntaxError
, getPos(), "Error in JPX COD marker segment");
1588 img
.tiles
[tileIdx
].tileComps
[0].nDecompLevels
= nDecompLevels
;
1589 img
.tiles
[tileIdx
].tileComps
[0].codeBlockW
+= 2;
1590 img
.tiles
[tileIdx
].tileComps
[0].codeBlockH
+= 2;
1591 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
1593 img
.tiles
[tileIdx
].tileComps
[comp
].style
=
1594 img
.tiles
[tileIdx
].tileComps
[0].style
;
1595 img
.tiles
[tileIdx
].tileComps
[comp
].nDecompLevels
=
1596 img
.tiles
[tileIdx
].tileComps
[0].nDecompLevels
;
1597 img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockW
=
1598 img
.tiles
[tileIdx
].tileComps
[0].codeBlockW
;
1599 img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockH
=
1600 img
.tiles
[tileIdx
].tileComps
[0].codeBlockH
;
1601 img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockStyle
=
1602 img
.tiles
[tileIdx
].tileComps
[0].codeBlockStyle
;
1603 img
.tiles
[tileIdx
].tileComps
[comp
].transform
=
1604 img
.tiles
[tileIdx
].tileComps
[0].transform
;
1606 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
=
1607 (JPXResLevel
*)greallocn(
1608 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
,
1609 (img
.tiles
[tileIdx
].tileComps
[comp
].nDecompLevels
+ 1),
1610 sizeof(JPXResLevel
));
1612 r
<= img
.tiles
[tileIdx
].tileComps
[comp
].nDecompLevels
;
1614 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
[r
].precincts
= NULL
;
1617 for (r
= 0; r
<= img
.tiles
[tileIdx
].tileComps
[0].nDecompLevels
; ++r
) {
1618 if (img
.tiles
[tileIdx
].tileComps
[0].style
& 0x01) {
1619 if (!readUByte(&precinctSize
)) {
1620 error(errSyntaxError
, getPos(), "Error in JPX COD marker segment");
1623 img
.tiles
[tileIdx
].tileComps
[0].resLevels
[r
].precinctWidth
=
1624 precinctSize
& 0x0f;
1625 img
.tiles
[tileIdx
].tileComps
[0].resLevels
[r
].precinctHeight
=
1626 (precinctSize
>> 4) & 0x0f;
1628 img
.tiles
[tileIdx
].tileComps
[0].resLevels
[r
].precinctWidth
= 15;
1629 img
.tiles
[tileIdx
].tileComps
[0].resLevels
[r
].precinctHeight
= 15;
1632 for (comp
= 1; comp
< img
.nComps
; ++comp
) {
1634 r
<= img
.tiles
[tileIdx
].tileComps
[comp
].nDecompLevels
;
1636 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
[r
].precinctWidth
=
1637 img
.tiles
[tileIdx
].tileComps
[0].resLevels
[r
].precinctWidth
;
1638 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
[r
].precinctHeight
=
1639 img
.tiles
[tileIdx
].tileComps
[0].resLevels
[r
].precinctHeight
;
1643 case 0x53: // COC - coding style component
1645 if ((img
.nComps
> 256 && !readUWord(&comp
)) ||
1646 (img
.nComps
<= 256 && !readUByte(&comp
)) ||
1647 comp
>= img
.nComps
||
1648 !readUByte(&style
) ||
1649 !readUByte(&nDecompLevels
) ||
1650 !readUByte(&img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockW
) ||
1651 !readUByte(&img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockH
) ||
1652 !readUByte(&img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockStyle
) ||
1653 !readUByte(&img
.tiles
[tileIdx
].tileComps
[comp
].transform
)) {
1654 error(errSyntaxError
, getPos(), "Error in JPX COC marker segment");
1657 if (nDecompLevels
> 32 ||
1658 img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockW
> 8 ||
1659 img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockH
> 8) {
1660 error(errSyntaxError
, getPos(), "Error in JPX COD marker segment");
1663 img
.tiles
[tileIdx
].tileComps
[comp
].nDecompLevels
= nDecompLevels
;
1664 img
.tiles
[tileIdx
].tileComps
[comp
].style
=
1665 (img
.tiles
[tileIdx
].tileComps
[comp
].style
& ~1) | (style
& 1);
1666 img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockW
+= 2;
1667 img
.tiles
[tileIdx
].tileComps
[comp
].codeBlockH
+= 2;
1668 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
=
1669 (JPXResLevel
*)greallocn(
1670 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
,
1671 (img
.tiles
[tileIdx
].tileComps
[comp
].nDecompLevels
+ 1),
1672 sizeof(JPXResLevel
));
1673 for (r
= 0; r
<= img
.tiles
[tileIdx
].tileComps
[comp
].nDecompLevels
; ++r
) {
1674 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
[r
].precincts
= NULL
;
1676 for (r
= 0; r
<= img
.tiles
[tileIdx
].tileComps
[comp
].nDecompLevels
; ++r
) {
1677 if (img
.tiles
[tileIdx
].tileComps
[comp
].style
& 0x01) {
1678 if (!readUByte(&precinctSize
)) {
1679 error(errSyntaxError
, getPos(), "Error in JPX COD marker segment");
1682 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
[r
].precinctWidth
=
1683 precinctSize
& 0x0f;
1684 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
[r
].precinctHeight
=
1685 (precinctSize
>> 4) & 0x0f;
1687 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
[r
].precinctWidth
= 15;
1688 img
.tiles
[tileIdx
].tileComps
[comp
].resLevels
[r
].precinctHeight
= 15;
1692 case 0x5c: // QCD - quantization default
1694 if (!readUByte(&img
.tiles
[tileIdx
].tileComps
[0].quantStyle
)) {
1695 error(errSyntaxError
, getPos(), "Error in JPX QCD marker segment");
1698 if ((img
.tiles
[tileIdx
].tileComps
[0].quantStyle
& 0x1f) == 0x00) {
1700 error(errSyntaxError
, getPos(), "Error in JPX QCD marker segment");
1703 img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
= segLen
- 3;
1704 img
.tiles
[tileIdx
].tileComps
[0].quantSteps
=
1705 (Guint
*)greallocn(img
.tiles
[tileIdx
].tileComps
[0].quantSteps
,
1706 img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
,
1708 for (i
= 0; i
< img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
; ++i
) {
1709 if (!readUByte(&img
.tiles
[tileIdx
].tileComps
[0].quantSteps
[i
])) {
1710 error(errSyntaxError
, getPos(), "Error in JPX QCD marker segment");
1714 } else if ((img
.tiles
[tileIdx
].tileComps
[0].quantStyle
& 0x1f) == 0x01) {
1715 img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
= 1;
1716 img
.tiles
[tileIdx
].tileComps
[0].quantSteps
=
1717 (Guint
*)greallocn(img
.tiles
[tileIdx
].tileComps
[0].quantSteps
,
1718 img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
,
1720 if (!readUWord(&img
.tiles
[tileIdx
].tileComps
[0].quantSteps
[0])) {
1721 error(errSyntaxError
, getPos(), "Error in JPX QCD marker segment");
1724 } else if ((img
.tiles
[tileIdx
].tileComps
[0].quantStyle
& 0x1f) == 0x02) {
1726 error(errSyntaxError
, getPos(), "Error in JPX QCD marker segment");
1729 img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
= (segLen
- 3) / 2;
1730 img
.tiles
[tileIdx
].tileComps
[0].quantSteps
=
1731 (Guint
*)greallocn(img
.tiles
[tileIdx
].tileComps
[0].quantSteps
,
1732 img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
,
1734 for (i
= 0; i
< img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
; ++i
) {
1735 if (!readUWord(&img
.tiles
[tileIdx
].tileComps
[0].quantSteps
[i
])) {
1736 error(errSyntaxError
, getPos(), "Error in JPX QCD marker segment");
1741 error(errSyntaxError
, getPos(), "Error in JPX QCD marker segment");
1744 for (comp
= 1; comp
< img
.nComps
; ++comp
) {
1745 img
.tiles
[tileIdx
].tileComps
[comp
].quantStyle
=
1746 img
.tiles
[tileIdx
].tileComps
[0].quantStyle
;
1747 img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
=
1748 img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
;
1749 img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
=
1750 (Guint
*)greallocn(img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
,
1751 img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
,
1753 for (j
= 0; j
< img
.tiles
[tileIdx
].tileComps
[0].nQuantSteps
; ++j
) {
1754 img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
[j
] =
1755 img
.tiles
[tileIdx
].tileComps
[0].quantSteps
[j
];
1759 case 0x5d: // QCC - quantization component
1761 if ((img
.nComps
> 256 && !readUWord(&comp
)) ||
1762 (img
.nComps
<= 256 && !readUByte(&comp
)) ||
1763 comp
>= img
.nComps
||
1764 !readUByte(&img
.tiles
[tileIdx
].tileComps
[comp
].quantStyle
)) {
1765 error(errSyntaxError
, getPos(), "Error in JPX QCC marker segment");
1768 if ((img
.tiles
[tileIdx
].tileComps
[comp
].quantStyle
& 0x1f) == 0x00) {
1769 if (segLen
<= (img
.nComps
> 256 ? 5U : 4U)) {
1770 error(errSyntaxError
, getPos(), "Error in JPX QCC marker segment");
1773 img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
=
1774 segLen
- (img
.nComps
> 256 ? 5 : 4);
1775 img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
=
1776 (Guint
*)greallocn(img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
,
1777 img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
,
1779 for (i
= 0; i
< img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
; ++i
) {
1780 if (!readUByte(&img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
[i
])) {
1781 error(errSyntaxError
, getPos(), "Error in JPX QCC marker segment");
1785 } else if ((img
.tiles
[tileIdx
].tileComps
[comp
].quantStyle
& 0x1f)
1787 img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
= 1;
1788 img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
=
1789 (Guint
*)greallocn(img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
,
1790 img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
,
1792 if (!readUWord(&img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
[0])) {
1793 error(errSyntaxError
, getPos(), "Error in JPX QCC marker segment");
1796 } else if ((img
.tiles
[tileIdx
].tileComps
[comp
].quantStyle
& 0x1f)
1798 if (segLen
< (img
.nComps
> 256 ? 5U : 4U) + 2) {
1799 error(errSyntaxError
, getPos(), "Error in JPX QCC marker segment");
1802 img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
=
1803 (segLen
- (img
.nComps
> 256 ? 5 : 4)) / 2;
1804 img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
=
1805 (Guint
*)greallocn(img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
,
1806 img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
,
1808 for (i
= 0; i
< img
.tiles
[tileIdx
].tileComps
[comp
].nQuantSteps
; ++i
) {
1809 if (!readUWord(&img
.tiles
[tileIdx
].tileComps
[comp
].quantSteps
[i
])) {
1810 error(errSyntaxError
, getPos(), "Error in JPX QCD marker segment");
1815 error(errSyntaxError
, getPos(), "Error in JPX QCC marker segment");
1819 case 0x5e: // RGN - region of interest
1821 #if 1 //~ ROI is unimplemented
1822 error(errUnimplemented
, -1, "Got a JPX RGN segment");
1823 for (i
= 0; i
< segLen
- 2; ++i
) {
1824 if (bufStr
->getChar() == EOF
) {
1825 error(errSyntaxError
, getPos(), "Error in JPX RGN marker segment");
1830 if ((img
.nComps
> 256 && !readUWord(&comp
)) ||
1831 (img
.nComps
<= 256 && !readUByte(&comp
)) ||
1832 comp
>= img
.nComps
||
1833 !readUByte(&compInfo
[comp
].roi
.style
) ||
1834 !readUByte(&compInfo
[comp
].roi
.shift
)) {
1835 error(errSyntaxError
, getPos(), "Error in JPX RGN marker segment");
1840 case 0x5f: // POC - progression order change
1842 #if 1 //~ progression order changes are unimplemented
1843 error(errUnimplemented
, -1, "Got a JPX POC segment");
1844 for (i
= 0; i
< segLen
- 2; ++i
) {
1845 if (bufStr
->getChar() == EOF
) {
1846 error(errSyntaxError
, getPos(), "Error in JPX POC marker segment");
1851 nTileProgs
= (segLen
- 2) / (img
.nComps
> 256 ? 9 : 7);
1852 tileProgs
= (JPXProgOrder
*)gmallocn(nTileProgs
, sizeof(JPXProgOrder
));
1853 for (i
= 0; i
< nTileProgs
; ++i
) {
1854 if (!readUByte(&tileProgs
[i
].startRes
) ||
1855 !(img
.nComps
> 256 && readUWord(&tileProgs
[i
].startComp
)) ||
1856 !(img
.nComps
<= 256 && readUByte(&tileProgs
[i
].startComp
)) ||
1857 !readUWord(&tileProgs
[i
].endLayer
) ||
1858 !readUByte(&tileProgs
[i
].endRes
) ||
1859 !(img
.nComps
> 256 && readUWord(&tileProgs
[i
].endComp
)) ||
1860 !(img
.nComps
<= 256 && readUByte(&tileProgs
[i
].endComp
)) ||
1861 !readUByte(&tileProgs
[i
].progOrder
)) {
1862 error(errSyntaxError
, getPos(), "Error in JPX POC marker segment");
1868 case 0x61: // PPT - packed packet headers, tile-part hdr
1870 #if 1 //~ packed packet headers are unimplemented
1871 error(errUnimplemented
, -1, "Got a JPX PPT segment");
1872 for (i
= 0; i
< segLen
- 2; ++i
) {
1873 if (bufStr
->getChar() == EOF
) {
1874 error(errSyntaxError
, getPos(), "Error in JPX PPT marker segment");
1879 case 0x58: // PLT - packet length, tile-part header
1882 for (i
= 0; i
< segLen
- 2; ++i
) {
1883 if (bufStr
->getChar() == EOF
) {
1884 error(errSyntaxError
, getPos(), "Error in JPX PLT marker segment");
1889 case 0x64: // COM - comment
1892 for (i
= 0; i
< segLen
- 2; ++i
) {
1893 if (bufStr
->getChar() == EOF
) {
1894 error(errSyntaxError
, getPos(), "Error in JPX COM marker segment");
1899 case 0x93: // SOD - start of data
1905 error(errSyntaxError
, getPos(),
1906 "Unknown marker segment {0:02x} in JPX tile-part stream",
1908 for (i
= 0; i
< segLen
- 2; ++i
) {
1909 if (bufStr
->getChar() == EOF
) {
1917 //----- initialize the tile, precincts, and code-blocks
1918 if (tilePartIdx
== 0) {
1919 tile
= &img
.tiles
[tileIdx
];
1921 i
= tileIdx
/ img
.nXTiles
;
1922 j
= tileIdx
% img
.nXTiles
;
1923 if ((tile
->x0
= img
.xTileOffset
+ j
* img
.xTileSize
) < img
.xOffset
) {
1924 tile
->x0
= img
.xOffset
;
1926 if ((tile
->y0
= img
.yTileOffset
+ i
* img
.yTileSize
) < img
.yOffset
) {
1927 tile
->y0
= img
.yOffset
;
1929 if ((tile
->x1
= img
.xTileOffset
+ (j
+ 1) * img
.xTileSize
) > img
.xSize
) {
1930 tile
->x1
= img
.xSize
;
1932 if ((tile
->y1
= img
.yTileOffset
+ (i
+ 1) * img
.yTileSize
) > img
.ySize
) {
1933 tile
->y1
= img
.ySize
;
1939 tile
->maxNDecompLevels
= 0;
1940 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
1941 tileComp
= &tile
->tileComps
[comp
];
1942 if (tileComp
->nDecompLevels
> tile
->maxNDecompLevels
) {
1943 tile
->maxNDecompLevels
= tileComp
->nDecompLevels
;
1945 tileComp
->x0
= jpxCeilDiv(tile
->x0
, tileComp
->hSep
);
1946 tileComp
->y0
= jpxCeilDiv(tile
->y0
, tileComp
->vSep
);
1947 tileComp
->x1
= jpxCeilDiv(tile
->x1
, tileComp
->hSep
);
1948 tileComp
->y1
= jpxCeilDiv(tile
->y1
, tileComp
->vSep
);
1949 tileComp
->w
= tileComp
->x1
- tileComp
->x0
;
1950 tileComp
->cbW
= 1 << tileComp
->codeBlockW
;
1951 tileComp
->cbH
= 1 << tileComp
->codeBlockH
;
1952 tileComp
->data
= (int *)gmallocn((tileComp
->x1
- tileComp
->x0
) *
1953 (tileComp
->y1
- tileComp
->y0
),
1955 if (tileComp
->x1
- tileComp
->x0
> tileComp
->y1
- tileComp
->y0
) {
1956 n
= tileComp
->x1
- tileComp
->x0
;
1958 n
= tileComp
->y1
- tileComp
->y0
;
1960 tileComp
->buf
= (int *)gmallocn(n
+ 8, sizeof(int));
1961 for (r
= 0; r
<= tileComp
->nDecompLevels
; ++r
) {
1962 resLevel
= &tileComp
->resLevels
[r
];
1963 k
= r
== 0 ? tileComp
->nDecompLevels
1964 : tileComp
->nDecompLevels
- r
+ 1;
1965 resLevel
->x0
= jpxCeilDivPow2(tileComp
->x0
, k
);
1966 resLevel
->y0
= jpxCeilDivPow2(tileComp
->y0
, k
);
1967 resLevel
->x1
= jpxCeilDivPow2(tileComp
->x1
, k
);
1968 resLevel
->y1
= jpxCeilDivPow2(tileComp
->y1
, k
);
1970 resLevel
->bx0
[0] = resLevel
->x0
;
1971 resLevel
->by0
[0] = resLevel
->y0
;
1972 resLevel
->bx1
[0] = resLevel
->x1
;
1973 resLevel
->by1
[0] = resLevel
->y1
;
1975 resLevel
->bx0
[0] = jpxCeilDivPow2(tileComp
->x0
- (1 << (k
-1)), k
);
1976 resLevel
->by0
[0] = resLevel
->y0
;
1977 resLevel
->bx1
[0] = jpxCeilDivPow2(tileComp
->x1
- (1 << (k
-1)), k
);
1978 resLevel
->by1
[0] = resLevel
->y1
;
1979 resLevel
->bx0
[1] = resLevel
->x0
;
1980 resLevel
->by0
[1] = jpxCeilDivPow2(tileComp
->y0
- (1 << (k
-1)), k
);
1981 resLevel
->bx1
[1] = resLevel
->x1
;
1982 resLevel
->by1
[1] = jpxCeilDivPow2(tileComp
->y1
- (1 << (k
-1)), k
);
1983 resLevel
->bx0
[2] = jpxCeilDivPow2(tileComp
->x0
- (1 << (k
-1)), k
);
1984 resLevel
->by0
[2] = jpxCeilDivPow2(tileComp
->y0
- (1 << (k
-1)), k
);
1985 resLevel
->bx1
[2] = jpxCeilDivPow2(tileComp
->x1
- (1 << (k
-1)), k
);
1986 resLevel
->by1
[2] = jpxCeilDivPow2(tileComp
->y1
- (1 << (k
-1)), k
);
1988 resLevel
->precincts
= (JPXPrecinct
*)gmallocn(1, sizeof(JPXPrecinct
));
1989 for (pre
= 0; pre
< 1; ++pre
) {
1990 precinct
= &resLevel
->precincts
[pre
];
1991 precinct
->x0
= resLevel
->x0
;
1992 precinct
->y0
= resLevel
->y0
;
1993 precinct
->x1
= resLevel
->x1
;
1994 precinct
->y1
= resLevel
->y1
;
1995 nSBs
= r
== 0 ? 1 : 3;
1996 precinct
->subbands
=
1997 (JPXSubband
*)gmallocn(nSBs
, sizeof(JPXSubband
));
1998 for (sb
= 0; sb
< nSBs
; ++sb
) {
1999 subband
= &precinct
->subbands
[sb
];
2000 subband
->x0
= resLevel
->bx0
[sb
];
2001 subband
->y0
= resLevel
->by0
[sb
];
2002 subband
->x1
= resLevel
->bx1
[sb
];
2003 subband
->y1
= resLevel
->by1
[sb
];
2004 subband
->nXCBs
= jpxCeilDivPow2(subband
->x1
,
2005 tileComp
->codeBlockW
)
2006 - jpxFloorDivPow2(subband
->x0
,
2007 tileComp
->codeBlockW
);
2008 subband
->nYCBs
= jpxCeilDivPow2(subband
->y1
,
2009 tileComp
->codeBlockH
)
2010 - jpxFloorDivPow2(subband
->y0
,
2011 tileComp
->codeBlockH
);
2012 n
= subband
->nXCBs
> subband
->nYCBs
? subband
->nXCBs
2014 for (subband
->maxTTLevel
= 0, --n
;
2016 ++subband
->maxTTLevel
, n
>>= 1) ;
2018 for (level
= subband
->maxTTLevel
; level
>= 0; --level
) {
2019 nx
= jpxCeilDivPow2(subband
->nXCBs
, level
);
2020 ny
= jpxCeilDivPow2(subband
->nYCBs
, level
);
2023 subband
->inclusion
=
2024 (JPXTagTreeNode
*)gmallocn(n
, sizeof(JPXTagTreeNode
));
2025 subband
->zeroBitPlane
=
2026 (JPXTagTreeNode
*)gmallocn(n
, sizeof(JPXTagTreeNode
));
2027 for (k
= 0; k
< n
; ++k
) {
2028 subband
->inclusion
[k
].finished
= gFalse
;
2029 subband
->inclusion
[k
].val
= 0;
2030 subband
->zeroBitPlane
[k
].finished
= gFalse
;
2031 subband
->zeroBitPlane
[k
].val
= 0;
2033 subband
->cbs
= (JPXCodeBlock
*)gmallocn(subband
->nXCBs
*
2035 sizeof(JPXCodeBlock
));
2036 sbx0
= jpxFloorDivPow2(subband
->x0
, tileComp
->codeBlockW
);
2037 sby0
= jpxFloorDivPow2(subband
->y0
, tileComp
->codeBlockH
);
2038 if (r
== 0) { // (NL)LL
2039 sbCoeffs
= tileComp
->data
;
2040 } else if (sb
== 0) { // (NL-r+1)HL
2041 sbCoeffs
= tileComp
->data
2042 + resLevel
->bx1
[1] - resLevel
->bx0
[1];
2043 } else if (sb
== 1) { // (NL-r+1)LH
2044 sbCoeffs
= tileComp
->data
2045 + (resLevel
->by1
[0] - resLevel
->by0
[0]) * tileComp
->w
;
2046 } else { // (NL-r+1)HH
2047 sbCoeffs
= tileComp
->data
2048 + (resLevel
->by1
[0] - resLevel
->by0
[0]) * tileComp
->w
2049 + resLevel
->bx1
[1] - resLevel
->bx0
[1];
2052 for (cbY
= 0; cbY
< subband
->nYCBs
; ++cbY
) {
2053 for (cbX
= 0; cbX
< subband
->nXCBs
; ++cbX
) {
2054 cb
->x0
= (sbx0
+ cbX
) << tileComp
->codeBlockW
;
2055 cb
->x1
= cb
->x0
+ tileComp
->cbW
;
2056 if (subband
->x0
> cb
->x0
) {
2057 cb
->x0
= subband
->x0
;
2059 if (subband
->x1
< cb
->x1
) {
2060 cb
->x1
= subband
->x1
;
2062 cb
->y0
= (sby0
+ cbY
) << tileComp
->codeBlockH
;
2063 cb
->y1
= cb
->y0
+ tileComp
->cbH
;
2064 if (subband
->y0
> cb
->y0
) {
2065 cb
->y0
= subband
->y0
;
2067 if (subband
->y1
< cb
->y1
) {
2068 cb
->y1
= subband
->y1
;
2072 cb
->nextPass
= jpxPassCleanup
;
2073 cb
->nZeroBitPlanes
= 0;
2074 cb
->dataLenSize
= 1;
2075 cb
->dataLen
= (Guint
*)gmalloc(sizeof(Guint
));
2076 cb
->coeffs
= sbCoeffs
2077 + (cb
->y0
- subband
->y0
) * tileComp
->w
2078 + (cb
->x0
- subband
->x0
);
2079 cb
->touched
= (char *)gmalloc(1 << (tileComp
->codeBlockW
2080 + tileComp
->codeBlockH
));
2082 for (cbj
= 0; cbj
< cb
->y1
- cb
->y0
; ++cbj
) {
2083 for (cbi
= 0; cbi
< cb
->x1
- cb
->x0
; ++cbi
) {
2084 cb
->coeffs
[cbj
* tileComp
->w
+ cbi
] = 0;
2087 memset(cb
->touched
, 0,
2088 (1 << (tileComp
->codeBlockW
+ tileComp
->codeBlockH
)));
2089 cb
->arithDecoder
= NULL
;
2100 return readTilePartData(tileIdx
, tilePartLen
, tilePartToEOC
);
2103 GBool
JPXStream::readTilePartData(Guint tileIdx
,
2104 Guint tilePartLen
, GBool tilePartToEOC
) {
2106 JPXTileComp
*tileComp
;
2107 JPXResLevel
*resLevel
;
2108 JPXPrecinct
*precinct
;
2109 JPXSubband
*subband
;
2112 Guint bits
, cbX
, cbY
, nx
, ny
, i
, j
, n
, sb
;
2115 tile
= &img
.tiles
[tileIdx
];
2117 // read all packets from this tile-part
2119 if (tilePartToEOC
) {
2120 //~ peek for an EOC marker
2122 } else if (tilePartLen
== 0) {
2126 tileComp
= &tile
->tileComps
[tile
->comp
];
2127 resLevel
= &tileComp
->resLevels
[tile
->res
];
2128 precinct
= &resLevel
->precincts
[tile
->precinct
];
2130 //----- packet header
2133 startBitBuf(tilePartLen
);
2134 if (tileComp
->style
& 0x02) {
2139 if (!readBits(1, &bits
)) {
2143 // packet is empty -- clear all code-block inclusion flags
2145 for (sb
= 0; sb
< (Guint
)(tile
->res
== 0 ? 1 : 3); ++sb
) {
2146 subband
= &precinct
->subbands
[sb
];
2147 for (cbY
= 0; cbY
< subband
->nYCBs
; ++cbY
) {
2148 for (cbX
= 0; cbX
< subband
->nXCBs
; ++cbX
) {
2149 cb
= &subband
->cbs
[cbY
* subband
->nXCBs
+ cbX
];
2150 cb
->included
= gFalse
;
2156 for (sb
= 0; sb
< (Guint
)(tile
->res
== 0 ? 1 : 3); ++sb
) {
2157 subband
= &precinct
->subbands
[sb
];
2158 for (cbY
= 0; cbY
< subband
->nYCBs
; ++cbY
) {
2159 for (cbX
= 0; cbX
< subband
->nXCBs
; ++cbX
) {
2160 cb
= &subband
->cbs
[cbY
* subband
->nXCBs
+ cbX
];
2162 // skip code-blocks with no coefficients
2163 if (cb
->x0
>= cb
->x1
|| cb
->y0
>= cb
->y1
) {
2165 cb
->included
= gFalse
;
2169 // code-block inclusion
2172 if (!readBits(1, &cb
->included
)) {
2179 for (level
= subband
->maxTTLevel
; level
>= 0; --level
) {
2180 nx
= jpxCeilDivPow2(subband
->nXCBs
, level
);
2181 ny
= jpxCeilDivPow2(subband
->nYCBs
, level
);
2182 j
= i
+ (cbY
>> level
) * nx
+ (cbX
>> level
);
2183 if (!subband
->inclusion
[j
].finished
&&
2184 !subband
->inclusion
[j
].val
) {
2185 subband
->inclusion
[j
].val
= ttVal
;
2187 ttVal
= subband
->inclusion
[j
].val
;
2189 while (!subband
->inclusion
[j
].finished
&&
2190 ttVal
<= tile
->layer
) {
2191 if (!readBits(1, &bits
)) {
2195 subband
->inclusion
[j
].finished
= gTrue
;
2200 subband
->inclusion
[j
].val
= ttVal
;
2201 if (ttVal
> tile
->layer
) {
2206 cb
->included
= level
< 0;
2212 // zero bit-plane count
2217 for (level
= subband
->maxTTLevel
; level
>= 0; --level
) {
2218 nx
= jpxCeilDivPow2(subband
->nXCBs
, level
);
2219 ny
= jpxCeilDivPow2(subband
->nYCBs
, level
);
2220 j
= i
+ (cbY
>> level
) * nx
+ (cbX
>> level
);
2221 if (!subband
->zeroBitPlane
[j
].finished
&&
2222 !subband
->zeroBitPlane
[j
].val
) {
2223 subband
->zeroBitPlane
[j
].val
= ttVal
;
2225 ttVal
= subband
->zeroBitPlane
[j
].val
;
2227 while (!subband
->zeroBitPlane
[j
].finished
) {
2228 if (!readBits(1, &bits
)) {
2232 subband
->zeroBitPlane
[j
].finished
= gTrue
;
2237 subband
->zeroBitPlane
[j
].val
= ttVal
;
2240 cb
->nZeroBitPlanes
= ttVal
;
2243 // number of coding passes
2244 if (!readBits(1, &bits
)) {
2249 cb
->nCodingPasses
= 1;
2251 if (!readBits(1, &bits
)) {
2256 cb
->nCodingPasses
= 2;
2259 if (!readBits(2, &bits
)) {
2264 cb
->nCodingPasses
= 3 + bits
;
2267 if (!readBits(5, &bits
)) {
2272 cb
->nCodingPasses
= 6 + bits
;
2275 if (!readBits(7, &bits
)) {
2278 cb
->nCodingPasses
= 37 + bits
;
2286 if (!readBits(1, &bits
)) {
2295 // one codeword segment for each of the coding passes
2296 if (tileComp
->codeBlockStyle
& 0x04) {
2297 if (cb
->nCodingPasses
> cb
->dataLenSize
) {
2298 cb
->dataLenSize
= cb
->nCodingPasses
;
2299 cb
->dataLen
= (Guint
*)greallocn(cb
->dataLen
,
2305 for (i
= 0; i
< cb
->nCodingPasses
; ++i
) {
2306 if (!readBits(cb
->lBlock
, &cb
->dataLen
[i
])) {
2311 // one codeword segment for all of the coding passes
2315 for (n
= cb
->lBlock
, i
= cb
->nCodingPasses
>> 1;
2318 if (!readBits(n
, &cb
->dataLen
[0])) {
2327 if (tileComp
->style
& 0x04) {
2330 tilePartLen
= finishBitBuf();
2334 for (sb
= 0; sb
< (Guint
)(tile
->res
== 0 ? 1 : 3); ++sb
) {
2335 subband
= &precinct
->subbands
[sb
];
2336 for (cbY
= 0; cbY
< subband
->nYCBs
; ++cbY
) {
2337 for (cbX
= 0; cbX
< subband
->nXCBs
; ++cbX
) {
2338 cb
= &subband
->cbs
[cbY
* subband
->nXCBs
+ cbX
];
2340 if (!readCodeBlockData(tileComp
, resLevel
, precinct
, subband
,
2341 tile
->res
, sb
, cb
)) {
2344 if (tileComp
->codeBlockStyle
& 0x04) {
2345 for (i
= 0; i
< cb
->nCodingPasses
; ++i
) {
2346 tilePartLen
-= cb
->dataLen
[i
];
2349 tilePartLen
-= cb
->dataLen
[0];
2359 switch (tile
->progOrder
) {
2360 case 0: // layer, resolution level, component, precinct
2362 if (++tile
->comp
== img
.nComps
) {
2364 if (++tile
->res
== tile
->maxNDecompLevels
+ 1) {
2366 if (++tile
->layer
== tile
->nLayers
) {
2372 case 1: // resolution level, layer, component, precinct
2374 if (++tile
->comp
== img
.nComps
) {
2376 if (++tile
->layer
== tile
->nLayers
) {
2378 if (++tile
->res
== tile
->maxNDecompLevels
+ 1) {
2384 case 2: // resolution level, precinct, component, layer
2385 //~ this isn't correct -- see B.12.1.3
2387 if (++tile
->layer
== tile
->nLayers
) {
2389 if (++tile
->comp
== img
.nComps
) {
2391 if (++tile
->res
== tile
->maxNDecompLevels
+ 1) {
2395 tileComp
= &tile
->tileComps
[tile
->comp
];
2396 if (tile
->res
>= tileComp
->nDecompLevels
+ 1) {
2397 if (++tile
->comp
== img
.nComps
) {
2403 case 3: // precinct, component, resolution level, layer
2404 //~ this isn't correct -- see B.12.1.4
2406 if (++tile
->layer
== tile
->nLayers
) {
2408 if (++tile
->res
== tile
->maxNDecompLevels
+ 1) {
2410 if (++tile
->comp
== img
.nComps
) {
2416 case 4: // component, precinct, resolution level, layer
2417 //~ this isn't correct -- see B.12.1.5
2419 if (++tile
->layer
== tile
->nLayers
) {
2421 if (++tile
->res
== tile
->maxNDecompLevels
+ 1) {
2423 if (++tile
->comp
== img
.nComps
) {
2435 error(errSyntaxError
, getPos(), "Error in JPX stream");
2439 GBool
JPXStream::readCodeBlockData(JPXTileComp
*tileComp
,
2440 JPXResLevel
*resLevel
,
2441 JPXPrecinct
*precinct
,
2442 JPXSubband
*subband
,
2443 Guint res
, Guint sb
,
2445 int *coeff0
, *coeff1
, *coeff
;
2446 char *touched0
, *touched1
, *touched
;
2447 Guint horiz
, vert
, diag
, all
, cx
, xorBit
;
2448 int horizSign
, vertSign
, bit
;
2452 if (cb
->arithDecoder
) {
2454 cb
->arithDecoder
->restart(cb
->dataLen
[0]);
2457 cb
->arithDecoder
= new JArithmeticDecoder();
2458 cb
->arithDecoder
->setStream(bufStr
, cb
->dataLen
[0]);
2459 cb
->arithDecoder
->start();
2460 cb
->stats
= new JArithmeticDecoderStats(jpxNContexts
);
2461 cb
->stats
->setEntry(jpxContextSigProp
, 4, 0);
2462 cb
->stats
->setEntry(jpxContextRunLength
, 3, 0);
2463 cb
->stats
->setEntry(jpxContextUniform
, 46, 0);
2466 for (i
= 0; i
< cb
->nCodingPasses
; ++i
) {
2467 if ((tileComp
->codeBlockStyle
& 0x04) && i
> 0) {
2468 cb
->arithDecoder
->setStream(bufStr
, cb
->dataLen
[i
]);
2469 cb
->arithDecoder
->start();
2472 switch (cb
->nextPass
) {
2474 //----- significance propagation pass
2475 case jpxPassSigProp
:
2477 for (y0
= cb
->y0
, coeff0
= cb
->coeffs
, touched0
= cb
->touched
;
2479 y0
+= 4, coeff0
+= 4 * tileComp
->w
,
2480 touched0
+= 4 << tileComp
->codeBlockW
) {
2481 for (x
= cb
->x0
, coeff1
= coeff0
, touched1
= touched0
;
2483 ++x
, ++coeff1
, ++touched1
) {
2484 for (y1
= 0, coeff
= coeff1
, touched
= touched1
;
2485 y1
< 4 && y0
+y1
< cb
->y1
;
2486 ++y1
, coeff
+= tileComp
->w
, touched
+= tileComp
->cbW
) {
2488 horiz
= vert
= diag
= 0;
2489 horizSign
= vertSign
= 2;
2493 horizSign
+= coeff
[-1] < 0 ? -1 : 1;
2495 if (y0
+y1
> cb
->y0
) {
2496 diag
+= coeff
[-(int)tileComp
->w
- 1] ? 1 : 0;
2498 if (y0
+y1
< cb
->y1
- 1 &&
2499 (!(tileComp
->codeBlockStyle
& 0x08) || y1
< 3)) {
2500 diag
+= coeff
[tileComp
->w
- 1] ? 1 : 0;
2503 if (x
< cb
->x1
- 1) {
2506 horizSign
+= coeff
[1] < 0 ? -1 : 1;
2508 if (y0
+y1
> cb
->y0
) {
2509 diag
+= coeff
[-(int)tileComp
->w
+ 1] ? 1 : 0;
2511 if (y0
+y1
< cb
->y1
- 1 &&
2512 (!(tileComp
->codeBlockStyle
& 0x08) || y1
< 3)) {
2513 diag
+= coeff
[tileComp
->w
+ 1] ? 1 : 0;
2516 if (y0
+y1
> cb
->y0
) {
2517 if (coeff
[-(int)tileComp
->w
]) {
2519 vertSign
+= coeff
[-(int)tileComp
->w
] < 0 ? -1 : 1;
2522 if (y0
+y1
< cb
->y1
- 1 &&
2523 (!(tileComp
->codeBlockStyle
& 0x08) || y1
< 3)) {
2524 if (coeff
[tileComp
->w
]) {
2526 vertSign
+= coeff
[tileComp
->w
] < 0 ? -1 : 1;
2529 cx
= sigPropContext
[horiz
][vert
][diag
][res
== 0 ? 1 : sb
];
2531 if (cb
->arithDecoder
->decodeBit(cx
, cb
->stats
)) {
2532 cx
= signContext
[horizSign
][vertSign
][0];
2533 xorBit
= signContext
[horizSign
][vertSign
][1];
2534 if (cb
->arithDecoder
->decodeBit(cx
, cb
->stats
) ^ xorBit
) {
2549 //----- magnitude refinement pass
2552 for (y0
= cb
->y0
, coeff0
= cb
->coeffs
, touched0
= cb
->touched
;
2554 y0
+= 4, coeff0
+= 4 * tileComp
->w
,
2555 touched0
+= 4 << tileComp
->codeBlockW
) {
2556 for (x
= cb
->x0
, coeff1
= coeff0
, touched1
= touched0
;
2558 ++x
, ++coeff1
, ++touched1
) {
2559 for (y1
= 0, coeff
= coeff1
, touched
= touched1
;
2560 y1
< 4 && y0
+y1
< cb
->y1
;
2561 ++y1
, coeff
+= tileComp
->w
, touched
+= tileComp
->cbW
) {
2562 if (*coeff
&& !*touched
) {
2563 if (*coeff
== 1 || *coeff
== -1) {
2566 all
+= coeff
[-1] ? 1 : 0;
2567 if (y0
+y1
> cb
->y0
) {
2568 all
+= coeff
[-(int)tileComp
->w
- 1] ? 1 : 0;
2570 if (y0
+y1
< cb
->y1
- 1 &&
2571 (!(tileComp
->codeBlockStyle
& 0x08) || y1
< 3)) {
2572 all
+= coeff
[tileComp
->w
- 1] ? 1 : 0;
2575 if (x
< cb
->x1
- 1) {
2576 all
+= coeff
[1] ? 1 : 0;
2577 if (y0
+y1
> cb
->y0
) {
2578 all
+= coeff
[-(int)tileComp
->w
+ 1] ? 1 : 0;
2580 if (y0
+y1
< cb
->y1
- 1 &&
2581 (!(tileComp
->codeBlockStyle
& 0x08) || y1
< 3)) {
2582 all
+= coeff
[tileComp
->w
+ 1] ? 1 : 0;
2585 if (y0
+y1
> cb
->y0
) {
2586 all
+= coeff
[-(int)tileComp
->w
] ? 1 : 0;
2588 if (y0
+y1
< cb
->y1
- 1 &&
2589 (!(tileComp
->codeBlockStyle
& 0x08) || y1
< 3)) {
2590 all
+= coeff
[tileComp
->w
] ? 1 : 0;
2596 bit
= cb
->arithDecoder
->decodeBit(cx
, cb
->stats
);
2598 *coeff
= (*coeff
<< 1) - bit
;
2600 *coeff
= (*coeff
<< 1) + bit
;
2610 //----- cleanup pass
2611 case jpxPassCleanup
:
2613 for (y0
= cb
->y0
, coeff0
= cb
->coeffs
, touched0
= cb
->touched
;
2615 y0
+= 4, coeff0
+= 4 * tileComp
->w
,
2616 touched0
+= 4 << tileComp
->codeBlockW
) {
2617 for (x
= cb
->x0
, coeff1
= coeff0
, touched1
= touched0
;
2619 ++x
, ++coeff1
, ++touched1
) {
2621 if (y0
+ 3 < cb
->y1
&&
2623 !(touched1
[tileComp
->cbW
]) &&
2624 !(touched1
[2 * tileComp
->cbW
]) &&
2625 !(touched1
[3 * tileComp
->cbW
]) &&
2626 (x
== cb
->x0
|| y0
== cb
->y0
||
2627 !coeff1
[-(int)tileComp
->w
- 1]) &&
2629 !coeff1
[-(int)tileComp
->w
]) &&
2630 (x
== cb
->x1
- 1 || y0
== cb
->y0
||
2631 !coeff1
[-(int)tileComp
->w
+ 1]) &&
2634 !coeff1
[tileComp
->w
- 1] &&
2635 !coeff1
[2 * tileComp
->w
- 1] &&
2636 !coeff1
[3 * tileComp
->w
- 1])) &&
2639 !coeff1
[tileComp
->w
+ 1] &&
2640 !coeff1
[2 * tileComp
->w
+ 1] &&
2641 !coeff1
[3 * tileComp
->w
+ 1])) &&
2642 ((tileComp
->codeBlockStyle
& 0x08) ||
2643 ((x
== cb
->x0
|| y0
+4 == cb
->y1
||
2644 !coeff1
[4 * tileComp
->w
- 1]) &&
2646 !coeff1
[4 * tileComp
->w
]) &&
2647 (x
== cb
->x1
- 1 || y0
+4 == cb
->y1
||
2648 !coeff1
[4 * tileComp
->w
+ 1])))) {
2649 if (cb
->arithDecoder
->decodeBit(jpxContextRunLength
, cb
->stats
)) {
2650 y1
= cb
->arithDecoder
->decodeBit(jpxContextUniform
, cb
->stats
);
2652 cb
->arithDecoder
->decodeBit(jpxContextUniform
, cb
->stats
);
2653 coeff
= &coeff1
[y1
* tileComp
->w
];
2654 cx
= signContext
[2][2][0];
2655 xorBit
= signContext
[2][2][1];
2656 if (cb
->arithDecoder
->decodeBit(cx
, cb
->stats
) ^ xorBit
) {
2666 for (coeff
= &coeff1
[y1
* tileComp
->w
],
2667 touched
= &touched1
[y1
<< tileComp
->codeBlockW
];
2668 y1
< 4 && y0
+ y1
< cb
->y1
;
2669 ++y1
, coeff
+= tileComp
->w
, touched
+= tileComp
->cbW
) {
2671 horiz
= vert
= diag
= 0;
2672 horizSign
= vertSign
= 2;
2676 horizSign
+= coeff
[-1] < 0 ? -1 : 1;
2678 if (y0
+y1
> cb
->y0
) {
2679 diag
+= coeff
[-(int)tileComp
->w
- 1] ? 1 : 0;
2681 if (y0
+y1
< cb
->y1
- 1 &&
2682 (!(tileComp
->codeBlockStyle
& 0x08) || y1
< 3)) {
2683 diag
+= coeff
[tileComp
->w
- 1] ? 1 : 0;
2686 if (x
< cb
->x1
- 1) {
2689 horizSign
+= coeff
[1] < 0 ? -1 : 1;
2691 if (y0
+y1
> cb
->y0
) {
2692 diag
+= coeff
[-(int)tileComp
->w
+ 1] ? 1 : 0;
2694 if (y0
+y1
< cb
->y1
- 1 &&
2695 (!(tileComp
->codeBlockStyle
& 0x08) || y1
< 3)) {
2696 diag
+= coeff
[tileComp
->w
+ 1] ? 1 : 0;
2699 if (y0
+y1
> cb
->y0
) {
2700 if (coeff
[-(int)tileComp
->w
]) {
2702 vertSign
+= coeff
[-(int)tileComp
->w
] < 0 ? -1 : 1;
2705 if (y0
+y1
< cb
->y1
- 1 &&
2706 (!(tileComp
->codeBlockStyle
& 0x08) || y1
< 3)) {
2707 if (coeff
[tileComp
->w
]) {
2709 vertSign
+= coeff
[tileComp
->w
] < 0 ? -1 : 1;
2712 cx
= sigPropContext
[horiz
][vert
][diag
][res
== 0 ? 1 : sb
];
2713 if (cb
->arithDecoder
->decodeBit(cx
, cb
->stats
)) {
2714 cx
= signContext
[horizSign
][vertSign
][0];
2715 xorBit
= signContext
[horizSign
][vertSign
][1];
2716 if (cb
->arithDecoder
->decodeBit(cx
, cb
->stats
) ^ xorBit
) {
2729 // look for a segmentation symbol
2730 if (tileComp
->codeBlockStyle
& 0x20) {
2731 segSym
= cb
->arithDecoder
->decodeBit(jpxContextUniform
,
2733 segSym
|= cb
->arithDecoder
->decodeBit(jpxContextUniform
,
2735 segSym
|= cb
->arithDecoder
->decodeBit(jpxContextUniform
,
2737 segSym
|= cb
->arithDecoder
->decodeBit(jpxContextUniform
,
2739 if (segSym
!= 0x0a) {
2740 // in theory this should be a fatal error, but it seems to
2742 error(errSyntaxWarning
, getPos(),
2743 "Missing or invalid segmentation symbol in JPX stream");
2746 cb
->nextPass
= jpxPassSigProp
;
2750 if (tileComp
->codeBlockStyle
& 0x02) {
2752 cb
->stats
->setEntry(jpxContextSigProp
, 4, 0);
2753 cb
->stats
->setEntry(jpxContextRunLength
, 3, 0);
2754 cb
->stats
->setEntry(jpxContextUniform
, 46, 0);
2757 if (tileComp
->codeBlockStyle
& 0x04) {
2758 cb
->arithDecoder
->cleanup();
2762 cb
->arithDecoder
->cleanup();
2766 // Inverse quantization, and wavelet transform (IDWT). This also does
2767 // the initial shift to convert to fixed point format.
2768 void JPXStream::inverseTransform(JPXTileComp
*tileComp
) {
2769 JPXResLevel
*resLevel
;
2770 JPXPrecinct
*precinct
;
2771 JPXSubband
*subband
;
2773 int *coeff0
, *coeff
;
2774 char *touched0
, *touched
;
2775 Guint qStyle
, guard
, eps
, shift
;
2779 Guint r
, cbX
, cbY
, x
, y
;
2783 //----- (NL)LL subband (resolution level 0)
2785 resLevel
= &tileComp
->resLevels
[0];
2786 precinct
= &resLevel
->precincts
[0];
2787 subband
= &precinct
->subbands
[0];
2789 // i-quant parameters
2790 qStyle
= tileComp
->quantStyle
& 0x1f;
2791 guard
= (tileComp
->quantStyle
>> 5) & 7;
2794 eps
= (tileComp
->quantSteps
[0] >> 3) & 0x1f;
2795 shift
= guard
+ eps
- 1;
2796 mu
= 0; // make gcc happy
2799 shift
= guard
- 1 + tileComp
->prec
;
2800 mu
= (double)(0x800 + (tileComp
->quantSteps
[0] & 0x7ff)) / 2048.0;
2802 if (tileComp
->transform
== 0) {
2807 // do fixed point adjustment and dequantization on (NL)LL
2809 for (cbY
= 0; cbY
< subband
->nYCBs
; ++cbY
) {
2810 for (cbX
= 0; cbX
< subband
->nXCBs
; ++cbX
) {
2811 for (y
= cb
->y0
, coeff0
= cb
->coeffs
, touched0
= cb
->touched
;
2813 ++y
, coeff0
+= tileComp
->w
, touched0
+= tileComp
->cbW
) {
2814 for (x
= cb
->x0
, coeff
= coeff0
, touched
= touched0
;
2816 ++x
, ++coeff
, ++touched
) {
2819 shift2
= shift
- (cb
->nZeroBitPlanes
+ cb
->len
+ *touched
);
2823 val
= (val
<< shift2
) - (1 << (shift2
- 1));
2825 val
= (val
<< shift2
) + (1 << (shift2
- 1));
2833 if (tileComp
->transform
== 0) {
2835 val
&= -1 << fracBits
;
2839 val
= (int)((double)val
* mu
);
2849 //----- IDWT for each level
2851 for (r
= 1; r
<= tileComp
->nDecompLevels
; ++r
) {
2852 resLevel
= &tileComp
->resLevels
[r
];
2854 // (n)LL is already in the upper-left corner of the
2855 // tile-component data array -- interleave with (n)HL/LH/HH
2856 // and inverse transform to get (n-1)LL, which will be stored
2857 // in the upper-left corner of the tile-component data array
2858 inverseTransformLevel(tileComp
, r
, resLevel
);
2862 // Do one level of the inverse transform:
2863 // - take (n)LL, (n)HL, (n)LH, and (n)HH from the upper-left corner
2864 // of the tile-component data array
2865 // - leave the resulting (n-1)LL in the same place
2866 void JPXStream::inverseTransformLevel(JPXTileComp
*tileComp
,
2867 Guint r
, JPXResLevel
*resLevel
) {
2868 JPXPrecinct
*precinct
;
2869 JPXSubband
*subband
;
2871 int *coeff0
, *coeff
;
2872 char *touched0
, *touched
;
2873 Guint qStyle
, guard
, eps
, shift
, t
;
2877 int *dataPtr
, *bufPtr
;
2878 Guint nx1
, nx2
, ny1
, ny2
, offset
;
2879 Guint x
, y
, sb
, cbX
, cbY
;
2881 //----- fixed-point adjustment and dequantization
2883 qStyle
= tileComp
->quantStyle
& 0x1f;
2884 guard
= (tileComp
->quantStyle
>> 5) & 7;
2885 precinct
= &resLevel
->precincts
[0];
2886 for (sb
= 0; sb
< 3; ++sb
) {
2888 // i-quant parameters
2891 const Guint stepIndex
= 3*r
- 2 + sb
;
2892 if (unlikely(stepIndex
>= tileComp
->nQuantSteps
)) {
2893 error(errSyntaxError
, getPos(),
2894 "Wrong index for quantSteps in inverseTransformLevel in JPX stream");
2897 eps
= (tileComp
->quantSteps
[stepIndex
] >> 3) & 0x1f;
2898 shift
= guard
+ eps
- 1;
2899 mu
= 0; // make gcc happy
2902 shift
= guard
+ tileComp
->prec
;
2907 const Guint stepIndex
= qStyle
== 1 ? 0 : (3*r
- 2 + sb
);
2908 if (unlikely(stepIndex
>= tileComp
->nQuantSteps
)) {
2909 error(errSyntaxError
, getPos(),
2910 "Wrong index for quantSteps in inverseTransformLevel in JPX stream");
2913 t
= tileComp
->quantSteps
[stepIndex
];
2914 mu
= (double)(0x800 + (t
& 0x7ff)) / 2048.0;
2916 if (tileComp
->transform
== 0) {
2921 // fixed point adjustment and dequantization
2922 subband
= &precinct
->subbands
[sb
];
2924 for (cbY
= 0; cbY
< subband
->nYCBs
; ++cbY
) {
2925 for (cbX
= 0; cbX
< subband
->nXCBs
; ++cbX
) {
2926 for (y
= cb
->y0
, coeff0
= cb
->coeffs
, touched0
= cb
->touched
;
2928 ++y
, coeff0
+= tileComp
->w
, touched0
+= tileComp
->cbW
) {
2929 for (x
= cb
->x0
, coeff
= coeff0
, touched
= touched0
;
2931 ++x
, ++coeff
, ++touched
) {
2934 shift2
= shift
- (cb
->nZeroBitPlanes
+ cb
->len
+ *touched
);
2938 val
= (val
<< shift2
) - (1 << (shift2
- 1));
2940 val
= (val
<< shift2
) + (1 << (shift2
- 1));
2948 if (tileComp
->transform
== 0) {
2949 val
&= -1 << fracBits
;
2953 val
= (int)((double)val
* mu
);
2964 //----- inverse transform
2966 // compute the subband bounds:
2973 // | LH | HH | <- ny1
2976 nx1
= precinct
->subbands
[1].x1
- precinct
->subbands
[1].x0
;
2977 nx2
= nx1
+ precinct
->subbands
[0].x1
- precinct
->subbands
[0].x0
;
2978 ny1
= precinct
->subbands
[0].y1
- precinct
->subbands
[0].y0
;
2979 ny2
= ny1
+ precinct
->subbands
[1].y1
- precinct
->subbands
[1].y0
;
2981 // horizontal (row) transforms
2982 if (r
== tileComp
->nDecompLevels
) {
2983 offset
= 3 + (tileComp
->x0
& 1);
2985 offset
= 3 + (tileComp
->resLevels
[r
+1].x0
& 1);
2987 for (y
= 0, dataPtr
= tileComp
->data
; y
< ny2
; ++y
, dataPtr
+= tileComp
->w
) {
2988 if (precinct
->subbands
[0].x0
== precinct
->subbands
[1].x0
) {
2990 for (x
= 0, bufPtr
= tileComp
->buf
+ offset
;
2993 *bufPtr
= dataPtr
[x
];
2996 for (x
= nx1
, bufPtr
= tileComp
->buf
+ offset
+ 1;
2999 *bufPtr
= dataPtr
[x
];
3003 for (x
= 0, bufPtr
= tileComp
->buf
+ offset
+ 1;
3006 *bufPtr
= dataPtr
[x
];
3009 for (x
= nx1
, bufPtr
= tileComp
->buf
+ offset
;
3012 *bufPtr
= dataPtr
[x
];
3015 if (tileComp
->x1
- tileComp
->x0
> tileComp
->y1
- tileComp
->y0
) {
3016 x
= tileComp
->x1
- tileComp
->x0
+ 5;
3018 x
= tileComp
->y1
- tileComp
->y0
+ 5;
3020 if (offset
+ nx2
> x
|| nx2
== 0) {
3021 error(errSyntaxError
, getPos(),
3022 "Invalid call of inverseTransform1D in inverseTransformLevel in JPX stream");
3025 inverseTransform1D(tileComp
, tileComp
->buf
, offset
, nx2
);
3026 for (x
= 0, bufPtr
= tileComp
->buf
+ offset
; x
< nx2
; ++x
, ++bufPtr
) {
3027 dataPtr
[x
] = *bufPtr
;
3031 // vertical (column) transforms
3032 if (r
== tileComp
->nDecompLevels
) {
3033 offset
= 3 + (tileComp
->y0
& 1);
3035 offset
= 3 + (tileComp
->resLevels
[r
+1].y0
& 1);
3037 for (x
= 0, dataPtr
= tileComp
->data
; x
< nx2
; ++x
, ++dataPtr
) {
3038 if (precinct
->subbands
[1].y0
== precinct
->subbands
[0].y0
) {
3040 for (y
= 0, bufPtr
= tileComp
->buf
+ offset
;
3043 *bufPtr
= dataPtr
[y
* tileComp
->w
];
3046 for (y
= ny1
, bufPtr
= tileComp
->buf
+ offset
+ 1;
3049 *bufPtr
= dataPtr
[y
* tileComp
->w
];
3053 for (y
= 0, bufPtr
= tileComp
->buf
+ offset
+ 1;
3056 *bufPtr
= dataPtr
[y
* tileComp
->w
];
3059 for (y
= ny1
, bufPtr
= tileComp
->buf
+ offset
;
3062 *bufPtr
= dataPtr
[y
* tileComp
->w
];
3065 if (tileComp
->x1
- tileComp
->x0
> tileComp
->y1
- tileComp
->y0
) {
3066 y
= tileComp
->x1
- tileComp
->x0
+ 5;
3068 y
= tileComp
->y1
- tileComp
->y0
+ 5;
3070 if (offset
+ ny2
> y
|| ny2
== 0) {
3071 error(errSyntaxError
, getPos(),
3072 "Invalid call of inverseTransform1D in inverseTransformLevel in JPX stream");
3075 inverseTransform1D(tileComp
, tileComp
->buf
, offset
, ny2
);
3076 for (y
= 0, bufPtr
= tileComp
->buf
+ offset
; y
< ny2
; ++y
, ++bufPtr
) {
3077 dataPtr
[y
* tileComp
->w
] = *bufPtr
;
3082 void JPXStream::inverseTransform1D(JPXTileComp
*tileComp
, int *data
,
3083 Guint offset
, Guint n
) {
3086 //----- special case for length = 1
3099 //----- extend right
3100 data
[end
] = data
[end
- 2];
3103 data
[end
+1] = data
[offset
+ 1];
3104 data
[end
+2] = data
[offset
];
3105 data
[end
+3] = data
[offset
+ 1];
3108 data
[end
+1] = data
[end
- 3];
3111 data
[end
+2] = data
[offset
+ 1];
3112 data
[end
+3] = data
[offset
+ 2];
3115 data
[end
+2] = data
[end
- 4];
3118 data
[end
+3] = data
[offset
+ 1];
3121 data
[end
+3] = data
[end
- 5];
3127 data
[offset
- 1] = data
[offset
+ 1];
3128 data
[offset
- 2] = data
[offset
+ 2];
3129 data
[offset
- 3] = data
[offset
+ 3];
3132 data
[0] = data
[offset
+ 4];
3135 //----- 9-7 irreversible filter
3137 if (tileComp
->transform
== 0) {
3140 for (i
= 1; i
<= end
+ 2; i
+= 2) {
3141 data
[i
] = (int)(idwtKappa
* data
[i
]);
3144 for (i
= 0; i
<= end
+ 3; i
+= 2) {
3145 data
[i
] = (int)(idwtIKappa
* data
[i
]);
3148 for (i
= 1; i
<= end
+ 2; i
+= 2) {
3149 data
[i
] = (int)(data
[i
] - idwtDelta
* (data
[i
-1] + data
[i
+1]));
3152 for (i
= 2; i
<= end
+ 1; i
+= 2) {
3153 data
[i
] = (int)(data
[i
] - idwtGamma
* (data
[i
-1] + data
[i
+1]));
3156 for (i
= 3; i
<= end
; i
+= 2) {
3157 data
[i
] = (int)(data
[i
] - idwtBeta
* (data
[i
-1] + data
[i
+1]));
3160 for (i
= 4; i
<= end
- 1; i
+= 2) {
3161 data
[i
] = (int)(data
[i
] - idwtAlpha
* (data
[i
-1] + data
[i
+1]));
3164 //----- 5-3 reversible filter
3169 for (i
= 3; i
<= end
; i
+= 2) {
3170 data
[i
] -= (data
[i
-1] + data
[i
+1] + 2) >> 2;
3173 for (i
= 4; i
< end
; i
+= 2) {
3174 data
[i
] += (data
[i
-1] + data
[i
+1]) >> 1;
3180 // Inverse multi-component transform and DC level shift. This also
3181 // converts fixed point samples back to integers.
3182 GBool
JPXStream::inverseMultiCompAndDC(JPXTile
*tile
) {
3183 JPXTileComp
*tileComp
;
3184 int coeff
, d0
, d1
, d2
, t
, minVal
, maxVal
, zeroVal
;
3186 Guint j
, comp
, x
, y
;
3188 //----- inverse multi-component transform
3190 if (tile
->multiComp
== 1) {
3192 if (img
.nComps
< 3 ||
3193 tile
->tileComps
[0].hSep
!= tile
->tileComps
[1].hSep
||
3194 tile
->tileComps
[0].vSep
!= tile
->tileComps
[1].vSep
||
3195 tile
->tileComps
[1].hSep
!= tile
->tileComps
[2].hSep
||
3196 tile
->tileComps
[1].vSep
!= tile
->tileComps
[2].vSep
) {
3200 // inverse irreversible multiple component transform
3201 if (tile
->tileComps
[0].transform
== 0) {
3204 for (y
= 0; y
< tile
->tileComps
[0].y1
- tile
->tileComps
[0].y0
; ++y
) {
3205 for (x
= 0; x
< tile
->tileComps
[0].x1
- tile
->tileComps
[0].x0
; ++x
) {
3206 d0
= tile
->tileComps
[0].data
[j
];
3207 d1
= tile
->tileComps
[1].data
[j
];
3208 d2
= tile
->tileComps
[2].data
[j
];
3209 tile
->tileComps
[0].data
[j
] = (int)(d0
+ 1.402 * d2
+ 0.5);
3210 tile
->tileComps
[1].data
[j
] =
3211 (int)(d0
- 0.34413 * d1
- 0.71414 * d2
+ 0.5);
3212 tile
->tileComps
[2].data
[j
] = (int)(d0
+ 1.772 * d1
+ 0.5);
3217 // inverse reversible multiple component transform
3221 for (y
= 0; y
< tile
->tileComps
[0].y1
- tile
->tileComps
[0].y0
; ++y
) {
3222 for (x
= 0; x
< tile
->tileComps
[0].x1
- tile
->tileComps
[0].x0
; ++x
) {
3223 d0
= tile
->tileComps
[0].data
[j
];
3224 d1
= tile
->tileComps
[1].data
[j
];
3225 d2
= tile
->tileComps
[2].data
[j
];
3226 tile
->tileComps
[1].data
[j
] = t
= d0
- ((d2
+ d1
) >> 2);
3227 tile
->tileComps
[0].data
[j
] = d2
+ t
;
3228 tile
->tileComps
[2].data
[j
] = d1
+ t
;
3235 //----- DC level shift
3236 for (comp
= 0; comp
< img
.nComps
; ++comp
) {
3237 tileComp
= &tile
->tileComps
[comp
];
3240 if (tileComp
->sgned
) {
3242 minVal
= -(1 << (tileComp
->prec
- 1));
3243 maxVal
= (1 << (tileComp
->prec
- 1)) - 1;
3244 dataPtr
= tileComp
->data
;
3245 for (y
= 0; y
< tileComp
->y1
- tileComp
->y0
; ++y
) {
3246 for (x
= 0; x
< tileComp
->x1
- tileComp
->x0
; ++x
) {
3248 if (tileComp
->transform
== 0) {
3252 if (coeff
< minVal
) {
3255 } else if (coeff
> maxVal
) {
3263 // unsigned: inverse DC level shift and clip
3266 maxVal
= (1 << tileComp
->prec
) - 1;
3267 zeroVal
= 1 << (tileComp
->prec
- 1);
3268 dataPtr
= tileComp
->data
;
3269 for (y
= 0; y
< tileComp
->y1
- tileComp
->y0
; ++y
) {
3270 for (x
= 0; x
< tileComp
->x1
- tileComp
->x0
; ++x
) {
3272 if (tileComp
->transform
== 0) {
3280 } else if (coeff
> maxVal
) {
3293 GBool
JPXStream::readBoxHdr(Guint
*boxType
, Guint
*boxLen
, Guint
*dataLen
) {
3296 if (!readULong(&len
) ||
3297 !readULong(boxType
)) {
3301 if (!readULong(&lenH
) || !readULong(&len
)) {
3305 error(errSyntaxError
, getPos(),
3306 "JPX stream contains a box larger than 2^32 bytes");
3310 *dataLen
= len
- 16;
3311 } else if (len
== 0) {
3321 int JPXStream::readMarkerHdr(int *segType
, Guint
*segLen
) {
3326 if ((c
= bufStr
->getChar()) == EOF
) {
3329 } while (c
!= 0xff);
3331 if ((c
= bufStr
->getChar()) == EOF
) {
3334 } while (c
== 0xff);
3335 } while (c
== 0x00);
3337 if ((c
>= 0x30 && c
<= 0x3f) ||
3338 c
== 0x4f || c
== 0x92 || c
== 0x93 || c
== 0xd9) {
3342 return readUWord(segLen
);
3345 GBool
JPXStream::readUByte(Guint
*x
) {
3348 if ((c0
= bufStr
->getChar()) == EOF
) {
3355 GBool
JPXStream::readByte(int *x
) {
3358 if ((c0
= bufStr
->getChar()) == EOF
) {
3368 GBool
JPXStream::readUWord(Guint
*x
) {
3371 if ((c0
= bufStr
->getChar()) == EOF
||
3372 (c1
= bufStr
->getChar()) == EOF
) {
3375 *x
= (Guint
)((c0
<< 8) | c1
);
3379 GBool
JPXStream::readULong(Guint
*x
) {
3382 if ((c0
= bufStr
->getChar()) == EOF
||
3383 (c1
= bufStr
->getChar()) == EOF
||
3384 (c2
= bufStr
->getChar()) == EOF
||
3385 (c3
= bufStr
->getChar()) == EOF
) {
3388 *x
= (Guint
)((c0
<< 24) | (c1
<< 16) | (c2
<< 8) | c3
);
3392 GBool
JPXStream::readNBytes(int nBytes
, GBool signd
, int *x
) {
3396 for (i
= 0; i
< nBytes
; ++i
) {
3397 if ((c
= bufStr
->getChar()) == EOF
) {
3403 if (y
& (1 << (8 * nBytes
- 1))) {
3404 y
|= -1 << (8 * nBytes
);
3411 void JPXStream::startBitBuf(Guint byteCountA
) {
3413 bitBufSkip
= gFalse
;
3414 byteCount
= byteCountA
;
3417 GBool
JPXStream::readBits(int nBits
, Guint
*x
) {
3420 while (bitBufLen
< nBits
) {
3421 if (byteCount
== 0 || (c
= bufStr
->getChar()) == EOF
) {
3426 bitBuf
= (bitBuf
<< 7) | (c
& 0x7f);
3429 bitBuf
= (bitBuf
<< 8) | (c
& 0xff);
3432 bitBufSkip
= c
== 0xff;
3434 *x
= (bitBuf
>> (bitBufLen
- nBits
)) & ((1 << nBits
) - 1);
3439 void JPXStream::skipSOP() {
3442 // SOP occurs at the start of the packet header, so we don't need to
3443 // worry about bit-stuff prior to it
3444 if (byteCount
>= 6 &&
3445 bufStr
->lookChar(0) == 0xff &&
3446 bufStr
->lookChar(1) == 0x91) {
3447 for (i
= 0; i
< 6; ++i
) {
3452 bitBufSkip
= gFalse
;
3456 void JPXStream::skipEPH() {
3459 k
= bitBufSkip
? 1 : 0;
3460 if (byteCount
>= (Guint
)(k
+ 2) &&
3461 bufStr
->lookChar(k
) == 0xff &&
3462 bufStr
->lookChar(k
+ 1) == 0x92) {
3463 for (i
= 0; i
< k
+ 2; ++i
) {
3468 bitBufSkip
= gFalse
;
3472 Guint
JPXStream::finishBitBuf() {