📄 tcq_dequant.c
字号:
/*****************************************************************************/
/* Copyright 1999 Science Applications International Corporation (SAIC). */
/* Copyright 1995 University of Arizona, Arizona Board of Regents. */
/* All rights reserved */
/* File: "tcq_dequant.c" */
/* Description: Trellis coded dequantization */
/* 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 <stdio.h>
#include <math.h>
#include <string.h>
#include <assert.h>
#include <ifc.h>
#include "tcq_dequant_local.h"
#ifndef MIN
#define MIN(A,B) ((A)<(B)?(A):(B))
#endif
/* SAIC General Decomp. Begin */
#ifndef MAX
#define MAX(A,B) ((A)>(B)?(A):(B))
#endif
/* SAIC General Decomp. End */
extern void fitcq (float *class_coef, std_int *quant_code_words,
std_int num_codewords, float step,
int fully_decoded, 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 ConvertDeTCQStates */
/*****************************************************************************/
static void
ConvertDeTCQStates(std_int *cast_buf, int width, int extra_lsbs,
int use_inverse_TCQ)
{
int i, sign_bit, sign_mask, isneg;
int extra_lsbs_neg = 0;
std_int tmp_buf;
if (extra_lsbs < 0) {
extra_lsbs_neg = 1;
extra_lsbs *= -1;
}
sign_bit = 1<<(31);
sign_mask = (1<<(31-extra_lsbs)) - 1;
if (extra_lsbs_neg == 0) {
for (i = 0; i < width; i++) {
isneg = (cast_buf[i] & sign_bit);
tmp_buf = cast_buf[i] >> extra_lsbs;
cast_buf[i] = tmp_buf & sign_mask;
if (!use_inverse_TCQ) {
/* Better for progressively decoding if odd indices are converted to even indices */
if (cast_buf[i] % 2) cast_buf[i] -= 1;
}
if (isneg) cast_buf[i] = -cast_buf[i];
}
}
else {
for (i = 0; i < width; i++) {
isneg = (cast_buf[i] & sign_bit);
tmp_buf = cast_buf[i] << extra_lsbs;
cast_buf[i] = tmp_buf & sign_mask;
if (!use_inverse_TCQ) {
/* Better for progressively decoding if odd indices are converted to even indices */
if (cast_buf[i] % 2) cast_buf[i] -= 1;
}
if (isneg) cast_buf[i] = -cast_buf[i];
}
}
}
/*****************************************************************************/
/* 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 DeTCQBlock */
/*****************************************************************************/
static void
DeTCQBlock(float **block, int block_width, int block_height,
int block_offset, float scale, int extra_lsbs,
tcq_dequantizer_ref self)
/* Dequantize 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. On entry, the relevant
portion of the `block' buffer should contain 32 bit integers representing
the quantized sample values recovered from the decoder. Returns with
floating point data obtained by dequantizing tehese samples. */
{
int j, tcq_len;
static float *data = NULL;
static std_int *states = NULL;
static int max_height, max_width;
int fully_decoded = 1;
int use_inverse_TCQ = 1;
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_height*block_width);
states = (std_int *)local_malloc(TCQ_MEM_KEY,
sizeof(std_int)*block_height*block_width);
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_height*block_width);
states = (std_int *)local_malloc(TCQ_MEM_KEY,
sizeof(std_int)*block_height*block_width);
max_height = block_height;
max_width = block_width;
}
tcq_len = 0;
for (j=0; j < block_height; j++)
{
memcpy(states+tcq_len,block[j]+block_offset,sizeof(float)*block_width);
tcq_len += block_width;
}
fully_decoded = 1;
for (j=0; j < tcq_len; j++)
{
if (!((states[j] >> (extra_lsbs - 1)) & 0x1))
{
fully_decoded = 0;
break;
}
if (!fully_decoded)
break;
}
if ((!fully_decoded) || self->use_approximate_itcq)
use_inverse_TCQ = 0;
ConvertDeTCQStates(states, tcq_len, extra_lsbs, use_inverse_TCQ);
scan_order = get_scan_order(block_height, block_width);
fitcq(data, states, tcq_len, scale, use_inverse_TCQ, scan_order);
local_free(scan_order);
tcq_len = 0;
for (j=0; j < block_height; j++)
{
memcpy(block[j]+block_offset,data+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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -