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