source: trunk/poppler/mypoppler/poppler/JPXStream.cc @ 2

Last change on this file since 2 was 2, checked in by Eugene Romanenko, 15 years ago

First import

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