📄 tarp.c
字号:
/* * * QccPack: Quantization, compression, and coding libraries * Copyright (C) 1997-2009 James E. Fowler * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, * MA 02139, USA. * */#include "libQccPack.h"#define QCCTARP_BOUNDARY_VALUE 0#define QCCTARP_INSIGNIFICANT 0#define QCCTARP_PREVIOUSLY_SIGNIFICANT 1#define QCCTARP_NEWLY_SIGNIFICANT 2#define QCCTARP_MAXBITPLANES 128typedef unsigned int QccWAVTarpFixedPoint;#define QCCTARP_FIXEDPOINT_BITS 30#define QccWAVTarpToFixedPoint(x) \((QccWAVTarpFixedPoint)rint((x) * (1 << QCCTARP_FIXEDPOINT_BITS)))#define QccWAVTarpFromFixedPoint(x) \(((double)(x)) / (1 << QCCTARP_FIXEDPOINT_BITS))#define QCCTARP_FIXEDPOINT_MULT_SHIFT (QCCTARP_FIXEDPOINT_BITS >> 1)#define QCCTARP_FIXEDPOINT_MULT_MASK ((1 << QCCTARP_FIXEDPOINT_MULT_SHIFT) - 1)#define QccWAVTarpFixedPointMultDiv(x) \((QccWAVTarpFixedPoint)((x) >> QCCTARP_FIXEDPOINT_MULT_SHIFT))#define QccWAVTarpFixedPointMultMask(x) \((QccWAVTarpFixedPoint)((x) & QCCTARP_FIXEDPOINT_MULT_MASK))#define QccWAVTarpFixedPointMult(x, y) \((QccWAVTarpFixedPoint)(QccWAVTarpFixedPointMultDiv((x)) * \QccWAVTarpFixedPointMultDiv((y)) + \QccWAVTarpFixedPointMultDiv(QccWAVTarpFixedPointMultMask((x)) * \QccWAVTarpFixedPointMultDiv((y))) + \QccWAVTarpFixedPointMultDiv(QccWAVTarpFixedPointMultMask((y)) * \QccWAVTarpFixedPointMultDiv((x))))) typedef QccWAVTarpFixedPoint *QccWAVTarpFixedPointVector;static QccWAVTarpFixedPointVectorQccWAVTarpFixedPointVectorAlloc(int vector_dimension){ QccWAVTarpFixedPointVector vector; if (vector_dimension <= 0) return(NULL); if ((vector = (QccWAVTarpFixedPointVector)calloc(vector_dimension, sizeof(QccWAVTarpFixedPoint))) == NULL) QccErrorAddMessage("(QccWAVTarpFixedPointVectorAlloc): Error allocating memory"); return(vector);}static void QccWAVTarpFixedPointVectorFree(QccWAVTarpFixedPointVector vector){ if (vector != NULL) QccFree(vector);}static int QccWAVTarpUpdateModel(QccENTArithmeticModel *model, QccWAVTarpFixedPoint prob){ int probabilities[2]; int symbol; int cum = 0; int freq; int max_freq; int context = 0; probabilities[1] = prob >> (QCCTARP_FIXEDPOINT_BITS - QCCENT_FREQUENCY_BITS); probabilities[0] = QCCENT_MAXFREQUENCY - probabilities[1]; max_freq = QCCENT_MAXFREQUENCY - model->num_symbols[context] + 1; for (symbol = model->num_symbols[context] - 2; symbol >= 0; symbol--) { freq = probabilities[symbol]; if (freq > max_freq) model->frequencies[context] [model->translate_symbol_to_index[context][symbol]] = max_freq; else if (freq <= 0) model->frequencies[context] [model->translate_symbol_to_index[context][symbol]] = 1; else model->frequencies[context] [model->translate_symbol_to_index[context][symbol]] = freq; } for (symbol = model->num_symbols[context]; symbol >= 0; symbol--) { model->cumulative_frequencies[context][symbol] = cum; cum += model->frequencies[context][symbol]; } return(0);}static int QccWAVTarpEncodeDWT(QccWAVSubbandPyramid *image_subband_pyramid, char **sign_array, const QccIMGImageComponent *image, int num_levels, double *image_mean, int *max_coefficient_bits, QccWAVSubbandPyramid *mask_subband_pyramid, const QccIMGImageComponent *mask, const QccWAVWavelet *wavelet){ double coefficient_magnitude; double max_coefficient = -MAXFLOAT; int row, col; if (mask == NULL) { if (QccMatrixCopy(image_subband_pyramid->matrix, image->image, image->num_rows, image->num_cols)) { QccErrorAddMessage("(QccWAVTarpEncodeDWT): Error calling QccMatrixCopy()"); return(1); } if (QccWAVSubbandPyramidSubtractMean(image_subband_pyramid, image_mean, NULL)) { QccErrorAddMessage("(QccWAVTarpEncodeDWT): Error calling QccWAVSubbandPyramidSubtractMean()"); return(1); } } else { if (QccMatrixCopy(mask_subband_pyramid->matrix, mask->image, mask->num_rows, mask->num_cols)) { QccErrorAddMessage("(QccWAVTarpEncodeDWT): Error calling QccMatrixCopy()"); return(1); } *image_mean = QccIMGImageComponentShapeAdaptiveMean(image, mask); 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; else image_subband_pyramid->matrix[row][col] = image->image[row][col] - *image_mean; } if (mask != NULL) { if (QccWAVSubbandPyramidShapeAdaptiveDWT(image_subband_pyramid, mask_subband_pyramid, num_levels, wavelet)) { QccErrorAddMessage("(QccWAVTarpEncodeDWT): Error calling QccWAVSubbandPyramidShapeAdaptiveDWT()"); return(1); } } else if (QccWAVSubbandPyramidDWT(image_subband_pyramid, num_levels, wavelet)) { QccErrorAddMessage("(QccWAVTarpEncodeDWT): Error calling QccWAVSubbandPyramidDWT()"); return(1); } for (row = 0; row < image_subband_pyramid->num_rows; row++) for (col = 0; col < image_subband_pyramid->num_cols; col++) { coefficient_magnitude = fabs(image_subband_pyramid->matrix[row][col]); if (image_subband_pyramid->matrix[row][col] != coefficient_magnitude) { image_subband_pyramid->matrix[row][col] = coefficient_magnitude; sign_array[row][col] = 1; } else sign_array[row][col] = 0; if (coefficient_magnitude > max_coefficient) max_coefficient = coefficient_magnitude; } *max_coefficient_bits = (int)floor(QccMathLog2(max_coefficient)); return(0);}int QccWAVTarpEncodeHeader(QccBitBuffer *output_buffer, double alpha, int num_levels, int num_rows, int num_cols, double image_mean, int max_coefficient_bits){ int return_value; if (QccBitBufferPutDouble(output_buffer, alpha)) { QccErrorAddMessage("(QccWAVTarpEncodeHeader): Error calling QccBitBufferPuDouble()"); goto Error; } if (QccBitBufferPutChar(output_buffer, (unsigned char)num_levels)) { QccErrorAddMessage("(QccWAVTarpEncodeHeader): Error calling QccBitBufferPuChar()"); goto Error; } if (QccBitBufferPutInt(output_buffer, num_rows)) { QccErrorAddMessage("(QccWAVTarpEncodeHeader): Error calling QccBitBufferPutInt()"); goto Error; } if (QccBitBufferPutInt(output_buffer, num_cols)) { QccErrorAddMessage("(QccWAVTarpEncodeHeader): Error calling QccBitBufferPutInt()"); goto Error; } if (QccBitBufferPutDouble(output_buffer, image_mean)) { QccErrorAddMessage("(QccWAVTarpEncodeHeader): Error calling QccBitBufferPutDouble()"); goto Error; } if (QccBitBufferPutInt(output_buffer, max_coefficient_bits)) { QccErrorAddMessage("(QccWAVTarpEncodeHeader): Error calling QccBitBufferPutInt()"); goto Error; } return_value = 0; goto Return; Error: return_value = 1; Return: return(return_value);}static int QccWAVTarpSignificanceInputOutput(double *coefficient, QccWAVTarpFixedPoint p, double threshold, char *sign, char *significance, QccENTArithmeticModel *model, QccBitBuffer *buffer){ int symbol; int return_value; if (*significance != QCCTARP_INSIGNIFICANT) return(0); if (QccWAVTarpUpdateModel(model, p)) { QccErrorAddMessage("(QccWAVTarpSignificanceInputOutput): Error calling QccWAVTarpUpdateModel()"); return(1); } if (buffer->type == QCCBITBUFFER_OUTPUT) { if (*coefficient >= threshold) { symbol = 1; *coefficient -= threshold; } else symbol = 0; return_value = QccENTArithmeticEncode(&symbol, 1, model, buffer); if (return_value == 2) return(2); else if (return_value) { QccErrorAddMessage("(QccWAVTarpSignificanceInputOutput): Error calling QccENTArithmeticEncode()"); return(1); } } else { if (QccENTArithmeticDecode(buffer, model, &symbol, 1)) return(2); if (symbol) *coefficient = 1.5 * threshold; } if (symbol) { *significance = QCCTARP_NEWLY_SIGNIFICANT; if (QccWAVTarpUpdateModel(model, QccWAVTarpToFixedPoint(0.5))) { QccErrorAddMessage("(QccWAVTarpSignificanceInputOutput): Error calling QccWAVTarpUpdateModel()"); return(1); } if (buffer->type == QCCBITBUFFER_OUTPUT) { symbol = (int)(*sign); return_value = QccENTArithmeticEncode(&symbol, 1, model, buffer); if (return_value == 2) return(2); else if (return_value) { QccErrorAddMessage("(QccWAVTarpSignificanceInputOutput): Error calling QccENTArithmeticEncode()"); return(1); } } else { if (QccENTArithmeticDecode(buffer, model, &symbol, 1)) return(2); *sign = (char)symbol; } } return(0);}static int QccWAVTarpSignificancePassSubband(QccWAVSubbandPyramid *coefficients, const QccWAVSubbandPyramid *mask, char **significance_map, char **sign_array, QccWAVTarpFixedPoint alpha, QccWAVTarpFixedPoint beta, int subband, double threshold, QccENTArithmeticModel *model, QccBitBuffer *buffer){ int return_value; int subband_origin_row; int subband_origin_col; int subband_num_rows; int subband_num_cols; int row, col; QccWAVTarpFixedPoint p1; QccWAVTarpFixedPointVector p2 = NULL; QccWAVTarpFixedPoint p3; QccWAVTarpFixedPoint p; QccWAVTarpFixedPoint v; int transparent; if (QccWAVSubbandPyramidSubbandSize(coefficients, subband, &subband_num_rows, &subband_num_cols)) { QccErrorAddMessage("(QccWAVTarpSignificancePassSubband): Error calling QccWAVSubbandPyramidSubbandSize()"); goto Error; } if (QccWAVSubbandPyramidSubbandOffsets(coefficients, subband, &subband_origin_row, &subband_origin_col)) { QccErrorAddMessage("(QccWAVTarpSignificancePassSubband): Error calling QccWAVSubbandPyramidSubbandOffsets()"); goto Error; } if ((!subband_num_rows) || (!subband_num_cols)) return(0); if ((p2 = QccWAVTarpFixedPointVectorAlloc(subband_num_cols)) == NULL) { QccErrorAddMessage("(QccWAVTarpSignificancePassSubband): Error calling QccWAVTarpFixedPointVectorAlloc()"); goto Error; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -