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

📄 tcq_quant.c

📁 JPEG2000实现的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************/
/* Copyright 1999 Science Applications International Corporation (SAIC).     */
/* Copyright 1995 University of Arizona, Arizona Board of Regents.           */
/* All rights reserved                                                       */
/* File: "tcq_quant.c"                                                       */
/* Description: Trellis coded quantization                                   */
/* Author: Joe Triscari/Tom Flohr                                            */
/* Affiliation: SAIC                                                         */
/* Version: VM9.0                                                            */
/* Last Revised: 20 April, 2001                                              */
/*****************************************************************************/

/*****************************************************************************/
/* Modified by David Taubman to support arbitrary reference points for the   */
/* transform and the various regular partitions, so as to facilitate         */
/* cropping and geometric transformations in the compressed domain and to    */
/* enable full support for CRF's single-sample overlap Wavelet transform,    */
/* as originally documented in Seoul.  Changes are too numerous to flag      */
/* individually within the code.  Changes copyrighted by HP with all rights  */
/* reserved for the modified parts.                                          */
/*****************************************************************************/

/*****************************************************************************/
/* Modified by David Taubman to support interface modifications, arbitrary   */
/* changes in coding parameters from component to component and from tile    */
/* to tile, to support the full generality of PART-1 of the JPEG2000         */
/* standard, and to support most anticipated generality of PART-2.  Changes  */
/* are too numerous to flag individually within the code, which in some      */
/* places has been completely rewritten.  All changes copyrighted by HP with */
/* all rights reserved for the modified parts.                               */
/*****************************************************************************/

/*****************************************************************************/
/* Modified for general wavelet decompositions.                              */
/* Copyright 2000 Science Applications International Corporation (SAIC).     */
/* Copyright 1995 University of Arizona, Arizona Board of Regents.           */
/* All Rights Reserved for modified parts.                                   */
/*****************************************************************************/

/*****************************************************************************/
/* Modified for general offset and scalar quantization.                      */
/* Copyright 2000 The MITRE Corporation.                                     */
/* All Rights Reserved for modified parts.                                   */
/*****************************************************************************/

#include <local_services.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <assert.h>
#include <ifc.h>
#include <markers.h>
#include "tcq_quant_local.h"

#ifndef MAX
#define MAX(A,B) ((A)>(B)?(A):(B))
#endif

#ifndef MIN
#define MIN(A,B) ((A)<(B)?(A):(B))
#endif

extern void ftcq(float *class_coef, std_int *quant_code_words, std_int n1,
		 float ql_step, int * scan_order);

/* ========================================================================= */
/* ---------------------------- Internal Functions ------------------------- */
/* ========================================================================= */

/*****************************************************************************/
/* STATIC                          is_power_of_2                             */
/*****************************************************************************/

static int
  is_power_of_2(int val)
{
  if (val == 0)
    return(0);
  while (!(val & 1))
    val>>=1;
  return(val == 1);
}

/*****************************************************************************/
/* STATIC                       AllocateBlockBuffer                          */
/*****************************************************************************/

static float **
  AllocateBlockBuffer(int width, int height)
{
  float **retval;
  int i;
  retval = (float **)local_malloc(TCQ_MEM_KEY,
				    sizeof(float*)*height);
  retval[0] = (float *)local_malloc(TCQ_MEM_KEY,
                                    sizeof(float)*width*height);
  for (i = 1; i < height; i++)
    retval[i] = retval[i-1] + width;
  return (retval);
}

/*****************************************************************************/
/* STATIC                        DeleteBlockBuffer                           */
/*****************************************************************************/

static void
  DeleteBlockBuffer(float **buffer)
{
  if (buffer == NULL) return;
  local_free(buffer[0]);
  local_free(buffer);
}

/*****************************************************************************/
/* STATIC                        ConvertTCQStates                            */
/*****************************************************************************/

static void
  ConvertTCQStates(std_int *cast_buf, int width, int extra_lsbs)
{
  int i, signbit;
  int extra_lsbs_neg = 0;

  if (extra_lsbs < 0) {
    extra_lsbs_neg = 1;
    extra_lsbs *= -1;
  }
  signbit = 1<<31;
  if (extra_lsbs_neg == 0) {
    for (i = 0; i < width; i++) { 
      if (cast_buf[i] < 0) cast_buf[i] = ((-cast_buf[i])<<extra_lsbs)|signbit;
      else cast_buf[i] <<= extra_lsbs;
    }
  }
  else {
    for (i = 0; i < width; i++) { 
      if (cast_buf[i] < 0) cast_buf[i] = ((-cast_buf[i])>>extra_lsbs)|signbit;
      else cast_buf[i] >>= extra_lsbs;
    }
  }
}

/*****************************************************************************/
/* STATIC                            get_scan_order                          */
/*****************************************************************************/

int *get_scan_order(int block_height, int block_width)

{

  int *scan_order;
  int upper_limit;
  int i, j, k, l = 0;

  scan_order = (int *) local_malloc(TCQ_MEM_KEY, sizeof(int)*block_height*block_width);
  for (i=0; i<block_height; i+=4) {
    upper_limit = MIN(i+4, block_height);
    for (j=0; j<block_width; j++) {
      for (k=i; k<upper_limit; k++) {
        scan_order[l++] = k*block_width + j;
      }
    }
  }

  return(scan_order);

}

/*****************************************************************************/
/* STATIC                            TCQBlock                                */
/*****************************************************************************/

static void
  TCQBlock(float **block, int block_width, int block_height,
           int block_offset, float scale, int extra_lsbs,
           tcq_quantizer_ref self)

 /* Quantize one block of the indicated dimensions from the `block' buffer.
    The first entry in each row of the buffer is found by adding `block_offset'
    to the corresponding entry in the `block' array.  Returns with the
    contents of the relevant portion of the `block' buffer overwritten with
    32 bit integers representing the quantized sample values to be sent
    on to the encoder.  The caller must pass these to the encoder, after
    aggregating all horizontally adjacent blocks in the tile and correcting
    for any mismatch between the size of "ifc_int" and "std_int" data
    types. */

{
  int j, tcq_len;
  static float *data = NULL;        /* It would be a good idea to get rid */
  static std_int *states = NULL;    /* of these static variables later;  */
  static int max_height, max_width; /* they make the code non-reentrant. */
  int *scan_order;

  if (block == NULL) {
    if (data) local_free(data);
    if (states) local_free(states);
    data = NULL;
    states = NULL;
    return; 
  }
  if (data == NULL) {
    data = (float *)local_malloc(TCQ_MEM_KEY,
				 sizeof(float)*block_width*block_height);
    states = (std_int *)local_malloc(TCQ_MEM_KEY,
				  sizeof(std_int)*block_width*block_height);
    max_height = block_height;
    max_width = block_width;
  }
  else if ((block_height*block_width) > (max_height*max_width)) {
    local_free(data);
    local_free(states);
    data = (float *)local_malloc(TCQ_MEM_KEY,
				 sizeof(float)*block_width*block_height);
    states = (std_int *)local_malloc(TCQ_MEM_KEY,
				  sizeof(std_int)*block_width*block_height);
    max_height = block_height;
    max_width = block_width;
  }

  tcq_len = 0;
  for (j=0; j < block_height; j++)
    {
      memcpy(data+tcq_len,block[j]+block_offset,sizeof(float)*block_width);
      tcq_len += block_width;
    }

  scan_order = get_scan_order(block_height, block_width);

  ftcq(data, states, tcq_len, scale, scan_order);
  local_free(scan_order);

  ConvertTCQStates(states, tcq_len, extra_lsbs);
  tcq_len = 0;
  for (j=0; j < block_height; j++)
    {
      memcpy(block[j]+block_offset,states+tcq_len,sizeof(float)*block_width);
      tcq_len += block_width;
    }
}

/*****************************************************************************/
/* STATIC                 destroy_component_structures                       */
/*****************************************************************************/

static void
  destroy_component_structures(tcq_component_info_ptr comp)
{
  tcq_level_info_ptr lev;
  tcq_band_info_ptr band;
  int n, b;

  /* Bug fix added by TJF */
  if (comp->levels == NULL)
    return;

  for (n=0; n <= comp->num_levels; n++)
    {
      lev = comp->levels + n;
      if (lev->bands != NULL)
        {
          for (b = lev->min_band; b <= lev->max_band; b++)
            {
              band = lev->bands + b;
              if (!band->valid_band)
                continue;
              assert(band->num_lines == 0);
              DeleteBlockBuffer(band->line_buffer);
            }
          local_free(lev->bands);
        }
    }
  local_free(comp->levels);
}

/*****************************************************************************/
/* STATIC                            start_tile                              */
/*****************************************************************************/

static void
  start_tile(tcq_quantizer_ref self)
{
  forward_info_ref info = self->info;
  encoder_ref encoder = self->encoder;
  int num_components = self->num_components;
  tcq_component_info_ptr comp;
  tcq_level_info_ptr lev;
  tcq_band_info_ptr band;
  int reversible, c, n, b;

  for (c=0; c < num_components; c++)
    {
      comp = self->components + c;
      destroy_component_structures(comp);

      comp->num_levels =
        info->get_var_tile_info(info,c,NULL,NULL,&reversible,NULL,NULL);
      if (reversible)
        local_error("Cannot use TCQ with reversible decompositions!");
      comp->levels = (tcq_level_info_ptr)
        local_malloc(TCQ_MEM_KEY,sizeof(tcq_level_info)*(comp->num_levels+1));
      for (n=0; n <= comp->num_levels; n++)
        {
          int max_hp_descent;
          float step_size;
          int exponent, extra_lsbs;

          lev = comp->levels + n;
          if (n == 0)
            lev->min_band = lev->max_band = LL_BAND;
          else
            {
              info->get_level_info(info,c,n,NULL,&max_hp_descent,NULL,NULL);
              if (max_hp_descent == 0)
                {
                  lev->min_band = 0;
                  lev->max_band = -1;
                  continue;
                }
              else
                {
                  lev->min_band = 1 << (max_hp_descent+max_hp_descent-2);
                  lev->max_band = (1<<(max_hp_descent+max_hp_descent)) - 1;
                }
            }
          lev->bands = (tcq_band_info_ptr)
            local_malloc(TCQ_MEM_KEY,
                         sizeof(tcq_band_info)*(lev->max_band+1));
          for (b=lev->min_band; b <= lev->max_band; b++)
            {
              band = lev->bands + b;
              info->get_band_info(info,c,n,b,NULL,NULL,NULL,NULL,NULL,NULL,&(band->valid_band));
              if (!band->valid_band)
                continue;
              info->get_quant_info(info,c,n,b,&step_size,&exponent,NULL,
                                   &extra_lsbs, NULL, NULL);
	      band->extra_lsbs = extra_lsbs;
	      band->line_buffer = NULL;
	      band->num_lines = 0;
	      band->scale = step_size;
              band->scale /= 2.0F;
            }
        }
    }

  /* Now set up the block structure. */

  for (c=0; c < self->num_components; c++)
    {
      comp = self->components + c;
      for (n=0; n <= comp->num_levels; n++)
        {
          canvas_dims dims;
          frame_info frame;

          lev = comp->levels + n;
          for (b=lev->min_band; b <= lev->max_band; b++)
            {
              int block_height, block_width;

              band = lev->bands + b;
              if (!band->valid_band)
                continue;
              info->get_band_info(info,c,n,b,&dims,&frame,NULL,NULL,NULL,NULL,NULL);
              encoder->get_block_ht_wd(encoder,c,n,b,
                                       &block_height,&block_width);
              assert(is_power_of_2(block_width) &&
                     is_power_of_2(block_height));
              band->first_block_width = block_width -
                ((dims.left_col - frame.dims.left_col) & (block_width - 1));
              band->first_block_height = block_height -
                ((dims.top_row - frame.dims.top_row) & (block_height - 1));
              if (band->first_block_height > dims.rows)
                band->first_block_height = dims.rows;
              if (band->first_block_width > dims.cols)
                band->first_block_width = dims.cols;
              band->block_width = block_width;
              band->block_height = block_height;
              band->num_lines = 0;
              band->remaining_tile_height = dims.rows;
              band->current_block_height = band->first_block_height;
            }
        }
    }
}


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

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

static void
  __initialize(quantizer_ref base, int num_components,

⌨️ 快捷键说明

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