Coverage Report

Created: 2023-09-25 06:41

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