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