📄 spiht.c
字号:
QccSPIHTGetCoefficientBlockFromNode(current_list_node);
if (current_coefficient_block->type == QCCSPIHT_TYPE_A)
{
if ((return_value =
QccSPIHTTypeA(subband_pyramid,
sign_array,
buffer,
current_coefficient_block,
current_list_node,
threshold,
LSP, LIP, LIS,
method,
model,
target_bit_cnt,
block_size)))
{
QccErrorAddMessage("(QccSPIHTSortingPass): Error calling QccSPIHTTypeA()");
return(return_value);
}
}
else
if ((return_value =
QccSPIHTTypeB(subband_pyramid,
sign_array,
buffer,
current_coefficient_block,
current_list_node,
threshold,
LIS,
method,
model,
target_bit_cnt,
block_size)))
{
QccErrorAddMessage("(QccSPIHTSortingPass): Error calling QccSPIHTTypeB()");
return(return_value);
}
current_list_node = next_list_node;
}
return(0);
}
static int QccSPIHTRefinementPass(QccWAVSubbandPyramid
*subband_pyramid,
QccBitBuffer *buffer,
double threshold,
QccList *LSP,
QccListNode *stop,
int method,
QccENTArithmeticModel *model,
int target_bit_cnt)
{
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))
{
QccErrorAddMessage("(QccSPIHTRefinementPass): Error calling QccSPIHTInputOutputRefinementBit()");
return(2);
}
current_node = current_node->next;
}
return(0);
}
int QccSPIHTEncode(const QccIMGImageComponent *image,
const QccIMGImageComponent *mask,
QccBitBuffer *buffer,
int num_levels,
const QccWAVWavelet *wavelet,
const QccWAVPerceptualWeights *perceptual_weights,
int target_bit_cnt,
int arithmetic_coded)
{
int return_value;
QccENTArithmeticModel *model = NULL;
QccWAVSubbandPyramid image_subband_pyramid;
QccWAVSubbandPyramid mask_subband_pyramid;
int **sign_array = NULL;
double image_mean;
int max_coefficient_bits;
QccList LSP;
QccList LIP;
QccList LIS;
QccListNode *stop;
double threshold;
int row;
int block_size;
if (image == NULL)
return(0);
if (buffer == NULL)
return(0);
if (wavelet == NULL)
return(0);
QccWAVSubbandPyramidInitialize(&image_subband_pyramid);
QccWAVSubbandPyramidInitialize(&mask_subband_pyramid);
QccListInitialize(&LSP);
QccListInitialize(&LIP);
QccListInitialize(&LIS);
image_subband_pyramid.num_levels = 0;
image_subband_pyramid.num_rows = image->num_rows;
image_subband_pyramid.num_cols = image->num_cols;
if (QccWAVSubbandPyramidAlloc(&image_subband_pyramid))
{
QccErrorAddMessage("(QccSPIHTEncode): Error calling QccWAVSubbandPyramidAlloc()");
goto QccError;
}
if (mask != NULL)
{
if ((mask->num_rows != image->num_rows) ||
(mask->num_cols != image->num_cols))
{
QccErrorAddMessage("(QccSPIHTEncode): Mask and image must be same size");
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("(QccSPIHTEncode): Error calling QccWAVSubbandPyramidAlloc()");
goto QccError;
}
}
if ((sign_array = (int **)malloc(sizeof(int *) * image->num_rows)) == NULL)
{
QccErrorAddMessage("(QccSPIHTEncode): Error allocating memory");
goto QccError;
}
for (row = 0; row < image->num_rows; row++)
if ((sign_array[row] =
(int *)malloc(sizeof(int) * image->num_cols)) == NULL)
{
QccErrorAddMessage("(QccSPIHTEncode): Error allocating memory");
goto QccError;
}
if (QccSPIHTEncodeDWT(&image_subband_pyramid,
sign_array,
image,
num_levels,
&image_mean,
&max_coefficient_bits,
&mask_subband_pyramid,
mask,
wavelet,
perceptual_weights))
{
QccErrorAddMessage("(QccSPIHTEncode): Error calling QccSPIHTEncodeDWT()");
goto QccError;
}
if (QccSPIHTEncodeHeader(buffer,
num_levels,
image->num_rows, image->num_cols,
image_mean,
max_coefficient_bits,
arithmetic_coded))
{
QccErrorAddMessage("(QccSPIHTEncode): Error calling QccSPIHTEncodeHeader()");
goto QccError;
}
if (arithmetic_coded)
{
if ((model =
QccENTArithmeticEncodeStart(QccSPIHTArithmeticContexts,
QCCSPIHT_NUM_CONTEXTS,
NULL,
QCCENT_ANYNUMBITS))
== NULL)
{
QccErrorAddMessage("(QccSPIHTEncode): Error calling QccENTArithmeticEncodeStart()");
goto QccError;
}
block_size = 2;
}
else
block_size = 1;
if (QccSPIHTAlgorithmInitialize(&image_subband_pyramid,
&LIP,
&LIS,
block_size))
{
QccErrorAddMessage("(QccSPIHTEncode): Error calling QccSPIHTAlgorithmInitialize()");
goto QccError;
}
threshold = pow((double)2, (double)max_coefficient_bits);
while (1)
{
stop = LSP.end;
return_value =
QccSPIHTSortingPass(&image_subband_pyramid,
sign_array,
buffer,
threshold,
&LSP,
&LIP,
&LIS,
QCCSPIHT_ENCODE,
model,
target_bit_cnt,
block_size);
if (return_value == 1)
{
QccErrorAddMessage("(QccSPIHTEncode): Error calling QccSPIHTSortingPass()");
goto QccError;
}
else
if (return_value == 2)
break;
return_value =
QccSPIHTRefinementPass(&image_subband_pyramid,
buffer,
threshold,
&LSP,
stop,
QCCSPIHT_ENCODE,
model,
target_bit_cnt);
if (return_value == 1)
{
QccErrorAddMessage("(QccSPIHTEncode): Error calling QccSPIHTRefinementPass()");
goto QccError;
}
else
if (return_value == 2)
break;
threshold /= 2.0;
}
return_value = 0;
QccErrorClearMessages();
goto QccReturn;
QccError:
return_value = 1;
QccReturn:
QccWAVSubbandPyramidFree(&image_subband_pyramid);
QccWAVSubbandPyramidFree(&mask_subband_pyramid);
if (sign_array != NULL)
{
for (row = 0; row < image->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 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("(QccSPIHTEncodeHeader): Error calling QccBitBufferPuChar()");
goto QccError;
}
*num_levels = (int)ch;
if (QccBitBufferGetInt(buffer, num_rows))
{
QccErrorAddMessage("(QccSPIHTEncodeHeader): Error calling QccBitBufferGetInt()");
goto QccError;
}
if (QccBitBufferGetInt(buffer, num_cols))
{
QccErrorAddMessage("(QccSPIHTEncodeHeader): Error calling QccBitBufferGetInt()");
goto QccError;
}
if (QccBitBufferGetDouble(buffer, image_mean))
{
QccErrorAddMessage("(QccSPIHTEncodeHeader): Error calling QccBitBufferGetDouble()");
goto QccError;
}
if (QccBitBufferGetChar(buffer, &ch))
{
QccErrorAddMessage("(QccSPIHTEncodeHeader): Error calling QccBitBufferGetChar()");
goto QccError;
}
*max_coefficient_bits = (int)ch;
if (QccBitBufferGetBit(buffer, arithmetic_coded))
{
QccErrorAddMessage("(QccSPIHTEncodeHeader): Error calling QccBitBufferGetBit()");
goto QccError;
}
return_value = 0;
goto QccReturn;
QccError:
return_value = 1;
QccReturn:
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 arithmetic_coded)
{
int return_value;
QccENTArithmeticModel *model = NULL;
QccWAVSubbandPyramid image_subband_pyramid;
QccWAVSubbandPyramid mask_subband_pyramid;
int **sign_array = NULL;
QccList LSP;
QccList LIP;
QccList LIS;
QccListNode *stop;
double threshold;
int row, col;
QccWAVWavelet lazy_wavelet_transform;
int block_size;
if (image == NULL)
return(0);
if (buffer == NULL)
return(0);
if (wavelet == NULL)
return(0);
QccWAVSubbandPyramidInitialize(&image_subband_pyramid);
QccWAVSubbandPyramidInitialize(&mask_subband_pyramid);
QccListInitialize(&LSP);
QccListInitialize(&LIP);
QccListInitialize(&LIS);
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 ((sign_array = (int **)malloc(sizeof(int *) * image->num_rows)) == NULL)
{
QccErrorAddMessage("(QccSPIHTDecode): Error allocating memory");
goto QccError;
}
for (row = 0; row < image->num_rows; row++)
if ((sign_array[row] =
(int *)malloc(sizeof(int) * image->num_cols)) == NULL)
{
QccErrorAddMessage("(QccSPIHTDecode): Error allocating memory");
goto QccError;
}
for (row = 0; row < image->num_rows; row++)
for (col = 0; col < image->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,
QCCENT_ANYNUMBITS))
== NULL)
{
QccErrorAddMessage("(QccSPIHTEncode): Error calling QccENTArithmeticDecodeStart()");
goto QccError;
}
block_size = 2;
}
else
block_size = 1;
if (QccSPIHTAlgorithmInitialize(&image_subband_pyramid,
&LIP,
&LIS,
block_size))
{
QccErrorAddMessage("(QccSPIHTDecode): Error calling QccSPIHTAlgorithmInitialize()");
goto QccError;
}
threshold = pow((double)2, (double)max_coefficient_bits);
while (1)
{
stop = LSP.end;
return_value =
QccSPIHTSortingPass(&image_subband_pyramid,
sign_array,
buffer,
threshold,
&LSP,
&LIP,
&LIS,
QCCSPIHT_DECODE,
model,
0,
block_size);
if (return_value == 1)
{
QccErrorAddMessage("(QccSPIHTDecode): 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);
if (return_value == 1)
{
QccErrorAddMessage("(QccSPIHTDecode): Error calling QccSPIHTRefinementPass()");
goto QccError;
}
else
if (return_value == 2)
break;
threshold /= 2.0;
}
if (QccSPIHTDecodeInverseDWT(&image_subband_pyramid,
((mask != NULL) ? &mask_subband_pyramid : NULL),
sign_array,
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);
if (sign_array != NULL)
{
for (row = 0; row < image->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);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -