#include "opj_includes.h"
+#include <assert.h>
+
/** @defgroup MQC MQC - Implementation of an MQ-Coder */
/*@{*/
/* <summary> */
/* This array defines all the possible states for a context. */
/* </summary> */
-static opj_mqc_state_t mqc_states[47 * 2] = {
+static const opj_mqc_state_t mqc_states[47 * 2] = {
{0x5601, 0, &mqc_states[2], &mqc_states[3]},
{0x5601, 1, &mqc_states[3], &mqc_states[2]},
{0x3401, 0, &mqc_states[4], &mqc_states[12]},
static void opj_mqc_byteout(opj_mqc_t *mqc)
{
- /* avoid accessing uninitialized memory*/
- if (mqc->bp == mqc->start - 1) {
- mqc->bp++;
- *mqc->bp = (OPJ_BYTE)(mqc->c >> 19);
- mqc->c &= 0x7ffff;
- mqc->ct = 8;
- } else if (*mqc->bp == 0xff) {
+ /* bp is initialized to start - 1 in opj_mqc_init_enc() */
+ /* but this is safe, see opj_tcd_code_block_enc_allocate_data() */
+ assert(mqc->bp >= mqc->start - 1);
+ if (*mqc->bp == 0xff) {
mqc->bp++;
*mqc->bp = (OPJ_BYTE)(mqc->c >> 20);
mqc->c &= 0xfffff;
==========================================================
*/
-opj_mqc_t* opj_mqc_create(void)
-{
- opj_mqc_t *mqc = (opj_mqc_t*)opj_malloc(sizeof(opj_mqc_t));
- return mqc;
-}
-
-void opj_mqc_destroy(opj_mqc_t *mqc)
-{
- if (mqc) {
- opj_free(mqc);
- }
-}
-
OPJ_UINT32 opj_mqc_numbytes(opj_mqc_t *mqc)
{
const ptrdiff_t diff = mqc->bp - mqc->start;
void opj_mqc_init_enc(opj_mqc_t *mqc, OPJ_BYTE *bp)
{
- /* TODO MSD: need to take a look to the v2 version */
+ /* To avoid the curctx pointer to be dangling, but not strictly */
+ /* required as the current context is always set before encoding */
opj_mqc_setcurctx(mqc, 0);
+
+ /* As specified in Figure C.10 - Initialization of the encoder */
+ /* (C.2.8 Initialization of the encoder (INITENC)) */
mqc->a = 0x8000;
mqc->c = 0;
+ /* Yes, we point before the start of the buffer, but this is safe */
+ /* given opj_tcd_code_block_enc_allocate_data() */
mqc->bp = bp - 1;
mqc->ct = 12;
+ /* At this point we should test *(mqc->bp) against 0xFF, but this is not */
+ /* necessary, as this is only used at the beginning of the code block */
+ /* and our initial fake byte is set at 0 */
+ assert(*(mqc->bp) != 0xff);
+
mqc->start = bp;
+ mqc->end_of_byte_stream_counter = 0;
}
void opj_mqc_encode(opj_mqc_t *mqc, OPJ_UINT32 d)
void opj_mqc_flush(opj_mqc_t *mqc)
{
+ /* C.2.9 Termination of coding (FLUSH) */
+ /* Figure C.11 – FLUSH procedure */
opj_mqc_setbits(mqc);
mqc->c <<= mqc->ct;
opj_mqc_byteout(mqc);
mqc->c <<= mqc->ct;
opj_mqc_byteout(mqc);
+ /* It is forbidden that a coding pass ends with 0xff */
if (*mqc->bp != 0xff) {
+ /* Advance pointer so that opj_mqc_numbytes() returns a valid value */
mqc->bp++;
}
}
+#define BYPASS_CT_INIT 0xDEADBEEF
+
void opj_mqc_bypass_init_enc(opj_mqc_t *mqc)
{
+ /* This function is normally called after at least one opj_mqc_flush() */
+ /* which will have advance mqc->bp by at least 2 bytes beyond its */
+ /* initial position */
+ assert(mqc->bp >= mqc->start);
mqc->c = 0;
- mqc->ct = 8;
- /*if (*mqc->bp == 0xff) {
- mqc->ct = 7;
- } */
+ /* in theory we should initialize to 8, but use this special value */
+ /* as a hint that opj_mqc_bypass_enc() has never been called, so */
+ /* as to avoid the 0xff 0x7f elimination trick in opj_mqc_bypass_flush_enc() */
+ /* to trigger when we don't have output any bit during this bypass sequence */
+ /* Any value > 8 will do */
+ mqc->ct = BYPASS_CT_INIT;
+ /* Given that we are called after opj_mqc_flush(), the previous byte */
+ /* cannot be 0xff. */
+ assert(mqc->bp[-1] != 0xff);
}
void opj_mqc_bypass_enc(opj_mqc_t *mqc, OPJ_UINT32 d)
{
+ if (mqc->ct == BYPASS_CT_INIT) {
+ mqc->ct = 8;
+ }
mqc->ct--;
mqc->c = mqc->c + (d << mqc->ct);
if (mqc->ct == 0) {
- mqc->bp++;
*mqc->bp = (OPJ_BYTE)mqc->c;
mqc->ct = 8;
+ /* If the previous byte was 0xff, make sure that the next msb is 0 */
if (*mqc->bp == 0xff) {
mqc->ct = 7;
}
+ mqc->bp++;
mqc->c = 0;
}
}
-OPJ_UINT32 opj_mqc_bypass_flush_enc(opj_mqc_t *mqc)
+OPJ_UINT32 opj_mqc_bypass_get_extra_bytes(opj_mqc_t *mqc, OPJ_BOOL erterm)
{
- OPJ_BYTE bit_padding;
-
- bit_padding = 0;
+ return (mqc->ct < 7 ||
+ (mqc->ct == 7 && (erterm || mqc->bp[-1] != 0xff))) ? 1 : 0;
+}
- if (mqc->ct != 0) {
+void opj_mqc_bypass_flush_enc(opj_mqc_t *mqc, OPJ_BOOL erterm)
+{
+ /* Is there any bit remaining to be flushed ? */
+ /* If the last output byte is 0xff, we can discard it, unless */
+ /* erterm is required (I'm not completely sure why in erterm */
+ /* we must output 0xff 0x2a if the last byte was 0xff instead of */
+ /* discarding it, but Kakadu requires it when decoding */
+ /* in -fussy mode) */
+ if (mqc->ct < 7 || (mqc->ct == 7 && (erterm || mqc->bp[-1] != 0xff))) {
+ OPJ_BYTE bit_value = 0;
+ /* If so, fill the remaining lsbs with an alternating sequence of */
+ /* 0,1,... */
+ /* Note: it seems the standard only requires that for a ERTERM flush */
+ /* and doesn't specify what to do for a regular BYPASS flush */
while (mqc->ct > 0) {
mqc->ct--;
- mqc->c += (OPJ_UINT32)(bit_padding << mqc->ct);
- bit_padding = (bit_padding + 1) & 0x01;
+ mqc->c += (OPJ_UINT32)(bit_value << mqc->ct);
+ bit_value = (OPJ_BYTE)(1U - bit_value);
}
- mqc->bp++;
*mqc->bp = (OPJ_BYTE)mqc->c;
- mqc->ct = 8;
- mqc->c = 0;
+ /* Advance pointer so that opj_mqc_numbytes() returns a valid value */
+ mqc->bp++;
+ } else if (mqc->ct == 7 && mqc->bp[-1] == 0xff) {
+ /* Discard last 0xff */
+ assert(!erterm);
+ mqc->bp --;
+ } else if (mqc->ct == 8 && !erterm &&
+ mqc->bp[-1] == 0x7f && mqc->bp[-2] == 0xff) {
+ /* Tiny optimization: discard terminating 0xff 0x7f since it is */
+ /* interpreted as 0xff 0x7f [0xff 0xff] by the decoder, and given */
+ /* the bit stuffing, in fact as 0xff 0xff [0xff ..] */
+ /* Happens once on opj_compress -i ../MAPA.tif -o MAPA.j2k -M 1 */
+ mqc->bp -= 2;
}
- return 1;
+ assert(mqc->bp[-1] != 0xff);
}
void opj_mqc_reset_enc(opj_mqc_t *mqc)
opj_mqc_setstate(mqc, T1_CTXNO_ZC, 0, 4);
}
+#ifdef notdef
OPJ_UINT32 opj_mqc_restart_enc(opj_mqc_t *mqc)
{
OPJ_UINT32 correction = 1;
return correction;
}
+#endif
void opj_mqc_restart_init_enc(opj_mqc_t *mqc)
{
/* <Re-init part> */
- opj_mqc_setcurctx(mqc, 0);
+
+ /* As specified in Figure C.10 - Initialization of the encoder */
+ /* (C.2.8 Initialization of the encoder (INITENC)) */
mqc->a = 0x8000;
mqc->c = 0;
mqc->ct = 12;
- mqc->bp--;
+ /* This function is normally called after at least one opj_mqc_flush() */
+ /* which will have advance mqc->bp by at least 2 bytes beyond its */
+ /* initial position */
+ mqc->bp --;
+ assert(mqc->bp >= mqc->start - 1);
+ assert(*mqc->bp != 0xff);
if (*mqc->bp == 0xff) {
mqc->ct = 13;
}
}
}
-OPJ_BOOL opj_mqc_init_dec(opj_mqc_t *mqc, OPJ_BYTE *bp, OPJ_UINT32 len)
+static void opj_mqc_init_dec_common(opj_mqc_t *mqc,
+ OPJ_BYTE *bp,
+ OPJ_UINT32 len,
+ OPJ_UINT32 extra_writable_bytes)
+{
+ (void)extra_writable_bytes;
+
+ assert(extra_writable_bytes >= OPJ_COMMON_CBLK_DATA_EXTRA);
+ mqc->start = bp;
+ mqc->end = bp + len;
+ /* Insert an artificial 0xFF 0xFF marker at end of the code block */
+ /* data so that the bytein routines stop on it. This saves us comparing */
+ /* the bp and end pointers */
+ /* But before inserting it, backup th bytes we will overwrite */
+ memcpy(mqc->backup, mqc->end, OPJ_COMMON_CBLK_DATA_EXTRA);
+ mqc->end[0] = 0xFF;
+ mqc->end[1] = 0xFF;
+ mqc->bp = bp;
+}
+void opj_mqc_init_dec(opj_mqc_t *mqc, OPJ_BYTE *bp, OPJ_UINT32 len,
+ OPJ_UINT32 extra_writable_bytes)
{
/* Implements ISO 15444-1 C.3.5 Initialization of the decoder (INITDEC) */
/* Note: alternate "J.1 - Initialization of the software-conventions */
/* decoder" has been tried, but does */
/* not bring any improvement. */
/* See https://github.com/uclouvain/openjpeg/issues/921 */
+ opj_mqc_init_dec_common(mqc, bp, len, extra_writable_bytes);
opj_mqc_setcurctx(mqc, 0);
- mqc->start = bp;
- mqc->end = bp + len;
- mqc->bp = bp;
+ mqc->end_of_byte_stream_counter = 0;
if (len == 0) {
mqc->c = 0xff << 16;
} else {
mqc->c <<= 7;
mqc->ct -= 7;
mqc->a = 0x8000;
- return OPJ_TRUE;
+}
+
+
+void opj_mqc_raw_init_dec(opj_mqc_t *mqc, OPJ_BYTE *bp, OPJ_UINT32 len,
+ OPJ_UINT32 extra_writable_bytes)
+{
+ opj_mqc_init_dec_common(mqc, bp, len, extra_writable_bytes);
+ mqc->c = 0;
+ mqc->ct = 0;
+}
+
+
+void opq_mqc_finish_dec(opj_mqc_t *mqc)
+{
+ /* Restore the bytes overwritten by opj_mqc_init_dec_common() */
+ memcpy(mqc->end, mqc->backup, OPJ_COMMON_CBLK_DATA_EXTRA);
}
void opj_mqc_resetstates(opj_mqc_t *mqc)