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

📄 ebcot_encoder.c

📁 JPEG2000 EBCOT算法源码
💻 C
📖 第 1 页 / 共 4 页
字号:
        }
    }
  state->A=A; state->C=C; state->word=word; state->rho=rho;
  state->available_bits=avail;
}

/*****************************************************************************/
/* STATIC                     reset_block_contexts                           */
/*****************************************************************************/

static void
  reset_block_contexts(std_short *ctxt, int rows, int cols, int row_gap)
{
  register int c;
  int outside;

  outside = (4-cols) & 3;
  row_gap -= (cols + outside);
  assert(row_gap > 0);
  for (; rows > 0; rows--, ctxt += row_gap)
    {
      for (c=cols; c > 0; c--)
        *(ctxt++) = 0;
      for (c=outside; c > 0; c--)
        *(ctxt++) = OUT_OF_BOUNDS;
    }
}

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

static void
  encode_block(the_encoder_ref self, ifc_int *sample_buffer,
               band_info_ptr band, 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, with
    consecutive rows of block samples separated by `self->master.row_gap'
    samples, which is always larger than the block width.  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 = &(self->master);
  code_subblock_ptr sblk;
  int block_rows, block_cols;
  double delta_wmse, scale_wmse;
  int bitplane_idx, last_bitplane, pass_idx;
  int last_bytes, n, significant, msb_first;
  heap_unit_ptr heap;
  int heap_pos;
  clock_t cpu_time;

  /* Get ready for the coding passes. */

  cpu_time = 1; /* prevent warnings from compiler. */
  if (master->cpu_time >= 0)
    cpu_time = clock();
  if (band->band_idx == HL_BAND)
    {
      master->sample_buffer =
        self->sample_buffer_heap_mgr->get_buffer(
                                      self->sample_buffer_heap_mgr);
      transpose_sample_buffer(sample_buffer,master->sample_buffer,
                              info->rows,info->cols,master->row_gap);
      block_rows = info->cols;
      block_cols = info->rows;
    }
  else
    {
      master->sample_buffer = sample_buffer;
      block_rows = info->rows;
      block_cols = info->cols;
    }
  for (sblk=master->first_subblock; sblk <= master->last_subblock; sblk++)
    {
      sblk->significant = 0;
      sblk->rows = block_rows - sblk->top_row;
      sblk->cols = block_cols - sblk->left_col;
      if (sblk->rows > master->max_sub_dim)
        sblk->rows = master->max_sub_dim;
      if (sblk->cols > master->max_sub_dim)
        sblk->cols = master->max_sub_dim;
    }
  master->zc_lut = band->zc_lut;
  master->bit_idx = IMPLEMENTATION_PRECISION-2;
  master->block_mag = initialize_quadtree(master);
  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;
  ebcot_arith_coder__initialize(&(master->coder_state),heap,heap_pos,
                                self->code_heap_mgr);
#ifdef LOG_SYMBOLS
  master->coder_state.symbol_log = start_symbol_log(band,info);
#endif /* LOG_SYMBOLS */
  reset_block_contexts(master->context_buffer,block_rows,block_cols,
                       master->row_gap);

  /* Perform the coding passes. */

  scale_wmse = band->step_wmse / ((double)(1<<(band->extra_lsbs<<1)));
  scale_wmse *= (1.0 / 64.0); /* Avoid overflow for at least 4 highest
                                 frequency resolution levels. */
  scale_wmse *= (double)(1<<(master->bit_idx<<1));
  scale_wmse *= 1.0 / ((double)(1<<13));
  last_bitplane = master->bit_idx - band->extra_lsbs;
  info->insignificant_msbs = 0;
  for (delta_wmse=0.0, pass_idx=0, bitplane_idx=0;
       bitplane_idx <= last_bitplane;
       bitplane_idx++, master->bit_idx--, scale_wmse*=0.25)
    {
      assert(master->bit_idx > 0);
      if ((master->block_mag >> master->bit_idx) & 1)
        master->block_update[0] |= QUAD_PARENT_SIGNIFICANT;
      significant = (master->block_update[0] & QUAD_PARENT_SIGNIFICANT);
      if (significant)
        encode_quadtree(master);
      else
        info->insignificant_msbs++;
      for (n=0; n < PASSES_PER_BITPLANE; n++, pass_idx++)
        {
          block_coding_pass_func pass_function;

          if (pass_idx == info->max_passes)
            { bitplane_idx = last_bitplane; break; }
          if (significant)
            {
              pass_function = band->pass_funcs[n];
              master->context_mask = band->pass_masks[n];
              delta_wmse += ((double) pass_function(master)) * scale_wmse;
              if (n == 0)
                ebcot_arith_coder__renormalize(&(master->coder_state));
            }
          assert(pass_idx < MAX_PASSES);
          master->cumulative_wmse[pass_idx] = delta_wmse;
          master->saved_states[pass_idx] = master->coder_state;
        }
    }
  ebcot_arith_coder__flush(&(master->coder_state));
#ifdef SYMBOL_LOG
  fclose(master->coder_state.symbol_log);
  master->coder_state.symbol_log = NULL;
#endif /* SYMBOL_LOG */

  /* Update state information in `info' and `band' to reflect operations. */

  info->first_unit = heap;
  info->first_pos = heap_pos;
  last_bytes = 0; /* prevent warnings from compiler. */
  for (n=0; n < pass_idx; n++)
    {
      int bits;
      
      bits = ebcot_arith_coder__get_minimum_bits(master->saved_states+n,
                                                 heap,heap_pos);
      info->passes[n].cumulative_bytes = last_bytes = (bits+7)>>3;
    }
  assert(last_bytes <= (master->coder_state.saved_words<<2));
  compute_rd_slopes(pass_idx,master->cumulative_wmse,
                    info->passes,master->slope_rates);
  for (; pass_idx < info->max_passes; pass_idx++)
    {
      info->passes[pass_idx].cumulative_bytes = last_bytes;
      info->passes[pass_idx].rd_slope = -1;
    }
  band->heap_tail = master->coder_state.heap;
  band->next_heap_pos = master->coder_state.next_heap_pos;

  /* End of timed section. */

  if (master->cpu_time >= 0)
    master->cpu_time += (long int)(clock()-cpu_time);

  /* See if code word byte order needs to be reversed. */

  msb_first = 1; *((std_byte *)(&msb_first)) = 0;
  if (!msb_first)
    { /* Least significant byte appears first in each code word.  Need to
         reverse this to allow the word buffers to be written out as byte
         buffers later when we generate the bit-stream. */
      std_int word, *wp;
      int heap_remnant;

      wp = heap->words + heap_pos;
      heap_remnant = HEAP_WORDS - heap_pos;
      assert(heap_remnant > 0);
      for (n=master->coder_state.saved_words; n > 0; n--)
        {
          word = *wp;
          word = ((word >> 24) & 0x000000FF) | ((word >>  8) & 0x0000FF00) |
                 ((word <<  8) & 0x00FF0000) | ((word << 24) & 0xFF000000);
          *(wp++) = word;
          if ((--heap_remnant) == 0)
            { heap_remnant = HEAP_WORDS; heap=heap->next; wp=heap->words; }
        }
    }

  if (master->sample_buffer != sample_buffer)
    self->sample_buffer_heap_mgr->return_buffer(self->sample_buffer_heap_mgr,
                                                master->sample_buffer);
}


/* ========================================================================= */
/* ------------------------- Interface Implementation ---------------------- */
/* ========================================================================= */

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

static void
  __initialize(encoder_ref base, int decomposition, int levels,
               int components, int component_rows[], int component_cols[],
               filter_info_ref info, int required_profile,
               int *supported_profile, int dedicated_bytes,
               int max_extra_bytes, bitstream_sink_ref output,
               int argc, char *argv[])
{
  the_encoder_ref self = (the_encoder_ref) base;
  component_info_ptr comp;
  level_info_ptr lev;
  code_subblock_ptr subblock;
  int block_dim, block_width, block_height, subblock_dim;
  int rows, cols, max_rows, max_cols;
  int num_subs, subs_total, context_size;
  int comp_idx, n, b, r, c, top_row, left_col;

  if (decomposition != DECOMPOSITION__MALLAT)
    {
      fprintf(stderr,"The current implementation of the EBCOT encoder "
              "object\n  does not support anything other than Mallat-style "
              "decompositions!\n");
      exit(-1);
    }
  *supported_profile = self->profile =
    process_profile_flags(required_profile);
  get_block_dimensions(argc,argv,&block_dim,&block_height,&subblock_dim);
  block_width = block_dim;
  self->max_block_height = block_height;
  assert(block_width >= block_height);
  self->num_levels = levels;
  self->num_components = components;
  for (max_rows=max_cols=0, comp_idx=0; comp_idx < components; comp_idx++)
    {
      rows = component_rows[comp_idx];
      cols = component_cols[comp_idx];
      if (rows > max_rows)
        max_rows = rows;
      if (cols > max_cols)
        max_cols = cols;
    }
  if (!rd_optimized_truncation_allowed(argc,argv,self->profile))
    max_extra_bytes = 100*max_rows*max_cols; /* Something very large. */
  get_layer_info(self,argc,argv,dedicated_bytes,max_extra_bytes,
                 max_rows,max_cols);

  
  self->components = (component_info_ptr)
    local_malloc(sizeof(component_info)*(size_t) components);
  for (comp_idx=0; comp_idx < components; comp_idx++)
    {
      comp = self->components + comp_idx;     
      comp->component_idx = comp_idx;
      rows = component_rows[comp_idx];
      cols = component_cols[comp_idx];
      comp->levels = (level_info_ptr)
        local_malloc(sizeof(level_info)*(size_t)(levels+1));
      memset(comp->levels,0,sizeof(level_info)*(size_t)(levels+1));
      for (lev=comp->levels, n=0; n <= levels; n++, lev++)
        {
          lev->component_idx = comp_idx;
          lev->level_idx = n;
          lev->min_band = (n==0)?0:1;
          lev->max_band = 3;
          if (n == levels)
            { /* Special level for whole image to cover degenerate case of a
                 zero level transform. */
              lev->min_band = lev->max_band = 0;
              if (levels > 0)
                lev->max_band = -1;
            }
        }
      n = levels; lev = comp->levels + n;
      lev->bands[0].band_rows = rows; lev->bands[0].band_cols = cols;
      while (n > 0)
        {
          n--; lev--;
          lev->bands[HL_BAND].band_cols =
            lev->bands[HH_BAND].band_cols = cols >> 1;
          lev->bands[LL_BAND].band_cols =
            lev->bands[LH_BAND].band_cols = (cols+1)>>1;
          lev->bands[LH_BAND].band_rows =
            lev->bands[HH_BAND].band_rows = rows >> 1;
          lev->bands[LL_BAND].band_rows =
            lev->bands[HL_BAND].band_rows = (rows+1)>>1;
          rows = lev->bands[LL_BAND].band_rows;
          cols = lev->bands[LL_BAND].band_cols;
        }
      for (n=0, lev=comp->levels; n <= levels; n++, lev++)
        for (b=lev->min_band; b <= lev->max_band; b++)
          { /* Complete band initialization. */
            band_info_ptr band = lev->bands + b;
            block_info_ptr block;
            pass_info_ptr passes;
            float step_wmse;
            int extra_lsbs, total_blocks, max_passes;

            band->component_idx = comp_idx;
            band->level_idx = n;
            band->band_idx = b;
            info->get_quant_info(info,comp_idx,n,b,
                                 NULL,NULL,&step_wmse,&extra_lsbs);
            max_passes =
              (IMPLEMENTATION_PRECISION-2-extra_lsbs)*PASSES_PER_BITPLANE + 1;
            band->blocks_high = 1 + ((band->band_rows-1) / block_height);
            band->blocks_wide = 1 + ((band->band_cols-1) / block_width);
            band->band_blocks = total_blocks =
              band->blocks_high*band->blocks_wide;
            band->blocks = block = (block_info_ptr)
              local_malloc(sizeof(block_info)*(size_t) total_blocks);
            memset(block,0,sizeof(block_info)*(size_t) total_blocks);
            passes = (pass_info_ptr)
              local_malloc(sizeof(pass_info)*
                           (size_t)(total_blocks*max_passes));
            memset(passes,0,
                   sizeof(pass_info)*(size_t)(total_blocks*max_passes));
            for (top_row=0, r=0; r < band->blocks_high;
                 r++, top_row+=block_height)
              for (left_col=0, c=0; c < band->blocks_wide;
                   c++, left_col+=block_width, block++, passes+=max_passes)
                { /* Complete block initialization. */
                  block->top_row = top_row;
                  block->left_col = left_col;
                  block->rows = band->band_rows - top_row;
                  if (block->rows > block_height)
                    block->rows = block_height;
                  block->cols = band->band_cols - left_col;
                  if (block->cols > block_width)
                    block->cols = block_width;
                  block->passes = passes;
                  block->max_passes = max_passes;
                }
            if (b == HH_BAND)
              band->zc_lut = ebcot_diag_zc_lut;
            else
              band->zc_lut = ebcot_main_zc_lut;
            ebcot_set_pass_funcs_and_masks(band,b);
            band->step_wmse = step_wmse;
            band->extra_lsbs = extra_lsbs;
            band->lines.num_lines = 0;
            band->lines.info = NULL;
            band->lines.buffers = NULL;
          }
    }
  self->output = output;
  num_subs = 1 + ((block_dim-1) / subblock_dim);
  subblock_dim = 1 + ((block_dim-1) / num_subs);
  subs_total = num_subs * num_subs;
  self->master.max_dim = block_dim;
  self->master.max_sub_dim = subblock_dim;
  self->master.row_gap = block_dim + 2;
  self->master.first_subblock = subblock = (code_subblock_ptr)
    local_malloc(sizeof(code_subblock)*(size_t) subs_total);
  self->master.last_subblock = subblock + subs_total - 1;
  create_quadtree(num_subs,num_subs,subblock,
                  &(self->master.first_quad),&(self->master.last_quad));
  self->master.block_update = (std_short *) self->master.first_quad;
  if (self->master.block_update == NULL)
    {
      assert(num_subs == 1);
      self->master.block_update = (std_short *) subblock;
    }
  memset(subblock,0,sizeof(code_subblock)*(size_t) subs_total);
  for (top_row=0, r=0; r < num_subs; r++, top_row+=subblock_dim)
    for (left_col=0, c=0; c < num_subs;
         c++, left_col+=subblock_dim, subblock++)
      {
        subblock->top_row = top_row;
        subblock->left_col = left_col;
        subblock->offset = top_row*self->master.row_gap + left_col;
      }
  context_size = self->master.row_gap * (block_dim+2) + 2;
  self->master.context_buffer = (std_short *)
    local_malloc(sizeof(std_short)*(size_t) context_size);

⌨️ 快捷键说明

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