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

Last change on this file since 461 was 257, checked in by Eugene Romanenko, 13 years ago

PDF plugin: Poppler library updated to version 0.10.0

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