Coverage Report

Created: 2025-07-23 08:18

/src/jasper/src/libjasper/jpc/jpc_t1enc.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 1999-2000 Image Power, Inc. and the University of
3
 *   British Columbia.
4
 * Copyright (c) 2001-2002 Michael David Adams.
5
 * All rights reserved.
6
 */
7
8
/* __START_OF_JASPER_LICENSE__
9
 * 
10
 * JasPer License Version 2.0
11
 * 
12
 * Copyright (c) 2001-2006 Michael David Adams
13
 * Copyright (c) 1999-2000 Image Power, Inc.
14
 * Copyright (c) 1999-2000 The University of British Columbia
15
 * 
16
 * All rights reserved.
17
 * 
18
 * Permission is hereby granted, free of charge, to any person (the
19
 * "User") obtaining a copy of this software and associated documentation
20
 * files (the "Software"), to deal in the Software without restriction,
21
 * including without limitation the rights to use, copy, modify, merge,
22
 * publish, distribute, and/or sell copies of the Software, and to permit
23
 * persons to whom the Software is furnished to do so, subject to the
24
 * following conditions:
25
 * 
26
 * 1.  The above copyright notices and this permission notice (which
27
 * includes the disclaimer below) shall be included in all copies or
28
 * substantial portions of the Software.
29
 * 
30
 * 2.  The name of a copyright holder shall not be used to endorse or
31
 * promote products derived from the Software without specific prior
32
 * written permission.
33
 * 
34
 * THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS
35
 * LICENSE.  NO USE OF THE SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER
36
 * THIS DISCLAIMER.  THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
37
 * "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
38
 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
39
 * PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.  IN NO
40
 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
41
 * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
42
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
43
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
44
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.  NO ASSURANCES ARE
45
 * PROVIDED BY THE COPYRIGHT HOLDERS THAT THE SOFTWARE DOES NOT INFRINGE
46
 * THE PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS OF ANY OTHER ENTITY.
47
 * EACH COPYRIGHT HOLDER DISCLAIMS ANY LIABILITY TO THE USER FOR CLAIMS
48
 * BROUGHT BY ANY OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL
49
 * PROPERTY RIGHTS OR OTHERWISE.  AS A CONDITION TO EXERCISING THE RIGHTS
50
 * GRANTED HEREUNDER, EACH USER HEREBY ASSUMES SOLE RESPONSIBILITY TO SECURE
51
 * ANY OTHER INTELLECTUAL PROPERTY RIGHTS NEEDED, IF ANY.  THE SOFTWARE
52
 * IS NOT FAULT-TOLERANT AND IS NOT INTENDED FOR USE IN MISSION-CRITICAL
53
 * SYSTEMS, SUCH AS THOSE USED IN THE OPERATION OF NUCLEAR FACILITIES,
54
 * AIRCRAFT NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL
55
 * SYSTEMS, DIRECT LIFE SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH
56
 * THE FAILURE OF THE SOFTWARE OR SYSTEM COULD LEAD DIRECTLY TO DEATH,
57
 * PERSONAL INJURY, OR SEVERE PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH
58
 * RISK ACTIVITIES").  THE COPYRIGHT HOLDERS SPECIFICALLY DISCLAIM ANY
59
 * EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH RISK ACTIVITIES.
60
 * 
61
 * __END_OF_JASPER_LICENSE__
62
 */
63
64
/*
65
 * Tier 1 Encoder
66
 *
67
 * $Id$
68
 */
69
70
/******************************************************************************\
71
* Includes.
72
\******************************************************************************/
73
74
#include "jpc_t1enc.h"
75
#include "jpc_t1cod.h"
76
#include "jpc_enc.h"
77
#include "jpc_math.h"
78
79
#include "jasper/jas_malloc.h"
80
#include "jasper/jas_math.h"
81
#include "jasper/jas_debug.h"
82
83
#include <stdio.h>
84
#include <stdlib.h>
85
#include <assert.h>
86
87
/* Encode a single code block. */
88
static int jpc_enc_enccblk(const jpc_enc_tcmpt_t *comp,
89
  const jpc_enc_band_t *band, jpc_enc_cblk_t *cblk);
90
91
static int jpc_encsigpass(jpc_mqenc_t *mqenc, int bitpos, enum jpc_tsfb_orient orient, bool vcausalflag,
92
  jas_matrix_t *flags, const jas_matrix_t *data, int term, long *nmsedec);
93
94
static int jpc_encrefpass(jpc_mqenc_t *mqenc, int bitpos, jas_matrix_t *flags,
95
  const jas_matrix_t *data, int term, long *nmsedec);
96
97
static int jpc_encclnpass(jpc_mqenc_t *mqenc, int bitpos, enum jpc_tsfb_orient orient, bool vcausalflag,
98
  bool segsym, jas_matrix_t *flags, const jas_matrix_t *data, int term, long *nmsedec);
99
100
static int jpc_encrawsigpass(jpc_bitstream_t *out, int bitpos, bool vcausalflag,
101
  jas_matrix_t *flags, const jas_matrix_t *data, int term, long *nmsedec);
102
103
static int jpc_encrawrefpass(jpc_bitstream_t *out, int bitpos,
104
  jas_matrix_t *flags, const jas_matrix_t *data, int term, long *nmsedec);
105
106
/******************************************************************************\
107
* Code for encoding code blocks.
108
\******************************************************************************/
109
110
/* Encode all of the code blocks associated with the current tile. */
111
int jpc_enc_enccblks(jpc_enc_t *enc)
112
0
{
113
0
  jpc_enc_tcmpt_t *tcmpt;
114
0
  jpc_enc_tcmpt_t *endcomps;
115
0
  jpc_enc_rlvl_t *lvl;
116
0
  jpc_enc_rlvl_t *endlvls;
117
0
  jpc_enc_band_t *band;
118
0
  jpc_enc_band_t *endbands;
119
0
  jpc_enc_cblk_t *cblk;
120
0
  jpc_enc_cblk_t *endcblks;
121
0
  jpc_fix_t mx;
122
0
  jpc_fix_t bmx;
123
0
  jpc_fix_t v;
124
0
  jpc_enc_tile_t *tile;
125
0
  uint_fast32_t prcno;
126
0
  jpc_enc_prc_t *prc;
127
128
0
  tile = enc->curtile;
129
130
0
  endcomps = &tile->tcmpts[tile->numtcmpts];
131
0
  for (tcmpt = tile->tcmpts; tcmpt != endcomps; ++tcmpt) {
132
0
    endlvls = &tcmpt->rlvls[tcmpt->numrlvls];
133
0
    for (lvl = tcmpt->rlvls; lvl != endlvls; ++lvl) {
134
0
      if (!lvl->bands) {
135
0
        continue;
136
0
      }
137
0
      endbands = &lvl->bands[lvl->numbands];
138
0
      for (band = lvl->bands; band != endbands; ++band) {
139
0
        if (!band->data) {
140
0
          continue;
141
0
        }
142
0
        for (prcno = 0, prc = band->prcs; prcno < lvl->numprcs; ++prcno, ++prc) {
143
0
          if (!prc->cblks) {
144
0
            continue;
145
0
          }
146
0
          bmx = 0;
147
0
          endcblks = &prc->cblks[prc->numcblks];
148
0
          for (cblk = prc->cblks; cblk != endcblks; ++cblk) {
149
0
            mx = 0;
150
0
            for (jas_matind_t i = 0; i < jas_matrix_numrows(cblk->data); ++i) {
151
0
              for (jas_matind_t j = 0; j < jas_matrix_numcols(cblk->data); ++j) {
152
0
                v = JAS_ABS(jas_matrix_get(cblk->data, i, j));
153
0
                if (v > mx) {
154
0
                  mx = v;
155
0
                }
156
0
              }
157
0
            }
158
0
            if (mx > bmx) {
159
0
              bmx = mx;
160
0
            }
161
0
            cblk->numbps = JAS_MAX(jpc_fix_firstone(mx) + 1 - JPC_NUMEXTRABITS, 0);
162
0
          }
163
164
0
          for (cblk = prc->cblks; cblk != endcblks; ++cblk) {
165
0
            cblk->numimsbs = band->numbps - cblk->numbps;
166
0
            assert(cblk->numimsbs >= 0);
167
0
          }
168
169
0
          for (cblk = prc->cblks; cblk != endcblks; ++cblk) {
170
0
            if (jpc_enc_enccblk(tcmpt, band, cblk)) {
171
0
              return -1;
172
0
            }
173
0
          }
174
0
        }
175
0
      }
176
0
    }
177
0
  }
178
0
  return 0;
179
0
}
180
181
static int getthebyte(jas_stream_t *in, long off)
182
0
{
183
0
  int c;
184
0
  long oldpos;
185
0
  oldpos = jas_stream_tell(in);
186
0
  assert(oldpos >= 0);
187
0
  jas_stream_seek(in, off, SEEK_SET);
188
0
  c = jas_stream_peekc(in);
189
0
  jas_stream_seek(in, oldpos, SEEK_SET);
190
0
  return c;
191
0
}
192
193
/* Encode a single code block. */
194
static int jpc_enc_enccblk(const jpc_enc_tcmpt_t *tcmpt, const jpc_enc_band_t *band, jpc_enc_cblk_t *cblk)
195
0
{
196
0
  jpc_enc_pass_t *pass;
197
0
  jpc_enc_pass_t *endpasses;
198
0
  int bitpos;
199
0
  int n;
200
0
  int ret;
201
0
  jpc_bitstream_t *bout;
202
0
  int c;
203
204
0
  bout = 0;
205
206
0
  if (!(cblk->stream = jas_stream_memopen(0, 0))) {
207
0
    goto error;
208
0
  }
209
0
  if (!(cblk->mqenc = jpc_mqenc_create(JPC_NUMCTXS, cblk->stream))) {
210
0
    goto error;
211
0
  }
212
0
  jpc_mqenc_setctxs(cblk->mqenc, JPC_NUMCTXS, jpc_mqctxs);
213
214
0
  cblk->numpasses = (cblk->numbps > 0) ? (3 * cblk->numbps - 2) : 0;
215
0
  if (cblk->numpasses > 0) {
216
0
    if (!(cblk->passes = jas_alloc2(cblk->numpasses,
217
0
      sizeof(jpc_enc_pass_t)))) {
218
0
      goto error;
219
0
    };
220
0
  } else {
221
0
    cblk->passes = 0;
222
0
  }
223
0
  endpasses = (cblk->passes) ? &cblk->passes[cblk->numpasses] : 0;
224
0
  for (pass = cblk->passes; pass != endpasses; ++pass) {
225
0
    pass->start = 0;
226
0
    pass->end = 0;
227
0
    pass->term = JPC_ISTERMINATED(pass - cblk->passes, 0, cblk->numpasses,
228
0
      (tcmpt->cblksty & JPC_COX_TERMALL) != 0,
229
0
      (tcmpt->cblksty & JPC_COX_LAZY) != 0);
230
0
    pass->type = JPC_SEGTYPE(pass - cblk->passes, 0,
231
0
      (tcmpt->cblksty & JPC_COX_LAZY) != 0);
232
0
    pass->lyrno = -1;
233
0
    if (pass == endpasses - 1) {
234
0
      assert(pass->term == 1);
235
0
      pass->term = 1;
236
0
    }
237
0
  }
238
239
0
  if (!(cblk->flags = jas_matrix_create(jas_matrix_numrows(cblk->data) + 2,
240
0
    jas_matrix_numcols(cblk->data) + 2))) {
241
0
    jas_logerrorf("cannot create matrix\n");
242
0
    goto error;
243
0
  }
244
245
0
  bitpos = cblk->numbps - 1;
246
0
  pass = cblk->passes;
247
0
  n = cblk->numpasses;
248
0
  while (--n >= 0) {
249
250
0
    if (pass->type == JPC_SEG_MQ) {
251
      /* NOP */
252
0
    } else {
253
0
      assert(pass->type == JPC_SEG_RAW);
254
0
      if (!bout) {
255
0
        bout = jpc_bitstream_sopen(cblk->stream, "w");
256
0
        if (!bout) {
257
0
          goto error;
258
0
        }
259
0
      }
260
0
    }
261
262
0
    enum jpc_passtype passtype = JPC_PASSTYPE(pass - cblk->passes);
263
0
    pass->start = jas_stream_tell(cblk->stream);
264
#if 0
265
assert(jas_stream_tell(cblk->stream) == jas_stream_getrwcount(cblk->stream));
266
#endif
267
0
    assert(bitpos >= 0);
268
0
    const bool vcausal = (tcmpt->cblksty & JPC_COX_VSC) != 0;
269
0
    const bool segsym = (tcmpt->cblksty & JPC_COX_SEGSYM) != 0;
270
0
    unsigned termmode;
271
0
    if (pass->term) {
272
0
      termmode = ((tcmpt->cblksty & JPC_COX_PTERM) ?
273
0
        JPC_MQENC_PTERM : JPC_MQENC_DEFTERM) + 1;
274
0
    } else {
275
0
      termmode = 0;
276
0
    }
277
0
    switch (passtype) {
278
0
    case JPC_SIGPASS:
279
0
      ret = (pass->type == JPC_SEG_MQ) ? jpc_encsigpass(cblk->mqenc,
280
0
        bitpos, band->orient, vcausal, cblk->flags,
281
0
        cblk->data, termmode, &pass->nmsedec) :
282
0
        jpc_encrawsigpass(bout, bitpos, vcausal, cblk->flags,
283
0
        cblk->data, termmode, &pass->nmsedec);
284
0
      break;
285
0
    case JPC_REFPASS:
286
0
      ret = (pass->type == JPC_SEG_MQ) ? jpc_encrefpass(cblk->mqenc,
287
0
        bitpos, cblk->flags, cblk->data, termmode,
288
0
        &pass->nmsedec) : jpc_encrawrefpass(bout, bitpos,
289
0
        cblk->flags, cblk->data, termmode,
290
0
        &pass->nmsedec);
291
0
      break;
292
0
    case JPC_CLNPASS:
293
0
      assert(pass->type == JPC_SEG_MQ);
294
0
      ret = jpc_encclnpass(cblk->mqenc, bitpos, band->orient,
295
0
        vcausal, segsym, cblk->flags, cblk->data, termmode,
296
0
        &pass->nmsedec);
297
0
      break;
298
0
    default:
299
0
      assert(0);
300
0
      break;
301
0
    }
302
303
0
    if (ret) {
304
0
      if (bout) {
305
0
        jpc_bitstream_close(bout);
306
0
      }
307
0
      goto error;
308
0
    }
309
310
0
    if (pass->type == JPC_SEG_MQ) {
311
0
      if (pass->term) {
312
0
        jpc_mqenc_init(cblk->mqenc);
313
0
      }
314
0
      jpc_mqenc_getstate(cblk->mqenc, &pass->mqencstate);
315
0
      pass->end = jas_stream_tell(cblk->stream);
316
0
      if (tcmpt->cblksty & JPC_COX_RESET) {
317
0
        jpc_mqenc_setctxs(cblk->mqenc, JPC_NUMCTXS, jpc_mqctxs);
318
0
      }
319
0
    } else {
320
0
      if (pass->term) {
321
0
        if (jpc_bitstream_pending(bout)) {
322
0
          jpc_bitstream_outalign(bout, 0x2a);
323
0
        }
324
0
        jpc_bitstream_close(bout);
325
0
        bout = 0;
326
0
        pass->end = jas_stream_tell(cblk->stream);
327
0
      } else {
328
0
        pass->end = jas_stream_tell(cblk->stream) +
329
0
          jpc_bitstream_pending(bout);
330
/* NOTE - This will not work.  need to adjust by # of pending output bytes */
331
0
      }
332
0
    }
333
#if 0
334
/* XXX - This assertion fails sometimes when various coding modes are used.
335
This seems to be harmless, but why does it happen at all? */
336
assert(jas_stream_tell(cblk->stream) == jas_stream_getrwcount(cblk->stream));
337
#endif
338
339
0
    pass->wmsedec = jpc_fixtodbl(band->rlvl->tcmpt->synweight) *
340
0
      jpc_fixtodbl(band->rlvl->tcmpt->synweight) *
341
0
      jpc_fixtodbl(band->synweight) *
342
0
      jpc_fixtodbl(band->synweight) *
343
0
      jpc_fixtodbl(band->absstepsize) * jpc_fixtodbl(band->absstepsize) *
344
0
      ((double) (1 << bitpos)) * ((double)(1 << bitpos)) *
345
0
      jpc_fixtodbl(pass->nmsedec);
346
0
    pass->cumwmsedec = pass->wmsedec;
347
0
    if (pass != cblk->passes) {
348
0
      pass->cumwmsedec += pass[-1].cumwmsedec;
349
0
    }
350
0
    if (passtype == JPC_CLNPASS) {
351
0
      --bitpos;
352
0
    }
353
0
    ++pass;
354
0
  }
355
356
#if 0
357
dump_passes(cblk->passes, cblk->numpasses, cblk);
358
#endif
359
360
0
  n = 0;
361
0
  endpasses = (cblk->passes) ? &cblk->passes[cblk->numpasses] : 0;
362
0
  for (pass = cblk->passes; pass != endpasses; ++pass) {
363
0
    if (pass->start < n) {
364
0
      pass->start = n;
365
0
    }
366
0
    if (pass->end < n) {
367
0
      pass->end = n;
368
0
    }
369
0
    if (!pass->term) {
370
0
      const jpc_enc_pass_t *termpass = pass;
371
0
      while (termpass - pass < cblk->numpasses &&
372
0
        !termpass->term) {
373
0
        ++termpass;
374
0
      }
375
0
      if (pass->type == JPC_SEG_MQ) {
376
0
        unsigned t = (pass->mqencstate.lastbyte == 0xff) ? 1 : 0;
377
0
        unsigned adjust;
378
0
        if (pass->mqencstate.ctreg >= 5) {
379
0
          adjust = 4 + t;
380
0
        } else {
381
0
          adjust = 5 + t;
382
0
        }
383
0
        pass->end += adjust;
384
0
      }
385
0
      if (pass->end > termpass->end) {
386
0
        pass->end = termpass->end;
387
0
      }
388
0
      if ((c = getthebyte(cblk->stream, pass->end - 1)) == EOF) {
389
0
        if (bout) {
390
0
          jpc_bitstream_close(bout);
391
0
        }
392
0
        return -1;
393
0
      }
394
0
      if (c == 0xff) {
395
0
        ++pass->end;
396
0
      }
397
0
      n = JAS_MAX(n, pass->end);
398
0
    } else {
399
0
      n = JAS_MAX(n, pass->end);
400
0
    }
401
0
  }
402
403
#if 0
404
dump_passes(cblk->passes, cblk->numpasses, cblk);
405
#endif
406
407
0
  if (bout) {
408
0
    jpc_bitstream_close(bout);
409
0
  }
410
411
0
  return 0;
412
413
0
error:
414
0
  return -1;
415
0
}
416
417
/******************************************************************************\
418
* Code for significance pass.
419
\******************************************************************************/
420
421
0
#define sigpass_step(fp, frowstep, dp, bitpos, one, nmsedec, orient, mqenc, vcausalflag) \
422
0
{ \
423
0
  jpc_fix_t f; \
424
0
  f = *(fp); \
425
0
  if ((f & JPC_OTHSIGMSK) && !(f & (JPC_SIG | JPC_VISIT))) { \
426
0
    bool v = (JAS_ABS(*(dp)) & (one)) != 0; \
427
0
    jpc_mqenc_setcurctx(mqenc, JPC_GETZCCTXNO(f, (orient))); \
428
0
    jpc_mqenc_putbit(mqenc, v); \
429
0
    if (v) { \
430
0
      *(nmsedec) += JPC_GETSIGNMSEDEC(JAS_ABS(*(dp)), (bitpos) + JPC_NUMEXTRABITS); \
431
0
      v = ((*(dp) < 0) ? 1 : 0); \
432
0
      jpc_mqenc_setcurctx(mqenc, JPC_GETSCCTXNO(f)); \
433
0
      jpc_mqenc_putbit(mqenc, v ^ JPC_GETSPB(f)); \
434
0
      JPC_UPDATEFLAGS4(fp, frowstep, v, vcausalflag); \
435
0
      *(fp) |= JPC_SIG; \
436
0
    } \
437
0
    *(fp) |= JPC_VISIT; \
438
0
  } \
439
0
}
440
441
static int jpc_encsigpass(jpc_mqenc_t *mqenc, int bitpos, enum jpc_tsfb_orient orient, bool vcausalflag,
442
  jas_matrix_t *flags, const jas_matrix_t *data, int term, long *nmsedec)
443
0
{
444
0
  int i;
445
0
  int one;
446
0
  jpc_fix_t *fstripestart;
447
0
  jpc_fix_t *fp;
448
0
  jpc_fix_t *fvscanstart;
449
450
0
  *nmsedec = 0;
451
0
  const unsigned width = jas_matrix_numcols(data);
452
0
  const unsigned height = jas_matrix_numrows(data);
453
0
  const unsigned frowstep = jas_matrix_rowstep(flags);
454
0
  const unsigned drowstep = jas_matrix_rowstep(data);
455
0
  const unsigned fstripestep = frowstep << 2;
456
0
  const unsigned dstripestep = drowstep << 2;
457
458
0
  one = 1 << (bitpos + JPC_NUMEXTRABITS);
459
460
0
  fstripestart = jas_matrix_getref(flags, 1, 1);
461
0
  const jpc_fix_t *dstripestart = jas_matrix_getref(data, 0, 0);
462
0
  for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
463
0
    dstripestart += dstripestep) {
464
0
    fvscanstart = fstripestart;
465
0
    const jpc_fix_t *dvscanstart = dstripestart;
466
0
    const unsigned vscanlen = JAS_MIN(i, 4);
467
0
    for (unsigned j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
468
0
      fp = fvscanstart;
469
0
      const jpc_fix_t *dp = dvscanstart;
470
0
      unsigned k = vscanlen;
471
472
0
      sigpass_step(fp, frowstep, dp, bitpos, one,
473
0
        nmsedec, orient, mqenc, vcausalflag);
474
0
      if (--k <= 0) {
475
0
        continue;
476
0
      }
477
0
      fp += frowstep;
478
0
      dp += drowstep;
479
0
      sigpass_step(fp, frowstep, dp, bitpos, one,
480
0
        nmsedec, orient, mqenc, 0);
481
0
      if (--k <= 0) {
482
0
        continue;
483
0
      }
484
0
      fp += frowstep;
485
0
      dp += drowstep;
486
0
      sigpass_step(fp, frowstep, dp, bitpos, one,
487
0
        nmsedec, orient, mqenc, 0);
488
0
      if (--k <= 0) {
489
0
        continue;
490
0
      }
491
0
      fp += frowstep;
492
0
      dp += drowstep;
493
0
      sigpass_step(fp, frowstep, dp, bitpos, one,
494
0
        nmsedec, orient, mqenc, 0);
495
496
0
    }
497
0
  }
498
499
0
  if (term) {
500
0
    jpc_mqenc_flush(mqenc, term - 1);
501
0
  }
502
503
0
  return jpc_mqenc_error(mqenc) ? (-1) : 0;
504
0
}
505
506
0
#define rawsigpass_step(fp, frowstep, dp, bitpos, one, nmsedec, out, vcausalflag) \
507
0
{ \
508
0
  jpc_fix_t f = *(fp); \
509
0
  if ((f & JPC_OTHSIGMSK) && !(f & (JPC_SIG | JPC_VISIT))) { \
510
0
    bool v = (JAS_ABS(*(dp)) & (one)) != 0; \
511
0
    if ((jpc_bitstream_putbit((out), v)) == EOF) { \
512
0
      return -1; \
513
0
    } \
514
0
    if (v) { \
515
0
      *(nmsedec) += JPC_GETSIGNMSEDEC(JAS_ABS(*(dp)), (bitpos) + JPC_NUMEXTRABITS); \
516
0
      v = *(dp) < 0; \
517
0
      if (jpc_bitstream_putbit(out, v) == EOF) { \
518
0
        return -1; \
519
0
      } \
520
0
      JPC_UPDATEFLAGS4(fp, frowstep, v, vcausalflag); \
521
0
      *(fp) |= JPC_SIG; \
522
0
    } \
523
0
    *(fp) |= JPC_VISIT; \
524
0
  } \
525
0
}
526
527
static int jpc_encrawsigpass(jpc_bitstream_t *out, int bitpos, bool vcausalflag, jas_matrix_t *flags,
528
  const jas_matrix_t *data, int term, long *nmsedec)
529
0
{
530
0
  int i;
531
0
  int one;
532
0
  jpc_fix_t *fstripestart;
533
0
  jpc_fix_t *fp;
534
0
  jpc_fix_t *fvscanstart;
535
536
0
  *nmsedec = 0;
537
0
  const unsigned width = jas_matrix_numcols(data);
538
0
  const unsigned height = jas_matrix_numrows(data);
539
0
  const unsigned frowstep = jas_matrix_rowstep(flags);
540
0
  const unsigned drowstep = jas_matrix_rowstep(data);
541
0
  const unsigned fstripestep = frowstep << 2;
542
0
  const unsigned dstripestep = drowstep << 2;
543
544
0
  one = 1 << (bitpos + JPC_NUMEXTRABITS);
545
546
0
  fstripestart = jas_matrix_getref(flags, 1, 1);
547
0
  const jpc_fix_t *dstripestart = jas_matrix_getref(data, 0, 0);
548
0
  for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
549
0
    dstripestart += dstripestep) {
550
0
    fvscanstart = fstripestart;
551
0
    const jpc_fix_t *dvscanstart = dstripestart;
552
0
    const unsigned vscanlen = JAS_MIN(i, 4);
553
0
    for (unsigned j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
554
0
      fp = fvscanstart;
555
0
      const jpc_fix_t *dp = dvscanstart;
556
0
      unsigned k = vscanlen;
557
558
0
      rawsigpass_step(fp, frowstep, dp, bitpos, one,
559
0
        nmsedec, out, vcausalflag);
560
0
      if (--k <= 0) {
561
0
        continue;
562
0
      }
563
0
      fp += frowstep;
564
0
      dp += drowstep;
565
566
0
      rawsigpass_step(fp, frowstep, dp, bitpos, one,
567
0
        nmsedec, out, 0);
568
0
      if (--k <= 0) {
569
0
        continue;
570
0
      }
571
0
      fp += frowstep;
572
0
      dp += drowstep;
573
574
0
      rawsigpass_step(fp, frowstep, dp, bitpos, one,
575
0
        nmsedec, out, 0);
576
0
      if (--k <= 0) {
577
0
        continue;
578
0
      }
579
0
      fp += frowstep;
580
0
      dp += drowstep;
581
582
0
      rawsigpass_step(fp, frowstep, dp, bitpos, one,
583
0
        nmsedec, out, 0);
584
0
      if (--k <= 0) {
585
0
        continue;
586
0
      }
587
0
      fp += frowstep;
588
0
      dp += drowstep;
589
590
0
    }
591
0
  }
592
593
0
  if (term) {
594
0
    jpc_bitstream_outalign(out, 0x2a);
595
0
  }
596
597
0
  return 0;
598
0
}
599
600
/******************************************************************************\
601
* Code for refinement pass.
602
\******************************************************************************/
603
604
0
#define refpass_step(fp, dp, bitpos, one, nmsedec, mqenc, vcausalflag) \
605
0
{ \
606
0
  jpc_fix_t d; \
607
0
  if (((*(fp)) & (JPC_SIG | JPC_VISIT)) == JPC_SIG) { \
608
0
    (d) = *(dp); \
609
0
    *(nmsedec) += JPC_GETREFNMSEDEC(JAS_ABS(d), (bitpos) + JPC_NUMEXTRABITS); \
610
0
    jpc_mqenc_setcurctx((mqenc), JPC_GETMAGCTXNO(*(fp))); \
611
0
    const bool v = (JAS_ABS(d) & (one)) != 0; \
612
0
    jpc_mqenc_putbit((mqenc), v); \
613
0
    *(fp) |= JPC_REFINE; \
614
0
  } \
615
0
}
616
617
static int jpc_encrefpass(jpc_mqenc_t *mqenc, int bitpos, jas_matrix_t *flags, const jas_matrix_t *data,
618
  int term, long *nmsedec)
619
0
{
620
0
  int i;
621
0
  int one;
622
0
  jpc_fix_t *fstripestart;
623
0
  jpc_fix_t *fvscanstart;
624
0
  jpc_fix_t *fp;
625
626
0
  *nmsedec = 0;
627
0
  const unsigned width = jas_matrix_numcols(data);
628
0
  const unsigned height = jas_matrix_numrows(data);
629
0
  const unsigned frowstep = jas_matrix_rowstep(flags);
630
0
  const unsigned drowstep = jas_matrix_rowstep(data);
631
0
  const unsigned fstripestep = frowstep << 2;
632
0
  const unsigned dstripestep = drowstep << 2;
633
634
0
  one = 1 << (bitpos + JPC_NUMEXTRABITS);
635
636
0
  fstripestart = jas_matrix_getref(flags, 1, 1);
637
0
  const jpc_fix_t *dstripestart = jas_matrix_getref(data, 0, 0);
638
0
  for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
639
0
    dstripestart += dstripestep) {
640
0
    fvscanstart = fstripestart;
641
0
    const jpc_fix_t *dvscanstart = dstripestart;
642
0
    const unsigned vscanlen = JAS_MIN(i, 4);
643
0
    for (unsigned j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
644
0
      fp = fvscanstart;
645
0
      const jpc_fix_t *dp = dvscanstart;
646
0
      unsigned k = vscanlen;
647
648
0
      refpass_step(fp, dp, bitpos, one, nmsedec,
649
0
        mqenc, vcausalflag);
650
0
      if (--k <= 0) {
651
0
        continue;
652
0
      }
653
0
      fp += frowstep;
654
0
      dp += drowstep;
655
0
      refpass_step(fp, dp, bitpos, one, nmsedec,
656
0
        mqenc, 0);
657
0
      if (--k <= 0) {
658
0
        continue;
659
0
      }
660
0
      fp += frowstep;
661
0
      dp += drowstep;
662
0
      refpass_step(fp, dp, bitpos, one, nmsedec,
663
0
        mqenc, 0);
664
0
      if (--k <= 0) {
665
0
        continue;
666
0
      }
667
0
      fp += frowstep;
668
0
      dp += drowstep;
669
0
      refpass_step(fp, dp, bitpos, one, nmsedec,
670
0
        mqenc, 0);
671
672
0
    }
673
0
  }
674
675
0
  if (term) {
676
0
    jpc_mqenc_flush(mqenc, term - 1);
677
0
  }
678
679
0
  return jpc_mqenc_error(mqenc) ? (-1) : 0;
680
0
}
681
682
0
#define rawrefpass_step(fp, dp, bitpos, one, nmsedec, out, vcausalflag) \
683
0
{ \
684
0
  jpc_fix_t d; \
685
0
  if (((*(fp)) & (JPC_SIG | JPC_VISIT)) == JPC_SIG) { \
686
0
    d = *(dp); \
687
0
    *(nmsedec) += JPC_GETREFNMSEDEC(JAS_ABS(d), (bitpos) + JPC_NUMEXTRABITS); \
688
0
    const bool v = (JAS_ABS(d) & (one)) != 0; \
689
0
    if (jpc_bitstream_putbit((out), v) == EOF) { \
690
0
      return -1; \
691
0
    } \
692
0
    *(fp) |= JPC_REFINE; \
693
0
  } \
694
0
}
695
696
static int jpc_encrawrefpass(jpc_bitstream_t *out, int bitpos, jas_matrix_t *flags,
697
  const jas_matrix_t *data, int term, long *nmsedec)
698
0
{
699
0
  int i;
700
0
  int one;
701
0
  jpc_fix_t *fstripestart;
702
0
  jpc_fix_t *fvscanstart;
703
0
  jpc_fix_t *fp;
704
705
0
  *nmsedec = 0;
706
0
  const unsigned width = jas_matrix_numcols(data);
707
0
  const unsigned height = jas_matrix_numrows(data);
708
0
  const unsigned frowstep = jas_matrix_rowstep(flags);
709
0
  const unsigned drowstep = jas_matrix_rowstep(data);
710
0
  const unsigned fstripestep = frowstep << 2;
711
0
  const unsigned dstripestep = drowstep << 2;
712
713
0
  one = 1 << (bitpos + JPC_NUMEXTRABITS);
714
715
0
  fstripestart = jas_matrix_getref(flags, 1, 1);
716
0
  const jpc_fix_t *dstripestart = jas_matrix_getref(data, 0, 0);
717
0
  for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
718
0
    dstripestart += dstripestep) {
719
0
    fvscanstart = fstripestart;
720
0
    const jpc_fix_t *dvscanstart = dstripestart;
721
0
    const unsigned vscanlen = JAS_MIN(i, 4);
722
0
    for (unsigned j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
723
0
      fp = fvscanstart;
724
0
      const jpc_fix_t *dp = dvscanstart;
725
0
      unsigned k = vscanlen;
726
727
0
      rawrefpass_step(fp, dp, bitpos, one, nmsedec,
728
0
        out, vcausalflag);
729
0
      if (--k <= 0) {
730
0
        continue;
731
0
      }
732
0
      fp += frowstep;
733
0
      dp += drowstep;
734
0
      rawrefpass_step(fp, dp, bitpos, one, nmsedec,
735
0
        out, vcausalflag);
736
0
      if (--k <= 0) {
737
0
        continue;
738
0
      }
739
0
      fp += frowstep;
740
0
      dp += drowstep;
741
0
      rawrefpass_step(fp, dp, bitpos, one, nmsedec,
742
0
        out, vcausalflag);
743
0
      if (--k <= 0) {
744
0
        continue;
745
0
      }
746
0
      fp += frowstep;
747
0
      dp += drowstep;
748
0
      rawrefpass_step(fp, dp, bitpos, one, nmsedec,
749
0
        out, vcausalflag);
750
751
0
    }
752
0
  }
753
754
0
  if (term) {
755
0
    jpc_bitstream_outalign(out, 0x2a);
756
0
  }
757
758
0
  return 0;
759
0
}
760
761
/******************************************************************************\
762
* Code for cleanup pass.
763
\******************************************************************************/
764
765
0
#define clnpass_step(fp, frowstep, dp, bitpos, one, orient, nmsedec, mqenc, label1, label2, vcausalflag) \
766
0
{ \
767
0
  jpc_fix_t f; \
768
0
label1 \
769
0
  f = *(fp); \
770
0
  if (!(f & (JPC_SIG | JPC_VISIT))) { \
771
0
    jpc_mqenc_setcurctx(mqenc, JPC_GETZCCTXNO(f, (orient))); \
772
0
    bool v = (JAS_ABS(*(dp)) & (one)) != 0; \
773
0
    jpc_mqenc_putbit((mqenc), v); \
774
0
    if (v) { \
775
0
label2 \
776
0
      f = *(fp); \
777
0
      /* Coefficient is significant. */ \
778
0
      *(nmsedec) += JPC_GETSIGNMSEDEC(JAS_ABS(*(dp)), (bitpos) + JPC_NUMEXTRABITS); \
779
0
      jpc_mqenc_setcurctx((mqenc), JPC_GETSCCTXNO(f)); \
780
0
      v = ((*(dp) < 0) ? 1 : 0); \
781
0
      jpc_mqenc_putbit((mqenc), v ^ JPC_GETSPB(f)); \
782
0
      JPC_UPDATEFLAGS4((fp), (frowstep), v, vcausalflag); \
783
0
      *(fp) |= JPC_SIG; \
784
0
    } \
785
0
  } \
786
0
  *(fp) &= ~JPC_VISIT; \
787
0
}
788
789
static int jpc_encclnpass(jpc_mqenc_t *mqenc, int bitpos, enum jpc_tsfb_orient orient, bool vcausalflag, bool segsymflag, jas_matrix_t *flags,
790
  const jas_matrix_t *data, int term, long *nmsedec)
791
0
{
792
0
  int i;
793
0
  jpc_fix_t *fp;
794
0
  int one;
795
0
  jpc_fix_t *fstripestart;
796
0
  jpc_fix_t *fvscanstart;
797
798
0
  *nmsedec = 0;
799
0
  const unsigned width = jas_matrix_numcols(data);
800
0
  const unsigned height = jas_matrix_numrows(data);
801
0
  const unsigned frowstep = jas_matrix_rowstep(flags);
802
0
  const unsigned drowstep = jas_matrix_rowstep(data);
803
0
  const unsigned fstripestep = frowstep << 2;
804
0
  const unsigned dstripestep = drowstep << 2;
805
806
0
  one = 1 << (bitpos + JPC_NUMEXTRABITS);
807
808
0
  fstripestart = jas_matrix_getref(flags, 1, 1);
809
0
  const jpc_fix_t *dstripestart = jas_matrix_getref(data, 0, 0);
810
0
  for (i = height; i > 0; i -= 4, fstripestart += fstripestep,
811
0
    dstripestart += dstripestep) {
812
0
    fvscanstart = fstripestart;
813
0
    const jpc_fix_t *dvscanstart = dstripestart;
814
0
    const unsigned vscanlen = JAS_MIN(i, 4);
815
0
    for (unsigned j = width; j > 0; --j, ++fvscanstart, ++dvscanstart) {
816
817
0
      fp = fvscanstart;
818
0
      const jpc_fix_t *dp;
819
0
      unsigned k;
820
0
      if (vscanlen >= 4 && !((*fp) & (JPC_SIG | JPC_VISIT |
821
0
        JPC_OTHSIGMSK)) && (fp += frowstep, !((*fp) & (JPC_SIG |
822
0
        JPC_VISIT | JPC_OTHSIGMSK))) && (fp += frowstep, !((*fp) &
823
0
        (JPC_SIG | JPC_VISIT | JPC_OTHSIGMSK))) && (fp += frowstep,
824
0
        !((*fp) & (JPC_SIG | JPC_VISIT | JPC_OTHSIGMSK)))) {
825
0
        dp = dvscanstart;
826
0
        for (k = 0; k < vscanlen; ++k) {
827
0
          const bool v = (JAS_ABS(*dp) & one) != 0;
828
0
          if (v) {
829
0
            break;
830
0
          }
831
0
          dp += drowstep;
832
0
        }
833
0
        unsigned runlen = k;
834
0
        if (runlen >= 4) {
835
0
          jpc_mqenc_setcurctx(mqenc, JPC_AGGCTXNO);
836
0
          jpc_mqenc_putbit(mqenc, false);
837
0
          continue;
838
0
        }
839
0
        jpc_mqenc_setcurctx(mqenc, JPC_AGGCTXNO);
840
0
        jpc_mqenc_putbit(mqenc, true);
841
0
        jpc_mqenc_setcurctx(mqenc, JPC_UCTXNO);
842
0
        jpc_mqenc_putbit(mqenc, runlen >> 1);
843
0
        jpc_mqenc_putbit(mqenc, runlen & 1);
844
0
        fp = fvscanstart + frowstep * runlen;
845
0
        dp = dvscanstart + drowstep * runlen;
846
0
        k = vscanlen - runlen;
847
0
        switch (runlen) {
848
0
        case 0:
849
0
          goto clnpass_partial0;
850
0
        case 1:
851
0
          goto clnpass_partial1;
852
0
        case 2:
853
0
          goto clnpass_partial2;
854
0
        case 3:
855
0
          goto clnpass_partial3;
856
0
        }
857
0
      } else {
858
0
        fp = fvscanstart;
859
0
        dp = dvscanstart;
860
0
        k = vscanlen;
861
0
        goto clnpass_full0;
862
0
      }
863
0
      clnpass_step(fp, frowstep, dp, bitpos, one,
864
0
        orient, nmsedec, mqenc, clnpass_full0:, clnpass_partial0:, vcausalflag);
865
0
      if (--k <= 0) {
866
0
        continue;
867
0
      }
868
0
      fp += frowstep;
869
0
      dp += drowstep;
870
0
      clnpass_step(fp, frowstep, dp, bitpos, one,
871
0
        orient, nmsedec, mqenc, ;, clnpass_partial1:, 0);
872
0
      if (--k <= 0) {
873
0
        continue;
874
0
      }
875
0
      fp += frowstep;
876
0
      dp += drowstep;
877
0
      clnpass_step(fp, frowstep, dp, bitpos, one,
878
0
        orient, nmsedec, mqenc, ;, clnpass_partial2:, 0);
879
0
      if (--k <= 0) {
880
0
        continue;
881
0
      }
882
0
      fp += frowstep;
883
0
      dp += drowstep;
884
0
      clnpass_step(fp, frowstep, dp, bitpos, one,
885
0
        orient, nmsedec, mqenc, ;, clnpass_partial3:, 0);
886
0
    }
887
0
  }
888
889
0
  if (segsymflag) {
890
0
    jpc_mqenc_setcurctx(mqenc, JPC_UCTXNO);
891
0
    jpc_mqenc_putbit(mqenc, true);
892
0
    jpc_mqenc_putbit(mqenc, false);
893
0
    jpc_mqenc_putbit(mqenc, true);
894
0
    jpc_mqenc_putbit(mqenc, false);
895
0
  }
896
897
0
  if (term) {
898
0
    jpc_mqenc_flush(mqenc, term - 1);
899
0
  }
900
901
0
  return jpc_mqenc_error(mqenc) ? (-1) : 0;
902
0
}