📄 spiht.c
字号:
#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 + -