Coverage Report

Created: 2022-03-21 07:20

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