spiht.c

来自「spiht的压缩解压缩c编写的」· C语言 代码 · 共 1,572 行 · 第 1/4 页

C
1,572
字号
              {
                QccErrorAddMessage("(QccSPIHTSortingPass): Error calling QccSPIHTTypeB()");
                goto Error;
              }
          break;

        default:
          break;
        }
      
      current_list_node = current_list_node->next;
    }
  
  return_value = 0;
  goto Return;
 Finished:
  return_value = 2;
  goto Return;
 Error:
  return_value = 1;
 Return:
  QccSPIHTListClean(LIP);
  QccSPIHTListClean(LIS);
  return(return_value);
}

static int QccSPIHTRefinementPass(QccWAVSubbandPyramid
                                  *subband_pyramid,
                                  QccBitBuffer *buffer,
                                  double threshold,
                                  QccList *LSP,
                                  QccListNode *stop,
                                  int method,
                                  QccENTArithmeticModel *model,
                                  int target_bit_cnt,
                                  QccSPIHTDistortionTrace *distortion_trace)
{
  QccListNode *current_node;
  QccSPIHTCoefficientBlock *current_coefficient;
  
  current_node = LSP->start;
  
  if ((current_node == NULL) || (stop == NULL))
    return(0);
  
  stop = stop->next;
  
  while (current_node != stop)
    {
      current_coefficient = QccSPIHTGetCoefficientBlockFromNode(current_node);
      
      if (QccSPIHTInputOutputRefinementBit(subband_pyramid,
                                           buffer,
                                           threshold,
                                           current_coefficient,
                                           method,
                                           model,
                                           target_bit_cnt,
                                           distortion_trace))
        {
          QccErrorAddMessage("(QccSPIHTRefinementPass): Error calling QccSPIHTInputOutputRefinementBit()");
          return(2);
        }
      
      current_node = current_node->next;
    }
  
  return(0);
}

int QccSPIHTDecodeHeader(QccBitBuffer *buffer, 
                         int *num_levels, 
                         int *num_rows, int *num_cols,
                         double *image_mean,
                         int *max_coefficient_bits,
                         int *arithmetic_coded)
{
  int return_value;
  unsigned char ch;
  
  if (QccBitBufferGetChar(buffer, &ch))
    {
      QccErrorAddMessage("(QccSPIHTDecodeHeader): Error calling QccBitBufferPuChar()");
      goto QccError;
    }
  *num_levels = (int)ch;
  
  if (QccBitBufferGetInt(buffer, num_rows))
    {
      QccErrorAddMessage("(QccSPIHTDecodeHeader): Error calling QccBitBufferGetInt()");
      goto QccError;
    }
  
  if (QccBitBufferGetInt(buffer, num_cols))
    {
      QccErrorAddMessage("(QccSPIHTDecodeHeader): Error calling QccBitBufferGetInt()");
      goto QccError;
    }
  
  if (QccBitBufferGetDouble(buffer, image_mean))
    {
      QccErrorAddMessage("(QccSPIHTDecodeHeader): Error calling QccBitBufferGetDouble()");
      goto QccError;
    }
  
  if (QccBitBufferGetInt(buffer, max_coefficient_bits))
    {
      QccErrorAddMessage("(QccSPIHTDecodeHeader): Error calling QccBitBufferGetChar()");
      goto QccError;
    }
  
  if (QccBitBufferGetBit(buffer, arithmetic_coded))
    {
      QccErrorAddMessage("(QccSPIHTDecodeHeader): Error calling QccBitBufferGetBit()");
      goto QccError;
    }
  
  return_value = 0;
  goto QccReturn;
 QccError:
  return_value = 1;
 QccReturn:
  return(return_value);
}

int QccSPIHTDecode2(QccBitBuffer *buffer,
                    QccWAVSubbandPyramid *image_subband_pyramid,
                    QccWAVSubbandPyramid *mask_subband_pyramid,
                    int max_coefficient_bits,
                    int target_bit_cnt,
                    int arithmetic_coded)
{
  int return_value;
  QccENTArithmeticModel *model = NULL;
  int **sign_array = NULL;
  QccList LSP;
  QccList LIP;
  QccList LIS;
  QccListNode *stop;
  double threshold;
  int row, col;
  int block_size;

  if (image_subband_pyramid == NULL)
    return(0);
  if (buffer == NULL)
    return(0);
  
  QccListInitialize(&LSP);
  QccListInitialize(&LIP);
  QccListInitialize(&LIS);
  
  if ((sign_array =
       (int **)malloc(sizeof(int *) * image_subband_pyramid->num_rows)) ==
      NULL)
    {
      QccErrorAddMessage("(QccSPIHTDecode2): Error allocating memory");
      goto QccError;
    }
  for (row = 0; row < image_subband_pyramid->num_rows; row++)
    if ((sign_array[row] =
         (int *)malloc(sizeof(int) * image_subband_pyramid->num_cols)) == NULL)
      {
        QccErrorAddMessage("(QccSPIHTDecode2): Error allocating memory");
        goto QccError;
      }
  
  for (row = 0; row < image_subband_pyramid->num_rows; row++)
    for (col = 0; col < image_subband_pyramid->num_cols; col++)
      {
        image_subband_pyramid->matrix[row][col] = 0.0;
        sign_array[row][col] = 0;
      }
  
  if (arithmetic_coded)
    {
      if ((model =
           QccENTArithmeticDecodeStart(buffer,
                                       QccSPIHTArithmeticContexts,
                                       QCCSPIHT_NUM_CONTEXTS,
                                       NULL,
                                       target_bit_cnt))
          == NULL)
        {
          QccErrorAddMessage("(QccSPIHTDecode2): Error calling QccENTArithmeticDecodeStart()");
          goto QccError;
        }
      block_size = 2;
    }
  else
    block_size = 1;

  if (QccSPIHTAlgorithmInitialize(image_subband_pyramid,
                                  mask_subband_pyramid,
                                  &LIP,
                                  &LIS,
                                  block_size))
    {
      QccErrorAddMessage("(QccSPIHTDecode2): Error calling QccSPIHTAlgorithmInitialize()");
      goto QccError;
    }
  
  threshold = pow((double)2, (double)max_coefficient_bits);

  while (1)
    {
      stop = LSP.end;
      
      return_value =
        QccSPIHTSortingPass(image_subband_pyramid,
                            mask_subband_pyramid,
                            sign_array,
                            buffer,
                            threshold,
                            &LSP,
                            &LIP,
                            &LIS,
                            QCCSPIHT_DECODE,
                            model,
                            0,
                            block_size,
                            NULL);
      if (return_value == 1)
        {
          QccErrorAddMessage("(QccSPIHTDecode2): Error calling QccSPIHTSortingPass()");
          goto QccError;
        }
      else
        if (return_value == 2)
          break;
      
      return_value =
        QccSPIHTRefinementPass(image_subband_pyramid,
                               buffer,
                               threshold,
                               &LSP,
                               stop,
                               QCCSPIHT_DECODE,
                               model,
                               0,
                               NULL);
      if (return_value == 1)
        {
          QccErrorAddMessage("(QccSPIHTDecode2): Error calling QccSPIHTRefinementPass()");
          goto QccError;
        }
      else
        if (return_value == 2)
          break;
      
      threshold /= 2.0;
    }
  
  if (QccSPIHTDecodeApplySigns(image_subband_pyramid,
                               sign_array))
    {
      QccErrorAddMessage("(QccSPIHTDecode2): Error calling QccSPIHTApplySigns()");
      goto QccError;
    }

  return_value = 0;
  QccErrorClearMessages();
  goto QccReturn;
 QccError:
  return_value = 1;
 QccReturn:
  if (sign_array != NULL)
    {
      for (row = 0; row < image_subband_pyramid->num_rows; row++)
        if (sign_array[row] != NULL)
          free(sign_array[row]);
      free(sign_array);
    }
  QccListFree(&LSP);
  QccListFree(&LIP);
  QccListFree(&LIS);
  QccENTArithmeticFreeModel(model);
  return(return_value);
}

int QccSPIHTDecode(QccBitBuffer *buffer,
                   QccIMGImageComponent *image,
                   const QccIMGImageComponent *mask,
                   int num_levels,
                   const QccWAVWavelet *wavelet,
                   const QccWAVPerceptualWeights *perceptual_weights,
                   double image_mean,
                   int max_coefficient_bits,
                   int target_bit_cnt,
                   int arithmetic_coded)
{
  int return_value;
  QccWAVSubbandPyramid image_subband_pyramid;
  QccWAVSubbandPyramid mask_subband_pyramid;
  QccWAVWavelet lazy_wavelet_transform;

  if (image == NULL)
    return(0);
  if (buffer == NULL)
    return(0);
  if (wavelet == NULL)
    return(0);
  
  QccWAVSubbandPyramidInitialize(&image_subband_pyramid);
  QccWAVSubbandPyramidInitialize(&mask_subband_pyramid);
  QccWAVWaveletInitialize(&lazy_wavelet_transform);
  
  image_subband_pyramid.num_levels = num_levels;
  image_subband_pyramid.num_rows = image->num_rows;
  image_subband_pyramid.num_cols = image->num_cols;
  if (QccWAVSubbandPyramidAlloc(&image_subband_pyramid))
    {
      QccErrorAddMessage("(QccSPIHTDecode): Error calling QccWAVSubbandPyramidAlloc()");
      goto QccError;
    }
  
  if (mask != NULL)
    {
      if ((mask->num_rows != image->num_rows) ||
          (mask->num_cols != image->num_cols))
        {
          QccErrorAddMessage("(QccSPIHTDecode): Mask and image must be same size");
          goto QccError;
        }

      if (QccWAVWaveletCreate(&lazy_wavelet_transform, "LWT.lft", "symmetric"))
        {
          QccErrorAddMessage("(QccSPIHTDecode): Error calling QccWAVWaveletCreate()");
          goto QccError;
        }

      mask_subband_pyramid.num_levels = 0;
      mask_subband_pyramid.num_rows = mask->num_rows;
      mask_subband_pyramid.num_cols = mask->num_cols;
      if (QccWAVSubbandPyramidAlloc(&mask_subband_pyramid))
        {
          QccErrorAddMessage("(QccSPIHTDecode): Error calling QccWAVSubbandPyramidAlloc()");
          goto QccError;
        }

      if (QccMatrixCopy(mask_subband_pyramid.matrix,
                        mask->image,
                        mask->num_rows,
                        mask->num_cols))
        {
          QccErrorAddMessage("(QccSPIHTDecode): Error calling QccMatrixCopy()");
          goto QccError;
        }

      if (QccWAVSubbandPyramidDWT(&mask_subband_pyramid,
                                  num_levels,
                                  &lazy_wavelet_transform))
        {
          QccErrorAddMessage("(QccSPIHTDecode): Error calling QccWAVSubbandPyramidDWT()");
          goto QccError;
        }
    }
  
  if (QccSPIHTDecode2(buffer,
                      &image_subband_pyramid,
                      (mask != NULL) ?
                      &mask_subband_pyramid : NULL,
                      max_coefficient_bits,
                      target_bit_cnt,
                      arithmetic_coded))
    {
      QccErrorAddMessage("(QccSPIHTDecode): Error calling QccSPIHTDecode2()");
      goto QccError;
    }

  if (QccSPIHTDecodeInverseDWT(&image_subband_pyramid,
                               ((mask != NULL) ? &mask_subband_pyramid : NULL),
                               image,
                               image_mean,
                               wavelet,
                               perceptual_weights))
    {
      QccErrorAddMessage("(QccSPIHTDecode): Error calling QccSPIHTDecodeInverseDWT()");
      goto QccError;
    }
  
  return_value = 0;
  QccErrorClearMessages();
  goto QccReturn;
 QccError:
  return_value = 1;
 QccReturn:
  QccWAVSubbandPyramidFree(&image_subband_pyramid);
  QccWAVSubbandPyramidFree(&mask_subband_pyramid);
  QccWAVWaveletFree(&lazy_wavelet_transform);
  return(return_value);
}

⌨️ 快捷键说明

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