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