1 //========================================================================
2 //
3 // JPXStream.cc
4 //
5 // Copyright 2002-2003 Glyph & Cog, LLC
6 //
7 //========================================================================
8 
9 //========================================================================
10 //
11 // Modified under the Poppler project - http://poppler.freedesktop.org
12 //
13 // All changes made under the Poppler project to this file are licensed
14 // under GPL version 2 or later
15 //
16 // Copyright (C) 2008, 2012, 2021 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>
19 // Copyright (C) 2019 Robert Niemi <robert.den.klurige@gmail.com>
20 //
21 // To see a description of the changes please see the Changelog file that
22 // came with your tarball or type make ChangeLog if you are building from git
23 //
24 //========================================================================
25 
26 #include <config.h>
27 
28 #include <climits>
29 #include "gmem.h"
30 #include "Error.h"
31 #include "JArithmeticDecoder.h"
32 #include "JPXStream.h"
33 
34 //~ to do:
35 //  - precincts
36 //  - ROI
37 //  - progression order changes
38 //  - packed packet headers
39 //  - support for palettes, channel maps, etc.
40 //  - make sure all needed JP2/JPX subboxes are parsed (readBoxes)
41 //  - can we assume that QCC segments must come after the QCD segment?
42 //  - handle tilePartToEOC in readTilePartData
43 //  - progression orders 2, 3, and 4
44 //  - in coefficient decoding (readCodeBlockData):
45 //    - selective arithmetic coding bypass
46 //      (this also affects reading the cb->dataLen array)
47 //    - coeffs longer than 31 bits (should just ignore the extra bits?)
48 //  - handle boxes larger than 2^32 bytes
49 //  - the fixed-point arithmetic won't handle 16-bit pixels
50 
51 //------------------------------------------------------------------------
52 
53 // number of contexts for the arithmetic decoder
54 #define jpxNContexts 19
55 
56 #define jpxContextSigProp 0 // 0 - 8: significance prop and cleanup
57 #define jpxContextSign 9 // 9 - 13: sign
58 #define jpxContextMagRef 14 // 14 -16: magnitude refinement
59 #define jpxContextRunLength 17 // cleanup: run length
60 #define jpxContextUniform 18 // cleanup: first signif coeff
61 
62 //------------------------------------------------------------------------
63 
64 #define jpxPassSigProp 0
65 #define jpxPassMagRef 1
66 #define jpxPassCleanup 2
67 
68 //------------------------------------------------------------------------
69 
70 // arithmetic decoder context for the significance propagation and
71 // cleanup passes:
72 //     [horiz][vert][diag][subband]
73 // where subband = 0 for HL
74 //               = 1 for LH and LL
75 //               = 2 for HH
76 static const unsigned int sigPropContext[3][3][5][3] = {
77     { { { 0, 0, 0 }, // horiz=0, vert=0, diag=0
78         { 1, 1, 3 }, // horiz=0, vert=0, diag=1
79         { 2, 2, 6 }, // horiz=0, vert=0, diag=2
80         { 2, 2, 8 }, // horiz=0, vert=0, diag=3
81         { 2, 2, 8 } }, // horiz=0, vert=0, diag=4
82       { { 5, 3, 1 }, // horiz=0, vert=1, diag=0
83         { 6, 3, 4 }, // horiz=0, vert=1, diag=1
84         { 6, 3, 7 }, // horiz=0, vert=1, diag=2
85         { 6, 3, 8 }, // horiz=0, vert=1, diag=3
86         { 6, 3, 8 } }, // horiz=0, vert=1, diag=4
87       { { 8, 4, 2 }, // horiz=0, vert=2, diag=0
88         { 8, 4, 5 }, // horiz=0, vert=2, diag=1
89         { 8, 4, 7 }, // horiz=0, vert=2, diag=2
90         { 8, 4, 8 }, // horiz=0, vert=2, diag=3
91         { 8, 4, 8 } } }, // horiz=0, vert=2, diag=4
92     { { { 3, 5, 1 }, // horiz=1, vert=0, diag=0
93         { 3, 6, 4 }, // horiz=1, vert=0, diag=1
94         { 3, 6, 7 }, // horiz=1, vert=0, diag=2
95         { 3, 6, 8 }, // horiz=1, vert=0, diag=3
96         { 3, 6, 8 } }, // horiz=1, vert=0, diag=4
97       { { 7, 7, 2 }, // horiz=1, vert=1, diag=0
98         { 7, 7, 5 }, // horiz=1, vert=1, diag=1
99         { 7, 7, 7 }, // horiz=1, vert=1, diag=2
100         { 7, 7, 8 }, // horiz=1, vert=1, diag=3
101         { 7, 7, 8 } }, // horiz=1, vert=1, diag=4
102       { { 8, 7, 2 }, // horiz=1, vert=2, diag=0
103         { 8, 7, 5 }, // horiz=1, vert=2, diag=1
104         { 8, 7, 7 }, // horiz=1, vert=2, diag=2
105         { 8, 7, 8 }, // horiz=1, vert=2, diag=3
106         { 8, 7, 8 } } }, // horiz=1, vert=2, diag=4
107     { { { 4, 8, 2 }, // horiz=2, vert=0, diag=0
108         { 4, 8, 5 }, // horiz=2, vert=0, diag=1
109         { 4, 8, 7 }, // horiz=2, vert=0, diag=2
110         { 4, 8, 8 }, // horiz=2, vert=0, diag=3
111         { 4, 8, 8 } }, // horiz=2, vert=0, diag=4
112       { { 7, 8, 2 }, // horiz=2, vert=1, diag=0
113         { 7, 8, 5 }, // horiz=2, vert=1, diag=1
114         { 7, 8, 7 }, // horiz=2, vert=1, diag=2
115         { 7, 8, 8 }, // horiz=2, vert=1, diag=3
116         { 7, 8, 8 } }, // horiz=2, vert=1, diag=4
117       { { 8, 8, 2 }, // horiz=2, vert=2, diag=0
118         { 8, 8, 5 }, // horiz=2, vert=2, diag=1
119         { 8, 8, 7 }, // horiz=2, vert=2, diag=2
120         { 8, 8, 8 }, // horiz=2, vert=2, diag=3
121         { 8, 8, 8 } } } // horiz=2, vert=2, diag=4
122 };
123 
124 // arithmetic decoder context and xor bit for the sign bit in the
125 // significance propagation pass:
126 //     [horiz][vert][k]
127 // where horiz/vert are offset by 2 (i.e., range is -2 .. 2)
128 // and k = 0 for the context
129 //       = 1 for the xor bit
130 static const unsigned int signContext[5][5][2] = {
131     { { 13, 1 }, // horiz=-2, vert=-2
132       { 13, 1 }, // horiz=-2, vert=-1
133       { 12, 1 }, // horiz=-2, vert= 0
134       { 11, 1 }, // horiz=-2, vert=+1
135       { 11, 1 } }, // horiz=-2, vert=+2
136     { { 13, 1 }, // horiz=-1, vert=-2
137       { 13, 1 }, // horiz=-1, vert=-1
138       { 12, 1 }, // horiz=-1, vert= 0
139       { 11, 1 }, // horiz=-1, vert=+1
140       { 11, 1 } }, // horiz=-1, vert=+2
141     { { 10, 1 }, // horiz= 0, vert=-2
142       { 10, 1 }, // horiz= 0, vert=-1
143       { 9, 0 }, // horiz= 0, vert= 0
144       { 10, 0 }, // horiz= 0, vert=+1
145       { 10, 0 } }, // horiz= 0, vert=+2
146     { { 11, 0 }, // horiz=+1, vert=-2
147       { 11, 0 }, // horiz=+1, vert=-1
148       { 12, 0 }, // horiz=+1, vert= 0
149       { 13, 0 }, // horiz=+1, vert=+1
150       { 13, 0 } }, // horiz=+1, vert=+2
151     { { 11, 0 }, // horiz=+2, vert=-2
152       { 11, 0 }, // horiz=+2, vert=-1
153       { 12, 0 }, // horiz=+2, vert= 0
154       { 13, 0 }, // horiz=+2, vert=+1
155       { 13, 0 } }, // horiz=+2, vert=+2
156 };
157 
158 //------------------------------------------------------------------------
159 
160 // constants used in the IDWT
161 #define idwtAlpha -1.586134342059924
162 #define idwtBeta -0.052980118572961
163 #define idwtGamma 0.882911075530934
164 #define idwtDelta 0.443506852043971
165 #define idwtKappa 1.230174104914001
166 #define idwtIKappa (1.0 / idwtKappa)
167 
168 // number of bits to the right of the decimal point for the fixed
169 // point arithmetic used in the IDWT
170 #define fracBits 16
171 
172 //------------------------------------------------------------------------
173 
174 // floor(x / y)
175 #define jpxFloorDiv(x, y) ((x) / (y))
176 
177 // floor(x / 2^y)
178 #define jpxFloorDivPow2(x, y) ((x) >> (y))
179 
180 // ceil(x / y)
181 #define jpxCeilDiv(x, y) (((x) + (y)-1) / (y))
182 
183 // ceil(x / 2^y)
184 #define jpxCeilDivPow2(x, y) (((x) + (1 << (y)) - 1) >> (y))
185 
186 //------------------------------------------------------------------------
187 
188 #if 1 //----- disable coverage tracking
189 
190 #    define cover(idx)
191 
192 #else //----- enable coverage tracking
193 
194 class JPXCover
195 {
196 public:
197     JPXCover(int sizeA);
198     ~JPXCover();
199     void incr(int idx);
200 
201 private:
202     int size, used;
203     int *data;
204 };
205 
JPXCover(int sizeA)206 JPXCover::JPXCover(int sizeA)
207 {
208     size = sizeA;
209     used = -1;
210     data = (int *)gmallocn(size, sizeof(int));
211     memset(data, 0, size * sizeof(int));
212 }
213 
~JPXCover()214 JPXCover::~JPXCover()
215 {
216     int i;
217 
218     printf("JPX coverage:\n");
219     for (i = 0; i <= used; ++i) {
220         printf("  %4d: %8d\n", i, data[i]);
221     }
222     gfree(data);
223 }
224 
incr(int idx)225 void JPXCover::incr(int idx)
226 {
227     if (idx < size) {
228         ++data[idx];
229         if (idx > used) {
230             used = idx;
231         }
232     }
233 }
234 
235 JPXCover jpxCover(150);
236 
237 #    define cover(idx) jpxCover.incr(idx)
238 
239 #endif //----- coverage tracking
240 
241 //------------------------------------------------------------------------
242 
JPXStream(Stream * strA)243 JPXStream::JPXStream(Stream *strA) : FilterStream(strA)
244 {
245     bufStr = new BufStream(str, 2);
246 
247     nComps = 0;
248     bpc = nullptr;
249     width = height = 0;
250     haveCS = false;
251     havePalette = false;
252     haveCompMap = false;
253     haveChannelDefn = false;
254 
255     img.tiles = nullptr;
256     bitBuf = 0;
257     bitBufLen = 0;
258     bitBufSkip = false;
259     byteCount = 0;
260 
261     curX = curY = 0;
262     curComp = 0;
263     readBufLen = 0;
264 }
265 
~JPXStream()266 JPXStream::~JPXStream()
267 {
268     close();
269     delete bufStr;
270 }
271 
reset()272 void JPXStream::reset()
273 {
274     bufStr->reset();
275     if (readBoxes()) {
276         curY = img.yOffset;
277     } else {
278         // readBoxes reported an error, so we go immediately to EOF
279         curY = img.ySize;
280     }
281     curX = img.xOffset;
282     curComp = 0;
283     readBufLen = 0;
284 }
285 
close()286 void JPXStream::close()
287 {
288     JPXTile *tile;
289     JPXTileComp *tileComp;
290     JPXResLevel *resLevel;
291     JPXPrecinct *precinct;
292     JPXSubband *subband;
293     JPXCodeBlock *cb;
294     unsigned int comp, i, k, r, pre, sb;
295 
296     gfree(bpc);
297     bpc = nullptr;
298     if (havePalette) {
299         gfree(palette.bpc);
300         gfree(palette.c);
301         havePalette = false;
302     }
303     if (haveCompMap) {
304         gfree(compMap.comp);
305         gfree(compMap.type);
306         gfree(compMap.pComp);
307         haveCompMap = false;
308     }
309     if (haveChannelDefn) {
310         gfree(channelDefn.idx);
311         gfree(channelDefn.type);
312         gfree(channelDefn.assoc);
313         haveChannelDefn = false;
314     }
315 
316     if (img.tiles) {
317         for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
318             tile = &img.tiles[i];
319             if (tile->tileComps) {
320                 for (comp = 0; comp < img.nComps; ++comp) {
321                     tileComp = &tile->tileComps[comp];
322                     gfree(tileComp->quantSteps);
323                     gfree(tileComp->data);
324                     gfree(tileComp->buf);
325                     if (tileComp->resLevels) {
326                         for (r = 0; r <= tileComp->nDecompLevels; ++r) {
327                             resLevel = &tileComp->resLevels[r];
328                             if (resLevel->precincts) {
329                                 for (pre = 0; pre < 1; ++pre) {
330                                     precinct = &resLevel->precincts[pre];
331                                     if (precinct->subbands) {
332                                         for (sb = 0; sb < (unsigned int)(r == 0 ? 1 : 3); ++sb) {
333                                             subband = &precinct->subbands[sb];
334                                             gfree(subband->inclusion);
335                                             gfree(subband->zeroBitPlane);
336                                             if (subband->cbs) {
337                                                 for (k = 0; k < subband->nXCBs * subband->nYCBs; ++k) {
338                                                     cb = &subband->cbs[k];
339                                                     gfree(cb->dataLen);
340                                                     gfree(cb->touched);
341                                                     if (cb->arithDecoder) {
342                                                         delete cb->arithDecoder;
343                                                     }
344                                                     if (cb->stats) {
345                                                         delete cb->stats;
346                                                     }
347                                                 }
348                                                 gfree(subband->cbs);
349                                             }
350                                         }
351                                         gfree(precinct->subbands);
352                                     }
353                                 }
354                                 gfree(img.tiles[i].tileComps[comp].resLevels[r].precincts);
355                             }
356                         }
357                         gfree(img.tiles[i].tileComps[comp].resLevels);
358                     }
359                 }
360                 gfree(img.tiles[i].tileComps);
361             }
362         }
363         gfree(img.tiles);
364         img.tiles = nullptr;
365     }
366     bufStr->close();
367 }
368 
getChar()369 int JPXStream::getChar()
370 {
371     int c;
372 
373     if (readBufLen < 8) {
374         fillReadBuf();
375     }
376     if (readBufLen == 8) {
377         c = readBuf & 0xff;
378         readBufLen = 0;
379     } else if (readBufLen > 8) {
380         c = (readBuf >> (readBufLen - 8)) & 0xff;
381         readBufLen -= 8;
382     } else if (readBufLen == 0) {
383         c = EOF;
384     } else {
385         c = (readBuf << (8 - readBufLen)) & 0xff;
386         readBufLen = 0;
387     }
388     return c;
389 }
390 
lookChar()391 int JPXStream::lookChar()
392 {
393     int c;
394 
395     if (readBufLen < 8) {
396         fillReadBuf();
397     }
398     if (readBufLen == 8) {
399         c = readBuf & 0xff;
400     } else if (readBufLen > 8) {
401         c = (readBuf >> (readBufLen - 8)) & 0xff;
402     } else if (readBufLen == 0) {
403         c = EOF;
404     } else {
405         c = (readBuf << (8 - readBufLen)) & 0xff;
406     }
407     return c;
408 }
409 
fillReadBuf()410 void JPXStream::fillReadBuf()
411 {
412     JPXTileComp *tileComp;
413     unsigned int tileIdx, tx, ty;
414     int pix, pixBits;
415 
416     do {
417         if (curY >= img.ySize) {
418             return;
419         }
420         tileIdx = ((curY - img.yTileOffset) / img.yTileSize) * img.nXTiles + (curX - img.xTileOffset) / img.xTileSize;
421 #if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid
422         if (img.tiles == nullptr || tileIdx >= img.nXTiles * img.nYTiles || img.tiles[tileIdx].tileComps == nullptr) {
423             error(errSyntaxError, getPos(), "Unexpected tileIdx in fillReadBuf in JPX stream");
424             return;
425         }
426         tileComp = &img.tiles[tileIdx].tileComps[curComp];
427 #else
428         tileComp = &img.tiles[tileIdx].tileComps[havePalette ? 0 : curComp];
429 #endif
430         tx = jpxCeilDiv((curX - img.xTileOffset) % img.xTileSize, tileComp->hSep);
431         ty = jpxCeilDiv((curY - img.yTileOffset) % img.yTileSize, tileComp->vSep);
432         if (unlikely(ty >= (tileComp->y1 - tileComp->y0))) {
433             error(errSyntaxError, getPos(), "Unexpected ty in fillReadBuf in JPX stream");
434             return;
435         }
436         if (unlikely(tx >= (tileComp->x1 - tileComp->x0))) {
437             error(errSyntaxError, getPos(), "Unexpected tx in fillReadBuf in JPX stream");
438             return;
439         }
440         pix = (int)tileComp->data[ty * (tileComp->x1 - tileComp->x0) + tx];
441         pixBits = tileComp->prec;
442 #if 1 //~ ignore the palette, assume the PDF ColorSpace object is valid
443         if (++curComp == img.nComps) {
444 #else
445         if (havePalette) {
446             if (pix >= 0 && pix < palette.nEntries) {
447                 pix = palette.c[pix * palette.nComps + curComp];
448             } else {
449                 pix = 0;
450             }
451             pixBits = palette.bpc[curComp];
452         }
453         if (++curComp == (unsigned int)(havePalette ? palette.nComps : img.nComps)) {
454 #endif
455             curComp = 0;
456             if (++curX == img.xSize) {
457                 curX = img.xOffset;
458                 ++curY;
459                 if (pixBits < 8) {
460                     pix <<= 8 - pixBits;
461                     pixBits = 8;
462                 }
463             }
464         }
465         if (pixBits == 8) {
466             readBuf = (readBuf << 8) | (pix & 0xff);
467         } else {
468             readBuf = (readBuf << pixBits) | (pix & ((1 << pixBits) - 1));
469         }
470         readBufLen += pixBits;
471     } while (readBufLen < 8);
472 }
473 
474 GooString *JPXStream::getPSFilter(int psLevel, const char *indent)
475 {
476     return nullptr;
477 }
478 
479 bool JPXStream::isBinary(bool last) const
480 {
481     return str->isBinary(true);
482 }
483 
484 void JPXStream::getImageParams(int *bitsPerComponent, StreamColorSpaceMode *csMode)
485 {
486     unsigned int boxType, boxLen, dataLen, csEnum;
487     unsigned int bpc1, dummy, i;
488     int csMeth, csPrec, csPrec1, dummy2;
489     StreamColorSpaceMode csMode1;
490     bool haveBPC, haveCSMode;
491 
492     csPrec = 0; // make gcc happy
493     haveBPC = haveCSMode = false;
494     bufStr->reset();
495     if (bufStr->lookChar() == 0xff) {
496         getImageParams2(bitsPerComponent, csMode);
497     } else {
498         while (readBoxHdr(&boxType, &boxLen, &dataLen)) {
499             if (boxType == 0x6a703268) { // JP2 header
500                 cover(0);
501                 // skip the superbox
502             } else if (boxType == 0x69686472) { // image header
503                 cover(1);
504                 if (readULong(&dummy) && readULong(&dummy) && readUWord(&dummy) && readUByte(&bpc1) && readUByte(&dummy) && readUByte(&dummy) && readUByte(&dummy)) {
505                     *bitsPerComponent = bpc1 + 1;
506                     haveBPC = true;
507                 }
508             } else if (boxType == 0x636F6C72) { // color specification
509                 cover(2);
510                 if (readByte(&csMeth) && readByte(&csPrec1) && readByte(&dummy2)) {
511                     if (csMeth == 1) {
512                         if (readULong(&csEnum)) {
513                             csMode1 = streamCSNone;
514                             if (csEnum == jpxCSBiLevel || csEnum == jpxCSGrayscale) {
515                                 csMode1 = streamCSDeviceGray;
516                             } else if (csEnum == jpxCSCMYK) {
517                                 csMode1 = streamCSDeviceCMYK;
518                             } else if (csEnum == jpxCSsRGB || csEnum == jpxCSCISesRGB || csEnum == jpxCSROMMRGB) {
519                                 csMode1 = streamCSDeviceRGB;
520                             }
521                             if (csMode1 != streamCSNone && (!haveCSMode || csPrec1 > csPrec)) {
522                                 *csMode = csMode1;
523                                 csPrec = csPrec1;
524                                 haveCSMode = true;
525                             }
526                             if (dataLen >= 7) {
527                                 for (i = 0; i < dataLen - 7; ++i) {
528                                     if (bufStr->getChar() == EOF)
529                                         break;
530                                 }
531                             }
532                         }
533                     } else {
534                         if (dataLen >= 3) {
535                             for (i = 0; i < dataLen - 3; ++i) {
536                                 if (bufStr->getChar() == EOF)
537                                     break;
538                             }
539                         }
540                     }
541                 }
542             } else if (boxType == 0x6A703263) { // codestream
543                 cover(3);
544                 if (!(haveBPC && haveCSMode)) {
545                     getImageParams2(bitsPerComponent, csMode);
546                 }
547                 break;
548             } else {
549                 cover(4);
550                 for (i = 0; i < dataLen; ++i) {
551                     if (unlikely(bufStr->getChar() == EOF)) {
552                         error(errSyntaxError, getPos(), "Unexpected EOF in getImageParams in JPX stream");
553                         break;
554                     }
555                 }
556             }
557         }
558     }
559     bufStr->close();
560 }
561 
562 // Get image parameters from the codestream.
563 void JPXStream::getImageParams2(int *bitsPerComponent, StreamColorSpaceMode *csMode)
564 {
565     int segType;
566     unsigned int segLen, nComps1, bpc1, dummy, i;
567 
568     while (readMarkerHdr(&segType, &segLen)) {
569         if (segType == 0x51) { // SIZ - image and tile size
570             cover(5);
571             if (readUWord(&dummy) && readULong(&dummy) && readULong(&dummy) && readULong(&dummy) && readULong(&dummy) && readULong(&dummy) && readULong(&dummy) && readULong(&dummy) && readULong(&dummy) && readUWord(&nComps1)
572                 && readUByte(&bpc1)) {
573                 *bitsPerComponent = (bpc1 & 0x7f) + 1;
574                 // if there's no color space info, take a guess
575                 if (nComps1 == 1) {
576                     *csMode = streamCSDeviceGray;
577                 } else if (nComps1 == 3) {
578                     *csMode = streamCSDeviceRGB;
579                 } else if (nComps1 == 4) {
580                     *csMode = streamCSDeviceCMYK;
581                 }
582             }
583             break;
584         } else {
585             cover(6);
586             if (segLen > 2) {
587                 for (i = 0; i < segLen - 2; ++i) {
588                     bufStr->getChar();
589                 }
590             }
591         }
592     }
593 }
594 
595 bool JPXStream::readBoxes()
596 {
597     unsigned int boxType, boxLen, dataLen;
598     unsigned int bpc1, compression, unknownColorspace, ipr;
599     unsigned int i, j;
600 
601     haveImgHdr = false;
602 
603     // initialize in case there is a parse error
604     img.xSize = img.ySize = 0;
605     img.xOffset = img.yOffset = 0;
606     img.xTileSize = img.yTileSize = 0;
607     img.xTileOffset = img.yTileOffset = 0;
608     img.nComps = 0;
609 
610     // check for a naked JPEG 2000 codestream (without the JP2/JPX
611     // wrapper) -- this appears to be a violation of the PDF spec, but
612     // Acrobat allows it
613     if (bufStr->lookChar() == 0xff) {
614         cover(7);
615         error(errSyntaxWarning, getPos(), "Naked JPEG 2000 codestream, missing JP2/JPX wrapper");
616         if (!readCodestream(0)) {
617             return false;
618         }
619         nComps = img.nComps;
620         bpc = (unsigned int *)gmallocn(nComps, sizeof(unsigned int));
621         for (i = 0; i < nComps; ++i) {
622             bpc[i] = img.tiles[0].tileComps[i].prec;
623         }
624         width = img.xSize - img.xOffset;
625         height = img.ySize - img.yOffset;
626         return true;
627     }
628 
629     while (readBoxHdr(&boxType, &boxLen, &dataLen)) {
630         switch (boxType) {
631         case 0x6a703268: // JP2 header
632             // this is a grouping box ('superbox') which has no real
633             // contents and doesn't appear to be used consistently, i.e.,
634             // some things which should be subboxes of the JP2 header box
635             // show up outside of it - so we simply ignore the JP2 header
636             // box
637             cover(8);
638             break;
639         case 0x69686472: // image header
640             cover(9);
641             if (!readULong(&height) || !readULong(&width) || !readUWord(&nComps) || !readUByte(&bpc1) || !readUByte(&compression) || !readUByte(&unknownColorspace) || !readUByte(&ipr)) {
642                 error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream");
643                 return false;
644             }
645             if (compression != 7) {
646                 error(errSyntaxError, getPos(), "Unknown compression type in JPX stream");
647                 return false;
648             }
649             bpc = (unsigned int *)gmallocn(nComps, sizeof(unsigned int));
650             for (i = 0; i < nComps; ++i) {
651                 bpc[i] = bpc1;
652             }
653             haveImgHdr = true;
654             break;
655         case 0x62706363: // bits per component
656             cover(10);
657             if (!haveImgHdr) {
658                 error(errSyntaxError, getPos(), "Found bits per component box before image header box in JPX stream");
659                 return false;
660             }
661             if (dataLen != nComps) {
662                 error(errSyntaxError, getPos(), "Invalid bits per component box in JPX stream");
663                 return false;
664             }
665             for (i = 0; i < nComps; ++i) {
666                 if (!readUByte(&bpc[i])) {
667                     error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream");
668                     return false;
669                 }
670             }
671             break;
672         case 0x636F6C72: // color specification
673             cover(11);
674             if (!readColorSpecBox(dataLen)) {
675                 return false;
676             }
677             break;
678         case 0x70636c72: // palette
679             cover(12);
680             if (!readUWord(&palette.nEntries) || !readUByte(&palette.nComps)) {
681                 error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream");
682                 return false;
683             }
684             palette.bpc = (unsigned int *)gmallocn(palette.nComps, sizeof(unsigned int));
685             palette.c = (int *)gmallocn(palette.nEntries * palette.nComps, sizeof(int));
686             for (i = 0; i < palette.nComps; ++i) {
687                 if (!readUByte(&palette.bpc[i])) {
688                     error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream");
689                     return false;
690                 }
691                 ++palette.bpc[i];
692             }
693             for (i = 0; i < palette.nEntries; ++i) {
694                 for (j = 0; j < palette.nComps; ++j) {
695                     if (!readNBytes(((palette.bpc[j] & 0x7f) + 7) >> 3, (palette.bpc[j] & 0x80) ? true : false, &palette.c[i * palette.nComps + j])) {
696                         error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream");
697                         return false;
698                     }
699                 }
700             }
701             havePalette = true;
702             break;
703         case 0x636d6170: // component mapping
704             cover(13);
705             compMap.nChannels = dataLen / 4;
706             compMap.comp = (unsigned int *)gmallocn(compMap.nChannels, sizeof(unsigned int));
707             compMap.type = (unsigned int *)gmallocn(compMap.nChannels, sizeof(unsigned int));
708             compMap.pComp = (unsigned int *)gmallocn(compMap.nChannels, sizeof(unsigned int));
709             for (i = 0; i < compMap.nChannels; ++i) {
710                 if (!readUWord(&compMap.comp[i]) || !readUByte(&compMap.type[i]) || !readUByte(&compMap.pComp[i])) {
711                     error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream");
712                     return false;
713                 }
714             }
715             haveCompMap = true;
716             break;
717         case 0x63646566: // channel definition
718             cover(14);
719             if (!readUWord(&channelDefn.nChannels)) {
720                 error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream");
721                 return false;
722             }
723             channelDefn.idx = (unsigned int *)gmallocn(channelDefn.nChannels, sizeof(unsigned int));
724             channelDefn.type = (unsigned int *)gmallocn(channelDefn.nChannels, sizeof(unsigned int));
725             channelDefn.assoc = (unsigned int *)gmallocn(channelDefn.nChannels, sizeof(unsigned int));
726             for (i = 0; i < channelDefn.nChannels; ++i) {
727                 if (!readUWord(&channelDefn.idx[i]) || !readUWord(&channelDefn.type[i]) || !readUWord(&channelDefn.assoc[i])) {
728                     error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream");
729                     return false;
730                 }
731             }
732             haveChannelDefn = true;
733             break;
734         case 0x6A703263: // contiguous codestream
735             cover(15);
736             if (!bpc) {
737                 error(errSyntaxError, getPos(), "JPX stream is missing the image header box");
738             }
739             if (!haveCS) {
740                 error(errSyntaxError, getPos(), "JPX stream has no supported color spec");
741             }
742             if (!readCodestream(dataLen)) {
743                 return false;
744             }
745             break;
746         default:
747             cover(16);
748             for (i = 0; i < dataLen; ++i) {
749                 if (bufStr->getChar() == EOF) {
750                     error(errSyntaxError, getPos(), "Unexpected EOF in JPX stream");
751                     return false;
752                 }
753             }
754             break;
755         }
756     }
757     return true;
758 }
759 
760 bool JPXStream::readColorSpecBox(unsigned int dataLen)
761 {
762     JPXColorSpec newCS;
763     unsigned int csApprox, csEnum;
764     unsigned int i;
765     bool ok;
766 
767     ok = false;
768     if (!readUByte(&newCS.meth) || !readByte(&newCS.prec) || !readUByte(&csApprox)) {
769         goto err;
770     }
771     switch (newCS.meth) {
772     case 1: // enumerated colorspace
773         cover(17);
774         if (!readULong(&csEnum)) {
775             goto err;
776         }
777         newCS.enumerated.type = (JPXColorSpaceType)csEnum;
778         switch (newCS.enumerated.type) {
779         case jpxCSBiLevel:
780             ok = true;
781             break;
782         case jpxCSYCbCr1:
783             ok = true;
784             break;
785         case jpxCSYCbCr2:
786             ok = true;
787             break;
788         case jpxCSYCBCr3:
789             ok = true;
790             break;
791         case jpxCSPhotoYCC:
792             ok = true;
793             break;
794         case jpxCSCMY:
795             ok = true;
796             break;
797         case jpxCSCMYK:
798             ok = true;
799             break;
800         case jpxCSYCCK:
801             ok = true;
802             break;
803         case jpxCSCIELab:
804             if (dataLen == 7 + 7 * 4) {
805                 if (!readULong(&newCS.enumerated.cieLab.rl) || !readULong(&newCS.enumerated.cieLab.ol) || !readULong(&newCS.enumerated.cieLab.ra) || !readULong(&newCS.enumerated.cieLab.oa) || !readULong(&newCS.enumerated.cieLab.rb)
806                     || !readULong(&newCS.enumerated.cieLab.ob) || !readULong(&newCS.enumerated.cieLab.il)) {
807                     goto err;
808                 }
809             } else if (dataLen == 7) {
810                 //~ this assumes the 8-bit case
811                 cover(92);
812                 newCS.enumerated.cieLab.rl = 100;
813                 newCS.enumerated.cieLab.ol = 0;
814                 newCS.enumerated.cieLab.ra = 255;
815                 newCS.enumerated.cieLab.oa = 128;
816                 newCS.enumerated.cieLab.rb = 255;
817                 newCS.enumerated.cieLab.ob = 96;
818                 newCS.enumerated.cieLab.il = 0x00443530;
819             } else {
820                 goto err;
821             }
822             ok = true;
823             break;
824         case jpxCSsRGB:
825             ok = true;
826             break;
827         case jpxCSGrayscale:
828             ok = true;
829             break;
830         case jpxCSBiLevel2:
831             ok = true;
832             break;
833         case jpxCSCIEJab:
834             // not allowed in PDF
835             goto err;
836         case jpxCSCISesRGB:
837             ok = true;
838             break;
839         case jpxCSROMMRGB:
840             ok = true;
841             break;
842         case jpxCSsRGBYCbCr:
843             ok = true;
844             break;
845         case jpxCSYPbPr1125:
846             ok = true;
847             break;
848         case jpxCSYPbPr1250:
849             ok = true;
850             break;
851         default:
852             goto err;
853         }
854         break;
855     case 2: // restricted ICC profile
856     case 3: // any ICC profile (JPX)
857     case 4: // vendor color (JPX)
858         cover(18);
859         for (i = 0; i < dataLen - 3; ++i) {
860             if (bufStr->getChar() == EOF) {
861                 goto err;
862             }
863         }
864         break;
865     }
866 
867     if (ok && (!haveCS || newCS.prec > cs.prec)) {
868         cs = newCS;
869         haveCS = true;
870     }
871 
872     return true;
873 
874 err:
875     error(errSyntaxError, getPos(), "Error in JPX color spec");
876     return false;
877 }
878 
879 bool JPXStream::readCodestream(unsigned int len)
880 {
881     JPXTile *tile;
882     JPXTileComp *tileComp;
883     int segType;
884     bool haveSIZ, haveCOD, haveQCD, haveSOT;
885     unsigned int precinctSize, style, nDecompLevels;
886     unsigned int segLen, capabilities, comp, i, j, r;
887 
888     //----- main header
889     haveSIZ = haveCOD = haveQCD = haveSOT = false;
890     do {
891         if (!readMarkerHdr(&segType, &segLen)) {
892             error(errSyntaxError, getPos(), "Error in JPX codestream");
893             return false;
894         }
895         switch (segType) {
896         case 0x4f: // SOC - start of codestream
897             // marker only
898             cover(19);
899             break;
900         case 0x51: // SIZ - image and tile size
901             cover(20);
902             if (haveSIZ) {
903                 error(errSyntaxError, getPos(), "Duplicate SIZ marker segment in JPX stream");
904                 return false;
905             }
906             if (!readUWord(&capabilities) || !readULong(&img.xSize) || !readULong(&img.ySize) || !readULong(&img.xOffset) || !readULong(&img.yOffset) || !readULong(&img.xTileSize) || !readULong(&img.yTileSize)
907                 || !readULong(&img.xTileOffset) || !readULong(&img.yTileOffset) || !readUWord(&img.nComps)) {
908                 error(errSyntaxError, getPos(), "Error in JPX SIZ marker segment");
909                 return false;
910             }
911             if (haveImgHdr && img.nComps != nComps) {
912                 error(errSyntaxError, getPos(), "Different number of components in JPX SIZ marker segment");
913                 return false;
914             }
915             if (img.xSize == 0 || img.ySize == 0 || img.xOffset >= img.xSize || img.yOffset >= img.ySize || img.xTileSize == 0 || img.yTileSize == 0 || img.xTileOffset > img.xOffset || img.yTileOffset > img.yOffset
916                 || img.xTileSize + img.xTileOffset <= img.xOffset || img.yTileSize + img.yTileOffset <= img.yOffset) {
917                 error(errSyntaxError, getPos(), "Error in JPX SIZ marker segment");
918                 return false;
919             }
920             img.nXTiles = (img.xSize - img.xTileOffset + img.xTileSize - 1) / img.xTileSize;
921             img.nYTiles = (img.ySize - img.yTileOffset + img.yTileSize - 1) / img.yTileSize;
922             // check for overflow before allocating memory
923             if (img.nXTiles <= 0 || img.nYTiles <= 0 || img.nXTiles >= 65535 / img.nYTiles) {
924                 error(errSyntaxError, getPos(), "Bad tile count in JPX SIZ marker segment");
925                 return false;
926             }
927             img.tiles = (JPXTile *)gmallocn(img.nXTiles * img.nYTiles, sizeof(JPXTile));
928             for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
929                 img.tiles[i].init = false;
930                 img.tiles[i].tileComps = (JPXTileComp *)gmallocn(img.nComps, sizeof(JPXTileComp));
931                 for (comp = 0; comp < img.nComps; ++comp) {
932                     img.tiles[i].tileComps[comp].quantSteps = nullptr;
933                     img.tiles[i].tileComps[comp].data = nullptr;
934                     img.tiles[i].tileComps[comp].buf = nullptr;
935                     img.tiles[i].tileComps[comp].resLevels = nullptr;
936                 }
937             }
938             for (comp = 0; comp < img.nComps; ++comp) {
939                 if (!readUByte(&img.tiles[0].tileComps[comp].prec) || !readUByte(&img.tiles[0].tileComps[comp].hSep) || !readUByte(&img.tiles[0].tileComps[comp].vSep)) {
940                     error(errSyntaxError, getPos(), "Error in JPX SIZ marker segment");
941                     return false;
942                 }
943                 if (img.tiles[0].tileComps[comp].hSep == 0 || img.tiles[0].tileComps[comp].vSep == 0) {
944                     error(errSyntaxError, getPos(), "Error in JPX SIZ marker segment");
945                     return false;
946                 }
947                 img.tiles[0].tileComps[comp].sgned = (img.tiles[0].tileComps[comp].prec & 0x80) ? true : false;
948                 img.tiles[0].tileComps[comp].prec = (img.tiles[0].tileComps[comp].prec & 0x7f) + 1;
949                 for (i = 1; i < img.nXTiles * img.nYTiles; ++i) {
950                     img.tiles[i].tileComps[comp] = img.tiles[0].tileComps[comp];
951                 }
952             }
953             haveSIZ = true;
954             break;
955         case 0x52: // COD - coding style default
956             cover(21);
957             if (!haveSIZ) {
958                 error(errSyntaxError, getPos(), "JPX COD marker segment before SIZ segment");
959                 return false;
960             }
961             if (img.tiles == nullptr || img.nXTiles * img.nYTiles == 0 || img.tiles[0].tileComps == nullptr) {
962                 error(errSyntaxError, getPos(), "Error in JPX COD marker segment");
963                 return false;
964             }
965             if (!readUByte(&img.tiles[0].tileComps[0].style) || !readUByte(&img.tiles[0].progOrder) || !readUWord(&img.tiles[0].nLayers) || !readUByte(&img.tiles[0].multiComp) || !readUByte(&nDecompLevels)
966                 || !readUByte(&img.tiles[0].tileComps[0].codeBlockW) || !readUByte(&img.tiles[0].tileComps[0].codeBlockH) || !readUByte(&img.tiles[0].tileComps[0].codeBlockStyle) || !readUByte(&img.tiles[0].tileComps[0].transform)) {
967                 error(errSyntaxError, getPos(), "Error in JPX COD marker segment");
968                 return false;
969             }
970             if (nDecompLevels > 32 || img.tiles[0].tileComps[0].codeBlockW > 8 || img.tiles[0].tileComps[0].codeBlockH > 8) {
971                 error(errSyntaxError, getPos(), "Error in JPX COD marker segment");
972                 return false;
973             }
974             img.tiles[0].tileComps[0].nDecompLevels = nDecompLevels;
975             img.tiles[0].tileComps[0].codeBlockW += 2;
976             img.tiles[0].tileComps[0].codeBlockH += 2;
977             for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
978                 if (i != 0) {
979                     img.tiles[i].progOrder = img.tiles[0].progOrder;
980                     img.tiles[i].nLayers = img.tiles[0].nLayers;
981                     img.tiles[i].multiComp = img.tiles[0].multiComp;
982                 }
983                 for (comp = 0; comp < img.nComps; ++comp) {
984                     if (!(i == 0 && comp == 0)) {
985                         img.tiles[i].tileComps[comp].style = img.tiles[0].tileComps[0].style;
986                         img.tiles[i].tileComps[comp].nDecompLevels = img.tiles[0].tileComps[0].nDecompLevels;
987                         img.tiles[i].tileComps[comp].codeBlockW = img.tiles[0].tileComps[0].codeBlockW;
988                         img.tiles[i].tileComps[comp].codeBlockH = img.tiles[0].tileComps[0].codeBlockH;
989                         img.tiles[i].tileComps[comp].codeBlockStyle = img.tiles[0].tileComps[0].codeBlockStyle;
990                         img.tiles[i].tileComps[comp].transform = img.tiles[0].tileComps[0].transform;
991                     }
992                     img.tiles[i].tileComps[comp].resLevels = (JPXResLevel *)gmallocn_checkoverflow((img.tiles[i].tileComps[comp].nDecompLevels + 1), sizeof(JPXResLevel));
993                     if (img.tiles[i].tileComps[comp].resLevels == nullptr) {
994                         error(errSyntaxError, getPos(), "Error in JPX COD marker segment");
995                         return false;
996                     }
997                     for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) {
998                         img.tiles[i].tileComps[comp].resLevels[r].precincts = nullptr;
999                     }
1000                 }
1001             }
1002             for (r = 0; r <= img.tiles[0].tileComps[0].nDecompLevels; ++r) {
1003                 if (img.tiles[0].tileComps[0].style & 0x01) {
1004                     cover(91);
1005                     if (!readUByte(&precinctSize)) {
1006                         error(errSyntaxError, getPos(), "Error in JPX COD marker segment");
1007                         return false;
1008                     }
1009                     img.tiles[0].tileComps[0].resLevels[r].precinctWidth = precinctSize & 0x0f;
1010                     img.tiles[0].tileComps[0].resLevels[r].precinctHeight = (precinctSize >> 4) & 0x0f;
1011                 } else {
1012                     img.tiles[0].tileComps[0].resLevels[r].precinctWidth = 15;
1013                     img.tiles[0].tileComps[0].resLevels[r].precinctHeight = 15;
1014                 }
1015             }
1016             for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
1017                 for (comp = 0; comp < img.nComps; ++comp) {
1018                     if (!(i == 0 && comp == 0)) {
1019                         for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) {
1020                             img.tiles[i].tileComps[comp].resLevels[r].precinctWidth = img.tiles[0].tileComps[0].resLevels[r].precinctWidth;
1021                             img.tiles[i].tileComps[comp].resLevels[r].precinctHeight = img.tiles[0].tileComps[0].resLevels[r].precinctHeight;
1022                         }
1023                     }
1024                 }
1025             }
1026             haveCOD = true;
1027             break;
1028         case 0x53: // COC - coding style component
1029             cover(22);
1030             if (!haveCOD) {
1031                 error(errSyntaxError, getPos(), "JPX COC marker segment before COD segment");
1032                 return false;
1033             }
1034             if ((img.nComps > 256 && !readUWord(&comp)) || (img.nComps <= 256 && !readUByte(&comp)) || comp >= img.nComps || !readUByte(&style) || !readUByte(&nDecompLevels) || !readUByte(&img.tiles[0].tileComps[comp].codeBlockW)
1035                 || !readUByte(&img.tiles[0].tileComps[comp].codeBlockH) || !readUByte(&img.tiles[0].tileComps[comp].codeBlockStyle) || !readUByte(&img.tiles[0].tileComps[comp].transform)) {
1036                 error(errSyntaxError, getPos(), "Error in JPX COC marker segment");
1037                 return false;
1038             }
1039             if (nDecompLevels > 32 || img.tiles[0].tileComps[comp].codeBlockW > 8 || img.tiles[0].tileComps[comp].codeBlockH > 8) {
1040                 error(errSyntaxError, getPos(), "Error in JPX COC marker segment");
1041                 return false;
1042             }
1043             img.tiles[0].tileComps[comp].nDecompLevels = nDecompLevels;
1044             img.tiles[0].tileComps[comp].style = (img.tiles[0].tileComps[comp].style & ~1) | (style & 1);
1045             img.tiles[0].tileComps[comp].codeBlockW += 2;
1046             img.tiles[0].tileComps[comp].codeBlockH += 2;
1047             for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
1048                 if (i != 0) {
1049                     img.tiles[i].tileComps[comp].style = img.tiles[0].tileComps[comp].style;
1050                     img.tiles[i].tileComps[comp].nDecompLevels = img.tiles[0].tileComps[comp].nDecompLevels;
1051                     img.tiles[i].tileComps[comp].codeBlockW = img.tiles[0].tileComps[comp].codeBlockW;
1052                     img.tiles[i].tileComps[comp].codeBlockH = img.tiles[0].tileComps[comp].codeBlockH;
1053                     img.tiles[i].tileComps[comp].codeBlockStyle = img.tiles[0].tileComps[comp].codeBlockStyle;
1054                     img.tiles[i].tileComps[comp].transform = img.tiles[0].tileComps[comp].transform;
1055                 }
1056                 img.tiles[i].tileComps[comp].resLevels = (JPXResLevel *)greallocn(img.tiles[i].tileComps[comp].resLevels, (img.tiles[i].tileComps[comp].nDecompLevels + 1), sizeof(JPXResLevel));
1057                 for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) {
1058                     img.tiles[i].tileComps[comp].resLevels[r].precincts = nullptr;
1059                 }
1060             }
1061             for (r = 0; r <= img.tiles[0].tileComps[comp].nDecompLevels; ++r) {
1062                 if (img.tiles[0].tileComps[comp].style & 0x01) {
1063                     if (!readUByte(&precinctSize)) {
1064                         error(errSyntaxError, getPos(), "Error in JPX COD marker segment");
1065                         return false;
1066                     }
1067                     img.tiles[0].tileComps[comp].resLevels[r].precinctWidth = precinctSize & 0x0f;
1068                     img.tiles[0].tileComps[comp].resLevels[r].precinctHeight = (precinctSize >> 4) & 0x0f;
1069                 } else {
1070                     img.tiles[0].tileComps[comp].resLevels[r].precinctWidth = 15;
1071                     img.tiles[0].tileComps[comp].resLevels[r].precinctHeight = 15;
1072                 }
1073             }
1074             for (i = 1; i < img.nXTiles * img.nYTiles; ++i) {
1075                 for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) {
1076                     img.tiles[i].tileComps[comp].resLevels[r].precinctWidth = img.tiles[0].tileComps[comp].resLevels[r].precinctWidth;
1077                     img.tiles[i].tileComps[comp].resLevels[r].precinctHeight = img.tiles[0].tileComps[comp].resLevels[r].precinctHeight;
1078                 }
1079             }
1080             break;
1081         case 0x5c: // QCD - quantization default
1082             cover(23);
1083             if (!haveSIZ) {
1084                 error(errSyntaxError, getPos(), "JPX QCD marker segment before SIZ segment");
1085                 return false;
1086             }
1087             if (!readUByte(&img.tiles[0].tileComps[0].quantStyle)) {
1088                 error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
1089                 return false;
1090             }
1091             if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x00) {
1092                 if (segLen <= 3) {
1093                     error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
1094                     return false;
1095                 }
1096                 img.tiles[0].tileComps[0].nQuantSteps = segLen - 3;
1097                 img.tiles[0].tileComps[0].quantSteps = (unsigned int *)greallocn(img.tiles[0].tileComps[0].quantSteps, img.tiles[0].tileComps[0].nQuantSteps, sizeof(unsigned int));
1098                 for (i = 0; i < img.tiles[0].tileComps[0].nQuantSteps; ++i) {
1099                     if (!readUByte(&img.tiles[0].tileComps[0].quantSteps[i])) {
1100                         error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
1101                         return false;
1102                     }
1103                 }
1104             } else if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x01) {
1105                 img.tiles[0].tileComps[0].nQuantSteps = 1;
1106                 img.tiles[0].tileComps[0].quantSteps = (unsigned int *)greallocn(img.tiles[0].tileComps[0].quantSteps, img.tiles[0].tileComps[0].nQuantSteps, sizeof(unsigned int));
1107                 if (!readUWord(&img.tiles[0].tileComps[0].quantSteps[0])) {
1108                     error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
1109                     return false;
1110                 }
1111             } else if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x02) {
1112                 if (segLen < 5) {
1113                     error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
1114                     return false;
1115                 }
1116                 img.tiles[0].tileComps[0].nQuantSteps = (segLen - 3) / 2;
1117                 img.tiles[0].tileComps[0].quantSteps = (unsigned int *)greallocn(img.tiles[0].tileComps[0].quantSteps, img.tiles[0].tileComps[0].nQuantSteps, sizeof(unsigned int));
1118                 for (i = 0; i < img.tiles[0].tileComps[0].nQuantSteps; ++i) {
1119                     if (!readUWord(&img.tiles[0].tileComps[0].quantSteps[i])) {
1120                         error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
1121                         return false;
1122                     }
1123                 }
1124             } else {
1125                 error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
1126                 return false;
1127             }
1128             for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
1129                 for (comp = 0; comp < img.nComps; ++comp) {
1130                     if (!(i == 0 && comp == 0)) {
1131                         img.tiles[i].tileComps[comp].quantStyle = img.tiles[0].tileComps[0].quantStyle;
1132                         img.tiles[i].tileComps[comp].nQuantSteps = img.tiles[0].tileComps[0].nQuantSteps;
1133                         img.tiles[i].tileComps[comp].quantSteps = (unsigned int *)greallocn(img.tiles[i].tileComps[comp].quantSteps, img.tiles[0].tileComps[0].nQuantSteps, sizeof(unsigned int));
1134                         for (j = 0; j < img.tiles[0].tileComps[0].nQuantSteps; ++j) {
1135                             img.tiles[i].tileComps[comp].quantSteps[j] = img.tiles[0].tileComps[0].quantSteps[j];
1136                         }
1137                     }
1138                 }
1139             }
1140             haveQCD = true;
1141             break;
1142         case 0x5d: // QCC - quantization component
1143             cover(24);
1144             if (!haveQCD) {
1145                 error(errSyntaxError, getPos(), "JPX QCC marker segment before QCD segment");
1146                 return false;
1147             }
1148             if ((img.nComps > 256 && !readUWord(&comp)) || (img.nComps <= 256 && !readUByte(&comp)) || comp >= img.nComps || !readUByte(&img.tiles[0].tileComps[comp].quantStyle)) {
1149                 error(errSyntaxError, getPos(), "Error in JPX QCC marker segment");
1150                 return false;
1151             }
1152             if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x00) {
1153                 if (segLen <= (img.nComps > 256 ? 5U : 4U)) {
1154                     error(errSyntaxError, getPos(), "Error in JPX QCC marker segment");
1155                     return false;
1156                 }
1157                 img.tiles[0].tileComps[comp].nQuantSteps = segLen - (img.nComps > 256 ? 5 : 4);
1158                 img.tiles[0].tileComps[comp].quantSteps = (unsigned int *)greallocn(img.tiles[0].tileComps[comp].quantSteps, img.tiles[0].tileComps[comp].nQuantSteps, sizeof(unsigned int));
1159                 for (i = 0; i < img.tiles[0].tileComps[comp].nQuantSteps; ++i) {
1160                     if (!readUByte(&img.tiles[0].tileComps[comp].quantSteps[i])) {
1161                         error(errSyntaxError, getPos(), "Error in JPX QCC marker segment");
1162                         return false;
1163                     }
1164                 }
1165             } else if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x01) {
1166                 img.tiles[0].tileComps[comp].nQuantSteps = 1;
1167                 img.tiles[0].tileComps[comp].quantSteps = (unsigned int *)greallocn(img.tiles[0].tileComps[comp].quantSteps, img.tiles[0].tileComps[comp].nQuantSteps, sizeof(unsigned int));
1168                 if (!readUWord(&img.tiles[0].tileComps[comp].quantSteps[0])) {
1169                     error(errSyntaxError, getPos(), "Error in JPX QCC marker segment");
1170                     return false;
1171                 }
1172             } else if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x02) {
1173                 if (segLen < (img.nComps > 256 ? 5U : 4U) + 2) {
1174                     error(errSyntaxError, getPos(), "Error in JPX QCC marker segment");
1175                     return false;
1176                 }
1177                 img.tiles[0].tileComps[comp].nQuantSteps = (segLen - (img.nComps > 256 ? 5 : 4)) / 2;
1178                 img.tiles[0].tileComps[comp].quantSteps = (unsigned int *)greallocn(img.tiles[0].tileComps[comp].quantSteps, img.tiles[0].tileComps[comp].nQuantSteps, sizeof(unsigned int));
1179                 for (i = 0; i < img.tiles[0].tileComps[comp].nQuantSteps; ++i) {
1180                     if (!readUWord(&img.tiles[0].tileComps[comp].quantSteps[i])) {
1181                         error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
1182                         return false;
1183                     }
1184                 }
1185             } else {
1186                 error(errSyntaxError, getPos(), "Error in JPX QCC marker segment");
1187                 return false;
1188             }
1189             for (i = 1; i < img.nXTiles * img.nYTiles; ++i) {
1190                 img.tiles[i].tileComps[comp].quantStyle = img.tiles[0].tileComps[comp].quantStyle;
1191                 img.tiles[i].tileComps[comp].nQuantSteps = img.tiles[0].tileComps[comp].nQuantSteps;
1192                 img.tiles[i].tileComps[comp].quantSteps = (unsigned int *)greallocn(img.tiles[i].tileComps[comp].quantSteps, img.tiles[0].tileComps[comp].nQuantSteps, sizeof(unsigned int));
1193                 for (j = 0; j < img.tiles[0].tileComps[comp].nQuantSteps; ++j) {
1194                     img.tiles[i].tileComps[comp].quantSteps[j] = img.tiles[0].tileComps[comp].quantSteps[j];
1195                 }
1196             }
1197             break;
1198         case 0x5e: // RGN - region of interest
1199             cover(25);
1200 #if 1 //~ ROI is unimplemented
1201             error(errUnimplemented, -1, "got a JPX RGN segment");
1202             for (i = 0; i < segLen - 2; ++i) {
1203                 if (bufStr->getChar() == EOF) {
1204                     error(errSyntaxError, getPos(), "Error in JPX RGN marker segment");
1205                     return false;
1206                 }
1207             }
1208 #else
1209             if ((img.nComps > 256 && !readUWord(&comp)) || (img.nComps <= 256 && !readUByte(&comp)) || comp >= img.nComps || !readUByte(&compInfo[comp].defROI.style) || !readUByte(&compInfo[comp].defROI.shift)) {
1210                 error(errSyntaxError, getPos(), "Error in JPX RGN marker segment");
1211                 return false;
1212             }
1213 #endif
1214             break;
1215         case 0x5f: // POC - progression order change
1216             cover(26);
1217 #if 1 //~ progression order changes are unimplemented
1218             error(errUnimplemented, -1, "got a JPX POC segment");
1219             for (i = 0; i < segLen - 2; ++i) {
1220                 if (bufStr->getChar() == EOF) {
1221                     error(errSyntaxError, getPos(), "Error in JPX POC marker segment");
1222                     return false;
1223                 }
1224             }
1225 #else
1226             nProgs = (segLen - 2) / (img.nComps > 256 ? 9 : 7);
1227             progs = (JPXProgOrder *)gmallocn(nProgs, sizeof(JPXProgOrder));
1228             for (i = 0; i < nProgs; ++i) {
1229                 if (!readUByte(&progs[i].startRes) || !(img.nComps > 256 && readUWord(&progs[i].startComp)) || !(img.nComps <= 256 && readUByte(&progs[i].startComp)) || !readUWord(&progs[i].endLayer) || !readUByte(&progs[i].endRes)
1230                     || !(img.nComps > 256 && readUWord(&progs[i].endComp)) || !(img.nComps <= 256 && readUByte(&progs[i].endComp)) || !readUByte(&progs[i].progOrder)) {
1231                     error(errSyntaxError, getPos(), "Error in JPX POC marker segment");
1232                     return false;
1233                 }
1234             }
1235 #endif
1236             break;
1237         case 0x60: // PPM - packed packet headers, main header
1238             cover(27);
1239 #if 1 //~ packed packet headers are unimplemented
1240             error(errUnimplemented, -1, "Got a JPX PPM segment");
1241             for (i = 0; i < segLen - 2; ++i) {
1242                 if (bufStr->getChar() == EOF) {
1243                     error(errSyntaxError, getPos(), "Error in JPX PPM marker segment");
1244                     return false;
1245                 }
1246             }
1247 #endif
1248             break;
1249         case 0x55: // TLM - tile-part lengths
1250             // skipped
1251             cover(28);
1252             for (i = 0; i < segLen - 2; ++i) {
1253                 if (bufStr->getChar() == EOF) {
1254                     error(errSyntaxError, getPos(), "Error in JPX TLM marker segment");
1255                     return false;
1256                 }
1257             }
1258             break;
1259         case 0x57: // PLM - packet length, main header
1260             // skipped
1261             cover(29);
1262             for (i = 0; i < segLen - 2; ++i) {
1263                 if (bufStr->getChar() == EOF) {
1264                     error(errSyntaxError, getPos(), "Error in JPX PLM marker segment");
1265                     return false;
1266                 }
1267             }
1268             break;
1269         case 0x63: // CRG - component registration
1270             // skipped
1271             cover(30);
1272             for (i = 0; i < segLen - 2; ++i) {
1273                 if (bufStr->getChar() == EOF) {
1274                     error(errSyntaxError, getPos(), "Error in JPX CRG marker segment");
1275                     return false;
1276                 }
1277             }
1278             break;
1279         case 0x64: // COM - comment
1280             // skipped
1281             cover(31);
1282             for (i = 0; i < segLen - 2; ++i) {
1283                 if (bufStr->getChar() == EOF) {
1284                     error(errSyntaxError, getPos(), "Error in JPX COM marker segment");
1285                     return false;
1286                 }
1287             }
1288             break;
1289         case 0x90: // SOT - start of tile
1290             cover(32);
1291             haveSOT = true;
1292             break;
1293         default:
1294             cover(33);
1295             error(errSyntaxError, getPos(), "Unknown marker segment {0:02x} in JPX stream", segType);
1296             for (i = 0; i < segLen - 2; ++i) {
1297                 if (bufStr->getChar() == EOF) {
1298                     break;
1299                 }
1300             }
1301             break;
1302         }
1303     } while (!haveSOT);
1304 
1305     if (!haveSIZ) {
1306         error(errSyntaxError, getPos(), "Missing SIZ marker segment in JPX stream");
1307         return false;
1308     }
1309     if (!haveCOD) {
1310         error(errSyntaxError, getPos(), "Missing COD marker segment in JPX stream");
1311         return false;
1312     }
1313     if (!haveQCD) {
1314         error(errSyntaxError, getPos(), "Missing QCD marker segment in JPX stream");
1315         return false;
1316     }
1317 
1318     //----- read the tile-parts
1319     while (1) {
1320         if (!readTilePart()) {
1321             return false;
1322         }
1323         if (!readMarkerHdr(&segType, &segLen)) {
1324             error(errSyntaxError, getPos(), "Error in JPX codestream");
1325             return false;
1326         }
1327         if (segType != 0x90) { // SOT - start of tile
1328             break;
1329         }
1330     }
1331 
1332     if (segType != 0xd9) { // EOC - end of codestream
1333         error(errSyntaxError, getPos(), "Missing EOC marker in JPX codestream");
1334         return false;
1335     }
1336 
1337     //----- finish decoding the image
1338     for (i = 0; i < img.nXTiles * img.nYTiles; ++i) {
1339         tile = &img.tiles[i];
1340         if (!tile->init) {
1341             error(errSyntaxError, getPos(), "Uninitialized tile in JPX codestream");
1342             return false;
1343         }
1344         for (comp = 0; comp < img.nComps; ++comp) {
1345             tileComp = &tile->tileComps[comp];
1346             inverseTransform(tileComp);
1347         }
1348         if (!inverseMultiCompAndDC(tile)) {
1349             return false;
1350         }
1351     }
1352 
1353     //~ can free memory below tileComps here, and also tileComp.buf
1354 
1355     return true;
1356 }
1357 
1358 bool JPXStream::readTilePart()
1359 {
1360     JPXTile *tile;
1361     JPXTileComp *tileComp;
1362     JPXResLevel *resLevel;
1363     JPXPrecinct *precinct;
1364     JPXSubband *subband;
1365     JPXCodeBlock *cb;
1366     int *sbCoeffs;
1367     bool haveSOD;
1368     unsigned int tileIdx, tilePartLen, tilePartIdx, nTileParts;
1369     bool tilePartToEOC;
1370     unsigned int precinctSize, style, nDecompLevels;
1371     unsigned int n, nSBs, nx, ny, sbx0, sby0, comp, segLen;
1372     unsigned int i, j, k, cbX, cbY, r, pre, sb, cbi, cbj;
1373     int segType, level;
1374 
1375     // process the SOT marker segment
1376     if (!readUWord(&tileIdx) || !readULong(&tilePartLen) || !readUByte(&tilePartIdx) || !readUByte(&nTileParts)) {
1377         error(errSyntaxError, getPos(), "Error in JPX SOT marker segment");
1378         return false;
1379     }
1380 
1381     if (tileIdx >= img.nXTiles * img.nYTiles || (tilePartIdx > 0 && !img.tiles[tileIdx].init)) {
1382         error(errSyntaxError, getPos(), "Weird tile index in JPX stream");
1383         return false;
1384     }
1385 
1386     tilePartToEOC = tilePartLen == 0;
1387     tilePartLen -= 12; // subtract size of SOT segment
1388 
1389     haveSOD = false;
1390     do {
1391         if (!readMarkerHdr(&segType, &segLen)) {
1392             error(errSyntaxError, getPos(), "Error in JPX tile-part codestream");
1393             return false;
1394         }
1395         tilePartLen -= 2 + segLen;
1396         switch (segType) {
1397         case 0x52: // COD - coding style default
1398             cover(34);
1399             if (!readUByte(&img.tiles[tileIdx].tileComps[0].style) || !readUByte(&img.tiles[tileIdx].progOrder) || !readUWord(&img.tiles[tileIdx].nLayers) || !readUByte(&img.tiles[tileIdx].multiComp) || !readUByte(&nDecompLevels)
1400                 || !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockW) || !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockH) || !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockStyle)
1401                 || !readUByte(&img.tiles[tileIdx].tileComps[0].transform)) {
1402                 error(errSyntaxError, getPos(), "Error in JPX COD marker segment");
1403                 return false;
1404             }
1405             if (nDecompLevels > 32 || img.tiles[tileIdx].tileComps[0].codeBlockW > 8 || img.tiles[tileIdx].tileComps[0].codeBlockH > 8) {
1406                 error(errSyntaxError, getPos(), "Error in JPX COD marker segment");
1407                 return false;
1408             }
1409             img.tiles[tileIdx].tileComps[0].nDecompLevels = nDecompLevels;
1410             img.tiles[tileIdx].tileComps[0].codeBlockW += 2;
1411             img.tiles[tileIdx].tileComps[0].codeBlockH += 2;
1412             for (comp = 0; comp < img.nComps; ++comp) {
1413                 if (comp != 0) {
1414                     img.tiles[tileIdx].tileComps[comp].style = img.tiles[tileIdx].tileComps[0].style;
1415                     img.tiles[tileIdx].tileComps[comp].nDecompLevels = img.tiles[tileIdx].tileComps[0].nDecompLevels;
1416                     img.tiles[tileIdx].tileComps[comp].codeBlockW = img.tiles[tileIdx].tileComps[0].codeBlockW;
1417                     img.tiles[tileIdx].tileComps[comp].codeBlockH = img.tiles[tileIdx].tileComps[0].codeBlockH;
1418                     img.tiles[tileIdx].tileComps[comp].codeBlockStyle = img.tiles[tileIdx].tileComps[0].codeBlockStyle;
1419                     img.tiles[tileIdx].tileComps[comp].transform = img.tiles[tileIdx].tileComps[0].transform;
1420                 }
1421                 img.tiles[tileIdx].tileComps[comp].resLevels = (JPXResLevel *)greallocn(img.tiles[tileIdx].tileComps[comp].resLevels, (img.tiles[tileIdx].tileComps[comp].nDecompLevels + 1), sizeof(JPXResLevel));
1422                 for (r = 0; r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; ++r) {
1423                     img.tiles[tileIdx].tileComps[comp].resLevels[r].precincts = nullptr;
1424                 }
1425             }
1426             for (r = 0; r <= img.tiles[tileIdx].tileComps[0].nDecompLevels; ++r) {
1427                 if (img.tiles[tileIdx].tileComps[0].style & 0x01) {
1428                     if (!readUByte(&precinctSize)) {
1429                         error(errSyntaxError, getPos(), "Error in JPX COD marker segment");
1430                         return false;
1431                     }
1432                     img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth = precinctSize & 0x0f;
1433                     img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight = (precinctSize >> 4) & 0x0f;
1434                 } else {
1435                     img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth = 15;
1436                     img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight = 15;
1437                 }
1438             }
1439             for (comp = 1; comp < img.nComps; ++comp) {
1440                 for (r = 0; r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; ++r) {
1441                     img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth = img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth;
1442                     img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight = img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight;
1443                 }
1444             }
1445             break;
1446         case 0x53: // COC - coding style component
1447             cover(35);
1448             if ((img.nComps > 256 && !readUWord(&comp)) || (img.nComps <= 256 && !readUByte(&comp)) || comp >= img.nComps || !readUByte(&style) || !readUByte(&nDecompLevels) || !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockW)
1449                 || !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockH) || !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockStyle) || !readUByte(&img.tiles[tileIdx].tileComps[comp].transform)) {
1450                 error(errSyntaxError, getPos(), "Error in JPX COC marker segment");
1451                 return false;
1452             }
1453             if (nDecompLevels > 32 || img.tiles[tileIdx].tileComps[comp].codeBlockW > 8 || img.tiles[tileIdx].tileComps[comp].codeBlockH > 8) {
1454                 error(errSyntaxError, getPos(), "Error in JPX COD marker segment");
1455                 return false;
1456             }
1457             img.tiles[tileIdx].tileComps[comp].nDecompLevels = nDecompLevels;
1458             img.tiles[tileIdx].tileComps[comp].style = (img.tiles[tileIdx].tileComps[comp].style & ~1) | (style & 1);
1459             img.tiles[tileIdx].tileComps[comp].codeBlockW += 2;
1460             img.tiles[tileIdx].tileComps[comp].codeBlockH += 2;
1461             img.tiles[tileIdx].tileComps[comp].resLevels = (JPXResLevel *)greallocn(img.tiles[tileIdx].tileComps[comp].resLevels, (img.tiles[tileIdx].tileComps[comp].nDecompLevels + 1), sizeof(JPXResLevel));
1462             for (r = 0; r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; ++r) {
1463                 img.tiles[tileIdx].tileComps[comp].resLevels[r].precincts = nullptr;
1464             }
1465             for (r = 0; r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; ++r) {
1466                 if (img.tiles[tileIdx].tileComps[comp].style & 0x01) {
1467                     if (!readUByte(&precinctSize)) {
1468                         error(errSyntaxError, getPos(), "Error in JPX COD marker segment");
1469                         return false;
1470                     }
1471                     img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth = precinctSize & 0x0f;
1472                     img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight = (precinctSize >> 4) & 0x0f;
1473                 } else {
1474                     img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth = 15;
1475                     img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight = 15;
1476                 }
1477             }
1478             break;
1479         case 0x5c: // QCD - quantization default
1480             cover(36);
1481             if (!readUByte(&img.tiles[tileIdx].tileComps[0].quantStyle)) {
1482                 error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
1483                 return false;
1484             }
1485             if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x00) {
1486                 if (segLen <= 3) {
1487                     error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
1488                     return false;
1489                 }
1490                 img.tiles[tileIdx].tileComps[0].nQuantSteps = segLen - 3;
1491                 img.tiles[tileIdx].tileComps[0].quantSteps = (unsigned int *)greallocn(img.tiles[tileIdx].tileComps[0].quantSteps, img.tiles[tileIdx].tileComps[0].nQuantSteps, sizeof(unsigned int));
1492                 for (i = 0; i < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++i) {
1493                     if (!readUByte(&img.tiles[tileIdx].tileComps[0].quantSteps[i])) {
1494                         error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
1495                         return false;
1496                     }
1497                 }
1498             } else if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x01) {
1499                 img.tiles[tileIdx].tileComps[0].nQuantSteps = 1;
1500                 img.tiles[tileIdx].tileComps[0].quantSteps = (unsigned int *)greallocn(img.tiles[tileIdx].tileComps[0].quantSteps, img.tiles[tileIdx].tileComps[0].nQuantSteps, sizeof(unsigned int));
1501                 if (!readUWord(&img.tiles[tileIdx].tileComps[0].quantSteps[0])) {
1502                     error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
1503                     return false;
1504                 }
1505             } else if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x02) {
1506                 if (segLen < 5) {
1507                     error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
1508                     return false;
1509                 }
1510                 img.tiles[tileIdx].tileComps[0].nQuantSteps = (segLen - 3) / 2;
1511                 img.tiles[tileIdx].tileComps[0].quantSteps = (unsigned int *)greallocn(img.tiles[tileIdx].tileComps[0].quantSteps, img.tiles[tileIdx].tileComps[0].nQuantSteps, sizeof(unsigned int));
1512                 for (i = 0; i < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++i) {
1513                     if (!readUWord(&img.tiles[tileIdx].tileComps[0].quantSteps[i])) {
1514                         error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
1515                         return false;
1516                     }
1517                 }
1518             } else {
1519                 error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
1520                 return false;
1521             }
1522             for (comp = 1; comp < img.nComps; ++comp) {
1523                 img.tiles[tileIdx].tileComps[comp].quantStyle = img.tiles[tileIdx].tileComps[0].quantStyle;
1524                 img.tiles[tileIdx].tileComps[comp].nQuantSteps = img.tiles[tileIdx].tileComps[0].nQuantSteps;
1525                 img.tiles[tileIdx].tileComps[comp].quantSteps = (unsigned int *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps, img.tiles[tileIdx].tileComps[0].nQuantSteps, sizeof(unsigned int));
1526                 for (j = 0; j < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++j) {
1527                     img.tiles[tileIdx].tileComps[comp].quantSteps[j] = img.tiles[tileIdx].tileComps[0].quantSteps[j];
1528                 }
1529             }
1530             break;
1531         case 0x5d: // QCC - quantization component
1532             cover(37);
1533             if ((img.nComps > 256 && !readUWord(&comp)) || (img.nComps <= 256 && !readUByte(&comp)) || comp >= img.nComps || !readUByte(&img.tiles[tileIdx].tileComps[comp].quantStyle)) {
1534                 error(errSyntaxError, getPos(), "Error in JPX QCC marker segment");
1535                 return false;
1536             }
1537             if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f) == 0x00) {
1538                 if (segLen <= (img.nComps > 256 ? 5U : 4U)) {
1539                     error(errSyntaxError, getPos(), "Error in JPX QCC marker segment");
1540                     return false;
1541                 }
1542                 img.tiles[tileIdx].tileComps[comp].nQuantSteps = segLen - (img.nComps > 256 ? 5 : 4);
1543                 img.tiles[tileIdx].tileComps[comp].quantSteps = (unsigned int *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps, img.tiles[tileIdx].tileComps[comp].nQuantSteps, sizeof(unsigned int));
1544                 for (i = 0; i < img.tiles[tileIdx].tileComps[comp].nQuantSteps; ++i) {
1545                     if (!readUByte(&img.tiles[tileIdx].tileComps[comp].quantSteps[i])) {
1546                         error(errSyntaxError, getPos(), "Error in JPX QCC marker segment");
1547                         return false;
1548                     }
1549                 }
1550             } else if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f) == 0x01) {
1551                 img.tiles[tileIdx].tileComps[comp].nQuantSteps = 1;
1552                 img.tiles[tileIdx].tileComps[comp].quantSteps = (unsigned int *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps, img.tiles[tileIdx].tileComps[comp].nQuantSteps, sizeof(unsigned int));
1553                 if (!readUWord(&img.tiles[tileIdx].tileComps[comp].quantSteps[0])) {
1554                     error(errSyntaxError, getPos(), "Error in JPX QCC marker segment");
1555                     return false;
1556                 }
1557             } else if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f) == 0x02) {
1558                 if (segLen < (img.nComps > 256 ? 5U : 4U) + 2) {
1559                     error(errSyntaxError, getPos(), "Error in JPX QCC marker segment");
1560                     return false;
1561                 }
1562                 img.tiles[tileIdx].tileComps[comp].nQuantSteps = (segLen - (img.nComps > 256 ? 5 : 4)) / 2;
1563                 img.tiles[tileIdx].tileComps[comp].quantSteps = (unsigned int *)greallocn(img.tiles[tileIdx].tileComps[comp].quantSteps, img.tiles[tileIdx].tileComps[comp].nQuantSteps, sizeof(unsigned int));
1564                 for (i = 0; i < img.tiles[tileIdx].tileComps[comp].nQuantSteps; ++i) {
1565                     if (!readUWord(&img.tiles[tileIdx].tileComps[comp].quantSteps[i])) {
1566                         error(errSyntaxError, getPos(), "Error in JPX QCD marker segment");
1567                         return false;
1568                     }
1569                 }
1570             } else {
1571                 error(errSyntaxError, getPos(), "Error in JPX QCC marker segment");
1572                 return false;
1573             }
1574             break;
1575         case 0x5e: // RGN - region of interest
1576             cover(38);
1577 #if 1 //~ ROI is unimplemented
1578             error(errUnimplemented, -1, "Got a JPX RGN segment");
1579             for (i = 0; i < segLen - 2; ++i) {
1580                 if (bufStr->getChar() == EOF) {
1581                     error(errSyntaxError, getPos(), "Error in JPX RGN marker segment");
1582                     return false;
1583                 }
1584             }
1585 #else
1586             if ((img.nComps > 256 && !readUWord(&comp)) || (img.nComps <= 256 && !readUByte(&comp)) || comp >= img.nComps || !readUByte(&compInfo[comp].roi.style) || !readUByte(&compInfo[comp].roi.shift)) {
1587                 error(errSyntaxError, getPos(), "Error in JPX RGN marker segment");
1588                 return false;
1589             }
1590 #endif
1591             break;
1592         case 0x5f: // POC - progression order change
1593             cover(39);
1594 #if 1 //~ progression order changes are unimplemented
1595             error(errUnimplemented, -1, "Got a JPX POC segment");
1596             for (i = 0; i < segLen - 2; ++i) {
1597                 if (bufStr->getChar() == EOF) {
1598                     error(errSyntaxError, getPos(), "Error in JPX POC marker segment");
1599                     return false;
1600                 }
1601             }
1602 #else
1603             nTileProgs = (segLen - 2) / (img.nComps > 256 ? 9 : 7);
1604             tileProgs = (JPXProgOrder *)gmallocn(nTileProgs, sizeof(JPXProgOrder));
1605             for (i = 0; i < nTileProgs; ++i) {
1606                 if (!readUByte(&tileProgs[i].startRes) || !(img.nComps > 256 && readUWord(&tileProgs[i].startComp)) || !(img.nComps <= 256 && readUByte(&tileProgs[i].startComp)) || !readUWord(&tileProgs[i].endLayer)
1607                     || !readUByte(&tileProgs[i].endRes) || !(img.nComps > 256 && readUWord(&tileProgs[i].endComp)) || !(img.nComps <= 256 && readUByte(&tileProgs[i].endComp)) || !readUByte(&tileProgs[i].progOrder)) {
1608                     error(errSyntaxError, getPos(), "Error in JPX POC marker segment");
1609                     return false;
1610                 }
1611             }
1612 #endif
1613             break;
1614         case 0x61: // PPT - packed packet headers, tile-part hdr
1615             cover(40);
1616 #if 1 //~ packed packet headers are unimplemented
1617             error(errUnimplemented, -1, "Got a JPX PPT segment");
1618             for (i = 0; i < segLen - 2; ++i) {
1619                 if (bufStr->getChar() == EOF) {
1620                     error(errSyntaxError, getPos(), "Error in JPX PPT marker segment");
1621                     return false;
1622                 }
1623             }
1624 #endif
1625         case 0x58: // PLT - packet length, tile-part header
1626             // skipped
1627             cover(41);
1628             for (i = 0; i < segLen - 2; ++i) {
1629                 if (bufStr->getChar() == EOF) {
1630                     error(errSyntaxError, getPos(), "Error in JPX PLT marker segment");
1631                     return false;
1632                 }
1633             }
1634             break;
1635         case 0x64: // COM - comment
1636             // skipped
1637             cover(42);
1638             for (i = 0; i < segLen - 2; ++i) {
1639                 if (bufStr->getChar() == EOF) {
1640                     error(errSyntaxError, getPos(), "Error in JPX COM marker segment");
1641                     return false;
1642                 }
1643             }
1644             break;
1645         case 0x93: // SOD - start of data
1646             cover(43);
1647             haveSOD = true;
1648             break;
1649         default:
1650             cover(44);
1651             error(errSyntaxError, getPos(), "Unknown marker segment {0:02x} in JPX tile-part stream", segType);
1652             for (i = 0; i < segLen - 2; ++i) {
1653                 if (bufStr->getChar() == EOF) {
1654                     break;
1655                 }
1656             }
1657             break;
1658         }
1659     } while (!haveSOD);
1660 
1661     //----- initialize the tile, precincts, and code-blocks
1662     if (tilePartIdx == 0) {
1663         tile = &img.tiles[tileIdx];
1664         tile->init = true;
1665         i = tileIdx / img.nXTiles;
1666         j = tileIdx % img.nXTiles;
1667         if ((tile->x0 = img.xTileOffset + j * img.xTileSize) < img.xOffset) {
1668             tile->x0 = img.xOffset;
1669         }
1670         if ((tile->y0 = img.yTileOffset + i * img.yTileSize) < img.yOffset) {
1671             tile->y0 = img.yOffset;
1672         }
1673         if ((tile->x1 = img.xTileOffset + (j + 1) * img.xTileSize) > img.xSize) {
1674             tile->x1 = img.xSize;
1675         }
1676         if ((tile->y1 = img.yTileOffset + (i + 1) * img.yTileSize) > img.ySize) {
1677             tile->y1 = img.ySize;
1678         }
1679         tile->comp = 0;
1680         tile->res = 0;
1681         tile->precinct = 0;
1682         tile->layer = 0;
1683         tile->maxNDecompLevels = 0;
1684         for (comp = 0; comp < img.nComps; ++comp) {
1685             tileComp = &tile->tileComps[comp];
1686             if (tileComp->nDecompLevels > tile->maxNDecompLevels) {
1687                 tile->maxNDecompLevels = tileComp->nDecompLevels;
1688             }
1689             tileComp->x0 = jpxCeilDiv(tile->x0, tileComp->hSep);
1690             tileComp->y0 = jpxCeilDiv(tile->y0, tileComp->vSep);
1691             tileComp->x1 = jpxCeilDiv(tile->x1, tileComp->hSep);
1692             tileComp->y1 = jpxCeilDiv(tile->y1, tileComp->vSep);
1693             tileComp->w = tileComp->x1 - tileComp->x0;
1694             tileComp->cbW = 1 << tileComp->codeBlockW;
1695             tileComp->cbH = 1 << tileComp->codeBlockH;
1696             tileComp->data = (int *)gmallocn((tileComp->x1 - tileComp->x0) * (tileComp->y1 - tileComp->y0), sizeof(int));
1697             if (tileComp->x1 - tileComp->x0 > tileComp->y1 - tileComp->y0) {
1698                 n = tileComp->x1 - tileComp->x0;
1699             } else {
1700                 n = tileComp->y1 - tileComp->y0;
1701             }
1702             tileComp->buf = (int *)gmallocn(n + 8, sizeof(int));
1703             for (r = 0; r <= tileComp->nDecompLevels; ++r) {
1704                 resLevel = &tileComp->resLevels[r];
1705                 k = r == 0 ? tileComp->nDecompLevels : tileComp->nDecompLevels - r + 1;
1706                 resLevel->x0 = jpxCeilDivPow2(tileComp->x0, k);
1707                 resLevel->y0 = jpxCeilDivPow2(tileComp->y0, k);
1708                 resLevel->x1 = jpxCeilDivPow2(tileComp->x1, k);
1709                 resLevel->y1 = jpxCeilDivPow2(tileComp->y1, k);
1710                 if (r == 0) {
1711                     resLevel->bx0[0] = resLevel->x0;
1712                     resLevel->by0[0] = resLevel->y0;
1713                     resLevel->bx1[0] = resLevel->x1;
1714                     resLevel->by1[0] = resLevel->y1;
1715                 } else {
1716                     resLevel->bx0[0] = jpxCeilDivPow2(tileComp->x0 - (1 << (k - 1)), k);
1717                     resLevel->by0[0] = resLevel->y0;
1718                     resLevel->bx1[0] = jpxCeilDivPow2(tileComp->x1 - (1 << (k - 1)), k);
1719                     resLevel->by1[0] = resLevel->y1;
1720                     resLevel->bx0[1] = resLevel->x0;
1721                     resLevel->by0[1] = jpxCeilDivPow2(tileComp->y0 - (1 << (k - 1)), k);
1722                     resLevel->bx1[1] = resLevel->x1;
1723                     resLevel->by1[1] = jpxCeilDivPow2(tileComp->y1 - (1 << (k - 1)), k);
1724                     resLevel->bx0[2] = jpxCeilDivPow2(tileComp->x0 - (1 << (k - 1)), k);
1725                     resLevel->by0[2] = jpxCeilDivPow2(tileComp->y0 - (1 << (k - 1)), k);
1726                     resLevel->bx1[2] = jpxCeilDivPow2(tileComp->x1 - (1 << (k - 1)), k);
1727                     resLevel->by1[2] = jpxCeilDivPow2(tileComp->y1 - (1 << (k - 1)), k);
1728                 }
1729                 resLevel->precincts = (JPXPrecinct *)gmallocn(1, sizeof(JPXPrecinct));
1730                 for (pre = 0; pre < 1; ++pre) {
1731                     precinct = &resLevel->precincts[pre];
1732                     precinct->x0 = resLevel->x0;
1733                     precinct->y0 = resLevel->y0;
1734                     precinct->x1 = resLevel->x1;
1735                     precinct->y1 = resLevel->y1;
1736                     nSBs = r == 0 ? 1 : 3;
1737                     precinct->subbands = (JPXSubband *)gmallocn(nSBs, sizeof(JPXSubband));
1738                     for (sb = 0; sb < nSBs; ++sb) {
1739                         subband = &precinct->subbands[sb];
1740                         subband->x0 = resLevel->bx0[sb];
1741                         subband->y0 = resLevel->by0[sb];
1742                         subband->x1 = resLevel->bx1[sb];
1743                         subband->y1 = resLevel->by1[sb];
1744                         subband->nXCBs = jpxCeilDivPow2(subband->x1, tileComp->codeBlockW) - jpxFloorDivPow2(subband->x0, tileComp->codeBlockW);
1745                         subband->nYCBs = jpxCeilDivPow2(subband->y1, tileComp->codeBlockH) - jpxFloorDivPow2(subband->y0, tileComp->codeBlockH);
1746                         n = subband->nXCBs > subband->nYCBs ? subband->nXCBs : subband->nYCBs;
1747                         for (subband->maxTTLevel = 0, --n; n; ++subband->maxTTLevel, n >>= 1)
1748                             ;
1749                         n = 0;
1750                         for (level = subband->maxTTLevel; level >= 0; --level) {
1751                             nx = jpxCeilDivPow2(subband->nXCBs, level);
1752                             ny = jpxCeilDivPow2(subband->nYCBs, level);
1753                             n += nx * ny;
1754                         }
1755                         subband->inclusion = (JPXTagTreeNode *)gmallocn(n, sizeof(JPXTagTreeNode));
1756                         subband->zeroBitPlane = (JPXTagTreeNode *)gmallocn(n, sizeof(JPXTagTreeNode));
1757                         for (k = 0; k < n; ++k) {
1758                             subband->inclusion[k].finished = false;
1759                             subband->inclusion[k].val = 0;
1760                             subband->zeroBitPlane[k].finished = false;
1761                             subband->zeroBitPlane[k].val = 0;
1762                         }
1763                         subband->cbs = (JPXCodeBlock *)gmallocn(subband->nXCBs * subband->nYCBs, sizeof(JPXCodeBlock));
1764                         sbx0 = jpxFloorDivPow2(subband->x0, tileComp->codeBlockW);
1765                         sby0 = jpxFloorDivPow2(subband->y0, tileComp->codeBlockH);
1766                         if (r == 0) { // (NL)LL
1767                             sbCoeffs = tileComp->data;
1768                         } else if (sb == 0) { // (NL-r+1)HL
1769                             sbCoeffs = tileComp->data + resLevel->bx1[1] - resLevel->bx0[1];
1770                         } else if (sb == 1) { // (NL-r+1)LH
1771                             sbCoeffs = tileComp->data + (resLevel->by1[0] - resLevel->by0[0]) * tileComp->w;
1772                         } else { // (NL-r+1)HH
1773                             sbCoeffs = tileComp->data + (resLevel->by1[0] - resLevel->by0[0]) * tileComp->w + resLevel->bx1[1] - resLevel->bx0[1];
1774                         }
1775                         cb = subband->cbs;
1776                         for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
1777                             for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
1778                                 cb->x0 = (sbx0 + cbX) << tileComp->codeBlockW;
1779                                 cb->x1 = cb->x0 + tileComp->cbW;
1780                                 if (subband->x0 > cb->x0) {
1781                                     cb->x0 = subband->x0;
1782                                 }
1783                                 if (subband->x1 < cb->x1) {
1784                                     cb->x1 = subband->x1;
1785                                 }
1786                                 cb->y0 = (sby0 + cbY) << tileComp->codeBlockH;
1787                                 cb->y1 = cb->y0 + tileComp->cbH;
1788                                 if (subband->y0 > cb->y0) {
1789                                     cb->y0 = subband->y0;
1790                                 }
1791                                 if (subband->y1 < cb->y1) {
1792                                     cb->y1 = subband->y1;
1793                                 }
1794                                 cb->seen = false;
1795                                 cb->lBlock = 3;
1796                                 cb->nextPass = jpxPassCleanup;
1797                                 cb->nZeroBitPlanes = 0;
1798                                 cb->dataLenSize = 1;
1799                                 cb->dataLen = (unsigned int *)gmalloc(sizeof(unsigned int));
1800                                 cb->coeffs = sbCoeffs + (cb->y0 - subband->y0) * tileComp->w + (cb->x0 - subband->x0);
1801                                 cb->touched = (char *)gmalloc(1 << (tileComp->codeBlockW + tileComp->codeBlockH));
1802                                 cb->len = 0;
1803                                 for (cbj = 0; cbj < cb->y1 - cb->y0; ++cbj) {
1804                                     for (cbi = 0; cbi < cb->x1 - cb->x0; ++cbi) {
1805                                         cb->coeffs[cbj * tileComp->w + cbi] = 0;
1806                                     }
1807                                 }
1808                                 memset(cb->touched, 0, (1 << (tileComp->codeBlockW + tileComp->codeBlockH)));
1809                                 cb->arithDecoder = nullptr;
1810                                 cb->stats = nullptr;
1811                                 ++cb;
1812                             }
1813                         }
1814                     }
1815                 }
1816             }
1817         }
1818     }
1819 
1820     return readTilePartData(tileIdx, tilePartLen, tilePartToEOC);
1821 }
1822 
1823 bool JPXStream::readTilePartData(unsigned int tileIdx, unsigned int tilePartLen, bool tilePartToEOC)
1824 {
1825     JPXTile *tile;
1826     JPXTileComp *tileComp;
1827     JPXResLevel *resLevel;
1828     JPXPrecinct *precinct;
1829     JPXSubband *subband;
1830     JPXCodeBlock *cb;
1831     unsigned int ttVal;
1832     unsigned int bits, cbX, cbY, nx, ny, i, j, n, sb;
1833     int level;
1834 
1835     tile = &img.tiles[tileIdx];
1836 
1837     // read all packets from this tile-part
1838     while (1) {
1839         if (tilePartToEOC) {
1840             //~ peek for an EOC marker
1841             cover(93);
1842         } else if (tilePartLen == 0) {
1843             break;
1844         }
1845 
1846         tileComp = &tile->tileComps[tile->comp];
1847         resLevel = &tileComp->resLevels[tile->res];
1848         precinct = &resLevel->precincts[tile->precinct];
1849 
1850         //----- packet header
1851 
1852         // setup
1853         startBitBuf(tilePartLen);
1854         if (tileComp->style & 0x02) {
1855             skipSOP();
1856         }
1857 
1858         // zero-length flag
1859         if (!readBits(1, &bits)) {
1860             goto err;
1861         }
1862         if (!bits) {
1863             // packet is empty -- clear all code-block inclusion flags
1864             cover(45);
1865             for (sb = 0; sb < (unsigned int)(tile->res == 0 ? 1 : 3); ++sb) {
1866                 subband = &precinct->subbands[sb];
1867                 for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
1868                     for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
1869                         cb = &subband->cbs[cbY * subband->nXCBs + cbX];
1870                         cb->included = false;
1871                     }
1872                 }
1873             }
1874         } else {
1875 
1876             for (sb = 0; sb < (unsigned int)(tile->res == 0 ? 1 : 3); ++sb) {
1877                 subband = &precinct->subbands[sb];
1878                 for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
1879                     for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
1880                         cb = &subband->cbs[cbY * subband->nXCBs + cbX];
1881 
1882                         // skip code-blocks with no coefficients
1883                         if (cb->x0 >= cb->x1 || cb->y0 >= cb->y1) {
1884                             cover(46);
1885                             cb->included = false;
1886                             continue;
1887                         }
1888 
1889                         // code-block inclusion
1890                         if (cb->seen) {
1891                             cover(47);
1892                             if (!readBits(1, &cb->included)) {
1893                                 goto err;
1894                             }
1895                         } else {
1896                             cover(48);
1897                             ttVal = 0;
1898                             i = 0;
1899                             for (level = subband->maxTTLevel; level >= 0; --level) {
1900                                 nx = jpxCeilDivPow2(subband->nXCBs, level);
1901                                 ny = jpxCeilDivPow2(subband->nYCBs, level);
1902                                 j = i + (cbY >> level) * nx + (cbX >> level);
1903                                 if (!subband->inclusion[j].finished && !subband->inclusion[j].val) {
1904                                     subband->inclusion[j].val = ttVal;
1905                                 } else {
1906                                     ttVal = subband->inclusion[j].val;
1907                                 }
1908                                 while (!subband->inclusion[j].finished && ttVal <= tile->layer) {
1909                                     if (!readBits(1, &bits)) {
1910                                         goto err;
1911                                     }
1912                                     if (bits == 1) {
1913                                         subband->inclusion[j].finished = true;
1914                                     } else {
1915                                         ++ttVal;
1916                                     }
1917                                 }
1918                                 subband->inclusion[j].val = ttVal;
1919                                 if (ttVal > tile->layer) {
1920                                     break;
1921                                 }
1922                                 i += nx * ny;
1923                             }
1924                             cb->included = level < 0;
1925                         }
1926 
1927                         if (cb->included) {
1928                             cover(49);
1929 
1930                             // zero bit-plane count
1931                             if (!cb->seen) {
1932                                 cover(50);
1933                                 ttVal = 0;
1934                                 i = 0;
1935                                 for (level = subband->maxTTLevel; level >= 0; --level) {
1936                                     nx = jpxCeilDivPow2(subband->nXCBs, level);
1937                                     ny = jpxCeilDivPow2(subband->nYCBs, level);
1938                                     j = i + (cbY >> level) * nx + (cbX >> level);
1939                                     if (!subband->zeroBitPlane[j].finished && !subband->zeroBitPlane[j].val) {
1940                                         subband->zeroBitPlane[j].val = ttVal;
1941                                     } else {
1942                                         ttVal = subband->zeroBitPlane[j].val;
1943                                     }
1944                                     while (!subband->zeroBitPlane[j].finished) {
1945                                         if (!readBits(1, &bits)) {
1946                                             goto err;
1947                                         }
1948                                         if (bits == 1) {
1949                                             subband->zeroBitPlane[j].finished = true;
1950                                         } else {
1951                                             ++ttVal;
1952                                         }
1953                                     }
1954                                     subband->zeroBitPlane[j].val = ttVal;
1955                                     i += nx * ny;
1956                                 }
1957                                 cb->nZeroBitPlanes = ttVal;
1958                             }
1959 
1960                             // number of coding passes
1961                             if (!readBits(1, &bits)) {
1962                                 goto err;
1963                             }
1964                             if (bits == 0) {
1965                                 cover(51);
1966                                 cb->nCodingPasses = 1;
1967                             } else {
1968                                 if (!readBits(1, &bits)) {
1969                                     goto err;
1970                                 }
1971                                 if (bits == 0) {
1972                                     cover(52);
1973                                     cb->nCodingPasses = 2;
1974                                 } else {
1975                                     cover(53);
1976                                     if (!readBits(2, &bits)) {
1977                                         goto err;
1978                                     }
1979                                     if (bits < 3) {
1980                                         cover(54);
1981                                         cb->nCodingPasses = 3 + bits;
1982                                     } else {
1983                                         cover(55);
1984                                         if (!readBits(5, &bits)) {
1985                                             goto err;
1986                                         }
1987                                         if (bits < 31) {
1988                                             cover(56);
1989                                             cb->nCodingPasses = 6 + bits;
1990                                         } else {
1991                                             cover(57);
1992                                             if (!readBits(7, &bits)) {
1993                                                 goto err;
1994                                             }
1995                                             cb->nCodingPasses = 37 + bits;
1996                                         }
1997                                     }
1998                                 }
1999                             }
2000 
2001                             // update Lblock
2002                             while (1) {
2003                                 if (!readBits(1, &bits)) {
2004                                     goto err;
2005                                 }
2006                                 if (!bits) {
2007                                     break;
2008                                 }
2009                                 ++cb->lBlock;
2010                             }
2011 
2012                             // one codeword segment for each of the coding passes
2013                             if (tileComp->codeBlockStyle & 0x04) {
2014                                 if (cb->nCodingPasses > cb->dataLenSize) {
2015                                     cb->dataLenSize = cb->nCodingPasses;
2016                                     cb->dataLen = (unsigned int *)greallocn(cb->dataLen, cb->dataLenSize, sizeof(unsigned int));
2017                                 }
2018 
2019                                 // read the lengths
2020                                 for (i = 0; i < cb->nCodingPasses; ++i) {
2021                                     if (!readBits(cb->lBlock, &cb->dataLen[i])) {
2022                                         goto err;
2023                                     }
2024                                 }
2025 
2026                                 // one codeword segment for all of the coding passes
2027                             } else {
2028 
2029                                 // read the length
2030                                 for (n = cb->lBlock, i = cb->nCodingPasses >> 1; i; ++n, i >>= 1)
2031                                     ;
2032                                 if (!readBits(n, &cb->dataLen[0])) {
2033                                     goto err;
2034                                 }
2035                             }
2036                         }
2037                     }
2038                 }
2039             }
2040         }
2041         if (tileComp->style & 0x04) {
2042             skipEPH();
2043         }
2044         tilePartLen = finishBitBuf();
2045 
2046         //----- packet data
2047 
2048         for (sb = 0; sb < (unsigned int)(tile->res == 0 ? 1 : 3); ++sb) {
2049             subband = &precinct->subbands[sb];
2050             for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
2051                 for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
2052                     cb = &subband->cbs[cbY * subband->nXCBs + cbX];
2053                     if (cb->included) {
2054                         if (!readCodeBlockData(tileComp, resLevel, precinct, subband, tile->res, sb, cb)) {
2055                             return false;
2056                         }
2057                         if (tileComp->codeBlockStyle & 0x04) {
2058                             for (i = 0; i < cb->nCodingPasses; ++i) {
2059                                 tilePartLen -= cb->dataLen[i];
2060                             }
2061                         } else {
2062                             tilePartLen -= cb->dataLen[0];
2063                         }
2064                         cb->seen = true;
2065                     }
2066                 }
2067             }
2068         }
2069 
2070         //----- next packet
2071 
2072         switch (tile->progOrder) {
2073         case 0: // layer, resolution level, component, precinct
2074             cover(58);
2075             if (++tile->comp == img.nComps) {
2076                 tile->comp = 0;
2077                 if (++tile->res == tile->maxNDecompLevels + 1) {
2078                     tile->res = 0;
2079                     if (++tile->layer == tile->nLayers) {
2080                         tile->layer = 0;
2081                     }
2082                 }
2083             }
2084             break;
2085         case 1: // resolution level, layer, component, precinct
2086             cover(59);
2087             if (++tile->comp == img.nComps) {
2088                 tile->comp = 0;
2089                 if (++tile->layer == tile->nLayers) {
2090                     tile->layer = 0;
2091                     if (++tile->res == tile->maxNDecompLevels + 1) {
2092                         tile->res = 0;
2093                     }
2094                 }
2095             }
2096             break;
2097         case 2: // resolution level, precinct, component, layer
2098             //~ this isn't correct -- see B.12.1.3
2099             cover(60);
2100             if (++tile->layer == tile->nLayers) {
2101                 tile->layer = 0;
2102                 if (++tile->comp == img.nComps) {
2103                     tile->comp = 0;
2104                     if (++tile->res == tile->maxNDecompLevels + 1) {
2105                         tile->res = 0;
2106                     }
2107                 }
2108                 tileComp = &tile->tileComps[tile->comp];
2109                 if (tile->res >= tileComp->nDecompLevels + 1) {
2110                     if (++tile->comp == img.nComps) {
2111                         return true;
2112                     }
2113                 }
2114             }
2115             break;
2116         case 3: // precinct, component, resolution level, layer
2117             //~ this isn't correct -- see B.12.1.4
2118             cover(61);
2119             if (++tile->layer == tile->nLayers) {
2120                 tile->layer = 0;
2121                 if (++tile->res == tile->maxNDecompLevels + 1) {
2122                     tile->res = 0;
2123                     if (++tile->comp == img.nComps) {
2124                         tile->comp = 0;
2125                     }
2126                 }
2127             }
2128             break;
2129         case 4: // component, precinct, resolution level, layer
2130             //~ this isn't correct -- see B.12.1.5
2131             cover(62);
2132             if (++tile->layer == tile->nLayers) {
2133                 tile->layer = 0;
2134                 if (++tile->res == tile->maxNDecompLevels + 1) {
2135                     tile->res = 0;
2136                     if (++tile->comp == img.nComps) {
2137                         tile->comp = 0;
2138                     }
2139                 }
2140             }
2141             break;
2142         }
2143     }
2144 
2145     return true;
2146 
2147 err:
2148     error(errSyntaxError, getPos(), "Error in JPX stream");
2149     return false;
2150 }
2151 
2152 bool JPXStream::readCodeBlockData(JPXTileComp *tileComp, JPXResLevel *resLevel, JPXPrecinct *precinct, JPXSubband *subband, unsigned int res, unsigned int sb, JPXCodeBlock *cb)
2153 {
2154     int *coeff0, *coeff1, *coeff;
2155     char *touched0, *touched1, *touched;
2156     unsigned int horiz, vert, diag, all, cx, xorBit;
2157     int horizSign, vertSign, bit;
2158     int segSym;
2159     unsigned int i, x, y0, y1;
2160 
2161     if (cb->arithDecoder) {
2162         cover(63);
2163         cb->arithDecoder->restart(cb->dataLen[0]);
2164     } else {
2165         cover(64);
2166         cb->arithDecoder = new JArithmeticDecoder();
2167         cb->arithDecoder->setStream(bufStr, cb->dataLen[0]);
2168         cb->arithDecoder->start();
2169         cb->stats = new JArithmeticDecoderStats(jpxNContexts);
2170         cb->stats->setEntry(jpxContextSigProp, 4, 0);
2171         cb->stats->setEntry(jpxContextRunLength, 3, 0);
2172         cb->stats->setEntry(jpxContextUniform, 46, 0);
2173     }
2174 
2175     for (i = 0; i < cb->nCodingPasses; ++i) {
2176         if ((tileComp->codeBlockStyle & 0x04) && i > 0) {
2177             cb->arithDecoder->setStream(bufStr, cb->dataLen[i]);
2178             cb->arithDecoder->start();
2179         }
2180 
2181         switch (cb->nextPass) {
2182 
2183         //----- significance propagation pass
2184         case jpxPassSigProp:
2185             cover(65);
2186             for (y0 = cb->y0, coeff0 = cb->coeffs, touched0 = cb->touched; y0 < cb->y1; y0 += 4, coeff0 += 4 * tileComp->w, touched0 += 4 << tileComp->codeBlockW) {
2187                 for (x = cb->x0, coeff1 = coeff0, touched1 = touched0; x < cb->x1; ++x, ++coeff1, ++touched1) {
2188                     for (y1 = 0, coeff = coeff1, touched = touched1; y1 < 4 && y0 + y1 < cb->y1; ++y1, coeff += tileComp->w, touched += tileComp->cbW) {
2189                         if (!*coeff) {
2190                             horiz = vert = diag = 0;
2191                             horizSign = vertSign = 2;
2192                             if (x > cb->x0) {
2193                                 if (coeff[-1]) {
2194                                     ++horiz;
2195                                     horizSign += coeff[-1] < 0 ? -1 : 1;
2196                                 }
2197                                 if (y0 + y1 > cb->y0) {
2198                                     diag += coeff[-(int)tileComp->w - 1] ? 1 : 0;
2199                                 }
2200                                 if (y0 + y1 < cb->y1 - 1 && (!(tileComp->codeBlockStyle & 0x08) || y1 < 3)) {
2201                                     diag += coeff[tileComp->w - 1] ? 1 : 0;
2202                                 }
2203                             }
2204                             if (x < cb->x1 - 1) {
2205                                 if (coeff[1]) {
2206                                     ++horiz;
2207                                     horizSign += coeff[1] < 0 ? -1 : 1;
2208                                 }
2209                                 if (y0 + y1 > cb->y0) {
2210                                     diag += coeff[-(int)tileComp->w + 1] ? 1 : 0;
2211                                 }
2212                                 if (y0 + y1 < cb->y1 - 1 && (!(tileComp->codeBlockStyle & 0x08) || y1 < 3)) {
2213                                     diag += coeff[tileComp->w + 1] ? 1 : 0;
2214                                 }
2215                             }
2216                             if (y0 + y1 > cb->y0) {
2217                                 if (coeff[-(int)tileComp->w]) {
2218                                     ++vert;
2219                                     vertSign += coeff[-(int)tileComp->w] < 0 ? -1 : 1;
2220                                 }
2221                             }
2222                             if (y0 + y1 < cb->y1 - 1 && (!(tileComp->codeBlockStyle & 0x08) || y1 < 3)) {
2223                                 if (coeff[tileComp->w]) {
2224                                     ++vert;
2225                                     vertSign += coeff[tileComp->w] < 0 ? -1 : 1;
2226                                 }
2227                             }
2228                             cx = sigPropContext[horiz][vert][diag][res == 0 ? 1 : sb];
2229                             if (cx != 0) {
2230                                 if (cb->arithDecoder->decodeBit(cx, cb->stats)) {
2231                                     cx = signContext[horizSign][vertSign][0];
2232                                     xorBit = signContext[horizSign][vertSign][1];
2233                                     if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) {
2234                                         *coeff = -1;
2235                                     } else {
2236                                         *coeff = 1;
2237                                     }
2238                                 }
2239                                 *touched = 1;
2240                             }
2241                         }
2242                     }
2243                 }
2244             }
2245             ++cb->nextPass;
2246             break;
2247 
2248         //----- magnitude refinement pass
2249         case jpxPassMagRef:
2250             cover(66);
2251             for (y0 = cb->y0, coeff0 = cb->coeffs, touched0 = cb->touched; y0 < cb->y1; y0 += 4, coeff0 += 4 * tileComp->w, touched0 += 4 << tileComp->codeBlockW) {
2252                 for (x = cb->x0, coeff1 = coeff0, touched1 = touched0; x < cb->x1; ++x, ++coeff1, ++touched1) {
2253                     for (y1 = 0, coeff = coeff1, touched = touched1; y1 < 4 && y0 + y1 < cb->y1; ++y1, coeff += tileComp->w, touched += tileComp->cbW) {
2254                         if (*coeff && !*touched) {
2255                             if (*coeff == 1 || *coeff == -1) {
2256                                 all = 0;
2257                                 if (x > cb->x0) {
2258                                     all += coeff[-1] ? 1 : 0;
2259                                     if (y0 + y1 > cb->y0) {
2260                                         all += coeff[-(int)tileComp->w - 1] ? 1 : 0;
2261                                     }
2262                                     if (y0 + y1 < cb->y1 - 1 && (!(tileComp->codeBlockStyle & 0x08) || y1 < 3)) {
2263                                         all += coeff[tileComp->w - 1] ? 1 : 0;
2264                                     }
2265                                 }
2266                                 if (x < cb->x1 - 1) {
2267                                     all += coeff[1] ? 1 : 0;
2268                                     if (y0 + y1 > cb->y0) {
2269                                         all += coeff[-(int)tileComp->w + 1] ? 1 : 0;
2270                                     }
2271                                     if (y0 + y1 < cb->y1 - 1 && (!(tileComp->codeBlockStyle & 0x08) || y1 < 3)) {
2272                                         all += coeff[tileComp->w + 1] ? 1 : 0;
2273                                     }
2274                                 }
2275                                 if (y0 + y1 > cb->y0) {
2276                                     all += coeff[-(int)tileComp->w] ? 1 : 0;
2277                                 }
2278                                 if (y0 + y1 < cb->y1 - 1 && (!(tileComp->codeBlockStyle & 0x08) || y1 < 3)) {
2279                                     all += coeff[tileComp->w] ? 1 : 0;
2280                                 }
2281                                 cx = all ? 15 : 14;
2282                             } else {
2283                                 cx = 16;
2284                             }
2285                             bit = cb->arithDecoder->decodeBit(cx, cb->stats);
2286                             if (*coeff < 0) {
2287                                 *coeff = (*coeff << 1) - bit;
2288                             } else {
2289                                 *coeff = (*coeff << 1) + bit;
2290                             }
2291                             *touched = 1;
2292                         }
2293                     }
2294                 }
2295             }
2296             ++cb->nextPass;
2297             break;
2298 
2299         //----- cleanup pass
2300         case jpxPassCleanup:
2301             cover(67);
2302             for (y0 = cb->y0, coeff0 = cb->coeffs, touched0 = cb->touched; y0 < cb->y1; y0 += 4, coeff0 += 4 * tileComp->w, touched0 += 4 << tileComp->codeBlockW) {
2303                 for (x = cb->x0, coeff1 = coeff0, touched1 = touched0; x < cb->x1; ++x, ++coeff1, ++touched1) {
2304                     y1 = 0;
2305                     if (y0 + 3 < cb->y1 && !(*touched1) && !(touched1[tileComp->cbW]) && !(touched1[2 * tileComp->cbW]) && !(touched1[3 * tileComp->cbW]) && (x == cb->x0 || y0 == cb->y0 || !coeff1[-(int)tileComp->w - 1])
2306                         && (y0 == cb->y0 || !coeff1[-(int)tileComp->w]) && (x == cb->x1 - 1 || y0 == cb->y0 || !coeff1[-(int)tileComp->w + 1])
2307                         && (x == cb->x0 || (!coeff1[-1] && !coeff1[tileComp->w - 1] && !coeff1[2 * tileComp->w - 1] && !coeff1[3 * tileComp->w - 1]))
2308                         && (x == cb->x1 - 1 || (!coeff1[1] && !coeff1[tileComp->w + 1] && !coeff1[2 * tileComp->w + 1] && !coeff1[3 * tileComp->w + 1]))
2309                         && ((tileComp->codeBlockStyle & 0x08)
2310                             || ((x == cb->x0 || y0 + 4 == cb->y1 || !coeff1[4 * tileComp->w - 1]) && (y0 + 4 == cb->y1 || !coeff1[4 * tileComp->w]) && (x == cb->x1 - 1 || y0 + 4 == cb->y1 || !coeff1[4 * tileComp->w + 1])))) {
2311                         if (cb->arithDecoder->decodeBit(jpxContextRunLength, cb->stats)) {
2312                             y1 = cb->arithDecoder->decodeBit(jpxContextUniform, cb->stats);
2313                             y1 = (y1 << 1) | cb->arithDecoder->decodeBit(jpxContextUniform, cb->stats);
2314                             coeff = &coeff1[y1 * tileComp->w];
2315                             cx = signContext[2][2][0];
2316                             xorBit = signContext[2][2][1];
2317                             if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) {
2318                                 *coeff = -1;
2319                             } else {
2320                                 *coeff = 1;
2321                             }
2322                             ++y1;
2323                         } else {
2324                             y1 = 4;
2325                         }
2326                     }
2327                     for (coeff = &coeff1[y1 * tileComp->w], touched = &touched1[y1 << tileComp->codeBlockW]; y1 < 4 && y0 + y1 < cb->y1; ++y1, coeff += tileComp->w, touched += tileComp->cbW) {
2328                         if (!*touched) {
2329                             horiz = vert = diag = 0;
2330                             horizSign = vertSign = 2;
2331                             if (x > cb->x0) {
2332                                 if (coeff[-1]) {
2333                                     ++horiz;
2334                                     horizSign += coeff[-1] < 0 ? -1 : 1;
2335                                 }
2336                                 if (y0 + y1 > cb->y0) {
2337                                     diag += coeff[-(int)tileComp->w - 1] ? 1 : 0;
2338                                 }
2339                                 if (y0 + y1 < cb->y1 - 1 && (!(tileComp->codeBlockStyle & 0x08) || y1 < 3)) {
2340                                     diag += coeff[tileComp->w - 1] ? 1 : 0;
2341                                 }
2342                             }
2343                             if (x < cb->x1 - 1) {
2344                                 if (coeff[1]) {
2345                                     ++horiz;
2346                                     horizSign += coeff[1] < 0 ? -1 : 1;
2347                                 }
2348                                 if (y0 + y1 > cb->y0) {
2349                                     diag += coeff[-(int)tileComp->w + 1] ? 1 : 0;
2350                                 }
2351                                 if (y0 + y1 < cb->y1 - 1 && (!(tileComp->codeBlockStyle & 0x08) || y1 < 3)) {
2352                                     diag += coeff[tileComp->w + 1] ? 1 : 0;
2353                                 }
2354                             }
2355                             if (y0 + y1 > cb->y0) {
2356                                 if (coeff[-(int)tileComp->w]) {
2357                                     ++vert;
2358                                     vertSign += coeff[-(int)tileComp->w] < 0 ? -1 : 1;
2359                                 }
2360                             }
2361                             if (y0 + y1 < cb->y1 - 1 && (!(tileComp->codeBlockStyle & 0x08) || y1 < 3)) {
2362                                 if (coeff[tileComp->w]) {
2363                                     ++vert;
2364                                     vertSign += coeff[tileComp->w] < 0 ? -1 : 1;
2365                                 }
2366                             }
2367                             cx = sigPropContext[horiz][vert][diag][res == 0 ? 1 : sb];
2368                             if (cb->arithDecoder->decodeBit(cx, cb->stats)) {
2369                                 cx = signContext[horizSign][vertSign][0];
2370                                 xorBit = signContext[horizSign][vertSign][1];
2371                                 if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) {
2372                                     *coeff = -1;
2373                                 } else {
2374                                     *coeff = 1;
2375                                 }
2376                             }
2377                         } else {
2378                             *touched = 0;
2379                         }
2380                     }
2381                 }
2382             }
2383             ++cb->len;
2384             // look for a segmentation symbol
2385             if (tileComp->codeBlockStyle & 0x20) {
2386                 segSym = cb->arithDecoder->decodeBit(jpxContextUniform, cb->stats) << 3;
2387                 segSym |= cb->arithDecoder->decodeBit(jpxContextUniform, cb->stats) << 2;
2388                 segSym |= cb->arithDecoder->decodeBit(jpxContextUniform, cb->stats) << 1;
2389                 segSym |= cb->arithDecoder->decodeBit(jpxContextUniform, cb->stats);
2390                 if (segSym != 0x0a) {
2391                     // in theory this should be a fatal error, but it seems to
2392                     // be problematic
2393                     error(errSyntaxWarning, getPos(), "Missing or invalid segmentation symbol in JPX stream");
2394                 }
2395             }
2396             cb->nextPass = jpxPassSigProp;
2397             break;
2398         }
2399 
2400         if (tileComp->codeBlockStyle & 0x02) {
2401             cb->stats->reset();
2402             cb->stats->setEntry(jpxContextSigProp, 4, 0);
2403             cb->stats->setEntry(jpxContextRunLength, 3, 0);
2404             cb->stats->setEntry(jpxContextUniform, 46, 0);
2405         }
2406 
2407         if (tileComp->codeBlockStyle & 0x04) {
2408             cb->arithDecoder->cleanup();
2409         }
2410     }
2411 
2412     cb->arithDecoder->cleanup();
2413     return true;
2414 }
2415 
2416 // Inverse quantization, and wavelet transform (IDWT).  This also does
2417 // the initial shift to convert to fixed point format.
2418 void JPXStream::inverseTransform(JPXTileComp *tileComp)
2419 {
2420     JPXResLevel *resLevel;
2421     JPXPrecinct *precinct;
2422     JPXSubband *subband;
2423     JPXCodeBlock *cb;
2424     int *coeff0, *coeff;
2425     char *touched0, *touched;
2426     unsigned int qStyle, guard, eps, shift;
2427     int shift2;
2428     double mu;
2429     int val;
2430     unsigned int r, cbX, cbY, x, y;
2431 
2432     cover(68);
2433 
2434     //----- (NL)LL subband (resolution level 0)
2435 
2436     resLevel = &tileComp->resLevels[0];
2437     precinct = &resLevel->precincts[0];
2438     subband = &precinct->subbands[0];
2439 
2440     // i-quant parameters
2441     qStyle = tileComp->quantStyle & 0x1f;
2442     guard = (tileComp->quantStyle >> 5) & 7;
2443     if (qStyle == 0) {
2444         cover(69);
2445         eps = (tileComp->quantSteps[0] >> 3) & 0x1f;
2446         shift = guard + eps - 1;
2447         mu = 0; // make gcc happy
2448     } else {
2449         cover(70);
2450         shift = guard - 1 + tileComp->prec;
2451         mu = (double)(0x800 + (tileComp->quantSteps[0] & 0x7ff)) / 2048.0;
2452     }
2453     if (tileComp->transform == 0) {
2454         cover(71);
2455         shift += fracBits;
2456     }
2457 
2458     // do fixed point adjustment and dequantization on (NL)LL
2459     cb = subband->cbs;
2460     for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
2461         for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
2462             for (y = cb->y0, coeff0 = cb->coeffs, touched0 = cb->touched; y < cb->y1; ++y, coeff0 += tileComp->w, touched0 += tileComp->cbW) {
2463                 for (x = cb->x0, coeff = coeff0, touched = touched0; x < cb->x1; ++x, ++coeff, ++touched) {
2464                     val = *coeff;
2465                     if (val != 0) {
2466                         shift2 = shift - (cb->nZeroBitPlanes + cb->len + *touched);
2467                         if (shift2 > 0) {
2468                             cover(94);
2469                             if (val < 0) {
2470                                 val = (((unsigned int)val) << shift2) - (1 << (shift2 - 1));
2471                             } else {
2472                                 val = (val << shift2) + (1 << (shift2 - 1));
2473                             }
2474                         } else {
2475                             cover(95);
2476                             val >>= -shift2;
2477                         }
2478                         if (qStyle == 0) {
2479                             cover(96);
2480                             if (tileComp->transform == 0) {
2481                                 cover(97);
2482                                 val &= 0xFFFFFFFF << fracBits;
2483                             }
2484                         } else {
2485                             cover(98);
2486                             val = (int)((double)val * mu);
2487                         }
2488                     }
2489                     *coeff = val;
2490                 }
2491             }
2492             ++cb;
2493         }
2494     }
2495 
2496     //----- IDWT for each level
2497 
2498     for (r = 1; r <= tileComp->nDecompLevels; ++r) {
2499         resLevel = &tileComp->resLevels[r];
2500 
2501         // (n)LL is already in the upper-left corner of the
2502         // tile-component data array -- interleave with (n)HL/LH/HH
2503         // and inverse transform to get (n-1)LL, which will be stored
2504         // in the upper-left corner of the tile-component data array
2505         inverseTransformLevel(tileComp, r, resLevel);
2506     }
2507 }
2508 
2509 // Do one level of the inverse transform:
2510 // - take (n)LL, (n)HL, (n)LH, and (n)HH from the upper-left corner
2511 //   of the tile-component data array
2512 // - leave the resulting (n-1)LL in the same place
2513 void JPXStream::inverseTransformLevel(JPXTileComp *tileComp, unsigned int r, JPXResLevel *resLevel)
2514 {
2515     JPXPrecinct *precinct;
2516     JPXSubband *subband;
2517     JPXCodeBlock *cb;
2518     int *coeff0, *coeff;
2519     char *touched0, *touched;
2520     unsigned int qStyle, guard, eps, shift, t;
2521     int shift2;
2522     double mu;
2523     int val;
2524     int *dataPtr, *bufPtr;
2525     unsigned int nx1, nx2, ny1, ny2, offset;
2526     unsigned int x, y, sb, cbX, cbY;
2527 
2528     //----- fixed-point adjustment and dequantization
2529 
2530     qStyle = tileComp->quantStyle & 0x1f;
2531     guard = (tileComp->quantStyle >> 5) & 7;
2532     precinct = &resLevel->precincts[0];
2533     for (sb = 0; sb < 3; ++sb) {
2534 
2535         // i-quant parameters
2536         if (qStyle == 0) {
2537             cover(100);
2538             const unsigned int stepIndex = 3 * r - 2 + sb;
2539             if (unlikely(stepIndex >= tileComp->nQuantSteps)) {
2540                 error(errSyntaxError, getPos(), "Wrong index for quantSteps in inverseTransformLevel in JPX stream");
2541                 break;
2542             }
2543             eps = (tileComp->quantSteps[stepIndex] >> 3) & 0x1f;
2544             shift = guard + eps - 1;
2545             mu = 0; // make gcc happy
2546         } else {
2547             cover(101);
2548             shift = guard + tileComp->prec;
2549             if (sb == 2) {
2550                 cover(102);
2551                 ++shift;
2552             }
2553             const unsigned int stepIndex = qStyle == 1 ? 0 : (3 * r - 2 + sb);
2554             if (unlikely(stepIndex >= tileComp->nQuantSteps)) {
2555                 error(errSyntaxError, getPos(), "Wrong index for quantSteps in inverseTransformLevel in JPX stream");
2556                 break;
2557             }
2558             t = tileComp->quantSteps[stepIndex];
2559             mu = (double)(0x800 + (t & 0x7ff)) / 2048.0;
2560         }
2561         if (tileComp->transform == 0) {
2562             cover(103);
2563             shift += fracBits;
2564         }
2565 
2566         // fixed point adjustment and dequantization
2567         subband = &precinct->subbands[sb];
2568         cb = subband->cbs;
2569         for (cbY = 0; cbY < subband->nYCBs; ++cbY) {
2570             for (cbX = 0; cbX < subband->nXCBs; ++cbX) {
2571                 for (y = cb->y0, coeff0 = cb->coeffs, touched0 = cb->touched; y < cb->y1; ++y, coeff0 += tileComp->w, touched0 += tileComp->cbW) {
2572                     for (x = cb->x0, coeff = coeff0, touched = touched0; x < cb->x1; ++x, ++coeff, ++touched) {
2573                         val = *coeff;
2574                         if (val != 0) {
2575                             shift2 = shift - (cb->nZeroBitPlanes + cb->len + *touched);
2576                             if (shift2 > 0) {
2577                                 cover(74);
2578                                 if (val < 0) {
2579                                     val = (((unsigned int)val) << shift2) - (1 << (shift2 - 1));
2580                                 } else {
2581                                     val = (val << shift2) + (1 << (shift2 - 1));
2582                                 }
2583                             } else {
2584                                 cover(75);
2585                                 val >>= -shift2;
2586                             }
2587                             if (qStyle == 0) {
2588                                 cover(76);
2589                                 if (tileComp->transform == 0) {
2590                                     val &= 0xFFFFFFFF << fracBits;
2591                                 }
2592                             } else {
2593                                 cover(77);
2594                                 val = (int)((double)val * mu);
2595                             }
2596                         }
2597                         *coeff = val;
2598                     }
2599                 }
2600                 ++cb;
2601             }
2602         }
2603     }
2604 
2605     //----- inverse transform
2606 
2607     // compute the subband bounds:
2608     //    0   nx1  nx2
2609     //    |    |    |
2610     //    v    v    v
2611     //   +----+----+
2612     //   | LL | HL | <- 0
2613     //   +----+----+
2614     //   | LH | HH | <- ny1
2615     //   +----+----+
2616     //               <- ny2
2617     nx1 = precinct->subbands[1].x1 - precinct->subbands[1].x0;
2618     nx2 = nx1 + precinct->subbands[0].x1 - precinct->subbands[0].x0;
2619     ny1 = precinct->subbands[0].y1 - precinct->subbands[0].y0;
2620     ny2 = ny1 + precinct->subbands[1].y1 - precinct->subbands[1].y0;
2621 
2622     // horizontal (row) transforms
2623     if (r == tileComp->nDecompLevels) {
2624         offset = 3 + (tileComp->x0 & 1);
2625     } else {
2626         offset = 3 + (tileComp->resLevels[r + 1].x0 & 1);
2627     }
2628     for (y = 0, dataPtr = tileComp->data; y < ny2; ++y, dataPtr += tileComp->w) {
2629         if (precinct->subbands[0].x0 == precinct->subbands[1].x0) {
2630             // fetch LL/LH
2631             for (x = 0, bufPtr = tileComp->buf + offset; x < nx1; ++x, bufPtr += 2) {
2632                 *bufPtr = dataPtr[x];
2633             }
2634             // fetch HL/HH
2635             for (x = nx1, bufPtr = tileComp->buf + offset + 1; x < nx2; ++x, bufPtr += 2) {
2636                 *bufPtr = dataPtr[x];
2637             }
2638         } else {
2639             // fetch LL/LH
2640             for (x = 0, bufPtr = tileComp->buf + offset + 1; x < nx1; ++x, bufPtr += 2) {
2641                 *bufPtr = dataPtr[x];
2642             }
2643             // fetch HL/HH
2644             for (x = nx1, bufPtr = tileComp->buf + offset; x < nx2; ++x, bufPtr += 2) {
2645                 *bufPtr = dataPtr[x];
2646             }
2647         }
2648         if (tileComp->x1 - tileComp->x0 > tileComp->y1 - tileComp->y0) {
2649             x = tileComp->x1 - tileComp->x0 + 5;
2650         } else {
2651             x = tileComp->y1 - tileComp->y0 + 5;
2652         }
2653         if (offset + nx2 > x || nx2 == 0) {
2654             error(errSyntaxError, getPos(), "Invalid call of inverseTransform1D in inverseTransformLevel in JPX stream");
2655             return;
2656         }
2657         inverseTransform1D(tileComp, tileComp->buf, offset, nx2);
2658         for (x = 0, bufPtr = tileComp->buf + offset; x < nx2; ++x, ++bufPtr) {
2659             dataPtr[x] = *bufPtr;
2660         }
2661     }
2662 
2663     // vertical (column) transforms
2664     if (r == tileComp->nDecompLevels) {
2665         offset = 3 + (tileComp->y0 & 1);
2666     } else {
2667         offset = 3 + (tileComp->resLevels[r + 1].y0 & 1);
2668     }
2669     for (x = 0, dataPtr = tileComp->data; x < nx2; ++x, ++dataPtr) {
2670         if (precinct->subbands[1].y0 == precinct->subbands[0].y0) {
2671             // fetch LL/HL
2672             for (y = 0, bufPtr = tileComp->buf + offset; y < ny1; ++y, bufPtr += 2) {
2673                 *bufPtr = dataPtr[y * tileComp->w];
2674             }
2675             // fetch LH/HH
2676             for (y = ny1, bufPtr = tileComp->buf + offset + 1; y < ny2; ++y, bufPtr += 2) {
2677                 *bufPtr = dataPtr[y * tileComp->w];
2678             }
2679         } else {
2680             // fetch LL/HL
2681             for (y = 0, bufPtr = tileComp->buf + offset + 1; y < ny1; ++y, bufPtr += 2) {
2682                 *bufPtr = dataPtr[y * tileComp->w];
2683             }
2684             // fetch LH/HH
2685             for (y = ny1, bufPtr = tileComp->buf + offset; y < ny2; ++y, bufPtr += 2) {
2686                 *bufPtr = dataPtr[y * tileComp->w];
2687             }
2688         }
2689         if (tileComp->x1 - tileComp->x0 > tileComp->y1 - tileComp->y0) {
2690             y = tileComp->x1 - tileComp->x0 + 5;
2691         } else {
2692             y = tileComp->y1 - tileComp->y0 + 5;
2693         }
2694         if (offset + ny2 > y || ny2 == 0) {
2695             error(errSyntaxError, getPos(), "Invalid call of inverseTransform1D in inverseTransformLevel in JPX stream");
2696             return;
2697         }
2698         inverseTransform1D(tileComp, tileComp->buf, offset, ny2);
2699         for (y = 0, bufPtr = tileComp->buf + offset; y < ny2; ++y, ++bufPtr) {
2700             dataPtr[y * tileComp->w] = *bufPtr;
2701         }
2702     }
2703 }
2704 
2705 void JPXStream::inverseTransform1D(JPXTileComp *tileComp, int *data, unsigned int offset, unsigned int n)
2706 {
2707     unsigned int end, i;
2708 
2709     //----- special case for length = 1
2710     if (n == 1) {
2711         cover(79);
2712         if (offset == 4) {
2713             cover(104);
2714             *data >>= 1;
2715         }
2716 
2717     } else {
2718         cover(80);
2719 
2720         end = offset + n;
2721 
2722         //----- extend right
2723         data[end] = data[end - 2];
2724         if (n == 2) {
2725             cover(81);
2726             data[end + 1] = data[offset + 1];
2727             data[end + 2] = data[offset];
2728             data[end + 3] = data[offset + 1];
2729         } else {
2730             cover(82);
2731             data[end + 1] = data[end - 3];
2732             if (n == 3) {
2733                 cover(105);
2734                 data[end + 2] = data[offset + 1];
2735                 data[end + 3] = data[offset + 2];
2736             } else {
2737                 cover(106);
2738                 data[end + 2] = data[end - 4];
2739                 if (n == 4) {
2740                     cover(107);
2741                     data[end + 3] = data[offset + 1];
2742                 } else {
2743                     cover(108);
2744                     data[end + 3] = data[end - 5];
2745                 }
2746             }
2747         }
2748 
2749         //----- extend left
2750         data[offset - 1] = data[offset + 1];
2751         data[offset - 2] = data[offset + 2];
2752         data[offset - 3] = data[offset + 3];
2753         if (offset == 4) {
2754             cover(83);
2755             data[0] = data[offset + 4];
2756         }
2757 
2758         //----- 9-7 irreversible filter
2759 
2760         if (tileComp->transform == 0) {
2761             cover(84);
2762             // step 1 (even)
2763             for (i = 1; i <= end + 2; i += 2) {
2764                 data[i] = (int)(idwtKappa * data[i]);
2765             }
2766             // step 2 (odd)
2767             for (i = 0; i <= end + 3; i += 2) {
2768                 data[i] = (int)(idwtIKappa * data[i]);
2769             }
2770             // step 3 (even)
2771             for (i = 1; i <= end + 2; i += 2) {
2772                 data[i] = (int)(data[i] - idwtDelta * (data[i - 1] + data[i + 1]));
2773             }
2774             // step 4 (odd)
2775             for (i = 2; i <= end + 1; i += 2) {
2776                 data[i] = (int)(data[i] - idwtGamma * (data[i - 1] + data[i + 1]));
2777             }
2778             // step 5 (even)
2779             for (i = 3; i <= end; i += 2) {
2780                 data[i] = (int)(data[i] - idwtBeta * (data[i - 1] + data[i + 1]));
2781             }
2782             // step 6 (odd)
2783             for (i = 4; i <= end - 1; i += 2) {
2784                 data[i] = (int)(data[i] - idwtAlpha * (data[i - 1] + data[i + 1]));
2785             }
2786 
2787             //----- 5-3 reversible filter
2788 
2789         } else {
2790             cover(85);
2791             // step 1 (even)
2792             for (i = 3; i <= end; i += 2) {
2793                 data[i] -= (data[i - 1] + data[i + 1] + 2) >> 2;
2794             }
2795             // step 2 (odd)
2796             for (i = 4; i < end; i += 2) {
2797                 data[i] += (data[i - 1] + data[i + 1]) >> 1;
2798             }
2799         }
2800     }
2801 }
2802 
2803 // Inverse multi-component transform and DC level shift.  This also
2804 // converts fixed point samples back to integers.
2805 bool JPXStream::inverseMultiCompAndDC(JPXTile *tile)
2806 {
2807     JPXTileComp *tileComp;
2808     int coeff, d0, d1, d2, t, minVal, maxVal, zeroVal;
2809     int *dataPtr;
2810     unsigned int j, comp, x, y;
2811 
2812     //----- inverse multi-component transform
2813 
2814     if (tile->multiComp == 1) {
2815         cover(86);
2816         if (img.nComps < 3 || tile->tileComps[0].hSep != tile->tileComps[1].hSep || tile->tileComps[0].vSep != tile->tileComps[1].vSep || tile->tileComps[1].hSep != tile->tileComps[2].hSep
2817             || tile->tileComps[1].vSep != tile->tileComps[2].vSep) {
2818             return false;
2819         }
2820 
2821         // inverse irreversible multiple component transform
2822         if (tile->tileComps[0].transform == 0) {
2823             cover(87);
2824             j = 0;
2825             for (y = 0; y < tile->tileComps[0].y1 - tile->tileComps[0].y0; ++y) {
2826                 for (x = 0; x < tile->tileComps[0].x1 - tile->tileComps[0].x0; ++x) {
2827                     d0 = tile->tileComps[0].data[j];
2828                     d1 = tile->tileComps[1].data[j];
2829                     d2 = tile->tileComps[2].data[j];
2830                     tile->tileComps[0].data[j] = (int)(d0 + 1.402 * d2 + 0.5);
2831                     tile->tileComps[1].data[j] = (int)(d0 - 0.34413 * d1 - 0.71414 * d2 + 0.5);
2832                     tile->tileComps[2].data[j] = (int)(d0 + 1.772 * d1 + 0.5);
2833                     ++j;
2834                 }
2835             }
2836 
2837             // inverse reversible multiple component transform
2838         } else {
2839             cover(88);
2840             j = 0;
2841             for (y = 0; y < tile->tileComps[0].y1 - tile->tileComps[0].y0; ++y) {
2842                 for (x = 0; x < tile->tileComps[0].x1 - tile->tileComps[0].x0; ++x) {
2843                     d0 = tile->tileComps[0].data[j];
2844                     d1 = tile->tileComps[1].data[j];
2845                     d2 = tile->tileComps[2].data[j];
2846                     tile->tileComps[1].data[j] = t = d0 - ((d2 + d1) >> 2);
2847                     tile->tileComps[0].data[j] = d2 + t;
2848                     tile->tileComps[2].data[j] = d1 + t;
2849                     ++j;
2850                 }
2851             }
2852         }
2853     }
2854 
2855     //----- DC level shift
2856     for (comp = 0; comp < img.nComps; ++comp) {
2857         tileComp = &tile->tileComps[comp];
2858 
2859         // signed: clip
2860         if (tileComp->sgned) {
2861             cover(89);
2862             minVal = -(1 << (tileComp->prec - 1));
2863             maxVal = (1 << (tileComp->prec - 1)) - 1;
2864             dataPtr = tileComp->data;
2865             for (y = 0; y < tileComp->y1 - tileComp->y0; ++y) {
2866                 for (x = 0; x < tileComp->x1 - tileComp->x0; ++x) {
2867                     coeff = *dataPtr;
2868                     if (tileComp->transform == 0) {
2869                         cover(109);
2870                         coeff >>= fracBits;
2871                     }
2872                     if (coeff < minVal) {
2873                         cover(110);
2874                         coeff = minVal;
2875                     } else if (coeff > maxVal) {
2876                         cover(111);
2877                         coeff = maxVal;
2878                     }
2879                     *dataPtr++ = coeff;
2880                 }
2881             }
2882 
2883             // unsigned: inverse DC level shift and clip
2884         } else {
2885             cover(90);
2886             maxVal = (1 << tileComp->prec) - 1;
2887             zeroVal = 1 << (tileComp->prec - 1);
2888             dataPtr = tileComp->data;
2889             for (y = 0; y < tileComp->y1 - tileComp->y0; ++y) {
2890                 for (x = 0; x < tileComp->x1 - tileComp->x0; ++x) {
2891                     coeff = *dataPtr;
2892                     if (tileComp->transform == 0) {
2893                         cover(112);
2894                         coeff >>= fracBits;
2895                     }
2896                     coeff += zeroVal;
2897                     if (coeff < 0) {
2898                         cover(113);
2899                         coeff = 0;
2900                     } else if (coeff > maxVal) {
2901                         cover(114);
2902                         coeff = maxVal;
2903                     }
2904                     *dataPtr++ = coeff;
2905                 }
2906             }
2907         }
2908     }
2909 
2910     return true;
2911 }
2912 
2913 bool JPXStream::readBoxHdr(unsigned int *boxType, unsigned int *boxLen, unsigned int *dataLen)
2914 {
2915     unsigned int len, lenH;
2916 
2917     if (!readULong(&len) || !readULong(boxType)) {
2918         return false;
2919     }
2920     if (len == 1) {
2921         if (!readULong(&lenH) || !readULong(&len)) {
2922             return false;
2923         }
2924         if (lenH) {
2925             error(errSyntaxError, getPos(), "JPX stream contains a box larger than 2^32 bytes");
2926             return false;
2927         }
2928         *boxLen = len;
2929         *dataLen = len - 16;
2930     } else if (len == 0) {
2931         *boxLen = 0;
2932         *dataLen = 0;
2933     } else {
2934         *boxLen = len;
2935         *dataLen = len - 8;
2936     }
2937     return true;
2938 }
2939 
2940 int JPXStream::readMarkerHdr(int *segType, unsigned int *segLen)
2941 {
2942     int c;
2943 
2944     do {
2945         do {
2946             if ((c = bufStr->getChar()) == EOF) {
2947                 return false;
2948             }
2949         } while (c != 0xff);
2950         do {
2951             if ((c = bufStr->getChar()) == EOF) {
2952                 return false;
2953             }
2954         } while (c == 0xff);
2955     } while (c == 0x00);
2956     *segType = c;
2957     if ((c >= 0x30 && c <= 0x3f) || c == 0x4f || c == 0x92 || c == 0x93 || c == 0xd9) {
2958         *segLen = 0;
2959         return true;
2960     }
2961     return readUWord(segLen);
2962 }
2963 
2964 bool JPXStream::readUByte(unsigned int *x)
2965 {
2966     int c0;
2967 
2968     if ((c0 = bufStr->getChar()) == EOF) {
2969         return false;
2970     }
2971     *x = (unsigned int)c0;
2972     return true;
2973 }
2974 
2975 bool JPXStream::readByte(int *x)
2976 {
2977     int c0;
2978 
2979     if ((c0 = bufStr->getChar()) == EOF) {
2980         return false;
2981     }
2982     *x = c0;
2983     if (c0 & 0x80) {
2984         *x |= -1 - 0xff;
2985     }
2986     return true;
2987 }
2988 
2989 bool JPXStream::readUWord(unsigned int *x)
2990 {
2991     int c0, c1;
2992 
2993     if ((c0 = bufStr->getChar()) == EOF || (c1 = bufStr->getChar()) == EOF) {
2994         return false;
2995     }
2996     *x = (unsigned int)((c0 << 8) | c1);
2997     return true;
2998 }
2999 
3000 bool JPXStream::readULong(unsigned int *x)
3001 {
3002     int c0, c1, c2, c3;
3003 
3004     if ((c0 = bufStr->getChar()) == EOF || (c1 = bufStr->getChar()) == EOF || (c2 = bufStr->getChar()) == EOF || (c3 = bufStr->getChar()) == EOF) {
3005         return false;
3006     }
3007     *x = (unsigned int)((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
3008     return true;
3009 }
3010 
3011 bool JPXStream::readNBytes(int nBytes, bool signd, int *x)
3012 {
3013     int y, c, i;
3014 
3015     y = 0;
3016     for (i = 0; i < nBytes; ++i) {
3017         if ((c = bufStr->getChar()) == EOF) {
3018             return false;
3019         }
3020         y = (y << 8) + c;
3021     }
3022     if (signd) {
3023         if (y & (1 << (8 * nBytes - 1))) {
3024             y |= -1 << (8 * nBytes);
3025         }
3026     }
3027     *x = y;
3028     return true;
3029 }
3030 
3031 void JPXStream::startBitBuf(unsigned int byteCountA)
3032 {
3033     bitBufLen = 0;
3034     bitBufSkip = false;
3035     byteCount = byteCountA;
3036 }
3037 
3038 bool JPXStream::readBits(int nBits, unsigned int *x)
3039 {
3040     int c;
3041 
3042     while (bitBufLen < nBits) {
3043         if (byteCount == 0 || (c = bufStr->getChar()) == EOF) {
3044             return false;
3045         }
3046         --byteCount;
3047         if (bitBufSkip) {
3048             bitBuf = (bitBuf << 7) | (c & 0x7f);
3049             bitBufLen += 7;
3050         } else {
3051             bitBuf = (bitBuf << 8) | (c & 0xff);
3052             bitBufLen += 8;
3053         }
3054         bitBufSkip = c == 0xff;
3055     }
3056     *x = (bitBuf >> (bitBufLen - nBits)) & ((1 << nBits) - 1);
3057     bitBufLen -= nBits;
3058     return true;
3059 }
3060 
3061 void JPXStream::skipSOP()
3062 {
3063     int i;
3064 
3065     // SOP occurs at the start of the packet header, so we don't need to
3066     // worry about bit-stuff prior to it
3067     if (byteCount >= 6 && bufStr->lookChar(0) == 0xff && bufStr->lookChar(1) == 0x91) {
3068         for (i = 0; i < 6; ++i) {
3069             bufStr->getChar();
3070         }
3071         byteCount -= 6;
3072         bitBufLen = 0;
3073         bitBufSkip = false;
3074     }
3075 }
3076 
3077 void JPXStream::skipEPH()
3078 {
3079     int i, k;
3080 
3081     k = bitBufSkip ? 1 : 0;
3082     if (byteCount >= (unsigned int)(k + 2) && bufStr->lookChar(k) == 0xff && bufStr->lookChar(k + 1) == 0x92) {
3083         for (i = 0; i < k + 2; ++i) {
3084             bufStr->getChar();
3085         }
3086         byteCount -= k + 2;
3087         bitBufLen = 0;
3088         bitBufSkip = false;
3089     }
3090 }
3091 
3092 unsigned int JPXStream::finishBitBuf()
3093 {
3094     if (bitBufSkip) {
3095         bufStr->getChar();
3096         --byteCount;
3097     }
3098     return byteCount;
3099 }
3100