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

📄 hplx_vert_synthesis_by_lifting.c

📁 JPEG2000实现的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*****************************************************************************/
/* Copyright 1998, Hewlett-Packard Company                                   */
/* All rights reserved                                                       */
/* File: "hplx_vert_synthesis_by_lifting.c"                                  */
/* Description: Implementation of the `hplx_analysis_stage' object for       */
/*              vertical synthesis via lifting.                              */
/* Author: David Taubman                                                     */
/* Affiliation: Hewlett-Packard and                                          */
/*              The University of New South Wales, Australia                 */
/* Acknowledgements: Partly developed in collaboration with                  */
/*                   Christos Chrysafis of HP Labs                           */
/* Version: VM9.0                                                            */
/* Last Revised: 20 April, 2001                                              */
/*****************************************************************************/

/*****************************************************************************/
/* Modifications tagged with comment lines or delimiters involving the       */
/* string, "David T mod" or "mod by David T", have been made by David        */
/* Taubman; they are copyrighted by Hewlett-Packard Company with all rights  */
/* reserved for the modified parts.                                          */
/*****************************************************************************/

/*****************************************************************************/
/* Modifications tagged with comment lines or delimiters involving the       */
/* string "BBDWT mod" have been made to implement the single-sample          */
/* overlap Wavelet transform within the frames paradigm -- this is the       */
/* BBDWT transform proposed by Canon Research France and accepted at the     */
/* meeting in Seoul, Korea.                                                  */
/*****************************************************************************/

/*****************************************************************************/
/* Modifications marked "Christos Chrysafis (HPL)" made to ensure that       */
/* the boundary extension policy for lifting is identical to that used for   */
/* convolution so that convolution vs. lifting is purely an implementation   */
/* decision.  Mods might cause problems for non-symmetric kernels, but that  */
/* should not be relevant to the standard.  The modifications are            */
/* copyrighted by Hewlett-Packard Company with all rights reserved for the   */
/* modified parts.                                                           */
/*****************************************************************************/

/*****************************************************************************/
/* Modified by David Taubman to support arbitrary reference points for the   */
/* transform and the various regular partitions, so as to facilitate         */
/* cropping and geometric transformations in the compressed domain and to    */
/* enable full support for CRF's single-sample overlap Wavelet transform,    */
/* as originally documented in Seoul.  Changes are too numerous to flag      */
/* individually within the code.  Changes copyrighted by HP with all rights  */
/* reserved for the modified parts.                                          */
/*****************************************************************************/

/*****************************************************************************/
/* Modified by David Taubman to support interface modifications, arbitrary   */
/* changes in coding parameters from component to component and from tile    */
/* to tile, to support the full generality of PART-1 of the JPEG2000         */
/* standard, and to support most anticipated generality of PART-2.  Changes  */
/* are too numerous to flag individually within the code, which in some      */
/* places has been completely rewritten.  All changes copyrighted by HP with */
/* all rights reserved for the modified parts.                               */
/*****************************************************************************/

/*****************************************************************************/
/* Modified by David Taubman to allow SSO-DWT style extension at tile        */
/* boundaries.  Changes copyrighted by HP with all rights reserved for the   */
/* modified parts.                                                           */
/*****************************************************************************/

/*****************************************************************************/
/* Modified for general wavelet decompositions.                              */
/* Copyright 2000 Science Applications International Corporation (SAIC).     */
/* Copyright 1995 University of Arizona, Arizona Board of Regents.           */
/* All Rights Reserved for modified parts.                                   */
/*****************************************************************************/

#include <local_services.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <ifc.h>
#include "hplx_vert_lifting.h"
#include "hplx_synthesis_local.h"

/* ========================================================================= */
/* ------------------------ Extended Object Definition --------------------- */
/* ========================================================================= */

typedef struct hplx_vert_synthesis_by_lifting_obj
  *hplx_vert_synthesis_by_lifting_ref;

/*****************************************************************************/
/*                          hplx_synth_buffering_stage                       */
/*****************************************************************************/

typedef
  struct hplx_synth_buffering_stage {
    hplx_buffering_stage base;
    hplx_vert_synthesis_by_lifting_ref owner_ref;
  } hplx_synth_buffering_stage, *hplx_synth_buffering_stage_ptr;
  /* Extends the basic `hplx_buffering_stage' structure to include the
     additional elements required to obtain new buffer rows when the
     `generator' field is NULL (see comments appearing with the
     definition of `hplx_buffering_stage' in "hplx_vert_synthesis.h").
     When this happens, the required buffer rows cannot be generated from
     other lifting steps within the same `hplx_synthesis_stage' object;
     they must be obtained either via the `pull_line' interface functions
     of another `hplx_synthesis_stage' object, or by invoking the relevant
     `pull_line' interface function of a dequantizer object.  In either
     case, the methods may be obtained and correctly invoked with the
     aid of a reference to the `hplx_vert_synthesis_by_lifting' object
     to which this stage belongs. */

/*****************************************************************************/
/*                      hplx_vert_synthesis_by_lifting_obj                   */
/*****************************************************************************/

typedef
  struct hplx_vert_synthesis_by_lifting_obj {
    hplx_synthesis_stage_obj base;
    int kernel_type;
    int num_steps;
    hplx_lifting_step_ptr steps;
    int num_buffering_stages;
    hplx_synth_buffering_stage_ptr buffering_stages;
    int branch_needs_scaling[2]; /* Only for float-lifting. */
    float branch_scale[2]; /* Only for float-lifting. */
    hplx_row_buffer_heap heap;
    int num_frames, frame_rows, frame_ref, frame_idx, first_frame_rows;
    int current_frame_rows, first_row_idx_in_frame;
    int rows_left_in_tile, rows_left_in_frame;
    int ovlp_top, ovlp_bottom;
  } hplx_vert_synthesis_by_lifting_obj;
  /* This structure defines the extended `hplx_synthesis_stage' object.
         `kernel_type' is one of INFO__FLOAT_LIFTING or INFO__INT_LIFTING.
         `num_steps' identifies the number of lifting steps.
         `steps' points to an array with `num_steps' entries, which describes
     each of the lifting steps.
         `num_buffering_stages' identifies the number of entries in the
     `buffering_stages' array.  There are always exactly two more buffering
     stages than lifting steps.  The first two buffering stages correspond
     to the odd and even line sub-sequences, respectively, which we can
     recover by undoing all relevant lifting steps.  Subsequent
     buffering stages hold the intermediate results which were produced
     during analysis by each of the consecutive lifting steps.  The last
     two buffering stages hold the vertically low- and high-pass subbands.
     Even indexed entries of the `buffering_stages' array always correspond
     to odd numbered lines and vice-versa.
         The `banch_needs_scaling' and `branch_scale' arrays are used only
     for float-lifting kernels.  If `branch_needs_scaling[b]' is non-zero
     then the subband samples for branch b (0=low-pass, 1=high-pass) must
     be scaled by `branch_scale[b]' immediately after they are retrieved
     from the relevant descendant synthesis stage object.
         `heap' manages a heap for recycled line buffers, so that they can
     be distributed amongst the buffering stages in the most efficient
     manner.
         The `num_frames' field holds the number of frames.  The SSO-DWT
     is applied if and only if `num_frames' is not equal to 1.  Even
     though the SSO-DWT is an overlapping transform, the number of frames
     is computed based upon a disjoint partition.  The overlap samples
     are then determined subsequently.  This is important, since it can
     happen that the overlap sample is an entire frame.
         The `frame_rows' field holds the nominal vertical frame
     dimension; it is meaningful only if `num_frames' > 1.
         The `frame_ref' field holds the vertical anchor coordinate
     for the frame partition.
         The `frame_idx' field runs from 0 to `num_frames'-1 and is used
     to determine whether we are processing and internal frame or one
     which abuts a boundary.
         The `current_frame_rows' and `first_row_idx_in_frame' hold the
     absolute size and location of the current frame which is being
     processed, with respect to the canvas coordinate system.
         The `ovlp_top' and `ovlp_bottom' fields indicate whether the
     frame which is currently being processed contains an extra overlap
     row (i.e. outside the nominal frame partition) at the top or bottom
     of the frame (exactly one of these must be true for internal frames
     being processed using the SSO-DWT).  These fields are used to mimic
     the type of processing which would be used to build an efficient
     hardware implementation of the SSO-DWT. */


/* ========================================================================= */
/* ---------------------------- Internal Functions ------------------------- */
/* ========================================================================= */

/*****************************************************************************/
/* STATIC                       start_vertical_frame                         */
/*****************************************************************************/

static void
  start_vertical_frame(hplx_vert_synthesis_by_lifting_ref self,
                       hplx_row_buffer_state_ptr ovlp)

 /* Performs the initialization code required to restart the vertical
    buffering at the start of each vertical frame.  The function administers
    the `self->first_row_idx_in_frame', `self->current_frame_rows',
    `self->ovlp_top' and `self->ovlp_bottom' fields, as well as
    setting up the fields in each buffering stage in preparation for the
    new frame.  The `ovlp' argument identifies a copy of the last row from
    the previous frame, if any, which is to be used to
    initialize the first row of the current frame in the 1-sample overlap
    mode. */
  
{
  hplx_buffering_stage_ptr stage;
  int b, n, k, num_buffers, even_taps;
  int special_first, special_last, skip_last;
  int top_boundary_odd, bottom_boundary_odd, ovlp_top, ovlp_bottom;
  int subseq_rows[2];

  if (self->frame_idx == 0)
    { /* Set the location and size of the current frame partition. */
      self->current_frame_rows = self->first_frame_rows;
      assert(self->current_frame_rows <= self->rows_left_in_tile);
      if (self->current_frame_rows == 0)
        return;
    }
  else
    {
      /* Adjust counters to reflect the true frame partition, rather than
         the current transform block. */
      self->current_frame_rows -= self->ovlp_top + self->ovlp_bottom;
      self->first_row_idx_in_frame += self->ovlp_top;

      /* Update the location and size of the current frame partition. */
      self->first_row_idx_in_frame += self->current_frame_rows;
      self->rows_left_in_tile -= self->current_frame_rows;
      self->current_frame_rows = self->frame_rows;
      if (self->current_frame_rows > self->rows_left_in_tile)
        self->current_frame_rows = self->rows_left_in_tile;
    }
  assert(self->current_frame_rows > 0);

  top_boundary_odd = self->first_row_idx_in_frame & 1;
  bottom_boundary_odd =
    (self->first_row_idx_in_frame+self->current_frame_rows-1) & 1;
  subseq_rows[0] = (self->current_frame_rows+1-top_boundary_odd) >> 1;
  subseq_rows[1] = (self->current_frame_rows+top_boundary_odd) >> 1;
  special_first = special_last = skip_last = ovlp_top = ovlp_bottom = 0;
  if (self->frame_idx > 0)
    { /* Internal top boundary. */
      special_first = 1;
      if (top_boundary_odd)
        { ovlp_top = 1; subseq_rows[0]++; top_boundary_odd = 0; }
    }
  else if (self->base.sso_ext && !top_boundary_odd)
    special_first = 1; /* Use SSO-DWT style extension at tile boundaries. */
  if (self->frame_idx < (self->num_frames-1))
    { /* Internal bottom boundary. */
      special_last = skip_last = 1;
      if (bottom_boundary_odd)
        { ovlp_bottom = 1; subseq_rows[0]++; bottom_boundary_odd = 0; }
    }
  else if (self->base.sso_ext && !bottom_boundary_odd)
    special_last = 1; /* Use SSO-DWT style extension at tile boundaries. */

  /* Make `first_row_idx_in_frame', `current_frame_rows' and
     `rows_left_in_frame' refer to the transform block, instead of the
     frame partition.  We will restore their interpretations when we
     re-enter this function at the beginning of the next frame (see above). */

  self->ovlp_bottom = ovlp_bottom;
  self->ovlp_top = ovlp_top;
  self->first_row_idx_in_frame -= ovlp_top;
  self->current_frame_rows += ovlp_top + ovlp_bottom;
  self->rows_left_in_frame = self->current_frame_rows;

  /* Now set up working buffers. */

  for (b=0; b < ((hplx_synthesis_stage_ref) self)->vert_limit; b++)
    { /* b = 0 corresponds to the sub-sequence of even rows in the frame */
      even_taps = (self->steps->neg_support + self->steps->pos_support+1) & 1;
      for (n=0; n < self->num_buffering_stages; n++)
        {
          stage = &(self->buffering_stages[n].base);
          if (stage->odd_lines == b)
            {
              if (even_taps)
                {
                  if (top_boundary_odd)
                    local_error("Cannot start image, tile or frame with an "
                                "odd indexed sample when using even length "
                                "filters!  Use odd length filters!");
                  stage->first_extension =
                    symmetric_extension_type(1,self->current_frame_rows&1,b,0);
                  stage->first_extension =
                    symmetric_extension_type(1,self->current_frame_rows&1,b,1);
                }
              else
                { /* Simple case for odd length filters. */
                  stage->first_extension = (top_boundary_odd^(1-b))?0:1;
                  stage->last_extension = (bottom_boundary_odd^(1-b))?0:1;
                }
              if (b == 0)
                {
                  stage->special_first = special_first;
                  stage->special_last = special_last;
                  stage->skip_last = skip_last;
                  stage->missing_first_row = top_boundary_odd;
                }
              else
                {
                  stage->special_first = 0;
                  stage->special_last = 0;
                  stage->skip_last = 0;
                  stage->missing_first_row = 0;
                }
              stage->rows = subseq_rows[b];
              num_buffers = stage->next_row_idx - stage->min_row_idx;
              for (k=0; k < num_buffers; k++)
                hplx_lift_heap__return_buffer(stage->heap,
                                              stage->row_buffers[k]);
              stage->min_row_idx = 0;
              stage->next_row_idx = 0;
            }
          else
            assert(stage->odd_lines == (1-b));
        }
    }

  if (special_first && (ovlp != NULL))
    { /* Need to copy `ovlp' buffer into the first row of low-pass subbands. */
      hplx_row_buffer_state_ptr buf;

      stage = &(self->buffering_stages[self->num_buffering_stages-1].base);
      if (stage->odd_lines)
        stage = &(self->buffering_stages[self->num_buffering_stages-2].base);
      assert(stage->generator == NULL);
      buf = hplx_lift_stage__add_row(stage);
      if (buf->float_buf != NULL)
        {
          float *sp, *dp, scale;

          assert(ovlp->float_buf != NULL);
          scale = self->branch_scale[0];
          for (sp=ovlp->float_buf, dp=buf->float_buf, n=stage->cols; n--; )
            *(dp++) = *(sp++) * scale;
        }
      else
        {
          ifc_int *sp, *dp;

          assert(ovlp->int_buf != NULL);
          for (sp=ovlp->int_buf, dp=buf->int_buf, n=stage->cols; n--; )
            *(dp++) = *(sp++);
        }
    }
}

/*****************************************************************************/
/* STATIC                 go_outside_synth_stage_for_row                     */
/*****************************************************************************/

⌨️ 快捷键说明

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