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


 
//#define PACK_SIGNS_AND_RESIDUALS	 
	/** helps compression 0.02 bpp, doesn't affect speed much ; 
		turning this off does amortize the damage for small flush_quanta **/ 
//#define LOG 
//#define DEBUG 
 
/********* 
 
SH_O1SB : Static-Huff Order1-SigBit 
 
	(similar to _o1_sb_ the older arithcoder version) 
 
see coder_sh_o1.c for more notes 
 
**********/ 
 
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
 
#include "coder.h" 
 
extern int tune_param; 
 
#define SH_FLUSH_QUANTUM 	(1<<16)	/** this really hates to be small **/ 
#define MERGE_LEN			(1<<10) 
 
#define ORDER1_RAWS			8		/** the optimum seems to be infinity, which turns this into a non-SB coder! **/ 
 
#define CN_MAX_PREV			4 
#define CN_MAX_PARENT		4 
#define CODE_CONTEXTS 		(1 + CN_MAX_PREV + (CN_MAX_PREV+1)*CN_MAX_PARENT) 
 
/*** the protos and structs ******/ 
 
void coderSH_O1SB_init(coder *c); 
void coderSH_O1SB_free(coder *c); 
void coderSH_O1SB_flush(coder *c); 
void coderSH_O1SB_encodeBand(coder *me,int *band,int w,int h,int fullw,int *parent); 
void coderSH_O1SB_decodeBand(coder *me,int *band,int w,int h,int fullw,int *parent); 
 
coder coderSH_O1SB = { 
		"SH O1 SB", 
		coderSH_O1SB_init, 
		coderSH_O1SB_free, 
		coderSH_O1SB_encodeBand, 
		coderSH_O1SB_decodeBand, 
		NULL,NULL,NULL,NULL,NULL,NULL, 
		coderSH_O1SB_flush 
	}; 
 
typedef struct { 
	coder *coder; 
	int coded_pels; 
	ubyte * comp_ptr; 
	bitInfo * signs_bi; 
		ubyte * signs_array; 
	bitInfo * residuals_bi; 
		ubyte * residuals_array;	 
	ubyte ** sigbits_array; 
	ubyte ** sigbits; 
	ubyte * merge_array; 
} myInfo; 
 
static void coderSH_O1SB_getHunk(myInfo *mi); 
static void coderSH_O1SB_putHunk(myInfo *mi); 
 
static void encode_val(myInfo *mi,int sym,int context); 
static int decode_val(myInfo *mi,int context); 
 
static int mcontext(int *cur_ptr,int parent,int x,int y,int width,int height,int fullw); 
 
/********* the functions *********/ 
 
void coderSH_O1SB_init(coder *c) 
{ 
myInfo *d; 
int i,alloc_len; 
 
	if ( (d = new(myInfo)) == NULL ) 
		errexit("malloc failed"); 
 
	d->coder = c; 
	c->data = d; 
 
	d->coded_pels = 0; 
	d->comp_ptr = c->w->comp; 
 
	alloc_len = c->w->width * c->w->height * c->w->planes; 
 
	if ( (d->merge_array = newarray(ubyte,alloc_len)) == NULL ) 
		errexit("malloc failed"); 
 
	if ( (d->signs_array = newarray(ubyte,alloc_len)) == NULL ) 
		errexit("malloc failed"); 
	if ( (d->residuals_array = newarray(ubyte,alloc_len)) == NULL ) 
		errexit("malloc failed"); 
 
	if ( (d->sigbits_array = newarray(ubyte *,CODE_CONTEXTS)) == NULL ) 
		errexit("malloc failed"); 
	if ( (d->sigbits = newarray(ubyte *,CODE_CONTEXTS)) == NULL ) 
		errexit("malloc failed"); 
 
	for(i=0;isigbits_array[i] = newarray(ubyte,alloc_len)) == NULL ) 
			errexit("malloc failed"); 
		d->sigbits[i] = d->sigbits_array[i]; 
	} 
 
	if ( (d->signs_bi = BitIO_Init(d->signs_array)) == NULL ) 
		errexit("bitio init failed"); 
 
	if ( (d->residuals_bi = BitIO_Init(d->residuals_array)) == NULL ) 
		errexit("bitio init failed"); 
 
return; 
} 
 
void coderSH_O1SB_flush(coder *c) 
{ 
	if ( c->data ) { 
		myInfo *d; 
		d = c->data; 
 
		if ( d->coded_pels > 0 ) 
			coderSH_O1SB_putHunk(d); 
	} 
} 
 
void coderSH_O1SB_free(coder *c) 
{ 
	if ( c->data ) { 
		myInfo *d; 
		int i; 
 
		d = c->data; 
 
		if ( d->signs_bi ) BitIO_CleanUp(d->signs_bi); 
		if ( d->residuals_bi ) BitIO_CleanUp(d->residuals_bi); 
 
		smartfree(d->merge_array); 
		smartfree(d->signs_array); 
		smartfree(d->residuals_array); 
		smartfree(d->sigbits); 
		if( d->sigbits_array ) { 
			for(i=0;isigbits_array[i]); 
			free(d->sigbits_array); 
		} 
 
		free(d); 
		c->data = NULL; 
	} 
} 
 
void coderSH_O1SB_encodeBand(coder *me,int *band,int width,int height,int fullw,int *parent) 
{ 
int x,y; 
int *dp,*pp,*dpp,*ppp; 
myInfo *mi = ((myInfo *)me->data); 
 
	dp = band; 
	pp = parent; 
	for(y=0;ycoded_pels += width*height; 
	if ( mi->coded_pels >= SH_FLUSH_QUANTUM )  
		coderSH_O1SB_putHunk(mi); 
} 
 
void coderSH_O1SB_decodeBand(coder *me,int *band,int width,int height,int fullw,int *parent) 
{ 
int x,y; 
int *dp,*pp,*dpp,*ppp; 
myInfo *mi = ((myInfo *)me->data); 
 
	if ( mi->coded_pels == 0 ) 
		coderSH_O1SB_getHunk(mi); 
 
	dp = band; 
	pp = parent; 
	for(y=0;ycoded_pels -= width*height; 
} 
 
static void coderSH_O1SB_putHunk(myInfo *mi) 
{ 
int i,len,merged; 
int n_signs,n_residuals; 
struct LBitIOInfo * BII; 
ubyte *merge_ptr; 
#ifdef LOG 
int signs_out,residuals_out; 
#endif 
 
/** flush out work bitios **/ 
 
	n_signs = BitIO_FlushWrite(mi->signs_bi); 
	n_residuals = BitIO_FlushWrite(mi->residuals_bi); 
 
/** write mi->coded_pels, other lengths **/ 
 
	if ( (BII = LBitIO_Init(mi->comp_ptr)) == NULL  ) 
		errexit("lbitio init failed!"); 
 
	cu_putExpanding_bii(mi->coded_pels,BII,15,4); 
	cu_putExpanding_bii(n_signs,BII,12,4); 
	cu_putExpanding_bii(n_residuals,BII,12,4); 
 
// huff mi->signs_array into mi->code_bi 
// huff mi->residuals_array into mi->code_bi 
 
#ifdef PACK_SIGNS_AND_RESIDUALS 
 
	O0HuffArrayBII(mi->signs_array,n_signs,BII,true); 
 
#ifdef LOG 
	signs_out = LBitio_GetPos(BII); 
#endif 
 
	O0HuffArrayBII(mi->residuals_array,n_residuals,BII,true); 
 
#ifdef LOG 
	residuals_out = LBitio_GetPos(BII) - signs_out; 
	printf("signs : %d -> %d , residuals : %d -> %d\n",n_signs,signs_out,n_residuals,residuals_out); 
#endif 
 
#endif //  PACK_SIGNS_AND_RESIDUALS 
 
// huff all the sigbits 
 
	merge_ptr = mi->merge_array; 
	merged = 0; 
 
	for(i=0;isigbits[i] - mi->sigbits_array[i]; 
		cu_putExpanding_bii(len,BII,12,4); 
		if ( len <= MERGE_LEN ) { 
			memcpy(merge_ptr,mi->sigbits_array[i],len); 
			merge_ptr += len; merged += len; 
		} 
	} 
 
	O0HuffArrayBII_RT(mi->merge_array,merged,BII,true);	 
 
	for(i=0;isigbits[i] - mi->sigbits_array[i]; 
		if ( len > MERGE_LEN ) { 
			O0HuffArrayBII_RT(mi->sigbits_array[i],len,BII,true);	 
		} 
	} 
 
	len = LBitIO_FlushWrite(BII); 
	mi->comp_ptr += len; 
 
#ifndef PACK_SIGNS_AND_RESIDUALS 
	memcpy(mi->comp_ptr,mi->signs_array,n_signs); mi->comp_ptr += n_signs; 
	memcpy(mi->comp_ptr,mi->residuals_array,n_residuals); mi->comp_ptr += n_residuals; 
#endif 
 
#ifdef DEBUG 
	*((ulong *)mi->comp_ptr) = crc32(mi->merge_array,merged); 
	mi->comp_ptr += 4; 
#endif 
 
#ifdef LOG 
	printf("putHunk : %d -> %d\n",mi->coded_pels,len); 
#endif 
 
/** now reset for another pass **/ 
 
	BitIO_ResetArray(mi->signs_bi,mi->signs_array); 
	BitIO_ResetArray(mi->residuals_bi,mi->residuals_array); 
 
	for(i=0;isigbits[i] = mi->sigbits_array[i]; 
 
	mi->coded_pels = 0; 
 
	/** fix up the main coding structures in case this is the last 
	*	Hunk we're decoding 
	***/ 
	arithEncodeReInit(mi->coder->arith,mi->comp_ptr); 
} 
 
static void coderSH_O1SB_getHunk(myInfo *mi) 
{ 
int i,len,merged; 
int n_signs,n_residuals; 
struct LBitIOInfo * BII; 
ubyte *merge_ptr; 
 
/** read mi->coded_pels, other lengths **/ 
 
	if ( (BII = LBitIO_Init(mi->comp_ptr)) == NULL  ) 
		errexit("lbitio init failed!"); 
 
	LBitIO_InitRead(BII); 
 
	mi->coded_pels = cu_getExpanding_bii(BII,15,4); 
	n_signs = cu_getExpanding_bii(BII,12,4); 
	n_residuals = cu_getExpanding_bii(BII,12,4); 
 
#ifdef LOG 
	printf("coded : %d , signs : %d, residuals : %d\n",mi->coded_pels,n_signs,n_residuals); 
#endif 
 
// dehuff mi->signs_array  
// dehuff mi->residuals_array 
 
#ifdef PACK_SIGNS_AND_RESIDUALS 
	O0HuffArrayBII(mi->signs_array,n_signs,BII,false); 
	O0HuffArrayBII(mi->residuals_array,n_residuals,BII,false); 
#endif 
 
// huff all the sigbits 
 
	merged = 0; 
 
	for(i=0;isigbits[i] = mi->sigbits_array[i] + cu_getExpanding_bii(BII,12,4); 
		len = mi->sigbits[i] - mi->sigbits_array[i]; 
		if ( len <= MERGE_LEN ) merged += len; 
	} 
 
	O0HuffArrayBII_RT(mi->merge_array,merged,BII,false); 
	merge_ptr = mi->merge_array; 
 
	for(i=0;isigbits[i] - mi->sigbits_array[i]; 
		if ( len <= MERGE_LEN ) { 
			memcpy(mi->sigbits_array[i],merge_ptr,len); 
			merge_ptr += len; 
		} else { 
			O0HuffArrayBII_RT(mi->sigbits_array[i],len,BII,false);	 
		} 
	} 
 
// done 
 
	len = LBitIO_GetPos(BII) - 4;	/* <> same as flushWrites' return? */ 
	mi->comp_ptr += len; 
 
#ifdef LOG 
	printf("getHunk : %d -> %d\n",len,mi->coded_pels); 
#endif 
 
#ifndef PACK_SIGNS_AND_RESIDUALS 
	memcpy(mi->signs_array,mi->comp_ptr,n_signs); mi->comp_ptr += n_signs; 
	memcpy(mi->residuals_array,mi->comp_ptr,n_residuals); mi->comp_ptr += n_residuals; 
#endif 
 
#ifdef DEBUG 
	/**/ { 
	ulong crc; 
	crc = *((ulong *)mi->comp_ptr);  mi->comp_ptr += 4; 
	if ( crc == crc32(mi->merge_array,merged) ) { 
		errputs("crc checked OK"); 
	} else { 
		errputs("crc failed on signs Uh-Oh"); 
		dbf(); 
	} 
	/**/ } 
#endif 
 
/** get ready to read from this unpacked hunk **/ 
 
	for(i=0;isigbits[i] = mi->sigbits_array[i]; 
 
	BitIO_ResetArray(mi->signs_bi,mi->signs_array); 
	BitIO_ResetArray(mi->residuals_bi,mi->residuals_array); 
 
	BitIO_InitRead(mi->signs_bi); 
	BitIO_InitRead(mi->residuals_bi); 
 
	/** fix up the main coding structures in case this is the last 
	*	Hunk we're decoding 
	***/ 
 
	arithDecodeReInit(mi->coder->arith,mi->comp_ptr); 
} 
 
static void encode_val(myInfo *mi,int sym,int context) 
{	 
	if ( sym == 0 ) { 
		*(mi->sigbits[context])++ = 0; 
	} else { 
 
		if ( isneg(sym) ) { BitIO_WriteOneBit(mi->signs_bi); sym = -sym; } 
		else BitIO_WriteZeroBit(mi->signs_bi); 
 
		if ( sym < ORDER1_RAWS ) {  
			*(mi->sigbits[context])++ = sym; 
		} else { 
			int bits,msb; 
 
			sym -= (ORDER1_RAWS-1); 	/** can't use zero **/ 
			bits = intlog2(sym); 
 
#if 0 
printf("%d %d\n",sym,bits); 
#endif 
 
			*(mi->sigbits[context])++ = bits + ORDER1_RAWS; 
 
			msb = (1<= msb ); 
#endif 
 
			sym -= msb; 
 
#ifdef DEBUG 
			assert( sym < msb ); 
#endif 
 
			for(msb>>=1;msb>=1;msb>>=1) { 
				BitIO_WriteBit(mi->residuals_bi,((sym&msb)?1:0)); 
			} 
		} 
	} 
} 
 
static int decode_val(myInfo *mi,int context) 
{ 
int bits; 
 
	bits = *(mi->sigbits[context])++; 
	if ( bits == 0 ) return 0; 
	else if ( bits < ORDER1_RAWS ) { 
		int sign; 
		BitIO_ReadBit(mi->signs_bi,sign); 
		if ( sign ) return -bits; 
		else return bits; 
	} else { 
		int msb,sym,sign; 
 
		msb = 1<<(bits - ORDER1_RAWS); 
		sym = msb + ORDER1_RAWS - 1; 
		for(msb>>=1;msb>=1;msb>>=1) { 
			BitIO_ReadBit(mi->residuals_bi,sign); 
			if ( sign ) sym += msb; 
		} 
 
#if 0 
printf("%d %d\n",sym,bits-1); 
#endif 
 
		BitIO_ReadBit(mi->signs_bi,sign); 
		if ( sign ) return -sym; 
		else return sym; 
	} 
} 
 
 
static int mcontext(int *cur_ptr,int parent,int x,int y,int width,int height,int fullw) 
{ 
int neighbors; 
 
	/** cur_ptr[0] is about to be coded **/ 
 
	if ( x==0 ) { 
		if ( y == 0 ) { 
			neighbors = 0; 
		} else { 
			neighbors = (cur_ptr[-fullw] + cur_ptr[-fullw+1]) >> 1; 
		} 
	} else if ( y == 0 ) { 
		neighbors = cur_ptr[-1]; 
	} else if ( x == (width-1) ) { 
		neighbors = (cur_ptr[-1] + cur_ptr[-fullw] + cur_ptr[-fullw] + cur_ptr[-fullw-1]) >> 2; 
	} else { 
		neighbors = (cur_ptr[-1] + cur_ptr[-fullw] + cur_ptr[-fullw+1] + cur_ptr[-fullw-1]) >> 2; 
	} 
 
parent = abs(parent); 
neighbors = abs(neighbors); 
parent = intlog2(parent+1); 
neighbors = intlog2(neighbors); 
 
return min(CN_MAX_PREV,neighbors) + (CN_MAX_PREV+1)*(min(CN_MAX_PARENT,parent)); 
}