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

📄 ebcot_encoder.c

📁 JPEG2000 EBCOT算法源码
💻 C
📖 第 1 页 / 共 4 页
字号:
  self->master.context_buffer += self->master.row_gap + 2;
  self->master.coder_state.contexts = self->master.contexts;
  self->master.cpu_time = -1;
  for (r=0; r < argc; r++)
    if (strcmp(argv[r],"-Ccpu") == 0)
      {
        argv[r] = "";
        self->master.cpu_time = 0;
      }

  self->sample_buffer_heap_mgr =
    ebcot_create_sample_buffer_heap(self->master.max_dim,
                                    self->master.row_gap);
  self->code_heap_mgr = create_codeword_heap();
  ebcot_initialize_global_luts();
}

/*****************************************************************************/
/* STATIC                         __print_usage                              */
/*****************************************************************************/

static void
  __print_usage(encoder_ref base, FILE *dest)
{
  fprintf(dest,">> EBCOT Block Encoder arguments:\n"
          "   -Cblk <dim> (default = 64)\n"
          "         -- Specify block size (dim x dim) to use in coding.\n"
          "   -Cheight <height> (default, same as block dimension)\n"
          "         -- Specifies a maximum block height; may not exceed\n"
          "            the block dimension, specified via `-Cblk'.\n"
          "   -Csub <dim> (default = 16)\n"
          "         -- Specify sub-block size (dim x dim) to use in coding.\n"
          "   -Clayers <rate> [+<layers>] [<rate> [+<layers>] [...]].\n"
          "         (default: 50 layers log-spaced from 0.015 to 2.0 bpp)\n"
          "         -- Explicitly specifies the bit-stream layer formation\n"
          "            parameters.  <rate> is the target rate (bpp) for the\n"
          "            first layer (not including a final layer for the \n"
          "            overall target bit-rate).  <layers> is the number of\n"
          "            extra layers which should be added for scalability.\n"
          "            Additional specific rate points may be specified.\n"
          "   -Cno_rd (default: use rate-distortion optimized truncation)\n"
          "         -- Turn off rate-distortion optimized block truncation\n"
          "            so that the generated bit-rate depends only on the\n"
          "            quantization step size and the maximum rate limit\n"
          "            is ignored.  This flag may not be used in conjunction\n"
          "            with any form of SNR scalability.\n"
          "   -Ccpu -- Report CPU time for block encoding engine.\n");
}

/*****************************************************************************/
/* STATIC                        __push_line                                 */
/*****************************************************************************/

static void
  __push_line(encoder_ref base, ifc_int *line_buf,
              int component_idx, int level_idx, int band_idx, int width)
{
  the_encoder_ref self = (the_encoder_ref) base;
  level_info_ptr lev;
  band_info_ptr band;  
  line_buffering_ptr lines;
  block_info_ptr info;
  int n, c, blocks_wide, offset;
  ifc_int *dp, *sp;

  assert(component_idx < self->num_components);
  lev = self->components[component_idx].levels + level_idx;
  band = lev->bands + band_idx;
  assert((level_idx <= self->num_levels) &&
         (band_idx >= lev->min_band) && (band_idx <= lev->max_band) &&
         (width == band->band_cols));
  lines = &(band->lines);
  blocks_wide = band->blocks_wide;
  if (lines->buffers == NULL)
    { /* First call to `__push_line'.  Allocate block buffers. */
      lines->num_lines = 0;
      lines->info = band->blocks;
      lines->buffers = (ifc_int **)
        local_malloc(sizeof(ifc_int *)*(size_t) blocks_wide);
      for (n=0; n < blocks_wide; n++)
        lines->buffers[n] =
          self->sample_buffer_heap_mgr->get_buffer(
                                        self->sample_buffer_heap_mgr);
    }

  /* Copy new line into all relevant block buffers. */

  info = lines->info;
  offset = self->master.row_gap * lines->num_lines;
  for (sp=line_buf, n=0; n < blocks_wide; n++)
    for (dp=lines->buffers[n]+offset, c=info[n].cols; c > 0; c--)
      *(dp++) = *(sp++);

  /* Advance counter and check to see if we can encode anything yet. */

  lines->num_lines++;
  if (lines->num_lines == info->rows)
    {
      for (n=0; n < blocks_wide; n++, info++)
        encode_block(self,lines->buffers[n],band,info);
      lines->num_lines = 0;
      lines->info = info;
    }
}

/*****************************************************************************/
/* STATIC                        __push_block                                */
/*****************************************************************************/

static void
  __push_block(encoder_ref base, ifc_int **block_buf,
               int component_idx, int level_idx, int band_idx,
               int block_rows, int block_cols, int top_row, int left_col)
{
  the_encoder_ref self = (the_encoder_ref) base;
  level_info_ptr lev;
  band_info_ptr band;
  block_info_ptr block, block_pp;
  int r, c, n, i, j;
  int row_gap, cur_left_col, cur_block_cols, xfer_rows, xfer_cols;
  ifc_int *sp, *dp, *dpp;

  assert(component_idx < self->num_components);
  lev = self->components[component_idx].levels + level_idx;
  band = lev->bands + band_idx;
  assert((level_idx <= self->num_levels) &&
         (band_idx >= lev->min_band) && (band_idx <= lev->max_band) &&
         (block_rows > 0) && (block_cols > 0));
  if (band->push_block_rows == 0)
    { /* First call to this function for this band. */
      band->push_block_rows = block_rows;
      band->push_block_cols = block_cols;
      for (block=band->blocks, n=0; n < band->band_blocks; n++, block++)
        {
          block->pushed_block_buffer = NULL;
          r = 1 + ((block->rows-1)/block_rows);
          c = 1 + ((block->cols-1)/block_cols);
          block->unpushed_blocks = r * c;
          if (n == 0)
            { /* Check that the push block dimensions are compatible. */
              if (((block_rows != band->band_rows) &&
                   (((r * block_rows) % block->rows) != 0)) ||
                  ((block_cols != band->band_cols) &&
                   (((c * block_cols) % block->cols) != 0)))
                {
                  fprintf(stderr,"Size of blocks pushed across the "
                          "encoder's `push_block'\n  interface function are "
                          "incompatible with code block dimensions!!\n"
                          "  Either the code block dimensions must divide "
                          "into the\n  pushed block dimensions, or vice "
                          "versa!\n");
                  exit(-1);
                }
            }
        }
    }
  assert((block_rows <= band->push_block_rows) &&
         (block_cols <= band->push_block_cols));

  /* First, find the first relevant code block. */

  block = band->blocks;
  r = top_row / block->rows;
  c = left_col / block->cols;
  block_pp = block + r*band->blocks_wide + c;
  assert((r < band->blocks_high) && (c < band->blocks_wide) &&
         (top_row >= block_pp->top_row) && (left_col >= block_pp->left_col));
  row_gap = self->master.row_gap;
  do {
    cur_left_col = left_col;
    cur_block_cols = block_cols;
    block = block_pp;
    n = c;
    do {
      xfer_rows = block->rows;
      xfer_cols = block->cols;
      if (xfer_rows > block_rows)
        xfer_rows = block_rows;
      if (xfer_cols > cur_block_cols)
        xfer_cols = cur_block_cols;
      if (block->pushed_block_buffer == NULL)
        block->pushed_block_buffer =
          self->sample_buffer_heap_mgr->get_buffer(
                                        self->sample_buffer_heap_mgr);
      dpp = block->pushed_block_buffer +
        row_gap*(top_row-block->top_row) + (cur_left_col-block->left_col);
      for (j=0; j < xfer_rows; j++, dpp += row_gap)
        for (dp=dpp, sp=block_buf[j]+(cur_left_col-left_col),
             i=xfer_cols; i > 0; i--)
          *(dp++) = *(sp++);
      block->unpushed_blocks--;
      if (block->unpushed_blocks == 0)
        {
          encode_block(self,block->pushed_block_buffer,band,block);
          self->sample_buffer_heap_mgr->return_buffer(
                                        self->sample_buffer_heap_mgr,
                                        block->pushed_block_buffer);
          block->pushed_block_buffer = NULL;
        }
      cur_block_cols -= xfer_cols;
      cur_left_col += xfer_cols;
      block++;
      n++;
      assert((cur_block_cols == 0) ||
             ((n < band->blocks_wide) && (cur_left_col == block->left_col)));
    } while (cur_block_cols > 0);
    block_buf += xfer_rows;
    block_rows -= xfer_rows;
    top_row += xfer_rows;
    block_pp += band->blocks_wide;
    r++;
    assert((block_rows == 0) ||
           ((r < band->blocks_high) && (top_row == block_pp->top_row)));
  } while (block_rows > 0);
}

/*****************************************************************************/
/* STATIC                        __push_tree                                 */
/*****************************************************************************/

static void
  __push_tree(encoder_ref base, ifc_int **tree_buf,
              int levels, int component_idx, int root_row, int root_col)
{
  the_encoder_ref self = (the_encoder_ref) base;
  int lev, b, top_row, left_col, rows, cols, max_dim, r, r_off, c_off;
  level_info_ptr li;
  band_info_ptr band;
  ifc_int **row_ptrs;

  assert((component_idx < self->num_components) &&
         (levels == self->num_levels));
  if (self->tree_to_block_map == NULL)
    self->tree_to_block_map = (ifc_int **)
      local_malloc(sizeof(ifc_int *)*(size_t)(1<<self->num_levels));
  row_ptrs = self->tree_to_block_map;
  for (lev=0; lev < levels; lev++)
    {
      li = self->components[component_idx].levels + lev;
      top_row = root_row << lev;
      left_col = root_col << lev;
      max_dim = 1<<lev;
      for (b=li->min_band; b <= li->max_band; b++)
        {
          band = li->bands + b;
          rows = band->band_rows - top_row;
          cols = band->band_cols - left_col;
          if (rows > max_dim)
            rows = max_dim;
          if (cols > max_dim)
            cols = max_dim;
          switch (b) {
            case LL_BAND: r_off = c_off = 0; break;
            case HL_BAND: r_off = 0; c_off = 1<<lev; break;
            case LH_BAND: r_off = 1<<lev; c_off = 0; break;
            case HH_BAND: r_off = 1<<lev; c_off = 1<<lev; break;
            default: assert(0);
          }
          for (r=0; r < rows; r++)
            row_ptrs[r] = tree_buf[r+r_off] + c_off;
          __push_block(base,row_ptrs,component_idx,lev,b,
                       rows,cols,top_row,left_col);
        }
    }
}

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

static void
  __terminate(encoder_ref base)
{
  the_encoder_ref self = (the_encoder_ref) base;
  int comp_idx, n, b;
  level_info_ptr lev;

  if (self->components == NULL)
    { /* Object was never initialized. */
      local_free(self);
      return;
    }

  if (self->master.cpu_time >= 0)
    {
      double seconds;
      int rows, cols, max_rows, max_cols;

      seconds = ((double)(self->master.cpu_time)) / ((double) CLOCKS_PER_SEC);
      max_rows = max_cols = 0;
      for (comp_idx=0; comp_idx < self->num_components; comp_idx++)
        {
          lev = self->components[comp_idx].levels + self->num_levels;
          rows = lev->bands[0].band_rows;
          cols = lev->bands[0].band_cols;
          if (rows > max_rows)
            max_rows = rows;
          if (cols > max_cols)
            max_cols = cols;
        }
      fprintf(stderr,
              ">> CPU time for EBCOT encoder:\n"
              "   %g seconds (%g micro-seconds per pixel)\n",
              seconds,seconds*1.0E6/((double)(max_rows*max_cols)));
    }
#ifdef COUNT_SYMBOLS
    {
      double symbol_rate;
      int rows, cols, max_rows, max_cols;

      max_rows = max_cols = 0;
      for (comp_idx=0; comp_idx < self->num_components; comp_idx++)
        {
          lev = self->components[comp_idx].levels + self->num_levels;
          rows = lev->bands[0].band_rows;
          cols = lev->bands[0].band_cols;
          if (rows > max_rows)
            max_rows = rows;
          if (cols > max_cols)
            max_cols = cols;
        }
      symbol_rate =
        ((double) ebcot_total_symbol_count) / ((double)(max_rows*max_cols));
      fprintf(stderr,
              ">> Symbol rate for EBCOT encoder:\n"
              "   %g symbols per sample\n",symbol_rate);
    }
#endif
  
  write_block_dimensions(self);
  write_layer_info(self);
  ebcot_send_bit_stream(self);

  /* Now deallocate storage. */

  for (comp_idx = 0; comp_idx < self->num_components; comp_idx++)
    {
      for (lev=self->components[comp_idx].levels,
           n=0; n <= self->num_levels; n++, lev++)
        for (b=lev->min_band; b <= lev->max_band; b++)
          {
            band_info_ptr band = lev->bands + b;

            local_free(band->blocks->passes);
            local_free(band->blocks);
            if (band->lines.buffers != NULL)
              {
                int n;

                for (n=0; n < band->blocks_wide; n++)
                  self->sample_buffer_heap_mgr->return_buffer(
                                            self->sample_buffer_heap_mgr,
                                            band->lines.buffers[n]);
                local_free(band->lines.buffers);
              }
          }
      local_free(self->components[comp_idx].levels);
    }
  local_free(self->components);
  local_free(self->master.first_subblock);
  local_free(self->master.first_quad);
  self->master.context_buffer -= self->master.row_gap + 2;
  local_free(self->master.context_buffer);
  self->code_heap_mgr->terminate(self->code_heap_mgr);
  self->sample_buffer_heap_mgr->terminate(self->sample_buffer_heap_mgr);
  local_free(self->layer_info);
  if (self->tree_to_block_map != NULL)
    local_free(self->tree_to_block_map);
  local_free(self);
}

/*****************************************************************************/
/* EXTERN                      create_ebcot_encoder                          */
/*****************************************************************************/

encoder_ref
  create_ebcot_encoder(void)
{
  the_encoder_ref result;

  result = (the_encoder_ref)
    local_malloc(sizeof(the_encoder_obj));
  memset(result,0,sizeof(the_encoder_obj));
  result->base.initialize = __initialize;
  result->base.print_usage = __print_usage;
  result->base.push_line = __push_line;
  result->base.push_block = __push_block;
  result->base.push_tree = __push_tree;
  result->base.terminate = __terminate;
  return((encoder_ref) result);
}

⌨️ 快捷键说明

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