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


 
//#define PACK_SIGNS	//helps about 0.007 
//#define LOG 
//#define DEBUG 
 
/********* 
 
SH_O1 : Static-Huff Order1	(not sigbit) 
 
	(similar to _o1_sb_ the older arithcoder version) 
 
compression is surprisingly competitive (off 0.1 bpp from bitplane) on 
	hi-fi files (quantizer < 4) (at large quant, the probability of zero 
	becomes too large for us). 
 
at large quantizer (eg. 20) the histogram looks like : 
	P(0) = 99.98 % 
	P(1) = 00.02 % 
	P(>1) = zero 
Huffman does not handle this well.  We could compensate by run-lengthing 
the zeros. 
 
speed is much worse than anticipated (only slightly better than BP). 
 
all arrays need to be self-extending !!! (copy order1-huff) 
 
**********/ 
 
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
 
#include "coder.h" 
 
extern int tune_param; 
 
#define SH_FLUSH_QUANTUM 	(1<<17)	/** <> decreasing this hurts a lot, unfortunately! **/ 
#define MERGE_LEN			(1<<11) 
 
#define ORDER1_RAWS			2 
#define ORDER1_ALPHABET		(16 + ORDER1_RAWS)	/** # of bits **/ 
 
#define CN_MAX_PREV			2 
#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_O1_init(coder *c); 
void coderSH_O1_free(coder *c); 
void coderSH_O1_flush(coder *c); 
void coderSH_O1_encodeBand(coder *me,int *band,int w,int h,int fullw,int *parent); 
void coderSH_O1_decodeBand(coder *me,int *band,int w,int h,int fullw,int *parent); 
 
coder coderSH_O1 = { 
		"StatHuff O1", 
		coderSH_O1_init, 
		coderSH_O1_free, 
		coderSH_O1_encodeBand, 
		coderSH_O1_decodeBand, 
		NULL,NULL,NULL,NULL,NULL,NULL, 
		coderSH_O1_flush 
	}; 
 
typedef struct { 
	coder *coder; 
	int coded_pels; 
	ubyte * comp_ptr; 
	bitInfo * signs_bi; 
		ubyte * signs_array; 
	ubyte ** sigbits_array; 
	ubyte ** sigbits; 
	ubyte * merge_array; 
} myInfo; 
 
static void coderSH_O1_getHunk(myInfo *mi); 
static void coderSH_O1_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_O1_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->signs_array = newarray(ubyte,alloc_len)) == NULL ) 
		errexit("malloc failed"); 
	if ( (d->merge_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"); 
 
return; 
} 
 
void coderSH_O1_flush(coder *c) 
{ 
	if ( c->data ) { 
		myInfo *d; 
		d = c->data; 
 
		if ( d->coded_pels > 0 ) 
			coderSH_O1_putHunk(d); 
	} 
} 
 
void coderSH_O1_free(coder *c) 
{ 
	if ( c->data ) { 
		myInfo *d; 
		int i; 
 
		d = c->data; 
 
		if ( d->signs_bi ) BitIO_CleanUp(d->signs_bi); 
 
		smartfree(d->signs_array); 
		smartfree(d->merge_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_O1_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_O1_putHunk(mi); 
} 
 
void coderSH_O1_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_O1_getHunk(mi); 
 
	dp = band; 
	pp = parent; 
	for(y=0;ycoded_pels -= width*height; 
} 
 
static void coderSH_O1_putHunk(myInfo *mi) 
{ 
int i,len,merged; 
int n_signs; 
struct LBitIOInfo * BII; 
ubyte *merge_ptr; 
 
/** flush out work bitios **/ 
 
	n_signs = BitIO_FlushWrite(mi->signs_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); 
 
// huff mi->signs_array into mi->code_bi 
 
#ifdef PACK_SIGNS 
	O0HuffArrayBII(mi->signs_array,n_signs,BII,true); 
#endif 
 
// 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 
	memcpy(mi->comp_ptr,mi->signs_array,n_signs);  
	mi->comp_ptr += n_signs; 
#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); 
 
	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_O1_getHunk(myInfo *mi) 
{ 
int i,len,merged; 
int n_signs; 
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); 
 
// dehuff mi->signs_array  
 
#ifdef PACK_SIGNS 
	O0HuffArrayBII(mi->signs_array,n_signs,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; 
 
#ifndef PACK_SIGNS 
	memcpy(mi->signs_array,mi->comp_ptr,n_signs);  
	mi->comp_ptr += n_signs; 
#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 
 
#ifdef LOG 
	printf("getHunk : %d -> %d\n",len,mi->coded_pels); 
#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_InitRead(mi->signs_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; 
		return; 
	} else { 
		int sign; 
 
		if ( isneg(sym) ) { sign = 1; sym = -sym; } 
		else sign = 0; 
 
		while ( sym >= 0xFF ) { 
			*(mi->sigbits[context])++ = 0xFF; 
			sym -= 0xFF; 
		} 
		*(mi->sigbits[context])++ = sym; 
 
		BitIO_WriteBit(mi->signs_bi,sign); 
	} 
 
} 
 
static int decode_val(myInfo *mi,int context) 
{ 
	if ( *(mi->sigbits[context]) == 0 ) { 
		mi->sigbits[context]++; 
		return 0; 
	} else { 
		int sign,sym,t; 
 
		sym  = 0; 
		do { 
			t = *(mi->sigbits[context])++; 
			sym += t; 
		} while( t == 0xFF ); 
 
		BitIO_ReadBit(mi->signs_bi,sign); 
		if ( sign ) sym = -sym; 
 
		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)); 
}