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

📄 spiht.c

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

#define QCCSPIHT_TYPE_A 0
#define QCCSPIHT_TYPE_B 1
#define QCCSPIHT_TYPE_DELETE 2
#define QCCSPIHT_ENCODE 0
#define QCCSPIHT_DECODE 1

#define QCCSPIHT_MAXBITPLANES 128

static const int QccSPIHTArithmeticContexts[] =
  {
    /*  LIP Context  */
    16, 8, 8, 4, 8, 4, 4, 2, 8, 4, 4, 2, 4, 2, 2,
    /*  LIS Type A Context  */
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    /*  LIS Type A Offspring Context  */
    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
    /*  LIS Type B Context  */
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    /* Sign Context  */
    2,
    /* Refinement Context  */
    2
  };

#define QCCSPIHT_LIP_CONTEXT 0
#define QCCSPIHT_LIS_TYPEA_CONTEXT (QCCSPIHT_LIP_CONTEXT + 15)
#define QCCSPIHT_LIS_TYPEA_OFFSPRING_CONTEXT (QCCSPIHT_LIS_TYPEA_CONTEXT + 16)
#define QCCSPIHT_LIS_TYPEB_CONTEXT (QCCSPIHT_LIS_TYPEA_OFFSPRING_CONTEXT + 16)
#define QCCSPIHT_SIGN_CONTEXT (QCCSPIHT_LIS_TYPEB_CONTEXT + 16)
#define QCCSPIHT_REFINEMENT_CONTEXT (QCCSPIHT_SIGN_CONTEXT + 1)
#define QCCSPIHT_NUM_CONTEXTS (QCCSPIHT_REFINEMENT_CONTEXT + 1)

typedef struct
{
  int row;
  int col;
  unsigned char type;
  unsigned char state;
} QccSPIHTCoefficientBlock;

typedef struct
{
  QccWAVSubbandPyramid original_coefficients;
  QccWAVSubbandPyramid reconstructed_coefficients;
  QccWAVSubbandPyramid squared_errors;
  double distortion;
  FILE *file;
} QccSPIHTDistortionTrace;

static QccSPIHTCoefficientBlock
*QccSPIHTGetCoefficientBlockFromNode(QccListNode *node)
{
  return((QccSPIHTCoefficientBlock *)(node->value));
}

static void QccSPIHTRefineCoefficient(double *coefficient,
                                      int bit,
                                      double threshold)
{
  *coefficient +=
    (bit) ? (threshold / 2) : (-threshold / 2);
}

static void QccSPIHTDistortionTraceUpdate(QccSPIHTDistortionTrace
                                          *distortion_trace,
                                          int row,
                                          int col,
                                          QccBitBuffer *buffer)
{
  double diff;

  QccMatrix original_coefficients =
    distortion_trace->original_coefficients.matrix;
  QccMatrix reconstructed_coefficients =
    distortion_trace->reconstructed_coefficients.matrix;
  QccMatrix squared_errors =
    distortion_trace->squared_errors.matrix;
  int num_rows = distortion_trace->original_coefficients.num_rows;
  int num_cols = distortion_trace->original_coefficients.num_cols;

  distortion_trace->distortion -= squared_errors[row][col];
  diff = original_coefficients[row][col] - 
    reconstructed_coefficients[row][col];
  squared_errors[row][col] = diff * diff;
  distortion_trace->distortion += squared_errors[row][col];

  fprintf(distortion_trace->file,
          "%16.6f\t%16.6f\n",
          (double)buffer->bit_cnt / num_rows / num_cols,
          distortion_trace->distortion / num_rows / num_cols);
}

static void QccSPIHTListClean(QccList *list)
{
  QccListNode *current_list_node;
  QccListNode *next_list_node;
  QccSPIHTCoefficientBlock *current_coefficient_block;

  current_list_node = list->start;
  while (current_list_node != NULL)
    {
      next_list_node = current_list_node->next;

      current_coefficient_block =
        QccSPIHTGetCoefficientBlockFromNode(current_list_node);

      if (current_coefficient_block->type == QCCSPIHT_TYPE_DELETE)
        QccListDeleteNode(list, current_list_node);

      current_list_node = next_list_node;
    }
}

static int QccSPIHTInputOutput(QccBitBuffer *buffer,
                               int *symbol,
                               int method,
                               QccENTArithmeticModel *model,
                               int target_bit_cnt)
{
  
  if (method == QCCSPIHT_ENCODE)
    {
      if (model == NULL)
        {
          if (QccBitBufferPutBit(buffer, *symbol))
            {
              QccErrorAddMessage("(QccSPIHTInputOutput): Error calling QccBitBufferPutBit()");
              return(1);
            }
        }
      else
        {
          if (QccENTArithmeticEncode(symbol, 1,
                                     model, buffer))
            {
              QccErrorAddMessage("(QccSPIHTInputOutput): Error calling QccENTArithmeticEncode()");
              return(1);
            }
        }
      if (buffer->bit_cnt >= target_bit_cnt)
        {
          QccBitBufferFlush(buffer);
          return(1);
        }
    }
  else
    if (model == NULL)
      {
        if (QccBitBufferGetBit(buffer, symbol))
          {
            QccErrorAddMessage("(QccSPIHTInputOutput): Error calling QccBitBufferGetBit()");
            return(1);
          }
      }
    else
      if (QccENTArithmeticDecode(buffer,
                                 model,
                                 symbol, 1))
        {
          QccErrorAddMessage("(QccSPIHTInputOutput): Error calling QccENTArithmeticDecode()");
          return(1);
        }

  return(0);
}

static int QccSPIHTDecodeApplySigns(QccWAVSubbandPyramid
                                    *image_subband_pyramid,
                                    int **sign_array)
{
  int row, col;
  
  for (row = 0; row < image_subband_pyramid->num_rows; row++)
    for (col = 0; col < image_subband_pyramid->num_cols; col++)
      if (sign_array[row][col])
        image_subband_pyramid->matrix[row][col] *= -1;
  
  return(0);
}

static int QccSPIHTDecodeInverseDWT(QccWAVSubbandPyramid
                                    *image_subband_pyramid,
                                    QccWAVSubbandPyramid
                                    *mask_subband_pyramid,
                                    QccIMGImageComponent *image,
                                    double image_mean,
                                    const QccWAVWavelet *wavelet,
                                    const QccWAVPerceptualWeights
                                    *perceptual_weights)
{
  int row, col;
  
  if (perceptual_weights != NULL)
    if (QccWAVPerceptualWeightsRemove(image_subband_pyramid,
                                      perceptual_weights))
      {
        QccErrorAddMessage("(QccSPIHTDecodeInverseDWT): Error calling QccWAVPerceptualWeightsRemove()");
        return(1);
      }
  
  if (mask_subband_pyramid != NULL)
    {
      if (QccWAVSubbandPyramidInverseShapeAdaptiveDWT(image_subband_pyramid,
                                                      mask_subband_pyramid,
                                                      wavelet))
        {
          QccErrorAddMessage("(QccSPIHTDecodeInverseDWT): Error calling QccWAVSubbandPyramidInverseShapeAdaptiveDWT()");
          return(1);
        }
    }
  else
    if (QccWAVSubbandPyramidInverseDWT(image_subband_pyramid,
                                       wavelet))
      {
        QccErrorAddMessage("(QccSPIHTDecodeInverseDWT): Error calling QccWAVSubbandPyramidInverseDWT()");
        return(1);
      }
  
  if (QccWAVSubbandPyramidAddMean(image_subband_pyramid,
                                  image_mean))
    {
      QccErrorAddMessage("(QccSPIHTDecodeInverseDWT): Error calling QccWAVSubbandPyramidAddMean()");
      return(1);
    }
  
  if (mask_subband_pyramid != NULL)
    for (row = 0; row < image_subband_pyramid->num_rows; row++)
      for (col = 0; col < image_subband_pyramid->num_cols; col++)
        if (QccAlphaTransparent(mask_subband_pyramid->matrix[row][col]))
          image_subband_pyramid->matrix[row][col] = 0;

  if (QccMatrixCopy(image->image, image_subband_pyramid->matrix,
                    image->num_rows, image->num_cols))
    {
      QccErrorAddMessage("(QccSPIHTDecodeInverseDWT): Error calling QccMatrixCopy()");
      return(1);
    }
  
  return(0);
}

static int QccSPIHTDescendantsOutsideMask(QccWAVSubbandPyramid
                                          *subband_pyramid,
                                          QccWAVSubbandPyramid
                                          *mask,
                                          int row, int col,
                                          int block_size);

static int QccSPIHTGetOffspring(QccWAVSubbandPyramid
                                *subband_pyramid,
                                int row, int col,
                                int *offspring_row,
                                int *offspring_col,
                                int block_size)
{
  int baseband_num_rows;
  int baseband_num_cols;
  int num_offspring;
  
  if ((2*row >= subband_pyramid->num_rows) ||
      (2*col >= subband_pyramid->num_cols))
    return(0);
  
  QccWAVSubbandPyramidSubbandSize(subband_pyramid,
                                  0,
                                  &baseband_num_rows,
                                  &baseband_num_cols);
  
  if ((row < baseband_num_rows) &&
      (col < baseband_num_cols))
    {
      num_offspring = 3;
      offspring_row[0] = row;
      offspring_col[0] = col + baseband_num_cols;
      offspring_row[1] = row + baseband_num_rows;
      offspring_col[1] = col;
      offspring_row[2] = row + baseband_num_rows;
      offspring_col[2] = col + baseband_num_cols;
    }
  else
    {
      num_offspring = 4;
      offspring_row[0] = row * 2;
      offspring_col[0] = col * 2;
      offspring_row[1] = row * 2 + block_size;
      offspring_col[1] = col * 2;
      offspring_row[2] = row * 2;
      offspring_col[2] = col * 2 + block_size;
      offspring_row[3] = row * 2 + block_size;
      offspring_col[3] = col * 2 + block_size;
    }
  
  return(num_offspring);
}

static int QccSPIHTOutsideMask(QccWAVSubbandPyramid
                               *subband_pyramid,
                               QccWAVSubbandPyramid
                               *mask,
                               int row, int col,
                               int block_size)
{
  int block_row, block_col;
  
  if (mask == NULL)
    return(0);

  for (block_row = 0; block_row < block_size; block_row++)
    for (block_col = 0; block_col < block_size; block_col++)
      if (!QccAlphaTransparent(mask->matrix
                               [row + block_row][col + block_col]))
        return(0);
  
  if (!QccSPIHTDescendantsOutsideMask(subband_pyramid,
                                      mask,
                                      row, col,
                                      block_size))
    return(0);

  return(1);
}

static int QccSPIHTDescendantsOutsideMask(QccWAVSubbandPyramid
                                          *subband_pyramid,
                                          QccWAVSubbandPyramid
                                          *mask,
                                          int row, int col,
                                          int block_size)
{
  int offspring_row[4];
  int offspring_col[4];
  int num_offspring;
  int offspring;
  
  if (mask == NULL)
    return(0);

  num_offspring = 
    QccSPIHTGetOffspring(subband_pyramid,
                         row, col,
                         offspring_row, offspring_col,
                         block_size);
  
  if (!num_offspring)
    return(1);

  for (offspring = 0; offspring < num_offspring; offspring++)
    if (!QccSPIHTOutsideMask(subband_pyramid,
                             mask,
                             offspring_row[offspring],
                             offspring_col[offspring],
                             block_size))
      return(0);
  
  return(1);
}

static int QccSPIHTAlgorithmInitialize(QccWAVSubbandPyramid
                                       *subband_pyramid,
                                       QccWAVSubbandPyramid
                                       *mask,
                                       QccList *LIP,
                                       QccList *LIS,
                                       int block_size)
{
  int subband_num_rows, subband_num_cols;
  int row, col;
  QccSPIHTCoefficientBlock coefficient_block;
  QccListNode *new_node;
  
  if (QccWAVSubbandPyramidSubbandSize(subband_pyramid,
                                      0,
                                      &subband_num_rows,
                                      &subband_num_cols))
    {
      QccErrorAddMessage("(QccSPIHTAlgorithmInitialize): Error calling QccWAVSubbandPyramidSubbandSize()");
      return(1);
    }
  
  for (row = 0; row < subband_num_rows; row += block_size)
    for (col = 0; col < subband_num_cols; col += block_size)
      if (!QccSPIHTOutsideMask(subband_pyramid,
                               mask,
                               row, col,
                               block_size))
        {
          coefficient_block.row = row;
          coefficient_block.col = col;
          coefficient_block.type = QCCSPIHT_TYPE_A;
          coefficient_block.state = 0;

⌨️ 快捷键说明

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