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