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

📄 ebcot_encoder.c

📁 JPEG2000 EBCOT算法源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*****************************************************************************/
/* File name: "ebcot_encoder.c"                                              */
/* Author: David Taubman                                                     */
/* Copyright 1998, Hewlett-Packard Company                                   */
/* All rights reserved                                                       */
/*****************************************************************************/
#include <local_heap.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <assert.h>
#include <line_block_ifc.h>
#include <ebcot_common.h>
#include "ebcot_encoder.h"
#include "ebcot_arith_encoder.h"
#include "ebcot_send_bits.h"


/* ========================================================================= */
/* ----------------------- Compressed Bit-Stream Heap ---------------------- */
/* ========================================================================= */

/*****************************************************************************/
/* STATIC                  codeword_heap__get_unit                           */
/*****************************************************************************/

static heap_unit_ptr
  codeword_heap__get_unit(codeword_heap_ref self)
{
  heap_group_ptr scan;
  heap_unit_ptr unit;
  int i;

  for (scan=self->heap; scan != NULL; scan=scan->next)
    if (scan->free_units)
      break;
  if (scan == NULL)
    {
      scan = (heap_group_ptr)
        local_malloc(sizeof(heap_group));
      scan->next = self->heap;
      self->heap = scan;
      scan->free_units = HEAP_GROUP_UNITS;
      for (unit=scan->units, i=HEAP_GROUP_UNITS; i > 0; i--, unit++)
        {
          unit->next = NULL;
          unit->group = NULL;
        }
    }
  for (unit=scan->units, i=HEAP_GROUP_UNITS; i > 0; i--, unit++)
    if (unit->group == NULL)
      break;
  assert(i > 0);
  scan->free_units--;
  unit->group = scan;
  unit->next = NULL;
  return(unit);
}

/*****************************************************************************/
/* STATIC                 codeword_heap__return_unit                         */
/*****************************************************************************/

static void
  codeword_heap__return_unit(codeword_heap_ref self, heap_unit_ptr unit)
{
  heap_group_ptr group;

  group = unit->group;
  assert((group != NULL) && (group->free_units < HEAP_GROUP_UNITS));
  group->free_units++;
  unit->group = NULL;
}

/*****************************************************************************/
/* STATIC                  codeword_heap__terminate                          */
/*****************************************************************************/

static void
  codeword_heap__terminate(codeword_heap_ref self)
{
  heap_group_ptr tmp;

  while ((tmp=self->heap) != NULL)
    {
      self->heap = tmp->next;
      local_free(tmp);
    }
  local_free(self);
}

/*****************************************************************************/
/* STATIC                     create_codeword_heap                           */
/*****************************************************************************/

static codeword_heap_ref
  create_codeword_heap(void)
{
  codeword_heap_ref result;

  result = (codeword_heap_ref) local_malloc(sizeof(codeword_heap_obj));
  memset(result,0,sizeof(codeword_heap_obj));
  result->get_unit = codeword_heap__get_unit;
  result->return_unit = codeword_heap__return_unit;
  result->terminate = codeword_heap__terminate;
  return(result);
}


/* ========================================================================= */
/* -------------------- Configuration Utility Functions -------------------- */
/* ========================================================================= */

/*****************************************************************************/
/* STATIC                      start_symbol_log                              */
/*****************************************************************************/
#ifdef LOG_SYMBOLS
static FILE *
  start_symbol_log(band_info_ptr band, block_info_ptr block)
{
  FILE *fp;
  char fname[81];

  sprintf(fname,"symbol_log_%d_%d_%d",band->level_idx,band->band_idx,
          (int)(block-band->blocks));
  fp = fopen(fname,"wb");
  assert(fp != NULL);
  return(fp);
}
#endif /* LOG_SYMBOLS */

/*****************************************************************************/
/* STATIC                     process_profile_flags                          */
/*****************************************************************************/

static int
  process_profile_flags(int profile)

 /* This function checks that the `profile' flags can be
    satisfied and returns a potentially augmented set of profile flags
    which will actually be supported. */

{
  profile |= PROFILE__RANDOM_ACCESS; /* Always have this feature. */
  profile |= PROFILE__RESOLUTION_PARSABLE; /* Always have this too. */
  profile |= PROFILE__COMPONENT_PARSABLE; /* Always have this too. */
  if (profile & PROFILE__SNR_PROGRESSIVE)
    profile |= PROFILE__SNR_PARSABLE; /* Get this for free. */
  if (!(profile & PROFILE__SNR_PARSABLE))
    profile |= PROFILE__RESOLUTION_PROGRESSIVE; /* 1-pass always has this. */
  return(profile);
}

/*****************************************************************************/
/* STATIC                    get_block_dimensions                            */
/*****************************************************************************/

static void
  get_block_dimensions(int argc, char *argv[],
                       int *block_dim, int *block_height, int *subblock_dim)
{
  int i, dim, sub_dim, height;

  dim = 64; sub_dim = 16; height = 0;
  for (i=0; i < (argc-1); i++)
    if (strcmp(argv[i],"-Cblk") == 0)
      {
        argv[i] = "";
        if (sscanf(argv[i+1],"%d",&dim) == 0)
          {
            fprintf(stderr,"The \"-Cblk\" argument requires an integer "
                    "parameter!\n");
            exit(-1);
          }
        argv[i+1] = "";
      }
    else if (strcmp(argv[i],"-Csub") == 0)
      {
        argv[i] = "";
        if (sscanf(argv[i+1],"%d",&sub_dim) == 0)
          {
            fprintf(stderr,"The \"-Csub\" argument requires an integer "
                    "parameter!\n");
            exit(-1);
          }
        argv[i+1] = "";
      }
    else if (strcmp(argv[i],"-Cheight") == 0)
      {
        argv[i] = "";
        if (sscanf(argv[i+1],"%d",&height) == 0)
          {
            fprintf(stderr,"The \"-Cheight\" argument requires an integer "
                    "parameter!\n");
            exit(-1);
          }
        argv[i+1] = "";
      }
  if (height == 0)
    height = dim;
  if (sub_dim > dim)
    sub_dim = dim;
  if ((sub_dim < 1) || (dim > 256) || (sub_dim & 3) || (dim & 3))
    {
      fprintf(stderr,"Illegal block dimensions supplied via command line "
              "arguments\n  \"-Cblk\" and/or \"-Csub\"!\n  Block dimensions "
              "must be positive integers, not exceeding 256, which\n  must "
              "be divisible by 4.\n");
      exit(-1);
    }
  if ((height < 1) || (height > dim))
    {
      fprintf(stderr,"Illegal block height supplied via command line "
              "argument\n  \"-Cheight\"!  Block height may not exceed the "
              "main block\n  dimension supplied via `-Cblk'!\n");
      exit(-1);
    }
  *block_dim = dim;
  *subblock_dim = sub_dim;
  *block_height = height;
}

/*****************************************************************************/
/* STATIC              set_default_scalable_layer_info                       */
/*****************************************************************************/

static void
  set_default_scalable_layer_info(the_encoder_ref self, int dedicated_bytes,
                                  int max_extra_bytes, int rows, int cols)

 /* This function sets up the default layer parameters for SNR-scalable
    bit-streams.  The default settings have been selected so as to avoid
    bias toward any particular bit-rates; if the set of desired bit-rates
    is known ahead of time, these should be supplied via the `-Clayers'
    command line argument; performance can always be improved in this way.
    The default is to include 50 layers in the bit-stream for every
    resolution level, with the average bit-rate of these layers spaced
    approximately logarithmically (no attempt is made to achieve exact
    bit-rates) between 0.015 bpp and 2.0 bpp.  If the maximum desired bit-rate
    is less than 2.0 bpp, some of these default layers are dropped.  If the
    maximum desired bit-rate is more than 2.0 bpp, some default layers are
    added. */

{
  int total_layers, n;
  double r, log_min, log_spacing, log_max, bytes_to_bpp;

  bytes_to_bpp = 8.0 / ((double)(rows*cols));
  log_max = log(2.0);
  log_min = log(0.015);
  log_spacing = (log_max-log_min) / 49.0;
  log_max = log(((double)(max_extra_bytes+dedicated_bytes)) * bytes_to_bpp);
  total_layers = 1 + (int) floor(0.5 + (log_max-log_min)/log_spacing);
  log_spacing = (log_max-log_min) / (total_layers-1);
  self->bitstream_layers = total_layers;
  self->layer_info = (bitstream_layer_info_ptr)
    local_realloc(self->layer_info,
                  sizeof(bitstream_layer_info)*(size_t) total_layers);
  for (r=log_min, n=0; n < (total_layers-1); n++, r += log_spacing)
    {
      self->layer_info[n].max_cumulative_bytes =
        ((int) floor(0.5 + exp(r) / bytes_to_bpp)) - dedicated_bytes;
      self->layer_info[n].actual_cumulative_bytes = 0;
      self->layer_info[n].optimize = (n==0)?1:0;
      self->layer_info[n].rd_threshold = 0;
    }
  self->layer_info[n].max_cumulative_bytes = max_extra_bytes;
  self->layer_info[n].actual_cumulative_bytes = 0;
  self->layer_info[n].optimize = 1;
  self->layer_info[n].rd_threshold = 0;
}

/*****************************************************************************/
/* STATIC                    rd_optimized_truncation                         */
/*****************************************************************************/

static int
  rd_optimized_truncation_allowed(int argc, char *argv[], int profile)

 /* Parses the argument list to see if rate-distortion optimization should
    be allowed.  If not, the function returns 0, which will ultimately
    cause all bit-rate limits to be ignored. */

{
  for (; argc > 0; argc--, argv++)
    if (strcmp(*argv,"-Cno_rd") == 0)
      {
        *argv = "";
        return(0);
      }
  return(1);
}

/*****************************************************************************/
/* STATIC                        get_layer_info                              */
/*****************************************************************************/

static void
  get_layer_info(the_encoder_ref self, int argc, char *argv[],
                 int dedicated_bytes, int max_extra_bytes,
                 int rows, int cols)
{
  double rate;
  int extra_layers, total_layers, max_bytes, last_max_bytes, optimize, n;

  for (; argc > 0; argc--, argv++)
    if ((strcmp(*argv,"-Clayers") == 0) && (argc > 1))
      {
        *(argv++) = ""; argc--;
        break;
      }
  self->bitstream_layers = 1;
  self->layer_info = (bitstream_layer_info_ptr)
    local_malloc(sizeof(bitstream_layer_info));
  if (!(self->profile & (PROFILE__SNR_PROGRESSIVE | PROFILE__SNR_PARSABLE)))
    { /* Want only one layer. */
      if (argc > 0)
        {
          fprintf(stderr,"The `-Clayers' argument is only allowed in "
                  "conjunction with\n  the SNR-PROGRESSIVE or SNR-PARSABLE "
                  "bit-stream profiles!!\n");
          exit(-1);
        }
      self->layer_info->max_cumulative_bytes = max_extra_bytes;
      self->layer_info->actual_cumulative_bytes = 0;
      self->layer_info->optimize = 1;
      self->layer_info->rd_threshold = 0;
      return;      
    }
  else if (argc == 0)
    { /* Default SNR-scalable bit-stream. */
      set_default_scalable_layer_info(self,dedicated_bytes,
                                      max_extra_bytes,rows,cols);
      return;
    }

  n = 0;
  last_max_bytes = 0;
  total_layers = 0;
  while ((argc > 0) && (sscanf(*argv,"%lf",&rate) == 1))
    {
      *(argv++) = ""; argc--;
      extra_layers = 0;
      if ((argc > 0) && ((*argv)[0] == '+'))
        {
          if ((sscanf((*argv)+1,"%d",&extra_layers)==0) || (extra_layers < 0))
            {
              fprintf(stderr,"The `-Clayers' argument contains an "
                      "incorrectly formatted\n  parameter identifying "
                      "extra bit-stream layers!\n");
              exit(-1);
            }
          *(argv++) = ""; argc--;
        }
      max_bytes = (int)(rate * 0.125 * (double)(rows*cols));
      max_bytes -= dedicated_bytes;
      if (max_bytes >= max_extra_bytes)
        break;
      total_layers += 1 + extra_layers;
      self->layer_info = (bitstream_layer_info_ptr)
        local_realloc(self->layer_info,sizeof(bitstream_layer_info)*
                      (size_t)(total_layers+1));
      if (max_bytes <= last_max_bytes)
        {
          fprintf(stderr,"The specific rate targets supplied to "
                  "the `-Clayers'\n  argument must be strictly "
                  "increasing and all less than\n  the target bit-rate "
                  "for the overall bit-stream!\n");
          exit(-1);
        }
      last_max_bytes = max_bytes;
      for (optimize=1; extra_layers >= 0; extra_layers--, n++, optimize=0)
        {
          self->layer_info[n].max_cumulative_bytes = max_bytes;
          self->layer_info[n].actual_cumulative_bytes = 0;
          self->layer_info[n].optimize = optimize;
          self->layer_info[n].rd_threshold = 0;
        }
    }
  max_bytes = max_extra_bytes;
  assert((max_bytes > last_max_bytes) && (n == total_layers));
  total_layers++; /* Last layer always holds the overall rate target. */
  self->layer_info[n].max_cumulative_bytes = max_bytes;
  self->layer_info[n].actual_cumulative_bytes = 0;
  self->layer_info[n].optimize = 1;
  self->layer_info[n].rd_threshold = 0;
  self->bitstream_layers = total_layers;

  /* Now go through and assign target bit-rates to the layers which are
     not marked for optimization. */

  for(n=0; n < (total_layers-1); n++)
    {

⌨️ 快捷键说明

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