www.pudn.com > xiaobo.zip.zip > old_coder_bp_bin.c


 
/***** 
 
	these are the weights for combining the various 
	moments to make an estimate	of the local activity 
 
	these need to be trained on a test set	(not trivial) 
 
******/ 
 
#define C1A 64 
#define C1B 64 
#define C1C 64 
#define C1D 64 
#define C1E 64 
#define C1F 64 
#define C1G 64 
#define C1H 64 
#define C1I 64 
#define C1J 64 
 
#define C2A 83 
#define C2B 83 
#define C2C 83 
#define C2D 83 
#define C2E 83 
#define C2F 83 
#define C2G 83 
#define C2H 83 
#define C2I 83 
#define C2J 83 
 
#define C3A 300 
#define C3B 170 
#define C3C 40 
#define C3D 40 
#define C3E 40 
#define C3F 40 
#define C3G 20 
#define C3H 20 
#define C3I 20 
#define C3J 20 
 
#define C4A 0 
#define C4B 0 
#define C4C 0 
#define C4D 0 
#define C4E 0 
#define C4F 0 
#define C4G 0 
#define C4H 0 
#define C4I 0 
#define C4J 0 
 
/***** 
 
coder_bitplane : send bitplanes ; this is an "EZ" coder, 
	except that our calling structures ruins the embedding; 
			should loop on bands inside the loop on bitplane 
				(instead of the current, opposite way for modular) 
			it also hurts compression to scan this way, because 
				same-BPbins have similar statistics  
				(recall flushing between BPbins helps ezdct) 
 
	coding signs helps about 0.03 (better than the 0.02 observed 
		in earlier more primitive sign coders) 
 
binary version : codes each bit-pel as a separate binary event 
 
our LOE : 
	don't actually compare the four contexts' MPS's, but just the four coders' 
	recent performance: choose the coder that had the lowest entropy on the 
	last N pixels. (some decaying record). 
 
instead of LOE, blend them based on confidence 
		(this is unusually easy because of the fact that 
		the alphabet is binary) 
	something like P_tot = W_tot * Sum P[n] / w[n] 
 
	where w is the weight = actual recent coded len 
		(TMW uses 2^(-w) instead of 1/w ) 
		(that may actually be better cuz we can do it with shifts; 
		you need some subtlety : find the smallest weight and factor it out first) 
 
* we're very similar to ECECOW, but getting stomped.  This might 
	be attributed to our incorrect scan order. 
 
--- 
 
with all context-mixers at 32 we get : (lossless) 
 
	lena 512 : 4.182	(l6 : 4.171)	(ececow : 4.06) 
	lena 256 : 4.160 
	checa 256: 3.143 
	zelda 512: 3.891		(ececow : 3.71) 
 
*****/ 
 
#include  
#include  
#include  
#include  
#include  
#include  
#include "coder.h" 
 
extern int tune_param; 
 
#define	VAL_CONTEXTS		20 
#define	VAL_CONTEXT_MAX		(VAL_CONTEXTS -1) 
#define SHAPE_BASE			VAL_CONTEXTS 
#define SHAPE(x)			(SHAPE_BASE<<(x)) 
#define NUM_SHAPES			4 
#define NUM_CONTEXTS		(VAL_CONTEXTS< TOTMAX ) { PT >>= 1; P0 >>= 1; P0++; PT += 2; } } while(0) 
#define bitEnc(bit,ari,P0,PT)	do { arithEncBit(ari,P0,PT,bit);	bitModel(bit,P0,PT); } while(0) 
#define bitDec(bit,ari,P0,PT)	do { bit = arithDecBit(ari,P0,PT);	bitModel(bit,P0,PT); } while(0) 
 
#define AddSignContext(context,val,mask) do { context *= 3; if( abs(val)&(mask) ) { if ( (val) > 0 ) context ++; else context += 2; } } while(0) 
 
typedef struct { 
	int p0,pt; 
} binContext; 
 
void coderBPbin_encodeBand(coder *me,int *band,int w,int h,int fullw,int *parent); 
void coderBPbin_decodeBand(coder *me,int *band,int w,int h,int fullw,int *parent); 
 
typedef struct { 
	int band_n; 
	binContext signs[SIGN_CONTEXTS]; 
	binContext	stats1[NUM_CONTEXTS], 
				stats2[NUM_CONTEXTS], 
				stats3[NUM_CONTEXTS], 
				stats4[NUM_CONTEXTS]; 
} myInfo; 
 
void coderBPbin_init(coder *c) 
{ 
myInfo *d; 
int i; 
 
	if ( (d = new(myInfo)) == NULL ) 
		errexit("ozero init failed"); 
 
	c->data = d; 
 
	d->band_n = -1; 
 
	for(i=0;istats1[i].p0 = P0_INIT+1; d->stats1[i].pt = 2+P0_INIT+P1_INIT; 
		d->stats2[i].p0 = P0_INIT+1; d->stats2[i].pt = 2+P0_INIT+P1_INIT; 
		d->stats3[i].p0 = P0_INIT+1; d->stats3[i].pt = 2+P0_INIT+P1_INIT; 
		d->stats4[i].p0 = P0_INIT+1; d->stats4[i].pt = 2+P0_INIT+P1_INIT; 
	} 
 
	for(i=0;isigns[i].p0 = 100; 
		d->signs[i].pt = 200; 
	} 
 
} 
 
void coderBPbin_free(coder *c) 
{ 
	if ( c->data ) { 
		myInfo *d; 
		d = c->data; 
		free(d); 
		c->data = NULL; 
	} 
} 
 
coder coderBPbin = { 
		"BitPlane Binary", 
		coderBPbin_init, 
		coderBPbin_free, 
		coderBPbin_encodeBand, 
		coderBPbin_decodeBand 
	}; 
 
/********** 
 
lazy way to pass the state from getStats to fixStats 
	and also interacts with the codeBand() 
 
these are re-initialized at each codeBand() call, so this is 
	quite re-entrant as long as we aren't multi-threaded 
	(that is, no more than one call to codeBand() at a time) 
 
*********/ 
 
static int VD; 
static binContext *stats1,*stats2,*stats3,*stats4; 
static binContext *s1,*s2,*s3,*s4; 
static int bitmask,donemask,nextmask; 
static int len1,len2,len3,len4; 
static int band_n,*sister_x,*sister_y; 
static int p0,pt; 
 
void getStats(int *dp,int *pp,int x,int y,int width,int height,int fullw) 
{ 
int shapes; 
int P,N,W,NE,NW,X1,X2,X3,X4; 
int diff,lena,lenb; 
binContext *sa,*sb; 
 
	/*** elaborate context-making ***/ 
 
	VD	= abs(*dp)&donemask;	// current val already done 
 
	P	= abs(*pp)&nextmask; 
 
	if ( y == 0 ) { 
		N = NW = NE = VD; 
		if ( x == 0 ) W = VD; else W = abs(dp[-1]) & nextmask; 
	} else if ( x == 0 ) { 
		W = NW = 0; 
		N  = abs(dp[-fullw])	& nextmask; 
		NE = abs(dp[1-fullw])	& nextmask; 
	} else { 
		N = abs(dp[-fullw])		& nextmask; 
		W = abs(dp[-1])			& nextmask; 
		NW = abs(dp[-1-fullw])	& nextmask; 
		if ( x == (width-1) ) NE = VD; 
		else	NE = abs(dp[1-fullw]) & nextmask; 
	} 
 
	shapes = 0; 
	if ( N > VD ) shapes += SHAPE(0); 
	if ( W > VD ) shapes += SHAPE(1); 
	if ( NW > VD ) shapes += SHAPE(2); 
	if ( NE > VD ) shapes += SHAPE(3); 
 
	/** make several combos here and choose the best **/ 
 
	/** band 0 has more vertical correlation **/ 
 
	switch(band_n) { 
		case 0: 
			if ( y > 1 ) 			X1 = abs(dp[-fullw-fullw]) & nextmask; else X1 = VD;	//NN 
			if ( y < (height-1) )	X2 = abs(dp[fullw])		& donemask;	else X2 = VD;			//S 
			if ( y > 2 ) 			X3 = abs(pp[-fullw])	& nextmask; else X3 = VD;			//PN 
			if ( y < (height-2) )	X4 = abs(pp[fullw]) 	& nextmask; else X4 = VD;			//PS 
			break; 
		case 1: 
			if ( x > 1		)		X1 = abs(dp[-2]) & nextmask; else X1 = VD;	//WW 
			if ( x < (width-1) )	X2 = abs(dp[1])	 & donemask; else X2 = VD;	//E 
			if ( x > 2 ) 			X3 = abs(pp[-1]) & nextmask; else X3 = VD;	//PW 
			if ( x < (width-2) )	X4 = abs(pp[1])  & nextmask; else X4 = VD;	//PE 
			break; 
		case 2: 
			if ( y < (height-1) )	X1 = abs(dp[fullw])	& donemask;	else X1 = VD;	//S 
			if ( x < (width-1) )	X2 = abs(dp[1])		& donemask;	else X2 = VD;	//E 
			X3 = abs( sister_x[ x + fullw*y ] ) & nextmask; 
			X4 = abs( sister_y[ x + fullw*y ] ) & nextmask; 
			break; 
		default: 
			errputs("band_n not in 0-2 !"); 
			break; 
	} 
 
	s1 = &stats1[ min(VAL_CONTEXT_MAX, ((C1A * VD + C1B * P + C1C * N + C1D * W + C1E * NW + C1F * NE + C1G * X1 + C1H * X2 + C1I * X3 + C1J * X4)>>8)) + shapes ]; 
	s2 = &stats2[ min(VAL_CONTEXT_MAX, ((C2A * VD + C2B * P + C2C * N + C2D * W + C2E * NW + C2F * NE + C2G * X1 + C2H * X2 + C2I * X3 + C2J * X4)>>8)) + shapes ]; 
	s3 = &stats3[ min(VAL_CONTEXT_MAX, ((C3A * VD + C3B * P + C3C * N + C3D * W + C3E * NW + C3F * NE + C3G * X1 + C3H * X2 + C3I * X3 + C3J * X4)>>8)) + shapes ]; 
	s4 = &stats4[ min(VAL_CONTEXT_MAX, ((C4A * VD + C4B * P + C4C * N + C4D * W + C4E * NW + C4F * NE + C4G * X1 + C4H * X2 + C4I * X3 + C4J * X4)>>8)) + shapes ]; 
 
	/** weighting  
	* 
	*	find the best two, then weight them by 2^(-entropy)  
	**/ 
 
	lena = len1;	sa = s1; 
	lenb = len2;	sb = s2; 
	if ( len3 < lena ) { lena = len3; sa = s3; } 
	else if ( len3 < lenb ) { lenb = len3; sb = s3; } 
	if ( len4 < lenb ) { lenb = len4; sb = s4; } 
	else if ( len4 < lena ) { lena = len4; sa = s4; } 
 
	if ( lena == lenb ) { 
		p0 = (sa->p0 + sb->p0)>>1; 
		pt = (sa->pt + sb->pt)>>1; 
	} else if ( lenb < lena ) { 
		diff = 1 + ((lena-lenb+8)>>4); 
		if ( diff >= 18 ) { 
			p0 = sb->p0; 
			pt = sb->pt; 
		} else { 
			p0 = (((sb->p0)<p0))/((1<pt)<pt))/((1<>4); 
		if ( lenb-lena >= 18 ) { 
			p0 = sa->p0; 
			pt = sa->pt; 
		} else { 
			p0 = (((sa->p0)<p0))/((1<pt)<pt))/((1<pt ) - log2x16( s1->pt - s1->p0 ); 
		len2 += log2x16( s2->pt ) - log2x16( s2->pt - s2->p0 ); 
		len3 += log2x16( s3->pt ) - log2x16( s3->pt - s3->p0 ); 
		len4 += log2x16( s4->pt ) - log2x16( s4->pt - s4->p0 ); 
 
		if ( len1 > 40000 ) {	/** for safety **/ 
			len1 >>= 1; len2 >>= 1; len3 >>= 1; len4 >>= 1; 
		} 
	} else { 
		len1 += log2x16( s1->pt ) - log2x16( s1->p0 ); 
		len2 += log2x16( s2->pt ) - log2x16( s2->p0 ); 
		len3 += log2x16( s3->pt ) - log2x16( s3->p0 ); 
		len4 += log2x16( s4->pt ) - log2x16( s4->p0 ); 
	} 
 
	bitModel(bit,s1->p0,s1->pt); 
	bitModel(bit,s2->p0,s2->pt); 
	bitModel(bit,s3->p0,s3->pt); 
	bitModel(bit,s4->p0,s4->pt); 
 
} 
 
static void codeBand_init(coder *me,int *band,int width,int height,int fullw) 
{ 
myInfo *d; 
 
	d = (myInfo *)me->data; 
 
	if ( ++d->band_n == 3 ) d->band_n = 0; 
	band_n = d->band_n; 
	if ( band_n == 2 ) { 
		sister_x = band - width; 
		sister_y = band - height*fullw; 
	} else { 
		sister_x = sister_y = NULL; 
	} 
 
	len1=len2=len3=len4=0; 
	stats1 = d->stats1; 
	stats2 = d->stats2; 
	stats3 = d->stats3; 
	stats4 = d->stats4; 
} 
 
void coderBPbin_encodeBand(coder *me,int *band,int width,int height,int fullw,int *parent) 
{ 
int x,y,bit; 
int *dp,*pp,*dpn; 
int top_val,top_bitpn; 
arithInfo *ari = me->arith; 
binContext *signs = ((myInfo *)me->data)->signs; 
 
	codeBand_init(me,band,width,height,fullw); 
 
	dp = band;	top_val = 0; 
	for(y=0;y top_val ) top_val = abs(*dp); 
			dp++; 
		} 
		dp += fullw - width; 
	} 
	for(top_bitpn=0;(1<<(top_bitpn+1))<=top_val;top_bitpn++) ; 
 
	cu_putExpanding_ari(top_bitpn,ari,8,8); 
 
	top_val = 1<=1;bitmask>>=1) { 
		donemask = nextmask; 
		nextmask = donemask + bitmask; 
 
		dp = band;	pp = parent; 
		for(y=0;y>1],x,y,width,height,fullw); 
 
				bit = (abs(dp[x])&bitmask)?1:0; 
				arithEncBit(ari,p0,pt,bit); 
 
				fixStats(bit); 
 
				if ( bit & !VD ) { 
					int context; 
					/** code the sign **/ 
					context = 0; 
					if ( x < (width-1) )	AddSignContext(context,dp[x+1],donemask); else context *= 3; 
					if ( x > 0 )			AddSignContext(context,dp[x-1],nextmask); else context *= 3; 
					if ( y < (height-1) )	AddSignContext(context,dp[x+fullw],donemask); else context *= 3; 
					if ( y > 0 )			AddSignContext(context,dp[x-fullw],nextmask); else context *= 3; 
#ifdef BIG_SIGN_CONTEXT 
					if ( y > 0 && x > 0 )	AddSignContext(context,dp[x-fullw-1],nextmask); else context *= 3; 
					if ( y > 0 && x < (width-1) )	AddSignContext(context,dp[x-fullw+1],nextmask); else context *= 3; 
#endif 
					bitEnc( (isneg(dp[x])?1:0) ,ari,signs[context].p0,signs[context].pt); 
				} 
			} 
			if ( y&1 ) pp += fullw; 
			dp += fullw; 
		} 
	} 
} 
 
void coderBPbin_decodeBand(coder *me,int *band,int width,int height,int fullw,int *parent) 
{ 
int x,y,bit; 
int *dp,*pp,*dpn; 
int top_val,top_bitpn; 
arithInfo *ari = me->arith; 
binContext *signs = ((myInfo *)me->data)->signs; 
 
	codeBand_init(me,band,width,height,fullw); 
 
/**** done in mainline now 
	dp = band; 
	for(y=0;y=1;bitmask>>=1) { 
		donemask = nextmask; 
		nextmask = donemask + bitmask; 
		dp = band;	pp = parent; 
		for(y=0;y>1],x,y,width,height,fullw); 
 
				bit = arithDecBit(ari,p0,pt); 
 
				fixStats(bit); 
 
				if ( bit ) { 
					if ( isneg(dp[x]) ) dp[x] -= bitmask; 
					else dp[x] += bitmask;  
					if ( ! VD ) { 
						int context; 
						/** code the sign **/ 
						context = 0; 
						if ( x < (width-1) )	AddSignContext(context,dp[x+1],donemask); else context *= 3; 
						if ( x > 0 )			AddSignContext(context,dp[x-1],nextmask); else context *= 3; 
						if ( y < (height-1) )	AddSignContext(context,dp[x+fullw],donemask); else context *= 3; 
						if ( y > 0 )			AddSignContext(context,dp[x-fullw],nextmask); else context *= 3; 
#ifdef BIG_SIGN_CONTEXT 
						if ( y > 0 && x > 0 )	AddSignContext(context,dp[x-fullw-1],nextmask); else context *= 3; 
						if ( y > 0 && x < (width-1) )	AddSignContext(context,dp[x-fullw+1],nextmask); else context *= 3; 
#endif 
						bitDec(bit,ari,signs[context].p0,signs[context].pt); 
						if ( bit ) dp[x] = - dp[x]; 
					} 
				} 
			} 
			if ( y&1 ) pp += fullw; 
			dp += fullw; 
		} 
	} 
}