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;i parent == 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;i parent = 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;i encodeBandBP || encoder->encodeSubbandBP ) { int bitmask; for(bitmask = TOP_BITMASK;bitmask>=1;bitmask>>=1) { for(i=0;i w->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;i decodeBandBP || decoder->decodeSubbandBP ) { int bitmask; for(bitmask = TOP_BITMASK;bitmask>=1;bitmask>>=1) { for(i=0;i band; 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;i leaf ) { 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; }