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