www.pudn.com > wavecode.rar > coder_sm.c


/***** 
 
SigMap : send "significance map" then residual values 
 
	the sigmap is a mask of five entries : "0,1,-1, positive > 1, negative < -1" 
		it is order-1 context coded bases on the the parents' sigmap entry. 
	if one of the later two escapes is sent, their magnitude is coded (the residual) 
		with an order-1 context coder based on the parents MSB (log2 of value) 
		(we use a truncated alphabet then do order-minus-1 on the rest) 
 
	could try better ways to code residuals 
 
----- 
 
S+P Lena lossless : 4.255 bpp 
 
******/ 
 
#include  
#include  
#include  
#include  
#include  
#include  
 
extern int tune_param; 
 
/*** some convenient debug routines: 
** #define SEND_TAG()	if(0); else { arithEncode(ari,43,44,77); } 
** #define GET_TAG()	if(0); else { int got; got = arithGet(ari,77); arithDecode(ari,43,44,77); if ( got != 43 ) errexit("tag failure"); } 
********/ 
 
#define CNTX_CAP			10	/** I'm very surprised that this tunes so high! **/ 
#define SIGMAP_CONTEXTS		(CNTX_CAP+CNTX_CAP+1) 
#define SIGMAP_ALPHABET		5	/** 0,1,-1,pos,neg **/ 
 
#define SIGMAP_TOTMAX		5000 
#define SIGMAP_INC			30 
 
#define ORDER0_CNTXMAX		8 
#define ORDER0_CONTEXTS		(ORDER0_CNTXMAX+1) 
#define ORDER0_TOTMAX		500 
#define ORDER0_ALPHABET		25 
#define ORDER0_ESCAPE		(ORDER0_ALPHABET-1) 
 
#include "coder.h" 
 
void coderSigMap_encodeBand(coder *me,int *band,int w,int h,int fullw,int *parent); 
void coderSigMap_decodeBand(coder *me,int *band,int w,int h,int fullw,int *parent); 
 
typedef struct { 
	ozero ** o0; 
	scontext ** o1; 
} myInfo; 
 
void coderSigMap_init(coder *c) 
{ 
myInfo *d; 
int i; 
 
	if ( (d = new(myInfo)) == NULL ) 
		errexit("ozero init failed"); 
 
	c->data = d; 
 
	if ( (d->o0 = newarray(void *,ORDER0_CONTEXTS)) == NULL ) 
		errexit("Order0_Init failed!"); 
 
	for(i=0;io0[i] = ozeroCreateMax(c->arith,ORDER0_ALPHABET,ORDER0_TOTMAX)) == NULL ) 
			errexit("ozero init failed"); 
 
	if ( (d->o1 = newarray(void *,SIGMAP_CONTEXTS)) == NULL ) 
		errexit("Order1_Init failed!"); 
 
	for(i=0;io1[i] = scontextCreate(c->arith,SIGMAP_ALPHABET,0, 
				SIGMAP_TOTMAX,SIGMAP_INC,true)) == NULL ) 
			errexit("context creation failed!"); 
 
} 
 
void coderSigMap_free(coder *c) 
{ 
	if ( c->data ) { 
		myInfo *d; 
		d = c->data; 
		if ( d->o0 ) { 
			int i; 
			for(i=0;io0[i] ) ozeroFree(d->o0[i]); 
			free(d->o0); 
		} 
		if ( d->o1 ) { 
			int i; 
			for(i=0;io1[i] ) scontextFree(d->o1[i]); 
			} 
		} 
		free(d); 
		c->data = NULL; 
	} 
} 
 
coder coderSigMap = { 
		"SigMap", 
		coderSigMap_init, 
		coderSigMap_free, 
		coderSigMap_encodeBand, 
		coderSigMap_decodeBand 
	}; 
 
void coderSigMap_encodeBand(coder *me,int *band,int width,int height,int fullw,int *parent) 
{ 
int x,y,val,cntx; 
int *dp,*pp; 
int par_val,par_sig; 
ozero **o0 = ((myInfo *)me->data)->o0; 
scontext **o1 = ((myInfo *)me->data)->o1; 
arithInfo *ari = me->arith; 
 
	dp = band;	pp = parent; 
	for(y=0;y>1]; par_val = abs(par_sig); 
			par_sig = max(- CNTX_CAP,min(CNTX_CAP,par_sig)); par_sig += CNTX_CAP; 
 
			val = dp[x];	 
			switch(val) { 
				case 0:		scontextEncode(o1[par_sig],0); break; 
				case 1:		scontextEncode(o1[par_sig],1); break; 
				case -1:	scontextEncode(o1[par_sig],2); break; 
				default: 
					if ( isneg(val) ){	scontextEncode(o1[par_sig],3); val = -val; } 
					else 				scontextEncode(o1[par_sig],4); 
					val -= 2; 
					cntx = min(ORDER0_CNTXMAX, intlog2(par_val) ); 
					if ( val < ORDER0_ESCAPE ) ozeroEncode(o0[cntx],val); 
					else { 
						ozeroEncode(o0[cntx],ORDER0_ESCAPE); 
						encode_m1(ari,val - ORDER0_ESCAPE); 
					} 
					break; 
			} 
		} 
		if ( y&1 ) pp += fullw; 
		dp += fullw; 
	} 
} 
 
void coderSigMap_decodeBand(coder *me,int *band,int width,int height,int fullw,int *parent) 
{ 
int x,y,val,cntx,sign; 
int *dp,*pp; 
int par_val,par_sig; 
ozero **o0 = ((myInfo *)me->data)->o0; 
scontext **o1 = ((myInfo *)me->data)->o1; 
arithInfo *ari = me->arith; 
 
	dp = band;	pp = parent; 
	for(y=0;y>1]; par_val = abs(par_sig); 
			par_sig = max(- CNTX_CAP,min(CNTX_CAP,par_sig)); par_sig += CNTX_CAP; 
 
			switch( scontextDecode(o1[par_sig]) ) { 
				case 0:		dp[x] = 0; break; 
				case 1:		dp[x] = 1; break; 
				case 2:		dp[x] = -1; break; 
				case 3:		sign = -1; goto decode_val; 
				case 4:		sign = 1; 
				decode_val: 
					cntx = min(ORDER0_CNTXMAX, intlog2(par_val) ); 
					val = ozeroDecode(o0[cntx]); 
					if( val == ORDER0_ESCAPE ) val += decode_m1(ari); 
					dp[x] = sign * (val + 2); 
					break; 
				default: 	 
					errexit("decoded past alphabet!"); 
			} 
		} 
		if ( y&1 ) pp += fullw; 
		dp += fullw; 
	} 
}