/******
*
* <>
*
* these routines are obsoleted by "quantim" and need to make calls
* to the quantizeImage routines with passed-in qtypes and whatnot
*
*******/
#define NEVER_QUANT_LL // seems to be a winner
#define FASTQUANT_SHIFT 8
#define FASTQUANT_ONE (1<<FASTQUANT_SHIFT)
#define FASTQUANT_HALF (1<<(FASTQUANT_SHIFT-1))
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <crblib/inc.h>
#include "image.h"
#include "codeimage.h"
#include "quantutil.h"
/*************/
#define quantizeBands quantizeBandsDZ // not very cool to do this
#define quantizeBandsU quantizeBandsDZU // not very cool to do this
// quantizeBands() is used by the fiddle() and whatnot routines
#define VAL_SCALE 16
#define INV_VAL_SCALE (1.0/VAL_SCALE)
#define MAX_VAL 128
#define MAX_VAL_SCALED (MAX_VAL * VAL_SCALE)
#define TOP_VAL_SCALED (MAX_VAL_SCALED - 1)
#define SCALE_Q_UP 1.125
#define SCALE_Q_DN 0.9375
typedef struct {
int size;
int num_of_val[MAX_VAL_SCALED];
// used in fiddle:
int dD_up,dD_dn,dR_up,dR_dn;
double RoD_dn,RoD_up;
} bandInfo;
int distortion(int *num_of_val,double quantizer);
void infoBand(double *ptr,int w,int h,int fullw,bandInfo *bi);
ulong packedQuantizedImageSize(imageFloat *imf,coder *coder_template,int levels,float *quantizers);
ulong packedQuantizedImageStopErr(imageFloat *imf,coder *coder_template,int levels,double quantizer,int stopSize);
/*******
seekStoppedQ : scale the quantizers[] to get a desired rate.
this routine is imperfect, in that we almost always miss the target by
about 100 bytes. This is *not* a failure of the routine, but
actually a failure of the concept : sometimes you just don't get
rate changes when you move the quantizers a teeny bit - the image
is not floating-point.
********/
#define MIN_STEP 0.1
#define MAX_SEEK_Q 100
void seekStoppedQuantizers_Fast(imageFloat *imF,int levels,float * quantizers,int stopSize,
coder *coder_template)
{
//int nextErr_up,nextErr_dn,curErr;
int i,nbands;
double L,R,Lold,Rold,Lold_old,Rold_old;
int L_y,R_y,Lold_y,Rold_y;
double Lslope,Rslope,last_guess,guess;
#if 0 /** generate a plot **/
if ( 1 ) {
double sizer = 1.0 / imF->tot_size;
for(L=1.0;L<MAX_SEEK_Q;L += MIN_STEP) {
L_y = packedQuantizedImageStopErr(imF,coder_template,levels,L,stopSize);
printf("%2.2f %f\n",L,L_y*sizer);
}
return;
}
#endif
/******************
****
* this is an implementation of the tangent-intersection search.
* it converges in log(N) time.
Unfortunately it only works on data whose second derivative has
the same sign everywhere, and if you run the plots above you
see that's not us !
this search is like a binary search; we start with a L and R
which we hope are on either side of the minimum. We find
the tangent at each, then the intersection of the tangents.
This intersection is the "guess".
We then contract L & R to converge towards the guess.
There is one subtlety: after contraction we may have done a
bad step, in which case the two tangets will have the same
* sign of slope (they should always have opposite sign,
* indicating the trough or hill). When this happens we try
* to "reset" to resume the search.
**
** -> This algorithm is useless for me, because the actually shape
** of Error(Quantizer) is nearly chaotic.
***
**************/
nbands=3*levels+1;
Lold = 1.0;
Rold = MAX_SEEK_Q;
Lold_y = packedQuantizedImageStopErr(imF,coder_template,levels,Lold,stopSize);
Rold_y = packedQuantizedImageStopErr(imF,coder_template,levels,Rold,stopSize);
last_guess = guess = (Lold + Rold) * 0.5;
for(;;) {
last_guess = guess;
L = (Lold + guess)*0.5;
R = (Rold + guess)*0.5;
resetted:
L_y = packedQuantizedImageStopErr(imF,coder_template,levels,L,stopSize);
R_y = packedQuantizedImageStopErr(imF,coder_template,levels,R,stopSize);
Lslope = (L_y - Lold_y)/(L - Lold);
Rslope = (R_y - Rold_y)/(R - Rold);
fprintf(stderr,"Lold=%f, L=%f, guess=%f, R=%f, Rold=%f\n",Lold,L,guess,R,Rold);
fprintf(stderr,"Lold_y=%d, L_y=%d, R_y=%d, Rold_y=%d\n",Lold_y,L_y,R_y,Rold_y);
if ( Lslope > 0 ) { /** screwed up, must re-try **/
errputs("warning : reset left!");
R = Lold;
Rold = L;
L = (Lold + Lold_old)*0.5;
Lold = Lold_old;
if ( L == Lold || R == Rold ) {
errputs("warning : step size is zero; exiting");
break;
}
guess = (L + R) * 0.5;
goto resetted;
} else if ( Rslope < 0 ) {
errputs("warning : reset right!");
L = Rold;
Lold = R;
R = (Rold + Rold_old)*0.5;
Rold = Rold_old;
if ( L == Lold || R == Rold ) {
errputs("warning : step size is zero; exiting");
break;
}
guess = (L + R) * 0.5;
goto resetted;
}
guess = (Lslope * L - Rslope * R + R_y - L_y)/(Lslope - Rslope);
if ( fabs(last_guess - guess) < MIN_STEP ) {
break;
}
Lold_old = Lold; Lold = L; Lold_y = L_y;
Rold_old = Rold; Rold = R; Rold_y = R_y;
}
fprintf(stderr,"chose : %f\n",guess);
for(i=0;i<nbands;i++) quantizers[i] = (float) guess;
}
void seekStoppedQuantizers_Slow(imageFloat *imF,int levels,float * quantizers,int stopSize,
coder *coder_template)
{
double Q,best_Q;
ulong err,best_err,last_err;
int i;
image *im_work;
errputs("doing seek slow...");
best_err = LONG_MAX; best_Q = 1.0;
#if 0
for(Q=1.0;Q<MAX_SEEK_Q;Q += MIN_STEP) {
err = packedQuantizedImageStopErr(imF,coder_template,levels,Q,stopSize);
if ( err < best_err ) {
best_err = err;
best_Q = Q;
}
}
#else /** with a local copy of StopErr **/
if ( (im_work = newImageFromFloat(imF)) == NULL ) errexit("copyimage failed");
last_err =0;
for(Q=1.0;Q<MAX_SEEK_Q;Q += MIN_STEP) {
int p,r,qv,v;
double *dp,f,dv;
double quantme;
fprintf(stderr,"."); fflush(stderr);
quantizeBandsU(imF,im_work,levels,Q);
err = packedImageStopErr(im_work,coder_template,levels,stopSize);
quantme = 1.0 / Q;
v = (int)(LONG_MAX*quantme*quantme);
if ( err >= (ulong)v ) err = LONG_MAX;
else err = (ulong)(err*Q*Q);
for(p=0;p<imF->planes;p++) {
dp = imF->data[p][0];
for(r= imF->plane_size;r--;) {
f = *dp++; if ( f < 0 ) f = -f;
qv = (int)(f * quantme);
if ( qv == 0 ) dv = 0;
else dv = ((double)qv + 0.5) * Q;
err += (ulong)((dv - f)*(dv - f) + 0.5);
}
}
if ( err < best_err ) {
if ( err >= last_err ) { /* make sure it's stable */
best_err = err;
best_Q = Q;
}
}
last_err = err;
}
printf("chose Q = %f , best err = %d\n",best_Q,best_err);
freeImage(im_work);
#endif
for(i=0;i<=3*levels;i++) quantizers[i] = (float)best_Q;
}
void fiddleInfoBand(bandInfo *bic,double quantizer,float *quant_work,float *quant_spot,int R_cur,
imageFloat *imF,coder *coder_template,int levels);
void fiddleQuantizers(imageFloat *imF,int levels,float * quantizers,
coder *coder_template)
{
int nbands,b,p,l,best_up,best_dn,dR,dD,best_dD;
int R_cur,R_new,R_orig;
double **rows;
bool didFiddle;
double best_RoD;
bandInfo *bic;
bandInfo * bi = NULL; //alloc'ed
float *quant_work;
nbands = 3*levels + 1;
/**********
<> there's still some screw-up in the "distortion" measure
where we think the distortion is going down, but it
actually goes *UP* . In fact, the distortion almost
always goes up as a result of this fiddling, even
though we supposedly gaurantee it goes down. :(
A classic example :
barb.256.raw 256 256 -tw -qu20 -s1
barb.256.raw : 65536 -> 8192 = 1.000 bpb = 8.000 to 1
error: av= 5.03,max= 45,mse= 45.528,rmse= 6.75,psnr= 31.58
got option: fiddle quantizers
fiddle : band 1 up, 7 down
fiddle : got dR = 22, dD = -17365
fiddle : band 1 up, 8 down
fiddle : got dR = -10, dD = -11373
barb.256.raw : 65536 -> 8202 = 1.001