/* * arith.c: Adaptive arithmetic coding and decoding * * Written by: Ullrich Hafner * * This file is part of FIASCO (Fractal Image And Sequence COdec) * Copyright (C) 1994-2000 Ullrich Hafner */ /* * $Date: 2000/06/14 20:49:37 $ * $Author: hafner $ * $Revision: 5.1 $ * $State: Exp $ */ #include "config.h" #include "types.h" #include "macros.h" #include "error.h" #include "bit-io.h" #include "misc.h" #include "arith.h" /****************************************************************************** public code ******************************************************************************/ arith_t * alloc_encoder (bitfile_t *output) /* * Arithmetic coder constructor: * Initialize the arithmetic coder. * * Return value: * A pointer to the new coder structure */ { arith_t *arith = Calloc (1, sizeof (arith_t)); assert (output); arith->low = LOW; arith->high = HIGH; arith->underflow = 0; arith->file = output; return arith; } void free_encoder (arith_t *arith) /* * Arithmetic encoder destructor. * Flush the arithmetic coder. Append all remaining bits to the * output stream. Append zero bits to get the output file byte aligned. * * No return value. */ { u_word_t low; /* start of the current code range */ u_word_t high; /* end of the current code range */ u_word_t underflow; /* number of underflow bits pending */ bitfile_t *output; assert (arith); low = arith->low; high = arith->high; underflow = arith->underflow; output = arith->file; low = high; RESCALE_OUTPUT_INTERVAL; OUTPUT_BYTE_ALIGN (output); Free (arith); } real_t encode_symbol (unsigned symbol, arith_t *arith, model_t *model) /* * Encode the given 'symbol' using the given probability 'model'. * The current state of the arithmetic coder is given by 'arith'. * Output bits are appended to the stream 'output'. * * The model is updated after encoding the symbol (if necessary the * symbol counts are rescaled). * * Return value: * information content of the encoded symbol. * * Side effects: * 'model' is updated (probability distribution) * 'arith' is updated (coder state) */ { u_word_t low_count; /* lower bound of 'symbol' interval */ u_word_t high_count; /* upper bound of 'symbol' interval */ u_word_t scale; /* range of all 'm' symbol intervals */ unsigned range; /* range of current interval */ unsigned index; /* index of probability model */ u_word_t low; /* start of the current code range */ u_word_t high; /* end of the current code range */ u_word_t underflow; /* number of underflow bits pending */ bitfile_t *output; /* output file */ assert (model && arith); /* * Get interval values */ low = arith->low; high = arith->high; underflow = arith->underflow; output = arith->file; assert (high > low); if (model->order > 0) /* order-'n' model*/ { unsigned power; /* multiplicator */ unsigned i; /* * Compute index of the probability model to use. * See init_model() for more details. */ power = 1; /* multiplicator */ index = 0; /* address of prob. model */ for (i = 0; i < model->order; i++) /* generate a M-nary number */ { index += model->context [i] * power; power *= model->symbols; } index *= model->symbols + 1; /* we need space for M + 1 elements */ for (i = 0; i < model->order - 1; i++) model->context [i] = model->context [i + 1]; model->context [i] = symbol; } else index = 0; scale = model->totals [index + model->symbols]; low_count = model->totals [index + symbol]; high_count = model->totals [index + symbol + 1]; /* * Compute the new interval depending on the input 'symbol'. */ range = (high - low) + 1; high = low + (u_word_t) ((range * high_count) / scale - 1); low = low + (u_word_t) ((range * low_count) / scale); RESCALE_OUTPUT_INTERVAL; if (model->scale > 0) /* adaptive model */ { unsigned i; /* * Update probability model */ for (i = symbol + 1; i <= model->symbols; i++) model->totals [index + i]++; if (model->totals [index + model->symbols] > model->scale) /* scaling */ { for (i = 1; i <= model->symbols; i++) { model->totals [index + i] >>= 1; if (model->totals [index + i] <= model->totals [index + i - 1]) model->totals [index + i] = model->totals [index + i - 1] + 1; } } } /* * Store interval values */ arith->low = low; arith->high = high; arith->underflow = underflow; return - log2 ((high_count - low_count) / (real_t) scale); } void encode_array (bitfile_t *output, const unsigned *data, const unsigned *context, const unsigned *c_symbols, unsigned n_context, unsigned n_data, unsigned scaling) /* * Arithmetic coding of #'n_data' symbols given in the array 'data'. * If 'n_context' > 1 then a number (context [n]) is assigned to every * data element n, specifying which context (i.e. number of symbols given by * c_symbols [context [n]] and adaptive probability model) must be used. * Rescale probability models if range > 'scaling'. * * No return value. */ { u_word_t **totals; /* probability model */ if (!n_context) n_context = 1; /* always use one context */ assert (output && c_symbols && data); assert (n_context == 1 || context); /* * Allocate probability models, start with uniform distribution */ totals = Calloc (n_context, sizeof (u_word_t *)); { unsigned c; for (c = 0; c < n_context; c++) { unsigned i; totals [c] = Calloc (c_symbols [c] + 1, sizeof (u_word_t)); totals [c][0] = 0; for (i = 0; i < c_symbols [c]; i++) totals [c][i + 1] = totals [c][i] + 1; } } /* * Encode array elements */ { u_word_t low = 0; /* Start of the current code range */ u_word_t high = 0xffff; /* End of the current code range */ u_word_t underflow = 0; /* Number of underflow bits pending */ unsigned n; for (n = 0; n < n_data; n++) { u_word_t low_count; /* lower bound of 'symbol' interval */ u_word_t high_count; /* upper bound of 'symbol' interval */ u_word_t scale; /* range of all 'm' symbol intervals */ unsigned range; /* current range */ int d; /* current data symbol */ int c; /* context of current data symbol */ d = data [n]; c = n_context > 1 ? context [n] : 0; scale = totals [c][c_symbols [c]]; low_count = totals [c][d]; high_count = totals [c][d + 1]; /* * Rescale high and low for the new symbol. */ range = (high - low) + 1; high = low + (u_word_t) ((range * high_count) / scale - 1); low = low + (u_word_t) ((range * low_count) / scale); RESCALE_OUTPUT_INTERVAL; /* * Update probability models */ { unsigned i; for (i = d + 1; i < c_symbols [c] + 1; i++) totals [c][i]++; if (totals [c][c_symbols [c]] > scaling) /* scaling */ for (i = 1; i < c_symbols [c] + 1; i++) { totals [c][i] >>= 1; if (totals [c][i] <= totals [c][i - 1]) totals [c][i] = totals [c][i - 1] + 1; } } } /* * Flush arithmetic encoder */ low = high; RESCALE_OUTPUT_INTERVAL; OUTPUT_BYTE_ALIGN (output); } /* * Cleanup ... */ { unsigned c; for (c = 0; c < n_context; c++) Free (totals [c]); Free (totals); } } arith_t * alloc_decoder (bitfile_t *input) /* * Arithmetic decoder constructor: * Initialize the arithmetic decoder with the first * 16 input bits from the stream 'input'. * * Return value: * A pointer to the new decoder structure */ { arith_t *arith = Calloc (1, sizeof (arith_t)); assert (input); arith->low = LOW; arith->high = HIGH; arith->code = get_bits (input, 16); arith->file = input; return arith; } void free_decoder (arith_t *arith) /* * Arithmetic decoder destructor: * Flush the arithmetic decoder, i.e., read bits to get the input * file byte aligned. * * No return value. * * Side effects: * structure 'arith' is discarded. */ { assert (arith); INPUT_BYTE_ALIGN (arith->file); Free (arith); } unsigned decode_symbol (arith_t *arith, model_t *model) /* * Decode the next symbol - the state of the arithmetic decoder * is given in 'arith'. Read refinement bits from the stream 'input' * and use the given probability 'model'. Update the probability model after * decoding the symbol (if necessary also rescale the symbol counts). * * Return value: * decoded symbol * * Side effects: * 'model' is updated (probability distribution) * 'arith' is updated (decoder state) */ { unsigned range; /* range of current interval */ unsigned count; /* value in the current interval */ unsigned index; /* index of probability model */ unsigned symbol; /* decoded symbol */ u_word_t scale; /* range of all 'm' symbol intervals */ u_word_t low; /* start of the current code range */ u_word_t high; /* end of the current code range */ u_word_t code; /* the present input code value */ bitfile_t *input; /* input file */ assert (arith && model); /* * Get interval values */ low = arith->low; high = arith->high; code = arith->code; input = arith->file; assert (high > low); if (model->order > 0) /* order-'n' model */ { unsigned power; /* multiplicator */ unsigned i; /* * Compute index of the probability model to use. * See init_model() for more details. */ power = 1; /* multiplicator */ index = 0; /* address of prob. model */ for (i = 0; i < model->order; i++) /* generate a m-nary number */ { index += model->context[i] * power; power *= model->symbols; } index *= model->symbols + 1; /* we need space for m + 1 elements */ } else index = 0; scale = model->totals [index + model->symbols]; range = (high - low) + 1; count = ((code - low + 1) * scale - 1) / range; for (symbol = model->symbols; count < model->totals [index + symbol]; symbol--) ; if (model->order > 0) /* order-'n' model */ { unsigned i; for (i = 0; i < model->order - 1; i++) model->context [i] = model->context [i + 1]; model->context [i] = symbol; } /* * Compute interval boundaries */ { u_word_t low_count; /* lower bound of 'symbol' interval */ u_word_t high_count; /* upper bound of 'symbol' interval */ low_count = model->totals [index + symbol]; high_count = model->totals [index + symbol + 1]; high = low + (u_word_t) ((range * high_count) / scale - 1 ); low = low + (u_word_t) ((range * low_count) / scale ); } RESCALE_INPUT_INTERVAL; if (model->scale > 0) /* adaptive model */ { unsigned i; /* * Update probability model */ for (i = symbol + 1; i <= model->symbols; i++) model->totals [index + i]++; if (model->totals [index + model->symbols] > model->scale) /* scaling */ { for (i = 1; i <= model->symbols; i++) { model->totals [index + i] >>= 1; if (model->totals [index + i] <= model->totals [index + i - 1]) model->totals [index + i] = model->totals [index + i - 1] + 1; } } } /* * Store interval values */ arith->low = low; arith->high = high; arith->code = code; return symbol; } unsigned * decode_array (bitfile_t *input, const unsigned *context, const unsigned *c_symbols, unsigned n_context, unsigned n_data, unsigned scaling) /* * Arithmetic decoding of #'n_data' symbols. * If 'n_context' > 1 then a number (context [n]) is assigned to every * data element n, specifying which context (i.e. number of symbols given by * c_symbols [context [n]] and adaptive probability model) must be used. * Rescale probability models if range > 'scaling'. * * Return value: * pointer to array containing the decoded symbols */ { unsigned *data; /* array to store decoded symbols */ u_word_t **totals; /* probability model */ if (n_context < 1) n_context = 1; /* always use one context */ assert (input && c_symbols); assert (n_context == 1 || context); data = Calloc (n_data, sizeof (unsigned)); /* * Allocate probability models, start with uniform distribution */ totals = Calloc (n_context, sizeof (u_word_t *)); { unsigned c; for (c = 0; c < n_context; c++) { unsigned i; totals [c] = Calloc (c_symbols [c] + 1, sizeof (u_word_t)); totals [c][0] = 0; for (i = 0; i < c_symbols [c]; i++) totals [c][i + 1] = totals [c][i] + 1; } } /* * Fill array 'data' with decoded values */ { u_word_t code = get_bits (input, 16); /* The present input code value */ u_word_t low = 0; /* Start of the current code range */ u_word_t high = 0xffff; /* End of the current code range */ unsigned n; for (n = 0; n < n_data; n++) { u_word_t scale; /* range of all 'm' symbol intervals */ u_word_t low_count; /* lower bound of 'symbol' interval */ u_word_t high_count; /* upper bound of 'symbol' interval */ unsigned count; /* value in the current interval */ unsigned range; /* current interval range */ unsigned d; /* current data symbol */ unsigned c; /* context of current data symbol */ c = n_context > 1 ? context [n] : 0; assert (high > low); scale = totals [c][c_symbols [c]]; range = (high - low) + 1; count = (((code - low) + 1 ) * scale - 1) / range; for (d = c_symbols [c]; count < totals [c][d]; d--) /* next symbol */ ; low_count = totals [c][d]; high_count = totals [c][d + 1]; high = low + (u_word_t) ((range * high_count) / scale - 1 ); low = low + (u_word_t) ((range * low_count) / scale ); RESCALE_INPUT_INTERVAL; /* * Updata probability models */ { unsigned i; for (i = d + 1; i < c_symbols [c] + 1; i++) totals [c][i]++; if (totals [c][c_symbols [c]] > scaling) /* scaling */ for (i = 1; i < c_symbols [c] + 1; i++) { totals [c][i] >>= 1; if (totals [c][i] <= totals [c][i - 1]) totals [c][i] = totals [c][i - 1] + 1; } } data [n] = d; } INPUT_BYTE_ALIGN (input); } /* * Cleanup ... */ { unsigned c; for (c = 0; c < n_context; c++) Free (totals [c]); Free (totals); } return data; } model_t * alloc_model (unsigned m, unsigned scale, unsigned n, unsigned *totals) /* * Model constructor: * allocate and initialize an order-'n' probability model. * The size of the source alphabet is 'm'. Rescale the symbol counts after * 'scale' symbols are encoded/decoded. The initial probability of every * symbol is 1/m. * If 'scale' = 0 then use static modeling (p = 1/n). * If 'totals' is not NULL then use this array of 'm' values to set * the initial counts. * * Return value: * a pointer to the new probability model structure. * * Note: We recommend a small size of the alphabet because no escape codes * are used to encode/decode previously unseen symbols. * */ { model_t *model; /* new probability model */ unsigned num; /* number of contexts to allocate */ bool_t cont; /* continue flag */ bool_t dec; /* next order flag */ unsigned i; /* * Allocate memory for the structure */ model = Calloc (1, sizeof (model_t)); model->symbols = m; model->scale = scale; model->order = n; model->context = n > 0 ? Calloc (n, sizeof (unsigned)) : NULL; /* * Allocate memory for the probability model. * Each of the m^n different contexts requires its own probability model. */ for (num = 1, i = 0; i < model->order; i++) num *= model->symbols; model->totals = Calloc (num * (model->symbols + 1), sizeof (unsigned)); for (i = 0; i < model->order; i++) model->context[i] = 0; /* start with context 0,0, .. ,0 */ cont = YES; while (cont) /* repeat while context != M ... M */ { int power; /* multiplicator */ int index; /* index of probability model */ /* * There are m^n different contexts: * Let "context_1 context_2 ... context_n symbol" be the current input * stream then the index of the probability model is given by: * index = context_1 * M^0 + context_2 * M^1 + ... + context_n * M^(n-1) */ power = 1; /* multiplicator */ index = 0; /* address of prob. model */ for (i = 0; i < model->order; i++) /* generate a m-nary number */ { index += model->context[i] * power; power *= model->symbols; } index *= model->symbols + 1; /* size of each model is m + 1 */ model->totals [index + 0] = 0; /* always zero */ for (i = 1; i <= model->symbols; i++) /* prob of each symbol is 1/m or as given in totals */ model->totals[index + i] = model->totals [index + i - 1] + (totals ? totals [i - 1] : 1); if (model->order == 0) /* order-0 model */ cont = NO; else /* try next context */ for (i = model->order - 1, dec = YES; dec; i--) { dec = NO; model->context[i]++; if (model->context[i] >= model->symbols) { /* change previous context */ model->context[i] = 0; if (i > 0) /* there's still a context remaining */ dec = YES; else cont = NO; /* all context models initialized */ } } } for (i = 0; i < model->order; i++) model->context[i] = 0; /* start with context 0,0, .. ,0 */ return model; } void free_model (model_t *model) /* * Model destructor: * Free memory allocated by the arithmetic 'model'. * * No return value. * * Side effects: * struct 'model' is discarded */ { if (model != NULL) { if (model->context != NULL) Free (model->context); Free (model->totals); Free (model); } else warning ("Can't free model ."); }