📄 bw3.c
字号:
/*------------------------------------------------------------------------
$Workfile: BW3.C $
$Date: 3/11/96 12:51p $
$Revision: 2 $
* Purpose:
* Bin Width Calculation.
* Notes:
*
$History: BW3.C $
*
* ***************** Version 2 *****************
* User: Stevel Date: 3/11/96 Time: 12:51p
* Updated in $/601cman
* Add DLLEXPORT keyword to export functions for diagnostic test
*
* ***************** Version 1 *****************
* User: Stevel Date: 3/06/96 Time: 7:50p
* Created in $/601cman
* Initial release
This code and information is provided "as is" without warranty of any
kind, either expressed or implied, including but not limited to the
implied warranties of merchantability and/or fitness for a particular
purpose.
1996 Analog Devices, Inc.
-------------------------------------------------------------------------*/
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#define NBLOCKS 42
#include "bit-prec.h"
#include "bw.h"
#include "bw3tab.c"
#ifdef sgi
#define LOG10(X) log10f(X)
#else
#define LOG10(X) log10(X)
#endif
///////////////////////////////////////////////////////////////////////////
// Signal flag used by Bin Width Calculator
///////////////////////////////////////////////////////////////////////////
extern int *pBWrdyFlg;
///////////////////////////////////////////////////////////////////////////
// Configuration Parameters
///////////////////////////////////////////////////////////////////////////
BWCconfig config_rec;
static real levels0[6] = {0.4f, 0.3f, 0.25f, 0.2f, 0.15f, 0.1f};
static yuv_bias0[3] = {1, 1.25f, 1.25f};
static real diag_hor_vert0[3] = {1.2f, 1.0f, 1.0f};
static real levels1[6] = {96.0f, 64.0f, 32.0f, 16.0f, 8.0f, 4.0f};
static yuv_bias1[3] = {1, 2, 2};
static real diag_hor_vert1[3] = {1.2f, 1.0f, 1.0f};
static real bw_min[NBLOCKS];
static real bw_max[NBLOCKS];
static int block_sizes[NBLOCKS];
static real block_weights[NBLOCKS];
///////////////////////////////////////////////////////////////////////////
// Local function prototypes
///////////////////////////////////////////////////////////////////////////
static real estimate_bpp (real bw[]);
static void tau2bw (real tau, real bw[]);
static void expand_statistics (BWCinput *ip);
static void init_block_sizes (int img_width, int img_height);
///////////////////////////////////////////////////////////////////////////
// Local variables for Bin Width Calculator
///////////////////////////////////////////////////////////////////////////
BWCinput inrec; // Input for the Bin Width Calculator
BWCoutput outrec; // Ouput from the Bin Width Calculator
BWCinit init_rec; //
//=========================================================================
// Function to configure the Bin Width Calculator
//=========================================================================
DLLEXPORT void bw_config()
{
int bn, lev, dir, color;
config_rec.BppPrecision = 0.05f;
config_rec.BppFeedbackParm[0] = 0.0f;
config_rec.BppFeedbackParm[1] = 0.0f;
for (bn=0; bn<3; bn++) {
bw_min[bn] = levels0[0] * yuv_bias0[bn];
bw_max[bn] = levels1[0] * yuv_bias1[bn];
}
for (lev=1; lev<6; lev++) {
for (dir=0; dir<3; dir++) {
for (color=0; color<3; color++) {
if (bn < NBLOCKS) {
bw_min[bn] = levels0[lev]
* diag_hor_vert0[dir]
* yuv_bias0[color];
bw_max[bn] = levels1[lev]
* diag_hor_vert1[dir]
* yuv_bias1[color];
bn++;
}
}
}
}
}
//=========================================================================
// Function to convert Tau to Bin Width values
//=========================================================================
static void tau2bw(real tau, real bw[])
{
int bn;
for (bn=0; bn<NBLOCKS; bn++)
bw[bn] = (1.0-tau) * bw_min[bn] + tau * bw_max[bn];
}
///////////////////////////////////////////////////////////////////////////
// P24 actually corresponds to 10 bit shift:
// there are 14 bits built in into 9.7 precision of the wavelet transform.
///////////////////////////////////////////////////////////////////////////
static real b0 = 0.01f;
static real b1 = 100.0f;
#define P24 1024.0f
#define P26 (4.0*P24)
#define P28 (4.0*P26)
#define P30 (4.0*P28)
#define P32 (4.0*P30)
static real v2scale[NBLOCKS] = {
P32, P32, P32,
P30, P30, P30, P30, P30, P30, P30, P30, P30,
P28, P28, P28, P28, P28, P28, P28, P28, P28,
P26, P26, P26, P26, P26, P26, P26, P26, P26,
P24, P24, P24, P24, P24, P24, P24, P24, P24,
P24, P24, P24
};
static real v2scale_log[NBLOCKS];
///////////////////////////////////////////////////////////////////////////
// Internal Variables
///////////////////////////////////////////////////////////////////////////
real rate0, rate1;
static real b1log;
static real lbw_scale;
static real v2log[NBLOCKS]; /* half log of deviations */
//=========================================================================
// Bin Width Calculation
//=========================================================================
DLLEXPORT void bw_compute (BWCinput *in, BWCoutput *out)
{
real
bw_cur[NBLOCKS],
tau_low = 0.0,
tau_high = 1.0,
tau_mid, rhigh, rmid, rlow;
int done, bn;
expand_statistics(in);
tau2bw (tau_high, bw_cur);
rlow = estimate_bpp(bw_cur);
if (rlow < rate0) {
tau2bw (tau_low, bw_cur);
rhigh = estimate_bpp(bw_cur);
if (rate1 < rhigh)
{
for (done=0; ! done; ) {
tau_mid = 0.5f*(tau_low + tau_high);
tau2bw (tau_mid, bw_cur);
rmid = estimate_bpp(bw_cur);
if (rmid < rate0) {
rlow = rmid;
tau_high = tau_mid;
}
else if (rmid > rate1) {
rhigh = rmid;
tau_low = tau_mid;
}
else
done = 1;
}
}
}
for (bn=0; bn<NBLOCKS; bn++) {
real
bw = bw_cur[bn],
bwr = 1.0/bw;
out->BWCoeff[bn] = FLOAT2BW(bw);
out->RBWCoeff[bn] = FLOAT2BWI(bwr);
out->FieldDecim = 0;
}
}
//=========================================================================
// Function to initialize the Bin Width Calculator
//=========================================================================
static real bpp_table[NBLOCKS][NPT];
DLLEXPORT void bw_init (BWCinit *init_rec)
{
int bn;
switch (init_rec->ImgType) {
case GENERAL:
memcpy(bpp_table, general_bpp_table, sizeof(bpp_table));
break;
case NATURAL:
memcpy(bpp_table, natural_bpp_table, sizeof(bpp_table));
break;
case SYNTHETIC:
memcpy(bpp_table, synthetic_bpp_table, sizeof(bpp_table));
break;
default:
abort();
}
rate0 = (1.0 - config_rec.BppPrecision) * init_rec -> Bpp;
rate1 = (1.0 + config_rec.BppPrecision) * init_rec -> Bpp;
b1log = LOG10(b1);
lbw_scale = ((real)(NPT-1)) / (b1log - LOG10(b0));
init_block_sizes(init_rec->ImageWidth, init_rec->ImageHeight);
for (bn=0; bn<NBLOCKS; bn++) {
v2scale_log[bn] = LOG10(v2scale[bn]/(real)block_sizes[bn]);
}
/* Adjust bpp's according to block size */
for (bn=0; bn<NBLOCKS; bn++) {
int i;
real weight = block_weights[bn];
for (i=0; i<NPT; i++) {
bpp_table[bn][i] *= weight;
}
}
}
//=========================================================================
// Function to calculate the compression ratio
//=========================================================================
static real estimate_bpp (real bw[])
{
real total_bpp = 0.0f, bwl;
int bn;
for (bn=0; bn<NBLOCKS; bn++) {
real
*cb_table = bpp_table[bn],
cbw = bw[bn],
bw_log = LOG10(cbw), bpp;
bwl = (b1log - bw_log + v2log[bn]) * lbw_scale;
if (bwl > NPT-1) {
bpp = cb_table[NPT-1] +
(bwl-NPT+1) * (cb_table[NPT-1] - cb_table[NPT-2]);
}
else if (bwl < 0) {
bpp = cb_table[0] + bwl * (cb_table[1]-cb_table[0]);
if (bpp<0)
bpp = 0;
}
else {
int
bi0 = bwl,
bi1 = bi0+1;
real bfrac = bwl - bi0;
bpp = cb_table[bi0] +
bfrac * (cb_table[bi1] - cb_table[bi0]);
}
total_bpp += bpp;
}
return total_bpp;
}
//=========================================================================
// Function to expand the statistics (what does this mean ?)
//=========================================================================
static void expand_statistics (BWCinput *ip)
{
int bn;
for (bn=0; bn<NBLOCKS; bn++) {
real v2;
/* ADV601 doesn't do the rounding, so we have to adhjust */
v2 = 0.5 + ((real)(ip->SumOfSq[bn]));
v2log[bn] = 0.5 * (LOG10(v2) + v2scale_log[bn]) ;
}
}
//=========================================================================
// Function to initialize the block size
//=========================================================================
static void init_block_sizes (int img_width, int img_height)
{
real image_size = img_width * img_height;
int
h = img_height, w = img_width,
h1 = (h+1)/2, h1b = h - h1,
w1 = (w+1)/2, w1r = w - w1,
nn = 0, lev, bn;
/******** Set Luminance Block Sizes */
block_sizes[nn] = w1r * h;
w = w1;
for (lev=1; lev < 5; lev++) {
int
h1 = (h+1)/2, h1b = h - h1,
w1 = (w+1)/2, w1r = w - w1;
block_sizes[nn+3] = h1b * w1r;
block_sizes[nn+6] = h1 * w1r;
block_sizes[nn+9] = h1b * w1;
h = h1;
w = w1;
nn += 9;
}
block_sizes[nn+3] = h * w;
/******** Set Chrominance Block Sizes */
w = img_width;
h = img_height;
w1r = w/2;
w1 = w-w1r;
w1r = w1/2;
w1 = w1-w1r;
w = w1;
nn = 1;
block_sizes[nn] = block_sizes[nn+1] = w1r * h;
for (lev=1; lev < 5; lev++) {
int
h1 = (h+1)/2, h1b = h - h1,
w1 = (w+1)/2, w1r = w - w1;
block_sizes[nn+3] = block_sizes[nn+4] = h1b * w1r;
block_sizes[nn+6] = block_sizes[nn+7] = h1 * w1r;
block_sizes[nn+9] = block_sizes[nn+10] = h1b * w1;
h = h1;
w = w1;
nn += 9;
}
block_sizes[nn+3] = block_sizes[nn+4] = h*w;
for (bn=0; bn<NBLOCKS; bn++)
block_weights[bn] = ((real)block_sizes[bn])/image_size;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -