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


/********** 
 
the quantim.c version of quantizers per band is archaic; we no longer 
have an gauranteed band structure.  Any quantizer who even uses "levels" 
is archaic. 
 
**********/ 
/*********** 
 
target structure : 
 
	image -> [quant & trans] -> (subbands + wavelet struct + quantinfo) 
	subbands -> [sender] 
		sends activities & bitmap of the subband tree structure 
		sorts by activity 
		sets optimal cntx pointers 
	[sender] -> subband_leafs to coders 
		coders which care about contexts must look at cntx widths now 
 
---------- 
 
choosing cntx1 & cntx2 is not trivial ; for one thing, the end-coder has 
some preferences.  The great "bpb" and "bpb2" coders want sister contexts 
(same size as current); in this case we should use the two similar-activity 
contexts which are closest *and of the same size* 
 
***********/ 
 
#include  
#include  
#include  
#include  
#include  
 
#include "image.h" 
#include "subbands.h" 
#include "coder.h" 
#include "codezt.h" 
#include  
#include  
 
void freeSubbands(subband *root); 
 
void arithRLEinit(void); 
void arithBitRLE(arithInfo * ari,bool bit); 
bool arithGetBitRLE(arithInfo * ari); 
 
subband * imageToSubbands(image *im,int levels); 
subband * makeSubbandQuad(int *band,int w,int h,int fullw,int levels,subband_node *higher); 
 
subband_node *new_subband_node(); 
subband_node *new_subband_node_foliated(); 
subband_leaf *new_subband_leaf(); 
 
void encodeSubbands(coder * encoder,subband * root); 
void decodeSubbands(coder * encoder,subband * root); 
 
void encodeWaveletSubbands(wavelet *wavelet); 
void decodeWaveletSubbands(wavelet *wavelet); 
 
void encodeLowestSubband(coder *encoder,subband_leaf *sbl); 
void decodeLowestSubband(coder *decoder,subband_leaf *sbl); 
 
void activitySubbands(subband * sb); 
void getActivities(coder * decoder,subband * sb); 
void sendActivities(coder * encoder,subband * sb); 
void initActivityRLE(void); 
 
subband_leaf * LLleaf(subband *sb); 
subband_leaf * seekLeaf(subband_leaf **leaves,int num,int w,int type); 
subband_leaf * seekLeafByType(subband_leaf **leaves,int num,int w,int type); 
subband * seekNode(subband_leaf **leaves,int num,int w,int type); 
subband * seekNodeByType(subband_leaf **leaves,int num,int w,int type); 
 
#define TOP_BITMASK (CODE_MAX_VAL>>1) 
 
/***********************************************/ 
 
/** ! we send the LL band here ! **/ 
 
void encodeWaveletSubbands(wavelet *wavelet) 
{ 
coder *encoder; 
  
	if ( (encoder = coder_create_write(wavelet->coder_template,wavelet,wavelet->stoplen)) == NULL ) 
		errexit("coder_create_write failed!"); 
 
	encoder->init(encoder); 
 
	if ( encoder->encodeBandZT ) { 
		int w,h,p; 
		w= (wavelet->im->width)>>(wavelet->levels); 
		h= (wavelet->im->height)>>(wavelet->levels); 
		for(p=0;p<(wavelet->im->planes);p++) 
			coder_encodeDPCM(encoder,wavelet->im->data[p][0],w,h,(wavelet->im->width)-w); 
 
		encodeImageZT(encoder,wavelet->im,wavelet->levels); 
	} else { 
//		sendBandMap(encoder,wavelet->subband_root); , easy 
		encodeSubbands(encoder,wavelet->subband_root); 
	} 
 
	coder_flush_write(encoder); 
	encoder->free(encoder); 
	coder_destroy(encoder); 
} 
 
void decodeWaveletSubbands(wavelet *wavelet) 
{ 
coder *decoder; 
 
	if ( (decoder = coder_create_read(wavelet)) == NULL ) 
		errexit("decoder_create main failed!"); 
 
	decoder->init(decoder); 
 
	if ( decoder->decodeBandZT ) { 
		int w,h,p; 
		w= (wavelet->im->width)>>(wavelet->levels); 
		h= (wavelet->im->height)>>(wavelet->levels); 
		for(p=0;p<(wavelet->im->planes);p++) 
			coder_decodeDPCM(decoder,wavelet->im->data[p][0],w,h,(wavelet->im->width)-w); 
 
		decodeImageZT(decoder,wavelet->im,wavelet->levels); 
	} else { 
//		if ( wavelet->subband_root ) freeSubbands(wavelet->subband_root); 
//		wavelet->subband_root = getBandMapImage(decoder,im); 
		decodeSubbands(decoder,wavelet->subband_root); 
	} 
 
	decoder->free(decoder); 
	coder_flush_read(decoder); 
	coder_destroy(decoder); 
} 
 
void encodeSubbandLeaf(coder * encoder,subband_leaf * sbl) 
{ 
	if ( !sbl ) return; 
	if ( coder_timetostop(encoder) ) return; 
 
	if ( sbl->parent == NULL ) { 
		encodeLowestSubband(encoder,sbl); 
	} else { 
		encoder->encodeBand(encoder,sbl->band,sbl->width,sbl->height, 
			sbl->width + sbl->rowpad,sbl->parent->band); 
	} 
} 
 
void decodeSubbandLeaf(coder * decoder,subband_leaf * sbl) 
{ 
	if ( !sbl ) return; 
	if ( coder_timetostopd(decoder,0) ) return; 
 
	if ( sbl->parent == NULL ) { 
		decodeLowestSubband(decoder,sbl); 
	} else { 
		decoder->decodeBand(decoder,sbl->band,sbl->width,sbl->height, 
			sbl->width + sbl->rowpad,sbl->parent->band); 
	} 
} 
 
void encodeSubbandLeafBP(coder * encoder,subband_leaf * sbl,int bitmask) 
{ 
	if ( !sbl ) return; 
	if ( coder_timetostop(encoder) ) return; 
 
	if ( sbl->parent == NULL ) { 
		if ( bitmask == TOP_BITMASK ) 
			encodeLowestSubband(encoder,sbl); 
		return; 
	} 
 
	if ( bitmask > sbl->max_value ) { 
		arithBitRLE(encoder->arith,0); 
		return; 
	} else { 
		arithBitRLE(encoder->arith,1); 
	} 
 
	if ( encoder->encodeBandBP ) { 
		encoder->encodeBandBP(encoder,sbl->band,sbl->width,sbl->height, 
			sbl->width + sbl->rowpad,sbl->parent->band,bitmask); 
	} else { 
		encoder->encodeSubbandBP(encoder,sbl,bitmask); 
	} 
} 
 
void decodeSubbandLeafBP(coder * decoder,subband_leaf * sbl,int bitmask) 
{ 
	if ( !sbl ) return; 
	if ( coder_timetostopd(decoder,0) ) return; 
 
	if ( sbl->parent == NULL ) { 
		if ( bitmask == TOP_BITMASK ) 
			decodeLowestSubband(decoder,sbl); 
		return; 
	} 
 
	if ( ! arithGetBitRLE(decoder->arith) ) 
		return; 
 
	if ( decoder->decodeBandBP ) { 
		decoder->decodeBandBP(decoder,sbl->band,sbl->width,sbl->height, 
			sbl->width + sbl->rowpad,sbl->parent->band,bitmask); 
	} else { 
		decoder->decodeSubbandBP(decoder,sbl,bitmask); 
	} 
} 
 
void encodeLowestSubband(coder *encoder,subband_leaf *sbl) 
{ 
	coder_encodeDPCM(encoder,sbl->band,sbl->width,sbl->height,sbl->rowpad); 
} 
 
void decodeLowestSubband(coder *decoder,subband_leaf *sbl) 
{ 
	coder_decodeDPCM(decoder,sbl->band,sbl->width,sbl->height,sbl->rowpad); 
} 
 
int countLeaves(subband *sb) 
{ 
	if ( ! sb ) return 0; 
	if ( sb->leaf ) return 1; 
	else { 
		subband_node * sbn; 
		sbn = sb; 
		return countLeaves(sbn->LL) +countLeaves(sbn->LH) +countLeaves(sbn->HL) +countLeaves(sbn->HH); 
	} 
} 
 
void readInLeaves(subband *sb,subband_leaf ** leaves,int *index) 
{ 
	if ( !sb ) return; 
	if ( sb->leaf ) { 
		leaves[ *index ] = sb; 
		(*index) ++; 
		return; 
	} else { 
		subband_node * sbn = sb; 
		readInLeaves(sbn->LL,leaves,index); 
		readInLeaves(sbn->LH,leaves,index); 
		readInLeaves(sbn->HL,leaves,index); 
		readInLeaves(sbn->HH,leaves,index); 
	} 
} 
 
void setLeaveContexts(subband_leaf ** leaves,int nLeaves) 
{ 
int i,t,j; 
subband_leaf *cur,*c1,*c2; 
 
	for(i=3;i= 0;j--) { 
			c1  = leaves[j]; 
			if ( c1->width == cur->width ) 
				break; 
		} 
		if ( j < 0 ) c1 = leaves[i-1]; 
		for(j = j-1; j>= 0;j--) { 
			c2  = leaves[j]; 
			if ( c2->width == cur->width ) 
				break; 
		} 
		if ( j < 0 ) { c2 = leaves[i-2]; 
			if ( c2 == c1 ) c2 = leaves[i-1]; 
		} 
 
		cur->cntx1 = c1;	cur->cntx2 = c2; 
		cur->cntx1shift = cur->cntx2shift = 0; 
 
		for(t=cur->width; t > c1->width ; t>>= 1) cur->cntx1shift++; 
		for(t=cur->width; t < c1->width ; t<<= 1) cur->cntx1shift--; 
		for(t=cur->width; t > c2->width ; t>>= 1) cur->cntx2shift++; 
		for(t=cur->width; t < c2->width ; t<<= 1) cur->cntx2shift--; 
	}	 
} 
 
/*}{********* sort & find parents *******/ 
#if 1 
 
void sortLeaves(subband_leaf ** leaves,int nLeaves) 
{ 
subband_leaf *cur; 
int i,p,j; 
bool didStuff; 
 
	do { 
		didStuff = false; 
		for(i=0;iparent == NULL ) p = 0; 
			else { 
				p = 0; 
				while ( leaves[p] != cur->parent ) p++; 
				p++; 
				if ( p >= i ) continue; 
			} 
			// try to swap cur up to p 
			while(p < i ) { 
				if ( cur->activity > leaves[p]->activity ) { 
					// do it 
					for (j=i-1;j>=p;j--) { 
						leaves[j+1] = leaves[j]; 
					} 
					leaves[p] = cur; 
					didStuff = true; 
					break; 
				} 
				p++; 
			} 
		} 
	} while( didStuff); 
 
	setLeaveContexts(leaves,nLeaves); 
} 
 
#else 
/*}{********* sort & find parents : sort-favoring way *******/ 
 
int sortLeavesCompare(const void *p1,const void *p2) 
{ 
subband_leaf *l1,*l2; 
	l1 = *((subband_leaf **)p1); 
	l2 = *((subband_leaf **)p2); 
	if ( l2->width != l1->width )  
		return (l1->width) - (l2->width); 
return (l2->activity) - (l1->activity); 
} 
 
void sortLeaves(subband_leaf ** leaves,int nLeaves) 
{ 
subband_leaf *cur; 
int i,w,type; 
 
	// sort by activity 
 
	qsort(leaves,nLeaves,sizeofpointer,sortLeavesCompare); 
 
	/* now pick up parents	(unlike contexts, we will move 
	*	leaves around in order to get good parents 
	* 
	*	try to find a parent of half the size,  
	*		and the same type 
	*	we can use a node, instead of a leaf, as the parent 
	*		in this case, all children of the node must be 
	*		sent before us. 
	* 
	*/ 
 
	for(i=0;iparent = NULL; 
		type = cur->type; w = (cur->width)>>1; 
 
		if ( cur->parent = seekLeafByType(leaves,i,(w<<0),type) ) goto found; 
		if ( cur->parent = seekLeafByType(leaves,i,(w<<1),type) ) goto found; 
		if ( cur->parent = seekLeafByType(leaves,i,(w<<2),type) ) goto found; 
		if ( cur->parent = seekLeafByType(leaves,i,(w<<3),type) ) goto found; 
 
		if ( cur->parent = seekNodeByType(leaves,i,(w<<0),type) ) goto found; 
		if ( cur->parent = seekNodeByType(leaves,i,(w<<1),type) ) goto found; 
		if ( cur->parent = seekNodeByType(leaves,i,(w<<2),type) ) goto found; 
		if ( cur->parent = seekNodeByType(leaves,i,(w<<3),type) ) goto found; 
 
		// not found any! 
		continue; 
 
		found: 
		cur->parent = LLleaf(cur->parent); 
		// <> this is kind of sloppy, and means the parent won't be 
		//	quite right 
	} 
 
	setLeaveContexts(leaves,nLeaves); 
} 
 
#endif 
/*}{******* sort & find parents *************/ 
 
void sendBandMap(coder *encoder,subband *sb) 
{ 
	if ( sb->leaf ) { 
		arithBit(encoder->arith,0); 
	} else { 
		arithBit(encoder->arith,1); 
		sendBandMap(encoder,sb->LL); 
		sendBandMap(encoder,sb->LH); 
		sendBandMap(encoder,sb->HL); 
		sendBandMap(encoder,sb->HH); 
	} 
} 
 
void encodeSubbands(coder * encoder,subband * root) 
{ 
subband_leaf ** leaves; 
int nLeaves,i; 
 
	initActivityRLE(); 
	sendActivities(encoder,root); 
 
	encoder->w->stopline = - 1; 
 
	nLeaves = countLeaves(root); 
 
	if ( (leaves = malloc(sizeofpointer*nLeaves)) == NULL ) 
		errexit("can't alloc leaves"); 
 
	i = 0; 
	readInLeaves(root,leaves,&i); 
 
	/** 
	*	sorting seems to be a nice little win 
	**/ 
 
	sortLeaves(leaves,nLeaves); 
 
// printSubbandInfo(root,stdout,0); 
 
	arithRLEinit(); 
 
	if ( encoder->encodeBand ) { 
		for(i=0;iencodeBandBP || encoder->encodeSubbandBP ) { 
		int bitmask; 
 
		for(bitmask = TOP_BITMASK;bitmask>=1;bitmask>>=1) { 
			for(i=0;iw->stopline < 0 ) encoder->w->stopline = INT_MAX; 
 
	free(leaves); 
} 
 
void decodeSubbands(coder * decoder,subband * root) 
{ 
subband_leaf ** leaves; 
int nLeaves,i; 
 
	initActivityRLE(); 
	getActivities(decoder,root); 
 
	nLeaves = countLeaves(root); 
 
	if ( (leaves = malloc(sizeofpointer*nLeaves)) == NULL ) 
		errexit("can't alloc leaves"); 
 
	i = 0; 
	readInLeaves(root,leaves,&i); 
 
	sortLeaves(leaves,nLeaves); 
 
	arithRLEinit(); 
 
	if ( decoder->decodeBand ) { 
		for(i=0;idecodeBandBP || decoder->decodeSubbandBP ) { 
		int bitmask; 
 
		for(bitmask = TOP_BITMASK;bitmask>=1;bitmask>>=1) { 
			for(i=0;iband; 
	for(y=0; y<(sbl->height);y++) { 
		for(x=0; x<(sbl->width);x++) { 
			z = *bp++; z=abs(z); z = min(z,0xFF); 
			cnts[z]++; 
		} 
		bp += sbl->rowpad; 
	} 
	 
	ret = 0; y = (sbl->width) * (sbl->height); 
	for(x=0;x<256;x++) { 
		z = cnts[x]; 
		if ( z && x ) { 
			ret += z * intlog2x16(y/z); 
			ret += intlog2x16(z);	//bits to send that prob. 
		} 
	} 
	ret /= y; 
 
return ret; 
} 
 
int subbandDeltaO0Entropy(subband_leaf *sbl) 
{ 
int *bp,x,y,z,fullw,ret,pred; 
int cnts[256]; 
 
	memclear(cnts,sizeof(int)*256); 
 
	bp = sbl->band; fullw = sbl->width + sbl->rowpad; 
	for(y=0; y<(sbl->height);y++) { 
		for(x=0; x<(sbl->width);x++) { 
			z = *bp; 
			if ( x && y ) pred = (bp[-1] + bp[-fullw])>>1; 
			else if ( x ) pred = bp[-1]; 
			else if ( y ) pred = bp[-fullw]; 
			else pred = 0; 
			bp++; 
			z = abs(z - pred); z = min(z,0xFF); 
			cnts[z]++; 
		} 
		bp += sbl->rowpad; 
	} 
	 
	ret = 0; y = (sbl->width) * (sbl->height); 
	for(x=0;x<256;x++) { 
		z = cnts[x]; 
		if ( z && x ) {	// doesn't count cost of sending zeros 
			ret += z * intlog2x16(y/z); 
			ret += intlog2x16(z);	//bits to send that prob. 
		} 
	} 
	ret /= y; 
 
return ret; 
} 
 
/** <> the transform seems *awfully* sensitive to these 
*		parameters; on "tile1" we go from 3.432 to 3.8 to 4.5 bpp ! 
***/ 
 
#define MAX_QUANT	2 
#define MAX_SHIFT 	6 
#define MAX 		(1<band; fullw = sbl->width + sbl->rowpad; 
	for(y=0; y<(sbl->height);y++) { 
		for(x=0; x<(sbl->width);x++) { 
			z = abs(*bp); 
			if ( x && y ) pred = (abs(bp[-1]) + abs(bp[-fullw]))>>1; 
			else if ( x ) pred = abs(bp[-1]); 
			else if ( y ) pred = abs(bp[-fullw]); 
			else pred = 0; 
			bp++; 
			z >>= MAX_QUANT; pred >>= MAX_QUANT; 
			z = min(z,MAX_MASK);	pred = min(pred,MAX_MASK); 
 
			i = z + (pred< 1 ) { 
					escs[pred]--; tots[pred]--; 
				} 
			} else { 
				ret -= intlog2x16(escs[pred]); 
				ret += intlog2x16(z+1) + 1; 
				escs[pred]++; tots[pred]++; 
			} 
			 
			cnts[i]++; 
			tots[pred]++; 
		} 
		bp += sbl->rowpad; 
	} 
 
	ret /= (sbl->height)*(sbl->width); 
 
return ret; 
} 
 
void activitySubbands(subband * sb) 
{ 
	if ( !sb ) return; 
	if ( sb->leaf ) { 
		subband_leaf *sbl; 
		int *bp,x,y,z; 
		sbl = (subband_leaf *) sb; 
 
		bp = sbl->band; 
		sbl->max_value = sbl->activity = 0; 
		for(y=0; y<(sbl->height);y++) { 
			for(x=0; x<(sbl->width);x++) { 
				z = *bp++; if ( z < 0 ) z = -z; 
				if ( z > sbl->max_value ) sbl->max_value = z; 
				if ( z ) sbl->activity ++; 
			} 
			bp += sbl->rowpad; 
		} 
 
#if 0 
		sbl->activity = (sbl->activity << 6) / ((sbl->height)*(sbl->width)); 
#else 
		sbl->activity = subbandO1Entropy(sbl); 
#endif 
 
		return; 
	} { 
		subband_node *sbn; 
		int num; 
		sbn = (subband_node *) sb; 
		sbn->activity = sbn->max_value = 0; num = 0; 
		if ( sbn->LL ) { activitySubbands(sbn->LL); sbn->activity += sbn->LL->activity; sbn->max_value = max(sbn->max_value,sbn->LL->max_value); num++; }  
		if ( sbn->LH ) { activitySubbands(sbn->LH); sbn->activity += sbn->LH->activity; sbn->max_value = max(sbn->max_value,sbn->LH->max_value); num++; }  
		if ( sbn->HL ) { activitySubbands(sbn->HL); sbn->activity += sbn->HL->activity; sbn->max_value = max(sbn->max_value,sbn->HL->max_value); num++; }  
		if ( sbn->HH ) { activitySubbands(sbn->HH); sbn->activity += sbn->HH->activity; sbn->max_value = max(sbn->max_value,sbn->HH->max_value); num++; } 
		if ( num ) sbn->activity /= num; 
	} 
} 
 
static int last_activity; 
 
void initActivityRLE(void) { 
	last_activity = 0; 
} 
 
void sendActivities(coder * encoder,subband * sb) 
{ 
	if ( !sb ) return; 
	if ( sb->leaf ) { 
		subband_leaf *sbl; 
		sbl = (subband_leaf *) sb; 
 
		cu_putExpandingSigned_ari(sbl->activity - last_activity,encoder->arith,30,30); 
		last_activity = sbl->activity; 
 
		return; 
	} { 
		subband_node *sbn; 
		sbn = (subband_node *) sb; 
		if ( sbn->LL ) sendActivities(encoder,sbn->LL); 
		if ( sbn->LH ) sendActivities(encoder,sbn->LH); 
		if ( sbn->HL ) sendActivities(encoder,sbn->HL); 
		if ( sbn->HH ) sendActivities(encoder,sbn->HH); 
	} 
} 
 
void getActivities(coder * decoder,subband * sb) 
{ 
	if ( !sb ) return; 
	if ( sb->leaf ) { 
		subband_leaf *sbl; 
		sbl = (subband_leaf *) sb; 
 
		sbl->activity = cu_getExpandingSigned_ari(decoder->arith,30,30) + last_activity; 
		last_activity = sbl->activity; 
 
		sbl->max_value = 0; 
 
		return; 
	} { 
		subband_node *sbn; 
		sbn = (subband_node *) sb; 
		sbn->activity = 0; 
		if ( sbn->LL ) { getActivities(decoder,sbn->LL); sbn->activity += sbn->LL->activity; } 
		if ( sbn->LH ) { getActivities(decoder,sbn->LH); sbn->activity += sbn->LH->activity; } 
		if ( sbn->HL ) { getActivities(decoder,sbn->HL); sbn->activity += sbn->HL->activity; } 
		if ( sbn->HH ) { getActivities(decoder,sbn->HH); sbn->activity += sbn->HH->activity; } 
		sbn->max_value = 0; 
	} 
} 
 
void transposeSubbandLHs(subband *sb) 
{ 
	if ( !sb || sb->leaf ) return; 
	transposeSubbandLHs(sb->LL); 
	transposeSubbandLHs(sb->LH); 
	transposeSubbandLHs(sb->HL); 
	transposeSubbandLHs(sb->HH); 
	if ( sb->LH && sb->LH->leaf ) { 
		subband_leaf * sbl = sb->LH; 
		int *pa,*pb,x,y,z,fullw; 
		fullw = sbl->width + sbl->rowpad; 
		for(y=0;y< (sbl->height);y++) { 
			pa = pb = (sbl->band) + y*(fullw + 1); 
			for(x=y+1;x< (sbl->width);x++) { 
				pa ++;	pb += fullw; 
				z	= *pa; 
				*pa = *pb; 
				*pb = z; 
			} 
		} 
		sbl->transposed = true; 
	} 
} 
 
subband * imageToSubbands(image *im,int levels) 
{ 
int p; 
	assert( im->planes <= 4 ); 
	p = im->planes; 
	if ( p == 1 )  
		return makeSubbandQuad(im->data[0][0],im->width,im->height,im->width,levels-1,NULL); 
	else { 
		subband_node *sbn; 
		sbn = new_subband_node(); 
		if ( p >= 1 ) sbn->LL = makeSubbandQuad(im->data[0][0],im->width,im->height,im->width,levels-1,NULL); 
		if ( p >= 2 ) sbn->LH = makeSubbandQuad(im->data[1][0],im->width,im->height,im->width,levels-1,NULL); 
		if ( p >= 3 ) sbn->HL = makeSubbandQuad(im->data[2][0],im->width,im->height,im->width,levels-1,NULL); 
		if ( p >= 4 ) sbn->HH = makeSubbandQuad(im->data[3][0],im->width,im->height,im->width,levels-1,NULL); 
		return (subband *)sbn; 
	} 
} 
 
subband * makeSubbandQuad(int *band,int w,int h,int fullw,int levels,subband_node *higher) 
{ 
subband_leaf *LH,*HL,*HH; 
subband_node *sbn; 
 
	sbn = new_subband_node_foliated();	 
	sbn->prev = higher; 
	sbn->width = w; 
	sbn->height = h; 
    sbn->rowpad = fullw - w; 
 
	w >>= 1; h >>= 1; 
 
	HL = sbn->HL; 
	LH = sbn->LH; 
	HH = sbn->HH; 
 
    HL->width = w; 
    HL->height =h; 
    HL->rowpad = fullw - w; 
    HL->band = band + w; 
 
    LH->width = w; 
    LH->height =h; 
    LH->rowpad = fullw - w; 
    LH->band = band + h*fullw; 
 
	LH->transposed = true;	// we called transposeLHs earlier 
			/* <> should be set when the subbands are built, 
			*		when we do the actual transpose 
			*	there's a trouble here for the decoder, because he must know 
			*		"transposed?" before actually doing it; this bit must be sent, 
			*		unless we hard-code it to the LH (which isn't terrible) 
			*/ 
 
    HH->width = w; 
    HH->height =h; 
    HH->rowpad = fullw - w; 
    HH->band = LH->band + w; 
 
	if ( levels ) { 
		sbn->LL = makeSubbandQuad(band,w,h,fullw,levels-1,sbn); 
	} else { 
		subband_leaf *sbl; 
		// this is the LL band : 
 
		sbn->LL = sbl = new_subband_leaf(); 
		sbl->prev = sbn; 
		sbl->width = w; 
		sbl->height =h; 
		sbl->rowpad = fullw - w; 
		sbl->band = band; 
	} 
 
	sbn->LL->type = TYPE_LL; 
	sbn->LH->type = TYPE_LH; 
	sbn->HL->type = TYPE_HL; 
	sbn->HH->type = TYPE_HH; 
 
return sbn; 
} 
 
subband_node *new_subband_node() 
{ 
subband_node *ret; 
	if ( (ret = new(subband_node)) == NULL ) errexit("malloc subband failed"); 
	ret->leaf = false; 
return ret; 
} 
 
subband_node *new_subband_node_foliated() 
{ 
subband_node *ret; 
	if ( (ret = new(subband_node)) == NULL ) errexit("malloc subband failed"); 
	ret->leaf = false; 
	ret->LH = new_subband_leaf(); 
	ret->LH->prev = ret; 
	ret->HL = new_subband_leaf(); 
	ret->HL->prev = ret; 
	ret->HH = new_subband_leaf(); 
	ret->HH->prev = ret; 
return ret; 
} 
subband_leaf *new_subband_leaf() 
{ 
subband_leaf *ret; 
	if ( (ret = new(subband_leaf)) == NULL ) errexit("malloc subband failed"); 
	ret->leaf = true; 
return ret; 
} 
 
void freeSubbands(subband *root) 
{ 
	if ( ! root ) return; 
	if ( ! root->leaf ) { 
		subband_node *node = root; 
		freeSubbands(node->LL); 
		freeSubbands(node->LH); 
		freeSubbands(node->HL); 
		freeSubbands(node->HH); 
	} 
	free(root); 
} 
 
/***********************************************************/ 
 
static bool rle_last_bit; 
 
#define RLE_BIT_TOT	8192 
#define RLE_BIT_MID	358 
 
void arithRLEinit(void) 
{ 
rle_last_bit = 0; 
} 
 
void arithBitRLE(arithInfo * ari,bool bit) 
{ 
	bit = bit?1:0; 
	arithEncBit(ari,RLE_BIT_MID,RLE_BIT_TOT,( bit == rle_last_bit )?1:0); 
	rle_last_bit = bit; 
} 
 
bool arithGetBitRLE(arithInfo * ari) 
{ 
bool bit; 
	bit = arithDecBit(ari,RLE_BIT_MID,RLE_BIT_TOT); 
	if ( ! bit ) rle_last_bit ^= 1; 
 
return rle_last_bit; 
} 
 
/***********************************************************/ 
 
#define tabdepth(fp,depth) do { int i; for(i=0;ileaf ) { 
		subband_leaf *sbl = sb; 
		//tabdepth(fp,depth);  
		fprintf(fp,"%08X ; prev = %08X , parent = %08X\n",sbl,sbl->prev,sbl->parent); 
		tabdepth(fp,depth); fprintf(fp,"%dx%d",sbl->width,sbl->height); 
		if ( sbl->prev ) fprintf(fp," prev = %dx%d ",sbl->prev->width,sbl->prev->height); 
		if ( sbl->parent ) fprintf(fp," parent = %dx%d ",sbl->parent->width,sbl->parent->height); 
		fprintf(fp,"\n"); 
		tabdepth(fp,depth); fprintf(fp,"act = %d, max = %d, type = %d",sbl->activity,sbl->max_value,sbl->type); 
		if ( sbl->transposed ) fprintf(fp," transposed");	 
		fprintf(fp,"\n"); 
		 
	} else { 
		fprintf(fp,"%08X ; prev = %08X\n",sb,sb->prev); 
		if ( sb->LL ) { depthputs(fp,"LL:",depth); printSubbandInfo(sb->LL,fp,depth+1); } 
		if ( sb->LH ) { depthputs(fp,"LH:",depth); printSubbandInfo(sb->LH,fp,depth+1); } 
		if ( sb->HL ) { depthputs(fp,"HL:",depth); printSubbandInfo(sb->HL,fp,depth+1); } 
		if ( sb->HH ) { depthputs(fp,"HH:",depth); printSubbandInfo(sb->HH,fp,depth+1); } 
	} 
} 
 
subband_leaf * LLleaf(subband *sb) 
{ 
	while ( ! sb->leaf ) sb = sb->LL; 
	return sb; 
} 
 
 
subband_leaf * seekLeaf(subband_leaf **leaves,int num,int w,int type) 
{ 
subband_leaf * vs; 
int j; 
	for(j=num-1;j>=0;j--) { 
		vs = leaves[j]; 
		if ( vs->width == w && vs->type == type ) 
			return vs; 
	} 
return NULL; 
} 
subband * seekNode(subband_leaf **leaves,int num,int w,int type) 
{ 
subband * vs; 
int j; 
	for(j=num-1;j>=0;j--) { 
		vs = leaves[j]; 
		while(vs = vs->prev) { 
			if ( vs->width == w && vs->type == type ) 
				return vs; 
		} 
	} 
return NULL; 
} 
 
subband_leaf * seekLeafByType(subband_leaf **leaves,int num,int w,int type) 
{ 
int j; 
subband_leaf * ret; 
	j = type; 
	if ( j == TYPE_LL ) j = TYPE_HH; 
	 
	if ( ret = seekLeaf(leaves,num,w,j) ) return ret; 
	if ( (++j) == 4 ) j = 0; 
	if ( ret = seekLeaf(leaves,num,w,j) ) return ret; 
	if ( (++j) == 4 ) j = 0; 
	if ( ret = seekLeaf(leaves,num,w,j) ) return ret; 
	if ( (++j) == 4 ) j = 0; 
	if ( ret = seekLeaf(leaves,num,w,j) ) return ret; 
return NULL; 
} 
 
subband * seekNodeByType(subband_leaf **leaves,int num,int w,int type) 
{ 
int j; 
subband_leaf * ret; 
	j = type; 
	if ( j == TYPE_LL ) j = TYPE_HH; 
	 
	if ( ret = seekNode(leaves,num,w,j) ) return ret; 
	if ( (++j) == 4 ) j = 0; 
	if ( ret = seekNode(leaves,num,w,j) ) return ret; 
	if ( (++j) == 4 ) j = 0; 
	if ( ret = seekNode(leaves,num,w,j) ) return ret; 
	if ( (++j) == 4 ) j = 0; 
	if ( ret = seekNode(leaves,num,w,j) ) return ret; 
return NULL; 
}