Coverage Report

Created: 2026-05-24 07:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/jasper/src/libjasper/jpc/jpc_mqenc.c
Line
Count
Source
1
/*
2
 * Copyright (c) 1999-2000 Image Power, Inc. and the University of
3
 *   British Columbia.
4
 * Copyright (c) 2001-2003 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
 * MQ Arithmetic Encoder
66
 *
67
 * $Id$
68
 */
69
70
/******************************************************************************\
71
* Includes.
72
\******************************************************************************/
73
74
#include "jpc_mqenc.h"
75
76
#include "jasper/jas_stream.h"
77
#include "jasper/jas_malloc.h"
78
#include "jasper/jas_math.h"
79
#include "jasper/jas_debug.h"
80
81
#include <stdlib.h>
82
83
/******************************************************************************\
84
* Macros
85
\******************************************************************************/
86
87
#ifndef NDEBUG
88
#define JPC_MQENC_CALL(n, x) \
89
2.28G
  ((jas_get_debug_level() >= (n)) ? ((void)(x)) : ((void)0))
90
#else
91
#define JPC_MQENC_CALL(n, x)
92
#endif
93
94
#define jpc_mqenc_codemps9(areg, creg, ctreg, curctx, enc) \
95
{ \
96
  const jpc_mqstate_t *state = *(curctx); \
97
  (areg) -= state->qeval; \
98
  if (!((areg) & 0x8000)) { \
99
    if ((areg) < state->qeval) { \
100
      (areg) = state->qeval; \
101
    } else { \
102
      (creg) += state->qeval; \
103
    } \
104
    *(curctx) = state->nmps; \
105
    jpc_mqenc_renorme((areg), (creg), (ctreg), (enc)); \
106
  } else { \
107
    (creg) += state->qeval; \
108
  } \
109
}
110
111
455M
#define jpc_mqenc_codelps2(areg, creg, ctreg, curctx, enc) \
112
455M
{ \
113
455M
  const jpc_mqstate_t *state = *(curctx); \
114
455M
  (areg) -= state->qeval; \
115
455M
  if ((areg) < state->qeval) { \
116
103M
    (creg) += state->qeval; \
117
352M
  } else { \
118
352M
    (areg) = state->qeval; \
119
352M
  } \
120
455M
  *(curctx) = state->nlps; \
121
455M
  jpc_mqenc_renorme((areg), (creg), (ctreg), (enc)); \
122
455M
}
123
124
897M
#define jpc_mqenc_renorme(areg, creg, ctreg, enc) \
125
897M
{ \
126
1.15G
  do { \
127
1.15G
    (areg) <<= 1; \
128
1.15G
    (creg) <<= 1; \
129
1.15G
    if (!--(ctreg)) { \
130
144M
      jpc_mqenc_byteout((areg), (creg), (ctreg), (enc)); \
131
144M
    } \
132
1.15G
  } while (!((areg) & 0x8000)); \
133
897M
}
134
135
145M
#define jpc_mqenc_byteout(areg, creg, ctreg, enc) \
136
145M
{ \
137
145M
  if ((enc)->outbuf != 0xff) { \
138
144M
    if ((creg) & 0x8000000) { \
139
5.07M
      if (++((enc)->outbuf) == 0xff) { \
140
20.7k
        (creg) &= 0x7ffffff; \
141
20.7k
        jpc_mqenc_byteout2(enc); \
142
20.7k
        enc->outbuf = ((creg) >> 20) & 0xff; \
143
20.7k
        (creg) &= 0xfffff; \
144
20.7k
        (ctreg) = 7; \
145
5.05M
      } else { \
146
5.05M
        jpc_mqenc_byteout2(enc); \
147
5.05M
        enc->outbuf = ((creg) >> 19) & 0xff; \
148
5.05M
        (creg) &= 0x7ffff; \
149
5.05M
        (ctreg) = 8; \
150
5.05M
      } \
151
139M
    } else { \
152
139M
      jpc_mqenc_byteout2(enc); \
153
139M
      (enc)->outbuf = ((creg) >> 19) & 0xff; \
154
139M
      (creg) &= 0x7ffff; \
155
139M
      (ctreg) = 8; \
156
139M
    } \
157
144M
  } else { \
158
694k
    jpc_mqenc_byteout2(enc); \
159
694k
    (enc)->outbuf = ((creg) >> 20) & 0xff; \
160
694k
    (creg) &= 0xfffff; \
161
694k
    (ctreg) = 7; \
162
694k
  } \
163
145M
}
164
165
static void jpc_mqenc_byteout2(jpc_mqenc_t *enc)
166
145M
{
167
145M
  if (enc->outbuf >= 0) {
168
145M
    if (jas_stream_putc(enc->out, (unsigned char)enc->outbuf) == EOF) {
169
0
      enc->err = true;
170
0
    }
171
145M
  }
172
145M
  enc->lastbyte = enc->outbuf;
173
145M
}
174
175
/******************************************************************************\
176
* Local function protoypes.
177
\******************************************************************************/
178
179
static void jpc_mqenc_setbits(jpc_mqenc_t *mqenc);
180
181
/******************************************************************************\
182
* Code for creation and destruction of encoder.
183
\******************************************************************************/
184
185
/* Create a MQ encoder. */
186
187
jpc_mqenc_t *jpc_mqenc_create(unsigned maxctxs, jas_stream_t *out)
188
536k
{
189
536k
  jpc_mqenc_t *mqenc;
190
191
  /* Allocate memory for the MQ encoder. */
192
536k
  if (!(mqenc = jas_malloc(sizeof(jpc_mqenc_t)))) {
193
0
    goto error;
194
0
  }
195
536k
  mqenc->out = out;
196
536k
  mqenc->maxctxs = maxctxs;
197
198
  /* Allocate memory for the per-context state information. */
199
536k
  if (!(mqenc->ctxs = jas_alloc2(mqenc->maxctxs, sizeof(jpc_mqstate_t *)))) {
200
0
    goto error;
201
0
  }
202
203
  /* Set the current context to the first one. */
204
536k
  mqenc->curctx = mqenc->ctxs;
205
206
536k
  jpc_mqenc_init(mqenc);
207
208
  /* Initialize the per-context state information to something sane. */
209
536k
  jpc_mqenc_setctxs(mqenc, 0, 0);
210
211
536k
  return mqenc;
212
213
0
error:
214
0
  if (mqenc) {
215
0
    jpc_mqenc_destroy(mqenc);
216
0
  }
217
0
  return 0;
218
536k
}
219
220
/* Destroy a MQ encoder. */
221
222
void jpc_mqenc_destroy(jpc_mqenc_t *mqenc)
223
536k
{
224
536k
  jas_free(mqenc->ctxs);
225
536k
  jas_free(mqenc);
226
536k
}
227
228
/******************************************************************************\
229
* State initialization code.
230
\******************************************************************************/
231
232
/* Initialize the coding state of a MQ encoder. */
233
234
void jpc_mqenc_init(jpc_mqenc_t *mqenc)
235
671k
{
236
671k
  mqenc->areg = 0x8000;
237
671k
  mqenc->outbuf = -1;
238
671k
  mqenc->creg = 0;
239
671k
  mqenc->ctreg = 12;
240
671k
  mqenc->lastbyte = -1;
241
671k
  mqenc->err = false;
242
671k
}
243
244
/* Initialize one or more contexts. */
245
246
void jpc_mqenc_setctxs(jpc_mqenc_t *mqenc, unsigned numctxs, const jpc_mqctx_t *ctxs)
247
1.07M
{
248
1.07M
  const jpc_mqstate_t **ctx;
249
250
1.07M
  ctx = mqenc->ctxs;
251
1.07M
  unsigned n = JAS_MIN(mqenc->maxctxs, numctxs);
252
11.2M
  while (n-- > 0) {
253
10.1M
    *ctx = &jpc_mqstates[2 * ctxs->ind + ctxs->mps];
254
10.1M
    ++ctx;
255
10.1M
    ++ctxs;
256
10.1M
  }
257
1.07M
  n = mqenc->maxctxs - numctxs;
258
11.2M
  while (n-- > 0) {
259
10.1M
    *ctx = &jpc_mqstates[0];
260
10.1M
    ++ctx;
261
10.1M
  }
262
263
1.07M
}
264
265
/* Get the coding state for a MQ encoder. */
266
267
void jpc_mqenc_getstate(const jpc_mqenc_t *mqenc, jpc_mqencstate_t *state)
268
3.23M
{
269
3.23M
  state->areg = mqenc->areg;
270
3.23M
  state->creg = mqenc->creg;
271
3.23M
  state->ctreg = mqenc->ctreg;
272
3.23M
  state->lastbyte = mqenc->lastbyte;
273
3.23M
}
274
275
/******************************************************************************\
276
* Code for coding symbols.
277
\******************************************************************************/
278
279
/* Encode a bit. */
280
281
int jpc_mqenc_putbit(jpc_mqenc_t *mqenc, bool bit)
282
2.28G
{
283
2.28G
  const jpc_mqstate_t *state;
284
2.28G
  JAS_LOGDEBUGF(100, "jpc_mqenc_putbit(%p, %d)\n", mqenc, bit);
285
2.28G
  JPC_MQENC_CALL(100, jpc_mqenc_dump(mqenc));
286
287
2.28G
  state = *(mqenc->curctx);
288
289
2.28G
  if (state->mps == bit) {
290
    /* Apply the CODEMPS algorithm as defined in the standard. */
291
1.82G
    mqenc->areg -= state->qeval;
292
1.82G
    if (!(mqenc->areg & 0x8000)) {
293
441M
      jpc_mqenc_codemps2(mqenc);
294
1.38G
    } else {
295
1.38G
      mqenc->creg += state->qeval;
296
1.38G
    }
297
1.82G
  } else {
298
    /* Apply the CODELPS algorithm as defined in the standard. */
299
455M
    jpc_mqenc_codelps2(mqenc->areg, mqenc->creg, mqenc->ctreg, mqenc->curctx, mqenc);
300
455M
  }
301
302
2.28G
  return jpc_mqenc_error(mqenc) ? (-1) : 0;
303
2.28G
}
304
305
int jpc_mqenc_codemps2(jpc_mqenc_t *mqenc)
306
441M
{
307
  /* Note: This function only performs part of the work associated with
308
  the CODEMPS algorithm from the standard.  Some of the work is also
309
  performed by the caller. */
310
311
441M
  const jpc_mqstate_t *state = *(mqenc->curctx);
312
441M
  if (mqenc->areg < state->qeval) {
313
115M
    mqenc->areg = state->qeval;
314
325M
  } else {
315
325M
    mqenc->creg += state->qeval;
316
325M
  }
317
441M
  *mqenc->curctx = state->nmps;
318
441M
  jpc_mqenc_renorme(mqenc->areg, mqenc->creg, mqenc->ctreg, mqenc);
319
441M
  return jpc_mqenc_error(mqenc) ? (-1) : 0;
320
441M
}
321
322
int jpc_mqenc_codelps(jpc_mqenc_t *mqenc)
323
0
{
324
0
  jpc_mqenc_codelps2(mqenc->areg, mqenc->creg, mqenc->ctreg, mqenc->curctx, mqenc);
325
0
  return jpc_mqenc_error(mqenc) ? (-1) : 0;
326
0
}
327
328
/******************************************************************************\
329
* Miscellaneous code.
330
\******************************************************************************/
331
332
/* Terminate the code word. */
333
334
int jpc_mqenc_flush(jpc_mqenc_t *mqenc, int termmode)
335
135k
{
336
135k
  int_fast16_t k;
337
338
135k
  switch (termmode) {
339
0
  case JPC_MQENC_PTERM:
340
0
    k = 11 - mqenc->ctreg + 1;
341
0
    while (k > 0) {
342
0
      mqenc->creg <<= mqenc->ctreg;
343
0
      mqenc->ctreg = 0;
344
0
      jpc_mqenc_byteout(mqenc->areg, mqenc->creg, mqenc->ctreg,
345
0
        mqenc);
346
0
      k -= mqenc->ctreg;
347
0
    }
348
0
    if (mqenc->outbuf != 0xff) {
349
0
      jpc_mqenc_byteout(mqenc->areg, mqenc->creg, mqenc->ctreg, mqenc);
350
0
    }
351
0
    break;
352
135k
  case JPC_MQENC_DEFTERM:
353
135k
    jpc_mqenc_setbits(mqenc);
354
135k
    mqenc->creg <<= mqenc->ctreg;
355
135k
    jpc_mqenc_byteout(mqenc->areg, mqenc->creg, mqenc->ctreg, mqenc);
356
135k
    mqenc->creg <<= mqenc->ctreg;
357
135k
    jpc_mqenc_byteout(mqenc->areg, mqenc->creg, mqenc->ctreg, mqenc);
358
135k
    if (mqenc->outbuf != 0xff) {
359
35.8k
      jpc_mqenc_byteout(mqenc->areg, mqenc->creg, mqenc->ctreg, mqenc);
360
35.8k
    }
361
135k
    break;
362
0
  default:
363
0
    assert(false);
364
0
    JAS_UNREACHABLE();
365
135k
  }
366
135k
  return 0;
367
135k
}
368
369
static void jpc_mqenc_setbits(jpc_mqenc_t *mqenc)
370
135k
{
371
135k
  uint_least32_t tmp = mqenc->creg + mqenc->areg;
372
135k
  mqenc->creg |= 0xffff;
373
135k
  if (mqenc->creg >= tmp) {
374
27.5k
    mqenc->creg -= 0x8000;
375
27.5k
  }
376
135k
}
377
378
/* Dump a MQ encoder to a stream for debugging. */
379
380
int jpc_mqenc_dump(const jpc_mqenc_t *mqenc)
381
0
{
382
0
  jas_logprintf("AREG = %08"PRIxLEAST32", CREG = %08"PRIxLEAST32", CTREG = %"PRIuLEAST32"\n",
383
0
    mqenc->areg, mqenc->creg, mqenc->ctreg);
384
0
  jas_logprintf("IND = %02"PRIdPTR", MPS = %d, QEVAL = %04"PRIxLEAST16"\n",
385
0
    *mqenc->curctx - jpc_mqstates, (*mqenc->curctx)->mps,
386
0
    (*mqenc->curctx)->qeval);
387
0
  return 0;
388
0
}