⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hplx_vert_synthesis_by_lifting.c

📁 JPEG2000实现的源码
💻 C
📖 第 1 页 / 共 3 页
字号:

static void
  go_outside_synth_stage_for_row(hplx_synth_buffering_stage_ptr ext_stage)

 /* This function is called from within the `hplx_lift_stage__get_rows'
    function whenever a new row is required for a buffering stage which
    has no generator (result can be produced by a lifting step) within
    the current `hplx_synthesis_stage' object.  In this case, the row
    must be recovered via a `pull_line_xxx' interface function of either
    another `hplx_synthesis_stage' object or a dequantizer.  The
    appropriate object references and invocation arguments are all
    found within the current `hplx_vert_synthesis_by_lifting' object
    which is referenced by `ext_stage->owner_ref'. */

{
  hplx_buffering_stage_ptr stage = &(ext_stage->base);
  hplx_vert_synthesis_by_lifting_ref owner;
  hplx_synthesis_stage_ref synth;
  hplx_row_buffer_state_ptr buf;
  int branch_idx;

  assert(stage->generator == NULL);
  owner = ext_stage->owner_ref;
  buf = hplx_lift_stage__add_row(stage);
  branch_idx = stage->odd_lines;
  synth = owner->base.branches[branch_idx];
  if (buf->float_buf != NULL)
    {
      synth->pull_line_float(synth,buf->float_buf,stage->cols);
      if (owner->branch_needs_scaling[branch_idx])
        {
          float scale, *sp;
          int n;

          scale = owner->branch_scale[branch_idx];
          for (sp=buf->float_buf, n=stage->cols; n > 0; n--)
            *(sp++) *= scale;
        }
    }
  else
    synth->pull_line_fixed(synth,buf->int_buf,stage->cols);
}

/*****************************************************************************/
/* STATIC                   hplx_lift_stage__get_rows                        */
/*****************************************************************************/

static void
  hplx_lift_stage__get_rows(hplx_buffering_stage_ptr stage,
                            int min_row_idx, int num_rows,
                            hplx_row_buffer_state_ptr bufs[])

 /* This function does all the computational work associated with lifting,
    including management of extensions at the vertical boundaries of the
    image or tile.  The function tries to satisfy a request for a range
    of rows from the supplied buffering stage.  If the range extends beyond
    the upper or lower image boundaries, it is modified to include only
    those rows which lie within the image and the missing rows are
    extrapolated using the same zero-order hold policy which is adopted for
    horizontal lifting.  Once the range of valid row indices is determined
    in this way, the function generate any rows which it does
    not already have, either by undoing the lifting steps identified by
    buffering stage's `generator' field or, if there is no generator,
    by pulling rows from the dequantizer or another `hplx_synthesis_stage'
    object. */

{
  hplx_synth_buffering_stage_ptr ext_stage =
    (hplx_synth_buffering_stage_ptr) stage;
  int ext_before, ext_after, next_row_idx, offset, n, p;
  hplx_lifting_step_ptr step;
  hplx_row_buffer_state_ptr *fp, *lp;

  if ((min_row_idx >= stage->rows) || ((min_row_idx+num_rows) <= 0))
    { /* Request lies entirely outside image.  No extension will be applied
         here; caller should detect NULL buffers and skip the relevant
         lifting step. */
      while (num_rows--)
        *(bufs++) = NULL;
      return;
    }
  ext_before = 0;
  if (min_row_idx < 0)
    {
      ext_before = -min_row_idx;
      num_rows -= ext_before;
      min_row_idx = 0;
    }
  ext_after = (num_rows+min_row_idx) - stage->rows;
  if (ext_after > 0)
    num_rows -= ext_after;
  else
    ext_after = 0;
  assert((num_rows > 0) && (min_row_idx >= stage->min_row_idx));
  step = stage->generator;
  while ((next_row_idx=stage->next_row_idx) < (min_row_idx+num_rows))
    { /* Need to generate this row. */
      hplx_row_buffer_state_ptr source_bufs[8], target_buf, output_buf;
      int source_rows, min_source_idx;
      int n, k;

      if (step == NULL)
        {
          go_outside_synth_stage_for_row(ext_stage);
          continue;
        }

      /* Undo lifting steps. */

      min_source_idx = next_row_idx - step->neg_support;
      min_source_idx += step->target->missing_first_row -
                        step->source->missing_first_row;
      source_rows = step->pos_support + step->neg_support + 1;
      assert(source_rows <= 8);
      hplx_lift_stage__get_rows(step->source,min_source_idx,source_rows,
                                source_bufs);
      hplx_lift_stage__get_rows(step->target,next_row_idx,1,&target_buf);
      hplx_lift_stage__release_row(step->source,min_source_idx);
      hplx_lift_stage__release_row(step->target,next_row_idx);
      output_buf = hplx_lift_stage__add_row(stage);
      if (step->float_taps != NULL)
        { /* Undo floating-point lifting step. */
          float *taps, *sp[8], *tp, *op, sum;

          tp = target_buf->float_buf;
          op = output_buf->float_buf;
          if (source_bufs[0] == NULL)
            { /* Source range entirely outside image support; skip the step. */
              for (n=stage->cols; n > 0; n--)
                *(op++) = *(tp++);
            }
          else if (((next_row_idx == 0) && stage->special_first) ||
                   (next_row_idx == (stage->rows-stage->special_last)))
            { /* Simply scale the row instead of performing the actual
                 lifting step. */
              float dc_gain = 1.0F / step->dc_gain;

              for (n=stage->cols; n > 0; n--)
                *(op++) = *(tp++) * dc_gain;
            }
          else
            {
              for (k=0; k < source_rows; k++)
                sp[k] = source_bufs[k]->float_buf;
              taps = step->float_taps - step->neg_support;
              for (n=stage->cols; n > 0; n--)
                {
                  for (sum=0.0F, k=0; k < source_rows; k++)
                    sum += taps[k] * *((sp[k])++);
                  *(op++) = *(tp++) - sum;
                }
            }
        }
      else
        { /* Undo integer lifting step. */
          int *taps;
          ifc_int *sp[8], *tp, *op;
          std_int sum, offset, downshift;

          tp = target_buf->int_buf;
          op = output_buf->int_buf;
          if (source_bufs[0] == NULL)
            { /* Source range entirely outside image support; skip the step. */
              for (n=stage->cols; n > 0; n--)
                *(op++) = *(tp++);
            }
          else if (((next_row_idx == 0) && stage->special_first) ||
                   (next_row_idx == (stage->rows-stage->special_last)))
            { /* Skip lifting step on frame boundaries. */
              for (n=stage->cols; n > 0; n--)
                *(op++) = *(tp++);
            }
          else
            {
              for (k=0; k < source_rows; k++)
                sp[k] = source_bufs[k]->int_buf;
              taps = step->int_taps - step->neg_support;
              downshift = step->int_downshift;
              offset = (1<<downshift)>>1;
              for (n=stage->cols; n > 0; n--)
                {
                  for (sum=0, k=0; k < source_rows; k++)
                    sum += taps[k] * *((sp[k])++);
                  *(op++) = *(tp++) - ((sum+offset)>>downshift);
                }
            }
        }
    }

  /* Fill in the contents of the `bufs' array, applying the relevant
     symmetric extension policies as necessary. */

  offset = min_row_idx - stage->min_row_idx;
  fp = bufs + ext_before; /* Points to first interior row. */
  lp = fp + num_rows - 1; /* Points to last interior row. */
  for (n=0; n < num_rows; n++)
    fp[n] = stage->row_buffers[offset+n];

  /* Perform extensions, alternating between left and right extension
     until we are done.  Note that this code will probably not mimic
     symmetric extension for even length filters. */
  for (n=p=1; (n <= ext_before) || (p <= ext_after); )
    {
      int did_something;

      did_something = 0;
      if (n <= ext_before)
        { /* Still need extension to upper part of image. */
          if (stage->first_extension)
            { /* Half-point extension. */
              if (n <= (num_rows+p-1))
                { fp[-n] = fp[n-1]; n++; did_something = 1; }
            }
          else
            { /* Whole-point extension. */
              if (n < (num_rows+p-1))
                { fp[-n] = fp[n]; n++; did_something = 1; }
            }
        }
      if (p <= ext_after)
        { /* Still need extension to lower part of image. */
          if (stage->last_extension)
            { /* Half-point extension. */
              if (p <= (num_rows+n-1))
                { lp[p] = lp[-p+1]; p++; did_something = 1; }
            }
          else
            { /* Whole-point extension. */
              if (p < (num_rows+n-1))
                { lp[p] = lp[-p]; p++; did_something = 1; }
            }
        }
      assert(did_something);
    }
}

/* ========================================================================= */
/* ------------------ 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_vert_synthesis_by_lifting_ref self =
    (hplx_vert_synthesis_by_lifting_ref) base;
  frame_info frame;
  hplx_synth_buffering_stage_ptr ext_stage;
  hplx_buffering_stage_ptr stage;
  hplx_lifting_step_ptr step;
  int neg_supports[INFO__MAX_LIFTING_STEPS];
  int pos_supports[INFO__MAX_LIFTING_STEPS];
  int int_downshifts[INFO__MAX_LIFTING_STEPS];
  int *int_taps[INFO__MAX_LIFTING_STEPS];
  float *float_taps[INFO__MAX_LIFTING_STEPS];
  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,neg_supports,pos_supports,
                            int_taps,int_downshifts);
      for (b=0; b < base->vert_limit; b++)
        self->branch_needs_scaling[b] = 0;
    }
  else if (self->kernel_type == INFO__FLOAT_LIFTING)
    {
      self->num_steps =
        info->get_float_steps(info,base->direction,base->component_idx,
                              base->level_idx,neg_supports,pos_supports,
                              float_taps,self->branch_scale,
                              self->branch_scale+1);
      for (b=0; b < base->vert_limit; b++)
        {
          float val = self->branch_scale[b];
          self->branch_needs_scaling[b] = (val > 1.00001F) || (val < 0.99999F);
          self->branch_scale[b] = 1.0F / val;
        }
      self->heap.use_floats = 1;
    }
  else
    assert(0);
  self->steps = (hplx_lifting_step_ptr)
    local_malloc(XFORM_MEM_KEY,sizeof(hplx_lifting_step)*self->num_steps);
  memset(self->steps,0,sizeof(hplx_lifting_step)*(size_t)(self->num_steps));
  self->num_buffering_stages = self->num_steps + 2;
  self->buffering_stages = (hplx_synth_buffering_stage_ptr)
    local_malloc(XFORM_MEM_KEY,sizeof(hplx_synth_buffering_stage)*
                 self->num_buffering_stages);
  for (n=0; n < self->num_buffering_stages; n++)
    {
      ext_stage = self->buffering_stages + n;
      ext_stage->owner_ref = self;
      stage = &(ext_stage->base);
      stage->odd_lines = ((n & 1) == 0);
      stage->max_buffered_rows = 1;
      stage->num_users = 0;
      stage->row_buffers = (hplx_row_buffer_state_ptr *)
        local_malloc(XFORM_MEM_KEY,sizeof(hplx_row_buffer_state_ptr)*
                     stage->max_buffered_rows);
      if (n < self->num_steps)
        stage->generator = self->steps + n;
      stage->heap = &(self->heap);
    }
  for (n=0; n < self->num_steps; n++)
    {
      step = self->steps + n;
      step->source = &(self->buffering_stages[n+1].base);
      step->target = &(self->buffering_stages[n+2].base);
      step->source->num_users++;
      step->target->num_users++;
      step->neg_support = neg_supports[n];
      step->pos_support = pos_supports[n];
      if (self->kernel_type == INFO__INT_LIFTING)
        {
          step->int_taps = int_taps[n];
          step->int_downshift = int_downshifts[n];
        }
      else
        step->float_taps = float_taps[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++)
        {
          step = self->steps + n;
          current_gain = (n>=2)?(step[-2].dc_gain):1.0F;
          source_gain = (n>=1)?(step[-1].dc_gain):1.0F;
          step_gain = 0.0F;
          for (k=-step->neg_support; k <= step->pos_support; k++)
            step_gain += step->float_taps[k];
          step->dc_gain = current_gain + step_gain*source_gain;
        }
      for (current_gain=1.0F, n=1; n < self->num_steps; n+=2)

⌨️ 快捷键说明

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