hplx_hor_synthesis_by_lifting.c

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

C
929
字号
/* ========================================================================= */
/* ------------------ Implementation of Interface Functions ---------------- */
/* ========================================================================= */

/*****************************************************************************/
/* STATIC                         __initialize                               */
/*****************************************************************************/

static void
  __initialize(hplx_synthesis_stage_ref base, reverse_info_ref info,
               canvas_dims_ptr dims, canvas_dims_ptr frame_dims)
{
  hplx_hor_synthesis_by_lifting_ref self =
    (hplx_hor_synthesis_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__SYNTHESIS,
                          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);
      for (b=0; b < base->horiz_limit; b++)
        self->branch_scale[b] = 1.0F / self->branch_scale[b];
    }
  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)
    { /* 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);
    }
}

/*****************************************************************************/
/*                               __pull_line_float                           */
/*****************************************************************************/

static void
  __pull_line_float(hplx_synthesis_stage_ref base, float *line_buf,
                    int width)
{
  hplx_hor_synthesis_by_lifting_ref self =
    (hplx_hor_synthesis_by_lifting_ref) base;
  int n, b, first_sample_odd;

  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++)
      { /* Retrieve even and odd bands */
        base->branches[b]->pull_line_float(base->branches[b],
                                           self->branch_buf_float[b],
                                           (width+1-(b^first_sample_odd))>>1);
      }
    undo_1d_float_lifting(self);
    for (b=0; b < base->horiz_limit; b++)
      { /* Interleave even and odd sub-sequences. */
        float *sp, *dp;

        for (dp=line_buf+b, sp=self->branch_buf_float[b^first_sample_odd],
             n=(width+1-b)>>1; n > 0; n--, dp+=2, sp++)
          *dp = *sp;
      }
  }
  else {
    base->branches[0]->pull_line_float(base->branches[0], line_buf, width);
  }
}

/*****************************************************************************/
/*                               __pull_line_fixed                           */
/*****************************************************************************/

static void
  __pull_line_fixed(hplx_synthesis_stage_ref base, ifc_int *line_buf,
                    int width)
{
  hplx_hor_synthesis_by_lifting_ref self =
    (hplx_hor_synthesis_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++)
          { /* Retrieve even and odd bands */
            base->branches[b]->pull_line_float(base->branches[b],
                                              self->branch_buf_float[b],
                                              (width+1-(b^first_sample_odd))>>1);
          }
        undo_1d_float_lifting(self);
        for (b=0; b < base->horiz_limit; b++)
          { /* Convert and interleave even and odd sub-sequences. */
            ifc_int *dp;
            float *sp, val;

            for (dp=line_buf+b, sp=self->branch_buf_float[b^first_sample_odd],
                 n=(width+1-b)>>1; n > 0; n--, dp+=2, sp++)
              {
                val = *sp;
                *dp = (ifc_int)((val<0.0F)?(val-0.5F):(val+0.5F));
              }
          }
      }
      else {
        ifc_int *dp;
        float *sp, *tmp_buf;

        tmp_buf = (float *) local_malloc(XFORM_MEM_KEY, width*sizeof(float));
        base->branches[0]->pull_line_float(base->branches[0], tmp_buf, width);
        for (dp=line_buf, sp=tmp_buf, n=width; n > 0; n--)
          *(dp++) = (ifc_int) *(sp++);
      }
    }
  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++)
          { /* Retrieve even and odd bands */
            base->branches[b]->pull_line_fixed(base->branches[b],
                                              self->branch_buf_int[b],
                                              (width+1-(b^first_sample_odd))>>1);
          }
        undo_1d_int_lifting(self);
        for (b=0; b < base->horiz_limit; b++)
          { /* Interleave even and odd sub-sequences. */
            ifc_int *sp, *dp;

            for (dp=line_buf+b, sp=self->branch_buf_int[b^first_sample_odd],
                 n=(width+1-b)>>1; n > 0; n--, dp+=2, sp++)
              *dp = *sp;
          }
      }
      else {
        base->branches[0]->pull_line_fixed(base->branches[0], line_buf, width);
      }
    }
  else
    assert(0);
}

/*****************************************************************************/
/* STATIC                         __terminate                                */
/*****************************************************************************/

static void
  __terminate(hplx_synthesis_stage_ref base)
{
  hplx_hor_synthesis_by_lifting_ref self =
    (hplx_hor_synthesis_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);
      base->branches[b]->terminate(base->branches[b]);
      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);
    }
  local_free(self);
}

/*****************************************************************************/
/* EXTERN              create_hplx_hor_synthesis_by_lifting                  */
/*****************************************************************************/

hplx_synthesis_stage_ref
  create_hplx_hor_synthesis_by_lifting(void)
{
  hplx_hor_synthesis_by_lifting_ref result;

  result = (hplx_hor_synthesis_by_lifting_ref)
    local_malloc(XFORM_MEM_KEY,sizeof(hplx_hor_synthesis_by_lifting_obj));
  result->base.initialize = __initialize;
  result->base.pull_line_fixed = __pull_line_fixed;
  result->base.pull_line_float = __pull_line_float;
  result->base.terminate = __terminate;
  return((hplx_synthesis_stage_ref) result);
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?