⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dst_arith_encoder.c

📁 JPEG2000实现的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************/
/* Copyright 1998, Hewlett-Packard Company                                   */
/* All rights reserved                                                       */
/* File: "dst_arith_encoder.c"                                               */
/* Description: Implementation of non-macro arithmetic encoder functions     */
/* Author: David Taubman                                                     */
/* Affiliation: Hewlett-Packard and                                          */
/*              The University of New South Wales, Australia                 */
/* Version: VM7.0                                                            */
/* Last Revised: 24 March, 2000                                              */
/*****************************************************************************/

/*****************************************************************************/
/* Modified to incorporate MQ-coder by Mitsubishi Electric Corp.             */
/* Copyright 1999, Mitsubishi Electric Corp.                                 */
/* All rights reserved for modified parts                                    */
/*****************************************************************************/

/*****************************************************************************/
/* Modifications tagged with comment lines or delimiters involving the       */
/* string, "David T mod" or "mod by David T", have been made by David        */
/* Taubman; they are copyrighted by Hewlett-Packard Company with all rights  */
/* reserved for the modified parts.                                          */
/*****************************************************************************/

/*****************************************************************************/
/* Substantially modified by David Taubman to support flexible termination   */
/* of code stream segments and error resilience capabilities.  Copyright     */
/* 1999 by Hewlett-Packard Company with all rights reserved for the modified */
/* parts.                                                                    */
/*****************************************************************************/

/*****************************************************************************/
/* Modified by David Taubman to avoid the need for byte stuffing when resync */
/* markers are in use.  This simplifies the code and substantially improves  */
/* the usefulness of the system for applications requiring error resilience. */
/* Changes are as follows: a) changed SOT marker to lie within intra-packet  */
/* marker range 0xFF90 through 0xFFFF; b) introduced an MQ-like bit-stuffing */
/* policy in packet heads; c) introduced an MQ-like bit-stuffing policy in   */
/* the raw bit-stream segments generated by the entropy coder in lazy mode;  */
/* d) modified error resilient termination policy for raw bit-stream         */
/* to fill unused bits with the simpler code 0101... instead of 1010...;     */
/* e) eliminated the use of byte-stuffing with resync markers.  In the new   */
/* code, none of the packet segments (packet head, MQ segments and raw       */
/* segments) may contain any two byte sequence in the range 0xFF90 through   */
/* 0xFFFF; moreover, no segment can terminate with a 0xFF, so that the       */
/* entire packet is guaranteed to be free of two byte sequences in the above */
/* range.  All delimiting markers from the codestream (i.e. SOT, RESYNC and  */
/* EOC) are guaranteed to lie within that range.                             */
/* Copyright 1999 by Hewlett-Packard Company with all                        */
/* rights reserved for the modified parts.                                   */
/*****************************************************************************/

#include <local_services.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ifc.h>
#include <stdio.h>
#include "dst_arith_encoder.h"

/* ========================================================================= */
/* --------------------------- Private Macros ------------------------------ */
/* ========================================================================= */

/*****************************************************************************/
/* MACRO                         put_byte                                    */
/*****************************************************************************/

#define put_byte(_state,_value)                                           \
  {                                                                       \
    if (_state->mqe.io_enable)                                            \
      {                                                                   \
        _state->current_lsb -= 8;                                         \
        _state->word += (_value)<<(_state->current_lsb);                  \
        if (_state->current_lsb == 0)                                     \
          {                                                               \
            dst_arith_coder__output_word(_state,_state->word);            \
            _state->current_lsb = 32;                                     \
            _state->word = 0;                                             \
          }                                                               \
      }                                                                   \
    else                                                                  \
      _state->mqe.io_enable = SW_ON;                                      \
  }


/* ========================================================================= */
/* ------------------------- Internal Functions ---------------------------- */
/* ========================================================================= */

/*****************************************************************************/
/* STATIC                         init_enc                                   */
/*****************************************************************************/

static void
  init_enc(mqe_var_ptr mqe)
{
  mqe->areg = ENC_HALF;
  mqe->creg = LONG_ZERO;
  mqe->buffer = LONG_ZERO;
  mqe->io_enable = SW_OFF;
  mqe->ct = NEXTBITS_NML + SPACER + 1;
  mqe->active = 0; /* Wait until first call to `dst_arith_coder__activate'. */
  mqe->num_preceding_bytes = 0;
  mqe->have_unsent_ff = 0;
}

/*****************************************************************************/
/* STATIC                 perform_best_terminating_flush                     */
/*****************************************************************************/

static int
  perform_best_terminating_flush(dst_arith_state_ptr state)

 /* Flushes the arithmetic coder using a relatively complex, near optimal
    algorithm to determine the termination length.  Better performance
    cannot be achieved without compromising the operation of the code
    stream queueing system.  The termination length is returned to the
    caller. */

{
  int num_bytes, min_bytes;
  std_int upper_C, upper_buf, lower_C, lower_buf;
  std_short ct;

  min_bytes = state->mqe.num_preceding_bytes;
  num_bytes = (state->saved_words << 2) + ((32-state->current_lsb)>>3);
  if (state->mqe.io_enable)
    num_bytes++;
  num_bytes--;
  assert(num_bytes >= (min_bytes-1));
    /* `num_bytes' represents the number of bytes which have been pushed
       out to the heap by this stage, not including any value sent to
       the byte buffer in the `state->mqe' structure.  This value might
       be less than `min_bytes'.  For example, if no symbols have been coded
       at all, this value will be equal to `min_bytes'-1.  The interpretation
       of a value of `min_bytes'-1 is that the byte buffer in the `state->mqe'
       structure is itself empty. */

  ct = state->mqe.ct;
  lower_C = state->mqe.creg;
  upper_C = lower_C + state->mqe.areg;
  lower_C <<= ct;
  upper_C <<= ct;
  upper_buf = lower_buf = state->mqe.buffer;
  if (upper_C & M_CR_C)
    {
      upper_C -= M_CR_C;
      upper_buf++;
    }
  if (lower_C & M_CR_C)
    {
      lower_C -= M_CR_C;
      lower_buf++;
    }

  /* At this point, `upper_buf' holds the buffer value and
     `upper_C' the C-register value corresponding to an upper bound;
     Similarly, `lower_C' and `lower_buf' represent the lower bound on
     the arithmetic code-word.  After appending 1's to the truncated code-word,
     it must be strictly less than the upper bound and no less than the
     lower bound in order to ensure correct decoding.  We would normally
     only need to consider the upper bound, but the bit-stuffing policy
     used by the MQ coder renders this insufficient. */

  /* Now for the loop to find the minimum number of bytes required and also
     to output these as necessary to the code stream. */

  while (1)
    {
      if (state->mqe.have_unsent_ff)
        {  /* We may be able to terminate here and discard the FF.  Otherwise,
              we will need to send this FF which is still pending.  If we stop
              immediately before this pending FF, the decoder will replicate it
              with the extension convention and then will append 0x7F, 0xFF,
              0x7F, etc., which is equivalent to a number strictly less than
              128, but larger than any number less than 128. */
          state->mqe.have_unsent_ff = 0;
          if ((upper_buf >= 128) && (lower_buf < 128))
            { /* Can stop before the unsent FF.  Actually, we must not send
                 the trailing FF or we might accidentally introduce a false
                 marker at the boundary between segments of the bit-stream. */
              break;
            }
          put_byte(state,LONG_FF);
          num_bytes++;
        }
      else
        { /* If we stop here, the decoder will pad with 0xFF, 0x7F, ...,
             which is equivalent to a number strictly less than 256, but
             larger than any number less than 256. */
          if ((upper_buf >= 256) && (lower_buf < 256))
            break; /* We are done. */
        }

      /* Push a byte out and advance the bound registers and byte
         count accordingly. */

      assert(!(lower_C & M_CR_C)); /* Should not be able to get a carry. */
      if (lower_buf < 255)
        {
          put_byte(state,lower_buf);
          num_bytes++;
          upper_buf -= lower_buf;
          upper_buf <<= 8;
          upper_buf |= (upper_C >> (16+SPACER)) & 0x00FF;
          lower_buf = (lower_C >> (16+SPACER)) & 0x00FF;
          upper_C <<= 8; lower_C <<= 8;
        }
      else
        { /* buffer == BYTE_FF */
          state->mqe.have_unsent_ff = 1;
          upper_buf -= 255;
          lower_buf -= 255;
          upper_buf <<= 7;
          lower_buf <<= 7;
          upper_buf |= (upper_C >> (16+SPACER+1)) & 0x007F;
          lower_buf |= (lower_C >> (16+SPACER+1)) & 0x007F;
          upper_C <<= 7; lower_C <<= 7;
        }
      upper_C &= M_CR_BSX;
      lower_C &= M_CR_BSX;
    }
  assert(num_bytes >= min_bytes);
  return(num_bytes);  
}

/*****************************************************************************/
/* STATIC                 perform_easy_terminating_flush                     */
/*****************************************************************************/

static int
  perform_easy_terminating_flush(dst_arith_state_ptr state)

 /* Flushes the arithmetic coder using a simple, minimally invasive
    algorithm to determine the termination length, which is returned to
    the caller. */

{
  std_short ct;
  unsigned long creg;
  int bits_left;
  int num_bytes;

  ct = state->mqe.ct;
  creg = state->mqe.creg;
  bits_left = 8 + SPACER - ct + 1; /* Need only MSB of C register. */
  creg <<= ct; /* Shift bits in `creg' to upper portion. */
  for (; bits_left > 0; bits_left-=ct, creg<<=ct)
    creg = dst_arith_coder__byteout(creg,&ct,state);
  dst_arith_coder__byteout(creg,&ct,state); /* Flush `buffer'. */
  num_bytes = (state->saved_words << 2) + ((32-state->current_lsb)>>3);
  return(num_bytes);
}

/*****************************************************************************/
/* STATIC                 perform_error_resilient_flush                      */
/*****************************************************************************/

static int
  perform_error_resilient_flush(dst_arith_state_ptr state)

 /* The termination length is identical to that produce by
    `perform_easy_terminating_flush', but the spare code space is used
    to embed error resilience information.  Consult the comments appearing
    with the definition of the `dst_error_resilience' structure embedded
    in `state' for more information on this policy. */

{
  return(perform_easy_terminating_flush(state));
}

/*****************************************************************************/
/* STATIC                 perform_raw_terminating_flush                      */
/*****************************************************************************/

static int
  perform_raw_terminating_flush(dst_arith_state_ptr state)
{
  int num_bytes;
  std_int code;

  code = 0; /* By appending the sequence 01010... we avoid the possibility of
               terminating FF's. */
  while (state->current_lsb & 7)
    {
      state->current_lsb--;
      state->word |= code << state->current_lsb;
      code = 1-code;
    }
  if (state->current_lsb == 0)
    {
      dst_arith_coder__output_word(state,state->word);
      state->current_lsb = 32;
      state->word = 0;
    }
  num_bytes = (state->saved_words << 2) + ((32-state->current_lsb)>>3);
  return(num_bytes);
}


/* ========================================================================= */
/* ------------------------- External Functions ---------------------------- */
/* ========================================================================= */

/*****************************************************************************/
/* EXTERN               dst_arith_coder__initialize                          */
/*****************************************************************************/

void
  dst_arith_coder__initialize(dst_arith_state_ptr state, int num_contexts,
                              dst_context_state_ptr contexts,
                              dst_heap_unit_ptr heap, int next_heap_pos,
                              dst_codeword_heap_ref code_mgr,
                              int error_resilient_termination)
{
  init_enc(&(state->mqe));

  state->current_lsb = 32;
  state->word = 0;
  state->saved_words = 0;
  state->heap = heap;
  state->next_heap_pos = next_heap_pos;
  state->code_heap_mgr = code_mgr;
  state->num_contexts = num_contexts;
  state->contexts = contexts;
  state->error_resilient_termination = error_resilient_termination;
}

/*****************************************************************************/
/* EXTERN                dst_arith_coder__model_init                         */
/*****************************************************************************/

void
  dst_arith_coder__model_init(dst_arith_state_ptr state,
                              dst_context_state_ptr init)
{
  dst_context_state_ptr csp1, csp2;
  int n;

  csp1 = state->contexts;
  csp2 = csp1 + DST_ARITH_MAX_CTXTS;
  for (n=state->num_contexts; n > 0; n--, csp1++, csp2++, init++)
    {
      *csp1 = *init;
      *csp2 = dst_arith_state_to_delta[*csp1];
    }
}

/*****************************************************************************/
/* EXTERN                 dst_arith_coder__activate                          */
/*****************************************************************************/

void
  dst_arith_coder__activate(dst_arith_state_ptr state)
{
  /* Align on byte boundary. */

  state->current_lsb &= ~7;
  if (state->current_lsb == 0)
    {
      state->current_lsb = 32;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -