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

📄 ebcot_encoder.c

📁 JPEG2000实现的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    to make best use of the dynamic range available for the relevant
    computations; w_b is the L2-norm of the relevant subband's synthesis
    basis vectors; M_b is the value of the `masked_sensitivity_reduction'
    argument; e is the masking exponent value (typically 0.5) recorded in
    the `master' structure; and s'_b[k] is a normalized representation of
    s_b[k], whose maximum nominal magnitude is 1, i.e. s'_b[k] = 2s_b[k]/R_b
    where R_b is the value of the `nominal_range' argument.
        Note that when M_b = 1 or when the signal strength is very small,
    this reduces to G*(C_b)^2*(w_b)^2*(s_b[n])^2 which is just the CSF-weighted
    MSE metric.  Typically, M_b is much greater than 1.
        Finally, note that we approximate the denomenator of the above
    equation as constant over each 8x8 cell.  The purpose of this function
    is to compute G * the reciprocal of the denomenator for each cell and
    store these values in the `visibility_factor' field of each distortion
    cell.  The result has then only to be multiplied by (C_b)^2 * (w_b)^2 *
    (s_b[n])^2, where the product of the first two terms is obtained
    from the `step_wmse' value reported by `forward_info__get_quant_info'.
    We calculate G so as to ensure that the maximum amount of masking
    does not produce distortion-rate slope values which are too small to
    be accurately represented.  This is ensured provided we set G equal
    to the maximum value of M_b over all subbands, which value is provided
    via the `max_mask_sensitivity_reduction' argument. */

{
  int cell_rows, cell_cols, r, c, left_col, top_row;
  int block_rows, block_cols, sample_row_gap;
  int cells_wide, cells_high, cell_gap, i, j;
  ifc_int *bp, *bpp;
  distortion_cell_ptr cell;
  double masking_strength, nominal_max_masking_strength, size, exponent, val;

  block_rows = master->height;
  block_cols = master->width;
  sample_row_gap = master->sample_row_gap;
  cells_high = (block_rows+7)>>3;
  cells_wide = (block_cols+7)>>3;
  cell_gap = master->d_cell_row_gap - cells_wide;
  exponent = master->masking_exponent;
  assert((exponent > 0.0) && (exponent < 1.0));
  assert(masked_sensitivity_reduction >= 1.0);
  for (cell=master->d_cells, top_row=0, j=cells_high;
       j > 0;
       j--, cell+=cell_gap, top_row+=8)
    {
      cell_rows = block_rows - top_row;
      cell_rows = (cell_rows > 8)?8:cell_rows;
      for (left_col=0, i=cells_wide; i > 0; i--, cell++, left_col+=8)
        {
          cell_cols = block_cols - left_col;
          cell_cols = (cell_cols > 8)?8:cell_cols;
          size = (double)(cell_rows*cell_cols);
          masking_strength = 0.0;
          bpp = buffer + (top_row*sample_row_gap) + left_col;
          for (r=cell_rows; r > 0; r--, bpp+=sample_row_gap)
            for (bp=bpp, c=cell_cols; c > 0; c--, bp++)
              {
                val = (double)(*bp & MAX_IFC_INT);
                masking_strength += pow(val,exponent);
              }
          /* Normalize by maximum nominal masking strength. */
          val = 0.5 * nominal_range;
          nominal_max_masking_strength = size * pow(val,exponent);
          masking_strength = masking_strength / nominal_max_masking_strength;
          /* Compute the denomenator. */
          val = masking_strength * masking_strength;
          val = 1.0 + (masked_sensitivity_reduction-1.0)*val;
          val = max_masked_sensitivity_reduction / val;
          cell->visibility_factor = (float) val;
        }
    }
}
/* End David T Cvis mod */

/*****************************************************************************/
/* STATIC                   mark_termination_points                          */
/*****************************************************************************/

static void
  mark_termination_points(ebcot_pass_info_ptr passes, int insignificant_msbs,
                          int max_passes, int terminate_each_pass,
                          int full_effort_msbs)
{
  int pass_idx;
  int n;

  pass_idx = insignificant_msbs * PASSES_PER_BITPLANE;
  for (n=0; n < pass_idx; n++)
    passes[n].terminated = 0;
  for (n=0; pass_idx < max_passes; pass_idx++, n++)
    {
      if (n == PASSES_PER_BITPLANE)
        {
          n = 0;
          full_effort_msbs--;
        }
      passes[pass_idx].terminated = 0;
      if (terminate_each_pass || (pass_idx == (max_passes-1)) ||
          ((full_effort_msbs <= 0) &&
           ((n==0) || (n==(PASSES_PER_BITPLANE-1)))))
        passes[pass_idx].terminated = 1;
    }
}

/*****************************************************************************/
/* STATIC                     insert_segment_marker                          */
/*****************************************************************************/

static void
  insert_segment_marker(block_master_ptr master)

  /* Original function by Sarnoff, modified by David Taubman. */

{
  dst_arith_state_ptr state;
  std_int areg, creg, symbol, n;
  std_short ct;
  dst_context_state_ptr csp;

  state = &(master->coder_state);
  assert(state->mqe.active);
  areg = state->mqe.areg; creg = state->mqe.creg; ct = state->mqe.ct;
  csp = state->contexts + UNI_OFFSET;
  for (n=3; n >= 0; n--)
    {
      symbol = n & 1;
      dst_emit_symbol(areg,creg,ct,state,symbol,csp);
    }
  state->mqe.areg = areg; state->mqe.creg = creg; state->mqe.ct = ct;
}

/*****************************************************************************/
/* STATIC                         encode_block                               */
/*****************************************************************************/

static void
  encode_block(ebcot_encoder_ref self, ebcot_component_info_ptr comp,
               ifc_int *sample_buffer, ebcot_band_info_ptr band,
               ebcot_block_info_ptr info)

 /* Encodes a single block of sample values.  The actual dimensions of the
    block may be found in the `info' structure.  The `sample_buffer' array
    contains the samples organized in lexicographical fashion.
    The function modifies the `info' structure to reflect the locations of
    the code words and the rate distortion information associated with the
    coding operation.  It also updates state information in the `band'
    structure. */

{
  block_master_ptr master = &(comp->master);
  double delta_wmse, scale_wmse, wmse_factor, wmse_boost;
  int bitplane_idx, last_bitplane, pass_idx, extra_lsbs;
  int n, significant, msb_first, first_lossless_pass;
  int i, j, cells_wide, cells_high, cell_gap; /* David T Cvis mod */
  distortion_cell_ptr cell; /* David T Cvis mod */
  int last_bytes, last_terminated_bytes, next_terminated_bytes;
  dst_heap_unit_ptr heap;
  int heap_pos;
  clock_t cpu_time;

  next_terminated_bytes = 0; /* Suppress compiler warnings. */
  cpu_time = 1; /* prevent warnings from compiler. */
  if (self->cpu_time >= 0)
    cpu_time = clock();

  /* Check to see if this is the first block being coded for the subband. */

  if (info->passes == NULL)
    allocate_pass_info(band);

  /* Check ROI information and determine the actual number of extra LSB's. */

  extra_lsbs = band->extra_lsbs;
  wmse_boost = 1.0;
  if (band->roi != NULL)
    {
      int boost_delta, min_boost;

      if (master->roi_mask == NULL)
        master->roi_mask = (std_byte **)
          local_malloc(EBCOT_MEM_KEY,sizeof(std_byte *)*master->max_height);
      boost_delta =
        band->roi->check_roi(band->roi,band->component_idx,band->level_idx,
                             band->band_idx,info->rows,info->cols,
                             info->top_row,info->left_col,
                             &min_boost,master->roi_mask);
      wmse_boost = (double)(1<<min_boost);
      wmse_boost *= wmse_boost;
      assert((boost_delta >= 0) && (boost_delta <= band->max_roi_boost));
      extra_lsbs -= boost_delta; /* Need to code more LSB's to accommodate
                                    the downshifted sample values. */
      if (boost_delta)
        apply_roi_boost_mask(sample_buffer,info->rows,info->cols,
                             master->sample_row_gap,boost_delta,
                             master->roi_mask,band->roi_implicit);
    }
  while (extra_lsbs < 1)
    { /* Can't code all LSB's from least significant region. */
      extra_lsbs++;
      wmse_boost *= 4.0;
    }

  /* Determine the number of passes to encode. */

  {
    int max_planes;

    max_planes = IMPLEMENTATION_PRECISION - 1 - extra_lsbs;
    if (max_planes > (IMPLEMENTATION_PRECISION-2))
      max_planes = IMPLEMENTATION_PRECISION-2;
    if (max_planes > (IMPLEMENTATION_PRECISION-2))
      max_planes = IMPLEMENTATION_PRECISION-2;
    info->max_passes = 1 + PASSES_PER_BITPLANE*(max_planes-1);
    first_lossless_pass = -1;
    if (band->lossless)
      {
        first_lossless_pass = info->max_passes - PASSES_PER_BITPLANE;
        if (first_lossless_pass < 0)
          first_lossless_pass = 0;
      }
  }

  /* Set up per-block fields. */

  master->zc_lut = band->zc_lut;
  master->bit_idx = IMPLEMENTATION_PRECISION-2;
  master->initial_mse_lut = ebcot_initial_mse_lut;
  master->refinement_mse_lut = ebcot_refinement_mse_lut;
  master->height = info->rows;
  master->width = info->cols;
  master->stripes = (master->height+3)>>2;
  assert((master->height <= master->max_height) &&
         (master->width <= master->max_width) &&
         (master->stripes <= master->max_stripes));

  /* Prepare buffers. */

  master->block_mag = interleave_sample_buffer(master,sample_buffer);
  reset_block_contexts(master);
  /* Begin David T Cvis mod */
  cells_wide = (master->width+7)>>3;
  cells_high = (master->height+7)>>3;
  cell_gap = master->d_cell_row_gap - cells_wide;
  if (master->exploit_visual_masking)
    {
      ifc_int *tmp_buf;

      tmp_buf = sample_buffer; /* Reuse the `sample_buffer' storage since we
                                  have now safely copied its contents to
                                  the interleaved sample buffer for coding. */
      if (band->band_idx == LL_BAND)
        { /* Compute masking strength based upon high-pass filtered
             version of signal. */
          tmp_buf = comp->sample_buffer_heap_mgr->get_buffer(
                                                comp->sample_buffer_heap_mgr);
          compute_ll_band_local_activity(sample_buffer,tmp_buf,master->height,
                                         master->width,master->sample_row_gap);
        }
      compute_visibility_factors(master,tmp_buf,band->nominal_range,
                                 band->fully_masked_sensitivity_reduction,
                                 master->max_masked_sensitivity_reduction);
      if (band->band_idx == LL_BAND)
        comp->sample_buffer_heap_mgr->return_buffer(
                                    comp->sample_buffer_heap_mgr,tmp_buf);
    }
  else
    for (cell=master->d_cells, j=cells_high; j--; cell+=cell_gap)
      for (i=cells_wide; i--; cell++)
        cell->visibility_factor = 1.0F;
  /* End David T Cvis mod */

  /* Prepare for arithmetic code word generation. */

  if (band->heap_tail == NULL)
    {
      band->next_heap_pos = 0;
      band->heap_head = band->heap_tail =
        self->code_heap_mgr->get_unit(self->code_heap_mgr);
      band->heap_tail->next = NULL;
    }
  heap = band->heap_tail;
  heap_pos = band->next_heap_pos;
  dst_arith_coder__initialize(&(master->coder_state),EBCOT_TOTAL_CONTEXTS,
                               master->contexts,heap,heap_pos,
                               self->code_heap_mgr,
                               master->error_resilient_termination);
  dst_arith_coder__model_init(&(master->coder_state),initial_mq_contexts);

#ifdef DST_LOG_SYMBOLS
  master->coder_state.symbol_log = start_symbol_log(band,info);
#endif /* DST_LOG_SYMBOLS */

  /* Perform the coding passes. */

  wmse_factor = (double)(1<<extra_lsbs);
  scale_wmse = band->step_wmse / (wmse_factor*wmse_factor);
  scale_wmse *= (1.0 / 64.0); /* Avoid overflow for at least 4 highest
                                 frequency resolution levels. */
  wmse_factor = (double)(1<<master->bit_idx);
  scale_wmse *= wmse_factor * wmse_factor;
  scale_wmse *= 1.0 / ((double)(1<<13));
  scale_wmse *= wmse_boost;
  last_bitplane = master->bit_idx - extra_lsbs;
  info->insignificant_msbs = 0;
  master->first_bit_idx = -1;

  for (delta_wmse=0.0, pass_idx=0, bitplane_idx=0, significant=0;
       bitplane_idx <= last_bitplane;
       bitplane_idx++, master->bit_idx--, scale_wmse*=0.25)
    {
      assert(master->bit_idx > 0);
      if (!significant)
        {

⌨️ 快捷键说明

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