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

📄 ebcot_send_bits.c

📁 JPEG2000 EBCOT算法源码
💻 C
📖 第 1 页 / 共 3 页
字号:
        If `include_makeup_passes' is non-zero (true), the function includes
    the additional number of coding passes identified by each block's
    `makeup_passes' field.
        The `tags' argument supplies a `tag_buffer' object which may be
    used to manage the buffering of tag bits during the layer formation
    process.
        The function returns the actual number of bytes which are required
    to represent the new bit-stream layer, regardless of whether or not
    `output' is NULL. */

{
  band_info_ptr band;
  block_info_ptr block;
  int b, m, k, tag_val, extra_passes;
  int total_bytes, block_bytes, max_block_pass_bytes;

  total_bytes = 0;
  tag_buffer__reset(tags);
  tag_buffer__push_bit(tags,1); /* Indicates that the layer is in use. */
  for (b=level->min_band; b <= level->max_band; b++)
    {
      band = level->bands + b;
      if (layer_idx == 0)
        {
          band->byte_count_bits = 3; /* Minimum number of bits for
                                        signalling byte counts. */
          tag_tree__reset(band->inclusion_tree);
          tag_tree__reset(band->insignificant_msbs_tree);
        }

      /* Next, determine the number of coding passes to include in
         this bitstream layer and update the tag trees, as necessary. */

      for (block=band->blocks, m=0; m < band->band_blocks; m++, block++)
        {
          if (layer_idx == 0)
            {
              tag_tree__set_value(band->insignificant_msbs_tree+m,
                                  block->insignificant_msbs);
              block->old_passes = block->num_passes = 0;
            }
          else
            block->old_passes = block->num_passes;
          for (k=block->old_passes; k < block->max_passes; k++)
            {
              std_int rd;

              if ((rd = block->passes[k].rd_slope) <= 0)
                continue;
              if (rd >= rd_threshold)
                block->num_passes = k+1;
              else
                break;
            }
          if (block->num_passes && !block->old_passes) /* First inclusion. */
            tag_tree__set_value(band->inclusion_tree+m,layer_idx);
          if (include_makeup_passes)
            {
              assert((block->makeup_passes == 0) ||
                     (block->num_passes != 0));
              block->num_passes += block->makeup_passes;
            }
        }

      /* Now generate all tag information for the subband. */

      max_block_pass_bytes = 0;
      for (block=band->blocks, m=0; m < band->band_blocks; m++, block++)
        {
          /* Generate inclusion information. */

          extra_passes = block->num_passes - block->old_passes;
          if (block->old_passes == 0)
            { /* Not previously included. */
              tag_tree__encode(band->inclusion_tree+m,layer_idx+1,tags);
            }
          else
            { /* Block has already been included in a previous layer. */
              int inclusion_bit;

              inclusion_bit = (extra_passes == 0)?0:1;
              tag_buffer__push_bit(tags,inclusion_bit);
            }
          if (extra_passes == 0)
            continue;

          /* Generate `insignificant_msbs' information, if necessary. */

          if (block->old_passes == 0)
            {
              k = 1;
              while (!tag_tree__encode(band->insignificant_msbs_tree+m,k,tags))
                k++;
            }
          
          /* Now determine the number of new passes. */

          block_bytes = block->passes[block->num_passes-1].cumulative_bytes;
          if (block->old_passes == 0)
            extra_passes -= block->insignificant_msbs * PASSES_PER_BITPLANE;
          else
            block_bytes -= block->passes[block->old_passes-1].cumulative_bytes;
          assert((extra_passes >= 1) && (block_bytes > 0));
          total_bytes += block_bytes;
          for (k=extra_passes; k > 1; k = (k+1)>>1)
            block_bytes = (block_bytes+1)>>1;
          if (block_bytes > max_block_pass_bytes)
            max_block_pass_bytes = block_bytes;

          /* Generate tag information for the number of new passes. */

          extra_passes--;
          tag_val = (extra_passes > 0)?1:0;
          tag_buffer__push_bit(tags,tag_val);
          if (tag_val)
            {
              extra_passes -= tag_val;
              tag_val = (extra_passes > 0)?1:0;
              tag_buffer__push_bit(tags,tag_val);
              if (tag_val)
                {
                  extra_passes -= tag_val;
                  tag_val = (extra_passes > 2)?3:extra_passes;
                  tag_buffer__push_bits(tags,tag_val,2);
                  if (tag_val==3)
                    {
                      extra_passes -= tag_val;
                      tag_val = (extra_passes > 31)?31:extra_passes;
                      tag_buffer__push_bits(tags,tag_val,5);
                      if (tag_val==31)
                        {
                          extra_passes -= tag_val;
                          tag_val = extra_passes;
                          assert(tag_val < 128);
                          tag_buffer__push_bits(tags,tag_val,7);
                        }
                    }
                }
            }
        }

      if (max_block_pass_bytes > 0)
        {
          int num_bits;

          /* Send the number of bits which will be used to signal
             the number of new bytes for a single block coding pass. */

          num_bits = band->byte_count_bits;
          while (max_block_pass_bytes >= (1<<num_bits))
            {
              num_bits++;
              tag_buffer__push_bit(tags,1);
            }
          tag_buffer__push_bit(tags,0);
          band->byte_count_bits = num_bits;
          if (num_bits > 16)
            {
              fprintf(stderr,"Too many code bytes in a single bit-stream "
                      "layer for\n  one or more blocks!  Use smaller code "
                      "blocks or\n  more passes (SNR progressive)!\n");
              exit(-1);
            }

          /* Send the number of new bytes for each included block. */

          for (block=band->blocks, m=0; m < band->band_blocks; m++, block++)
            if ((extra_passes = (block->num_passes - block->old_passes)) > 0)
              {
                k = extra_passes;
                block_bytes =
                  block->passes[block->num_passes-1].cumulative_bytes;
                if (block->old_passes == 0)
                  k -= block->insignificant_msbs * PASSES_PER_BITPLANE;
                else
                  block_bytes -=
                    block->passes[block->old_passes-1].cumulative_bytes;
                for (num_bits=band->byte_count_bits; k > 1; k=(k+1)>>1)
                  num_bits++;
                assert(block_bytes < (1<<num_bits));
                tag_buffer__push_bits(tags,block_bytes,num_bits);
              }
        }
    }
  total_bytes += tag_buffer__flush(tags);
  if (output != NULL)
    {
      tag_buffer__output(tags,output);

      /* Now send the code bytes themselves, for each block for which
         information is being included. */

      for (b=level->min_band; b <= level->max_band; b++)
        {
          band = level->bands + b;
          for (block=band->blocks, m=0; m < band->band_blocks; m++, block++)
            if (block->num_passes > block->old_passes)
              {
                int offset, remaining;
                heap_unit_ptr heap;
                std_byte *buf;
                
                block_bytes =
                  block->passes[block->num_passes-1].cumulative_bytes;
                offset = 0;
                if ((k=block->old_passes) > 0)
                  offset = block->passes[k-1].cumulative_bytes;
                block_bytes -= offset;
                assert(block_bytes > 0);
                heap = block->first_unit;
                remaining = (HEAP_WORDS - block->first_pos) << 2;
                buf = ((std_byte *) heap->words) + HEAP_BYTES - remaining;
                while (offset > 0)
                  {
                    if (remaining >= offset)
                      {
                        buf += offset;
                        remaining -= offset;
                        offset = 0;
                      }
                    else
                      {
                        offset -= remaining;
                        heap = heap->next;
                        remaining = HEAP_BYTES;
                        buf = (std_byte *)(heap->words);
                      }
                  }
                while (block_bytes > 0)
                  {
                    if (remaining >= block_bytes)
                      {
                        output->push_bytes(output,buf,block_bytes);
                        block_bytes = 0;
                      }
                    else
                      {
                        output->push_bytes(output,buf,remaining);
                        block_bytes -= remaining;
                        heap = heap->next;
                        remaining = HEAP_BYTES;
                        buf = (std_byte *)(heap->words);
                      }
                  }
              }
        }
    }
  return(total_bytes);
}

/*****************************************************************************/
/* STATIC                      add_best_makeup_pass                          */
/*****************************************************************************/

static int
  add_best_makeup_pass(the_encoder_ref self, int layer_idx, int max_bytes)

 /* This function tries to utilize any portion of the overall bit-rate which
    is left over once rate-distortion optimization on the final layer is
    complete.  In particular, it passes through the various code blocks
    trying to find a new coding pass(es) which can be added (in addition to the
    number specified by the `num_passes' field), without violating any of
    the following four constraints:
      1) The relevant code block must already be included in the bit-stream;
         this minimizes the impact of including a new coding pass on the
         tag sizes and hence simplifies the algorithm.
      2) The number of additional code bytes must not exceed the `max_bytes'
         threshold.
      3) Either the number of new coding passes must have the same category
         code (i.e. 1,2,3-5,6-36) as that currently assigned for the layer,
         or else a penalty of 1 byte must be taken in satisfying (2).  Again,
         this constraint is enforced merely to simplify the task of identifying
         feasible makeup layers.  It may reduce the optimality of the
         algorithm somewhat, since the cost of coding the number of extra
         layers is generally much smaller than one byte.
      4) The current `byte_count_bits' value for the relevant subband must be
         sufficient to encode the number of code bytes sent for the block in
         the current layer, including bytes which were previously to be sent.
    The function finds the code block of this form which has the largest
    rate-distortion slope, updates the relevant `makeup_layer' and
    `makeup_passes' fields, and returns the number of additional bytes which
    are consumed by this new coding pass.  The function will be called
    iteratively until all remaining bytes have been consumed. */

{
  int n, b, k, m, comp_idx;
  level_info_ptr lev;
  band_info_ptr band;
  block_info_ptr block, best_block;
  std_int rd, best_rd;
  int current_passes, current_extra_passes, current_bytes, current_extra_bytes;
  int extra_passes, extra_bytes, max_extra_bytes;
  int best_extra_passes, best_extra_bytes;

  best_extra_passes = 0;
  best_extra_bytes = 0;
  best_block = NULL; best_rd = 0;
  for (n=0; n < self->num_levels; n++)
    for (comp_idx=0; comp_idx < self->num_components; comp_idx++)
      {
        lev = self->components[comp_idx].levels + n;
        for (b=lev->min_band; b <= lev->max_band; b++)
          {
            band = lev->bands + b;
            max_extra_bytes = 1<<(band->byte_count_bits);
            for (block=band->blocks, m=band->band_blocks; m > 0; m--, block++)
              {
                if (block->num_passes == 0)
                  continue; /* Doesn't satisfy first constraint. */
                current_passes = block->num_passes + block->makeup_passes;
                current_bytes =
                  block->passes[current_passes-1].cumulative_bytes;
                current_extra_passes = current_passes;
                current_extra_bytes = current_bytes;
                if (block->old_passes == 0)
                  current_extra_passes -=
                    block->insignificant_msbs * PASSES_PER_BITPLANE;
                else
                  {
                    current_extra_passes -= block->old_passes;
                    current_extra_bytes -=
                      block->passes[block->old_passes-1].cumulative_bytes;
                  }
                for (extra_passes=1, k=current_passes;
                     k < block->max_passes; k++, extra_passes++)
                  {
                    if (((rd = block->passes[k].rd_slope) < 0) ||
                        ((rd <= best_rd) && (best_block != NULL)))
                      continue;
                    extra_bytes =
                      block->passes[k].cumulative_bytes-current_bytes;
                    if ((extra_bytes > max_bytes) ||
                        ((extra_bytes+current_extra_bytes) > max_extra_bytes))
                      break;
                    if ((current_extra_passes <= 2) ||
                        ((current_extra_passes < 6) &&
                        ((current_extra_passes+extra_passes) >= 6)))
                      { /* Take one byte hit for encoding different # passes */
                        extra_bytes++;
                        if (extra_bytes > max_bytes)
                          break;
                      }
                    if ((current_extra_passes < 37) &&
                        ((current_extra_passes+extra_passes) >= 37))
                      { /* Take extra one byte hit to encode
                           different # passes. */
                        extra_bytes++;
                        if (extra_bytes > max_bytes)
                          break;
                      }
                    best_rd = rd;
                    best_block = block;
                    best_extra_bytes = extra_bytes;
                    best_extra_passes = extra_passes;
                  }
              }
          }
      }
  if (best_block == NULL)
    return(0);
  best_block->makeup_passes = best_extra_passes;
  return(best_extra_bytes);
}

/*****************************************************************************/
/* STATIC                    optimize_bitstream_layer                        */
/*****************************************************************************/

static std_int

⌨️ 快捷键说明

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