hplx_hor_analysis_by_lifting.c

来自「JPEG2000实现的源码」· C语言 代码 · 共 941 行 · 第 1/3 页

C
941
字号
  __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 + =
减小字号Ctrl + -
显示快捷键?