📄 hplx_hor_analysis_by_lifting.c
字号:
__initialize(hplx_analysis_stage_ref base, forward_info_ref info,
canvas_dims_ptr dims, canvas_dims_ptr frame_dims)
{
hplx_hor_analysis_by_lifting_ref self =
(hplx_hor_analysis_by_lifting_ref) base;
frame_info frame;
int b, n;
/* Begin by determining the Wavelet kernels and derivative properties. */
self->kernel_type =
info->get_kernel_type(info,base->direction,INFO__ANALYSIS,
base->component_idx,base->level_idx,NULL,NULL,
NULL,NULL);
if (self->kernel_type == INFO__INT_LIFTING)
{
self->num_steps =
info->get_int_steps(info,base->direction,base->component_idx,
base->level_idx,self->neg_supports,
self->pos_supports,self->int_taps,
self->int_downshifts);
}
else if (self->kernel_type == INFO__FLOAT_LIFTING)
{
self->num_steps =
info->get_float_steps(info,base->direction,base->component_idx,
base->level_idx,self->neg_supports,
self->pos_supports,self->float_taps,
self->branch_scale,self->branch_scale+1);
}
else
assert(0);
for (n=0; n < self->num_steps; n++)
{
if (self->neg_supports[n] > self->neg_extend)
self->neg_extend = self->neg_supports[n];
if (self->pos_supports[n] > self->pos_extend)
self->pos_extend = self->pos_supports[n];
}
if (self->kernel_type == INFO__FLOAT_LIFTING)
{ /* Compute DC gains associated with the output of each update lifting
step, i.e. the 1'st, 3'rd, ... lifting steps. */
float current_gain, source_gain, step_gain;
int k;
for (n=0; n < self->num_steps; n++)
{
current_gain = (n>=2)?(self->step_dc_gains[n-2]):1.0F;
source_gain = (n>=1)?(self->step_dc_gains[n-1]):1.0F;
step_gain = 0.0F;
for (k=-self->neg_supports[n]; k <= self->pos_supports[n]; k++)
step_gain += (self->float_taps[n])[k];
self->step_dc_gains[n] = current_gain + step_gain*source_gain;
}
for (current_gain=1.0F, n=1; n < self->num_steps; n+=2)
{ /* This step ensures that the update lifting steps identify
the incremental DC gain relative to the output of the previous
update step, rather than the absolute DC gain at the end of
each step. */
step_gain = self->step_dc_gains[n] / current_gain;
current_gain = self->step_dc_gains[n];
self->step_dc_gains[n] = step_gain;
}
}
/* Now determine tile and frame dimensions and attributes. */
self->tile_width = dims->cols;
self->first_idx = dims->left_col;
info->get_level_info(info,base->component_idx,base->level_idx,
NULL,NULL,&frame,NULL);
if (frame.hor_ssodwt)
{
int uses_overlap;
/* First check that filters have some overlap. */
for (uses_overlap=0, n=0; n < self->num_steps; n++)
if (((n & 1)==0) && (self->pos_supports[n] > 0))
uses_overlap = 1; /* Prediction step uses overlapping boundary */
if (!uses_overlap)
local_error("The 1-sample overlap method has no effect whatsoever "
"if all update steps in the lifting implementation of "
"the filter have only two taps! The method was designed "
"for use with odd length filters.");
/* Now set up frame dimensions. */
self->frame_cols = frame_dims->cols;
self->frame_ref = frame_dims->left_col;
self->first_frame_cols = self->frame_cols -
((self->first_idx - self->frame_ref) & (self->frame_cols - 1));
if (self->first_frame_cols >= self->tile_width)
{
self->first_frame_cols = self->tile_width;
self->num_frames = 1;
}
else
self->num_frames = 2 +
(self->tile_width - self->first_frame_cols - 1) / self->frame_cols;
}
else
{ /* No frames, set frame dimensions to refer to the entire tile. */
self->num_frames = 1;
self->frame_cols = self->first_frame_cols = self->tile_width;
self->frame_ref = self->first_idx;
}
/* Finally, perform branch-specific initialization. */
for (b=0; b < base->horiz_limit; b++)
{
canvas_dims branch_dims, branch_frame_dims;
int left, right;
branch_dims = *dims;
if (base->horiz_limit > 1) {
left = branch_dims.left_col;
right = left + branch_dims.cols - 1;
left = (left+1-b)>>1;
right = (right-b)>>1;
branch_dims.left_col = left;
branch_dims.cols = right+1-left;
}
branch_frame_dims = *frame_dims;
if (base->horiz_limit > 1) {
branch_frame_dims.cols >>= 1;
branch_frame_dims.left_col = (branch_frame_dims.left_col+1-b)>>1;
}
if (self->kernel_type == INFO__INT_LIFTING)
{
self->branch_buf_int[b] = (ifc_int *)
local_malloc(XFORM_HBUF_KEY,sizeof(ifc_int)*
(branch_dims.cols+self->neg_extend+self->pos_extend+1));
self->branch_buf_int[b] += self->neg_extend;
}
else if (self->kernel_type == INFO__FLOAT_LIFTING)
{
self->branch_buf_float[b] = (float *)
local_malloc(XFORM_HBUF_KEY,sizeof(float)*
(branch_dims.cols+self->neg_extend+self->pos_extend+1));
self->branch_buf_float[b] += self->neg_extend;
}
else
assert(0);
base->branches[b]->initialize(base->branches[b],info,
&branch_dims,&branch_frame_dims);
}
}
/*****************************************************************************/
/* __push_line_float */
/*****************************************************************************/
static void
__push_line_float(hplx_analysis_stage_ref base, float *line_buf,
int width)
{
hplx_hor_analysis_by_lifting_ref self =
(hplx_hor_analysis_by_lifting_ref) base;
int first_sample_odd, n, b;
assert(base->use_floats);
assert(width == self->tile_width);
if (width == 0)
return;
assert(self->kernel_type == INFO__FLOAT_LIFTING);
first_sample_odd = self->first_idx & 1;
if (base->horiz_limit > 1) {
for (b=0; b < base->horiz_limit; b++)
{ /* Split input into even and odd sub-sequences. */
float *sp, *dp;
for (sp=line_buf+b, dp=self->branch_buf_float[b^first_sample_odd],
n=(width+1-b)>>1; n > 0; n--, sp+=2, dp++)
*dp = *sp;
}
perform_1d_float_lifting(self);
for (b=0; b < base->horiz_limit; b++)
base->branches[b]->push_line_float(base->branches[b],
self->branch_buf_float[b],
(width+1-(b^first_sample_odd))>>1);
}
else {
float *sp, *dp;
for (sp=line_buf, dp=self->branch_buf_float[0], n=width; n > 0; n--, sp++, dp++)
*dp = *sp;
base->branches[0]->push_line_float(base->branches[0],
self->branch_buf_float[0], width);
}
}
/*****************************************************************************/
/* __push_line_fixed */
/*****************************************************************************/
static void
__push_line_fixed(hplx_analysis_stage_ref base, ifc_int *line_buf,
int width)
{
hplx_hor_analysis_by_lifting_ref self =
(hplx_hor_analysis_by_lifting_ref) base;
int n, b, first_sample_odd;
assert(width == self->tile_width);
if (width == 0)
return;
first_sample_odd = self->first_idx & 1;
if (self->kernel_type == INFO__FLOAT_LIFTING)
{
assert(base->use_floats);
if (base->horiz_limit > 1) {
for (b=0; b < base->horiz_limit; b++)
{ /* Split input into even and odd sub-sequences. */
ifc_int *sp;
float *dp;
for (sp=line_buf+b, dp=self->branch_buf_float[b^first_sample_odd],
n=(width+1-b)>>1; n > 0; n--, sp+=2, dp++)
*dp = (float) *sp;
}
perform_1d_float_lifting(self);
for (b=0; b < base->horiz_limit; b++)
base->branches[b]->push_line_float(base->branches[b],
self->branch_buf_float[b],
(width+1-(b^first_sample_odd))>>1);
}
else {
ifc_int *sp;
float *dp;
for (sp=line_buf, dp = self->branch_buf_float[0], n=width; n > 0; n--)
*(dp++) = (float) *(sp++);
base->branches[0]->push_line_float(base->branches[0],
self->branch_buf_float[0], width);
}
}
else if (self->kernel_type == INFO__INT_LIFTING)
{
assert(!base->use_floats);
if (base->horiz_limit > 1) {
for (b=0; b < base->horiz_limit; b++)
{ /* Split input into even and odd sub-sequences. */
ifc_int *sp, *dp;
for (sp=line_buf+b, dp=self->branch_buf_int[b^first_sample_odd],
n=(width+1-b)>>1; n > 0; n--, sp+=2, dp++)
*dp = *sp;
}
perform_1d_int_lifting(self);
for (b=0; b < base->horiz_limit; b++)
base->branches[b]->push_line_fixed(base->branches[b],
self->branch_buf_int[b],
(width+1-(b^first_sample_odd))>>1);
}
else {
ifc_int *sp, *dp;
for (sp=line_buf, dp=self->branch_buf_int[0], n=width; n > 0; n--, sp++, dp++)
*dp = *sp;
base->branches[0]->push_line_fixed(base->branches[0],
self->branch_buf_int[0], width);
}
}
else
assert(0);
}
/*****************************************************************************/
/* STATIC __terminate */
/*****************************************************************************/
static void
__terminate(hplx_analysis_stage_ref base)
{
hplx_hor_analysis_by_lifting_ref self =
(hplx_hor_analysis_by_lifting_ref) base;
int b;
for (b=0; b < base->horiz_limit; b++)
{
if (self->branch_buf_float[b] != NULL)
local_free(self->branch_buf_float[b]-self->neg_extend);
if (self->branch_buf_int[b] != NULL)
local_free(self->branch_buf_int[b]-self->neg_extend);
if (self->frame_work_buf_float[b] != NULL)
local_free(self->frame_work_buf_float[b]-self->neg_extend);
if (self->frame_work_buf_int[b] != NULL)
local_free(self->frame_work_buf_int[b]-self->neg_extend);
base->branches[b]->terminate(base->branches[b]);
}
local_free(self);
}
/*****************************************************************************/
/* EXTERN create_hplx_hor_analysis_by_lifting */
/*****************************************************************************/
hplx_analysis_stage_ref
create_hplx_hor_analysis_by_lifting(void)
{
hplx_hor_analysis_by_lifting_ref result;
result = (hplx_hor_analysis_by_lifting_ref)
local_malloc(XFORM_MEM_KEY,sizeof(hplx_hor_analysis_by_lifting_obj));
result->base.initialize = __initialize;
result->base.push_line_fixed = __push_line_fixed;
result->base.push_line_float = __push_line_float;
result->base.terminate = __terminate;
return((hplx_analysis_stage_ref) result);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -