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

📄 arithmetic.c

📁 spiht的压缩解压缩c编写的
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "spiht.h"
#include "spihtdecode.h"

static int QccENTArithmeticModelInitialize(QccENTArithmeticModel *model)
{
  if (model == NULL)
    return(0);

  model->num_contexts = 0;
  model->num_symbols = NULL;
  model->translate_symbol_to_index = NULL;
  model->translate_index_to_symbol = NULL;
  model->cumulative_frequencies = NULL;
  model->frequencies = NULL;
  model->low = model->high = 0;
  model->bits_to_follow = 0;
  model->garbage_bits = 0;
  model->target_num_bits = QCCENT_ANYNUMBITS;
  model->adaptive_model = QCCENT_ADAPTIVE;
  model->context_function = NULL;
  model->current_context = 0;
  model->current_code_value = 0;

  return(0);
}

static void QccENTArithmeticFreeArray(int **array, int num_contexts)
{
  int context;
  
  if (array == NULL)
    return;
  
  for (context = 0; context < num_contexts; context++)
    if (array[context] != NULL)
      free(array[context]);
  free(array);
  
}

static void QccENTArithmeticFreeModelArrays(QccENTArithmeticModel *model)
{
  if (model == NULL)
    return;

  QccENTArithmeticFreeArray(model->translate_symbol_to_index, 
                            model->num_contexts);
  QccENTArithmeticFreeArray(model->translate_index_to_symbol, 

                            model->num_contexts);
  QccENTArithmeticFreeArray(model->cumulative_frequencies, 
                            model->num_contexts);
  QccENTArithmeticFreeArray(model->frequencies, 
                            model->num_contexts);
}

static int **QccENTArithmeticAllocArray(const int *num_symbols,
                                        int num_contexts)
{
  int **array = NULL;
  int context;
  
  if (num_symbols == NULL)
    return(NULL);

  if ((array = (int **)malloc(sizeof(int *)*num_contexts)) == NULL)
    {
      QccErrorAddMessage("(QccENTArithmeticAllocArray): Error allocating memory");
      return(NULL);
    }
  
  /*  Save an extra space total cumulative frequency  */
  for (context = 0; context < num_contexts; context++)
    if ((array[context] = 
         (int *)malloc(sizeof(int)*(num_symbols[context] + 1))) == NULL)
      {
        QccErrorAddMessage("(QccENTArithmeticAllocArray): Error allocating memory");
        QccENTArithmeticFreeArray(array, num_contexts);
        return(NULL);
      }
  
  return(array);
}

static int QccENTArithmeticAllocModelArrays(QccENTArithmeticModel *model)
{
  if (model == NULL)
    return(0);
  if (model->num_symbols == NULL)
    return(0);

  if ((model->translate_symbol_to_index = 
       QccENTArithmeticAllocArray(model->num_symbols, model->num_contexts))
      == NULL)
    {
      QccErrorAddMessage("(QccENTArithmeticAllocModelArrays): Error calling QccENTArithmeticAllocArray()");
      QccENTArithmeticFreeModelArrays(model);
      return(0);
    }

  if ((model->translate_index_to_symbol = 
       QccENTArithmeticAllocArray(model->num_symbols, model->num_contexts))
      == NULL)
    {
      QccErrorAddMessage("(QccENTArithmeticAllocModelArrays): Error calling QccENTArithmeticAllocArray()");
      QccENTArithmeticFreeModelArrays(model);
      return(0);
    }

  if ((model->cumulative_frequencies =
       QccENTArithmeticAllocArray(model->num_symbols, model->num_contexts))
      == NULL)
    {
      QccErrorAddMessage("(QccENTArithmeticAllocModelArrays): Error calling QccENTArithmeticAllocArray()");
      QccENTArithmeticFreeModelArrays(model);
      return(0);
    }

  if ((model->frequencies = 
       QccENTArithmeticAllocArray(model->num_symbols, model->num_contexts))
      == NULL)
    {
      QccErrorAddMessage("(QccENTArithmeticAllocModelArrays): Error calling QccENTArithmeticAllocArray()");
      QccENTArithmeticFreeModelArrays(model);
      return(0);
    }

  return(0);
}

static int QccENTArithmeticUpdateModel(QccENTArithmeticModel *model,
                                       int symbol_index, int context)
{
  int new_index;
  int cum = 0;
  int symbol1, symbol2;

  if (model == NULL)
    return(0);

  if (model->cumulative_frequencies[context][0] == QCCENT_MAXFREQUENCY)
    for (new_index = model->num_symbols[context]; new_index >= 0; new_index--)
      {
        model->frequencies[context][new_index] =
          (model->frequencies[context][new_index] + 1)/2;
        model->cumulative_frequencies[context][new_index] = cum;
        cum += model->frequencies[context][new_index];
      }

  for (new_index = symbol_index; 
       (model->frequencies[context][new_index] == 
        model->frequencies[context][new_index - 1]);
       new_index--);

  if (new_index < symbol_index)
    {
      symbol1 = model->translate_index_to_symbol[context][new_index];
      symbol2 = model->translate_index_to_symbol[context][symbol_index];
      model->translate_index_to_symbol[context][new_index] = symbol2;
      model->translate_index_to_symbol[context][symbol_index] = symbol1;
      model->translate_symbol_to_index[context][symbol1] = symbol_index;
      model->translate_symbol_to_index[context][symbol2] = new_index;
    }

  model->frequencies[context][new_index] += 1;

  while (new_index > 0)
    {
      new_index--;
      model->cumulative_frequencies[context][new_index] += 1;
    }

  return(0);
}

void QccENTArithmeticFreeModel(QccENTArithmeticModel *model)
{
  if (model == NULL)
    return;

  QccENTArithmeticFreeModelArrays(model);
  if (model->num_symbols != NULL)
    free(model->num_symbols);    
  free(model);

}

static int 
QccENTArithmeticOutputBitPlusFollowingOppositeBits(int bit_value, 
                                                   QccENTArithmeticModel 
                                                   *model,
                                                   QccBitBuffer *output_buffer)
{
  if (QccBitBufferPutBit(output_buffer, bit_value))
    {
      QccErrorAddMessage("(QccENTArithmeticOutputBitPlusFollowingOppositeBits): Error calling QccBitBufferPutBit()");
      return(1);
    }
  if (model->target_num_bits != QCCENT_ANYNUMBITS)
    if (output_buffer->bit_cnt >= model->target_num_bits)
      return(2);
  while (model->bits_to_follow > 0)
    {
      if (QccBitBufferPutBit(output_buffer, !bit_value))
        {
          QccErrorAddMessage("(QccENTArithmeticOutputBitPlusFollowingOppositeBits): Error calling QccBitBufferPutBit()");
          return(1);
        }
      if (model->target_num_bits != QCCENT_ANYNUMBITS)
        if (output_buffer->bit_cnt >= model->target_num_bits)
          return(2);
      model->bits_to_follow--;
    }

  return(0);
}

static int QccENTArithmeticEncodeSymbol(int symbol_index, int context,
                                        QccENTArithmeticModel *model, 
                                        QccBitBuffer *output_buffer)
{
  int return_value;
  long range;

  range = (long)(model->high - model->low) + 1;
  model->high = model->low +
    (range * model->cumulative_frequencies[context][symbol_index - 1]) /
    model->cumulative_frequencies[context][0] - 1;
  model->low = model->low +
    (range * model->cumulative_frequencies[context][symbol_index]) /
    model->cumulative_frequencies[context][0];

  for (;;)
    {
      if (model->high < QCCENT_HALFVALUE)
        {
          return_value =
            QccENTArithmeticOutputBitPlusFollowingOppositeBits(0, model,
                                                               output_buffer);
          if (return_value == 2)
            return(2);
          else
            if (return_value == 1)
              {
                QccErrorAddMessage("(QccENTArithmeticEncodeSymbol): Error calling QccENTArithmeticOutputBitPlusFollowingOppositeBits()");
                return(1);
              }
        }
      else if (model->low >= QCCENT_HALFVALUE)
        {
          return_value =
            QccENTArithmeticOutputBitPlusFollowingOppositeBits(1, model,
                                                               output_buffer);
          if (return_value == 2)
            return(2);
          else
            if (return_value == 1)
              {
                QccErrorAddMessage("(QccENTArithmeticEncodeSymbol): Error calling QccENTArithmeticOutputBitPlusFollowingOppositeBits()");
                return(1);
              }
          model->low -= QCCENT_HALFVALUE;
          model->high -= QCCENT_HALFVALUE;
        }
      else if ((model->low >= QCCENT_FIRSTQUARTERVALUE) &&
               (model->high < QCCENT_THIRDQUARTERVALUE))
        {
          model->bits_to_follow += 1;
          model->low -= QCCENT_FIRSTQUARTERVALUE;
          model->high -= QCCENT_FIRSTQUARTERVALUE;
        }
      else
        break;
      model->low *= 2;
      model->high = model->high*2 + 1;
    }

  return(0);
}

int QccENTArithmeticEncode(const int *symbol_stream,
                           int symbol_stream_length,
                           QccENTArithmeticModel *model,
                           QccBitBuffer *output_buffer)
{
  int return_value;
  int current_symbol;
  int symbol_index;

  if (symbol_stream == NULL)
    return(0);
  if (output_buffer == NULL)
    return(0);
  if (model == NULL)
    return(0);

  for (current_symbol = 0; current_symbol < symbol_stream_length;
       current_symbol++)
    {
      if (model->context_function != NULL)
        model->current_context =
          (model->context_function)(symbol_stream, current_symbol);

      if ((model->current_context < 0) ||
          (model->current_context >= model->num_contexts))

⌨️ 快捷键说明

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