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

📄 dst_arith_encoder.c

📁 JPEG2000实现的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
      state->word = 0;
      dst_arith_coder__output_word(state,state->word);
    }
  state->mqe.num_preceding_bytes =
    (state->saved_words << 2) + ((32-state->current_lsb)>>3);
  
  /* Set active flags. */

  assert(!state->mqe.active);
  state->mqe.active = 1;
}

/*****************************************************************************/
/* EXTERN                dst_arith_coder__output_word                        */
/*****************************************************************************/

void
  dst_arith_coder__output_word(dst_arith_state_ptr state, std_int word)

 /* Outputs a word to the code word heap. */

{
  int pos;
  
  pos = state->next_heap_pos;
  state->heap->words[pos++] = word;
  state->saved_words++;
  if (pos == DST_HEAP_WORDS)
    {
      dst_heap_unit_ptr elt;

      pos = 0;
      elt = state->code_heap_mgr->get_unit(state->code_heap_mgr);
      elt->next = NULL;
      state->heap = state->heap->next = elt;
    }
  state->next_heap_pos = pos;
}

/*****************************************************************************/
/* EXTERN                    dst_arith_coder__byteout                        */
/*****************************************************************************/

std_int
  dst_arith_coder__byteout(std_int creg, std_short *ct, 
                           dst_arith_state_ptr state)
{
  assert(state->mqe.active);
  if (state->mqe.have_unsent_ff)
    {
      put_byte(state,LONG_FF);
      state->mqe.have_unsent_ff = 0;
    }
  if(state->mqe.buffer != LONG_FF)
    {
      if( !(creg & M_CR_C) )
        { /* No Carry */
          put_byte(state,state->mqe.buffer);
          state->mqe.buffer = (creg >> S_CR_B_NML);
          creg &= M_CR_SX_NML;
          *ct = NEXTBITS_NML;
        }
      else
        { /* Carry */
          state->mqe.buffer++; /* Carry propagation */
          if(state->mqe.buffer != LONG_FF)
            {
              put_byte(state,state->mqe.buffer);
              state->mqe.buffer = ((creg >> S_CR_B_NML) & M_CR_BUF8);
              creg  &= M_CR_SX_NML;
              *ct = NEXTBITS_NML;
            }
          else
            {
              state->mqe.have_unsent_ff = 1;
              state->mqe.buffer = ((creg >> S_CR_B_BS) & M_CR_BUF7);
              creg  &= M_CR_SX_BS;
              *ct = NEXTBITS_BS;
            }
        }
    }
  else
    { /* buffer == BYTE_FF */
      state->mqe.have_unsent_ff = 1;
      state->mqe.buffer = (creg >> S_CR_B_BS);
      creg  &= M_CR_SX_BS;
      *ct   = NEXTBITS_BS;
    }
  return(creg);
}

/*****************************************************************************/
/* EXTERN                  dst_arith_coder__deactivate                       */
/*****************************************************************************/

int
  dst_arith_coder__deactivate(dst_arith_state_ptr state,
                              int easy)
{
  int num_bytes;

  if (!state->mqe.active)
    num_bytes = perform_raw_terminating_flush(state);
  else
    {
      assert((state->current_lsb & 7) == 0);
      if (state->error_resilient_termination)
        num_bytes = perform_error_resilient_flush(state);
      else if (easy)
        num_bytes = perform_easy_terminating_flush(state);
      else
        num_bytes = perform_best_terminating_flush(state);
      init_enc(&(state->mqe));
    }
  return(num_bytes);
}

/*****************************************************************************/
/* EXTERN                   dst_arith_coder__flush                           */
/*****************************************************************************/

void
  dst_arith_coder__flush(dst_arith_state_ptr state)
{
  assert(!state->mqe.active); /* Encoder must already have been deactivated */
  if (state->current_lsb < 32)
    dst_arith_coder__output_word(state,state->word);
}

/*****************************************************************************/
/* EXTERN              dst_arith_coder__get_minimum_bytes                    */
/*****************************************************************************/

int
  dst_arith_coder__get_minimum_bytes(dst_arith_state_ptr state,
                                     dst_heap_unit_ptr heap, int heap_pos,
                                     int min_bytes, int max_bytes)

 /* Determines the minimum number of whole bytes which are required to
    correctly decode all coded symbols up to and including the last symbol
    whose coding resulted in the state recorded in the supplied `state'
    structure.  The `heap' and `heap_pos' arguments identify the heap unit
    structure and the word index within this structure, of the first word
    saved by the arithmetic coding engine.  The function indexes into the
    saved bit-stream to determine the effect of premature termination on
    successful decoding up to the point associated with `state'.  The
    function depends intimately on the assumption that the decoder will
    stuff 1's onto the end of the bit-stream as necessary and then
    replace consecutive FF's by the pattern FF,7F,FF,...  Consequently,
    the `dst_arith_coder__input_word' function and the `bytein' function
    in "dst_arith_decoder.c" must not be carelessly modified.
        The original version of this function (for the original EBCOT arithmetic
    coder) was bit oriented and never overestimated the required code length;
    however, the bit-stuffing policy in the MQ coder is byte oriented, which
    makes estimation of the minimum number of whole bytes directly somewhat
    simpler; this is sufficient, since the block coder represents truncation
    points in bytes, not bits.
        The `min_bytes' and `max_bytes' fields are provided to account for the
    fact that there may be multiple arithmetic code-word segments in the
    code stream where we are wanting to compute a termination point inside
    one of those segments.  The `min_bytes' field identifies the number of
    bytes in the code stream preceding the relevant segment, whereas the
    `max_bytes' field identifies the number of bytes in the code stream up
    until the end of the segment. */

{
  std_int upper_C, upper_buf, lower_C, lower_buf;
  std_int word, last_byte_is_ff, next_byte;
  std_short ct;
  std_int n, in_word_idx, tmp;
  int num_bytes;

  word = 0; /* Suppress compiler warnings. */
  next_byte = 0; /* Suppress compiler warnings. */

  if (!state->mqe.active)
    { /* Computing the length of a raw bit-stream segment -> easy! */
      int current_lsb;

      current_lsb = state->current_lsb & ~7;
      num_bytes = (state->saved_words << 2) + ((32-current_lsb)>>3);
      return(num_bytes);
    }

  assert((state->current_lsb & 7) == 0);
  num_bytes = (state->saved_words << 2) + ((32-state->current_lsb)>>3);
  if (state->mqe.io_enable)
    num_bytes++;
  num_bytes--;
  if (state->mqe.have_unsent_ff)
    num_bytes++;
  if (num_bytes > max_bytes)
    return(max_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 padding (due to truncation), the
     code-word 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.
     We start by checking whether or not we need any more than the
     `num_bytes' value, i.e. whether or not we need the byte whose
     position corresponds to that of the byte in `state->mqe.buffer'. */

  in_word_idx = -1; /* Illegal value. */
  last_byte_is_ff = state->mqe.have_unsent_ff;
  while (1)
    {
      if (last_byte_is_ff)
        { /* If we stop immediately before here, the decoder will pad
             with 0x7F, 0xFF, 0x7F, 0xFF, ..., which is equivalent to a
             number strictly less than 128, but larger than any number less
             than 128. */
          if ((upper_buf >= 128) && (lower_buf < 128))
            {
              num_bytes--; /* Do not need the preceding byte either since
                              the decoder will substitute the 0xFF
                              automatically as the first byte after the
                              end of the string. */
              break;
            }
        }
      else
        { /* If we stop immediately before here, the decoder will pad
             with 0xFF, 0x7F, 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. */
            }
        }

      /* Retrieve next actual byte in codeword segment. */

      if (in_word_idx < 0)
        { /* First access to heap. */
          word = 0; in_word_idx = 3;
          if (num_bytes >= 0)
            {
              n = num_bytes>>2; /* Number of whole words in heap to skip. */
              in_word_idx = num_bytes - (n<<2); /* Index of byte in word. */
              while (n)
                {
                  tmp = DST_HEAP_WORDS - heap_pos;
                  if (tmp > n)
                    {
                      heap_pos += n;
                      n = 0;
                    }
                  else
                    {
                      n -= tmp;
                      heap_pos = 0;
                      heap = heap->next;
                    }
                }
              word = heap->words[heap_pos++];
              word <<= (in_word_idx << 3);
              next_byte = (word>>24) & 0x00FF;
            }
        }
      else if (num_bytes >= 0)
        {
          in_word_idx++; word <<= 8;
          if (in_word_idx == 4)
            {
              if (heap_pos >= DST_HEAP_WORDS)
                { heap = heap->next; heap_pos = 0; }
              word = heap->words[heap_pos++];
              in_word_idx = 0;
            }
          next_byte = (word >> 24) & 0x00FF;
        }
      if (num_bytes < min_bytes)
        next_byte = 0;

      /* Advance to the next byte position. */

      upper_buf -= next_byte;
      lower_buf -= next_byte;
      num_bytes++;
      assert(num_bytes <= max_bytes);
      if (next_byte != 0x00FF)
        { /* move left-most 8 bits of C into buffer. */
          upper_buf <<= 8; lower_buf <<= 8;
          upper_buf |= (upper_C >> (16+SPACER)) & 0x00FF;
          lower_buf |= (lower_C >> (16+SPACER)) & 0x00FF;
          upper_C <<= 8; lower_C <<= 8;
          last_byte_is_ff = 0;
        }
      else
        { /* move left-most 7 bits of C into buffer. */
          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;
          last_byte_is_ff = 1;
        }
      upper_C &= M_CR_BSX;
      lower_C &= M_CR_BSX;
    }
  if (num_bytes < min_bytes)
    num_bytes = min_bytes;
  return(num_bytes);
}

/*****************************************************************************/
/* EXTERN                  dst_arith_coder__log_symbol                       */
/*****************************************************************************/

#ifdef DST_LOG_SYMBOLS
void
  dst_arith_coder__log_symbol(dst_arith_state_ptr state,
                              dst_context_state_ptr ctxt,
                              std_int symbol) /* David T mod */
{
  int val;
 
  if(state->symbol_log == NULL)
    return;

  if (ctxt == NULL)
    val = 255;
  else
    val = ctxt - state->contexts;
  putc(val,state->symbol_log);
  val = (symbol)?1:0;
  putc(val,state->symbol_log);
}
#endif /* DST_LOG_SYMBOLS */

⌨️ 快捷键说明

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