www.pudn.com > xiaobo.zip.zip > codezt.c
// <> "stop" functionality needed //#define WRITE_ZT #define WRITE_ZT_PLANE 7 #include#include #include #include #include #include #include "coder.h" #include "image.h" #define SIGN_CONTEXTS 4 #define TOTMAX 4000 #define INC 30 #define bitModel(bit,P0,PT) do { PT += INC; if (!(bit)) P0 += INC; if ( PT > TOTMAX ) { PT >>= 1; P0 >>= 1; P0++; PT += 2; } } while(0) #define bitEnc(bit,ari,P0,PT) do { arithEncBit(ari,P0,PT,bit); bitModel(bit,P0,PT); } while(0) #define bitDec(bit,ari,P0,PT) do { bit = arithDecBit(ari,P0,PT); bitModel(bit,P0,PT); } while(0) typedef struct { arithInfo *ari; int signs_p0[SIGN_CONTEXTS],signs_pt[SIGN_CONTEXTS]; } signInfo; void * initSigns(arithInfo *ari); void freeSigns(void *sign_coder); void encodeSigns(signInfo *me,int *band,int w,int h,int fullw,int *parent); void decodeSigns(signInfo *me,int *band,int w,int h,int fullw,int *parent); void * initSigns(arithInfo *ari) { signInfo *d; int i; if ( (d = new(signInfo)) == NULL ) errexit("ozero init failed"); d->ari = ari; for(i=0;i signs_p0[i] = 100; d->signs_pt[i] = 200; } return d; } void freeSigns(signInfo *d) { if ( d ) { free(d); } } void encodeSigns(signInfo *me,int *band,int width,int height,int fullw,int *parent) { int x,y,context; //,V; int *dp; arithInfo *ari; int *signs_p0,*signs_pt; ari = me->ari; signs_p0 = me->signs_p0; signs_pt = me->signs_pt; dp = band; for(x=0;x ari; signs_p0 = me->signs_p0; signs_pt = me->signs_pt; dp = band; for(x=0;x width; for(p=0;p planes;p++) { for(l=1;l width) >>l; h = (im->height)>>l; wt = w>>1; ht = h>>1; fmband = im->data[p][h *offy] + w *offx; toband = im->data[p][ht*offy] + wt*offx; fmp = fmband; top = toband; for(y=0;y encodeBandZT ) errexit("don't call imageZT unless you mean it!"); top_val = 0; for(p=0;p planes;p++) { rows = im->data[p]; /** global pre-pass : remove signs & find top_val **/ sizeX = (im->width) >> levels; sizeY = (im->height) >> levels; for(y=0;y<(im->height);y++) { dp = rows[y]; if ( y < sizeY ) { x = sizeX; dp += sizeX; } else x = 0; for(;x<(im->width);x++) { if ( isneg(*dp) ) *dp = 1 - (*dp + *dp); else *dp += *dp; if ( *dp > top_val ) top_val = *dp; dp++; } } } for(top_bitpn=0;(1<<(top_bitpn+1))<=top_val;top_bitpn++) ; cu_putExpanding_ari(top_bitpn,encoder->arith,16,8); for(bits = top_bitpn;bits>=1;bits--) { findZeroTrees(im,bits,levels,1,0); findZeroTrees(im,bits,levels,0,1); findZeroTrees(im,bits,levels,1,1); #ifdef WRITE_ZT if ( bits == WRITE_ZT_PLANE ) { /** write out a zero tree map **/ image *zt_im; int r,*ptr,bitmask; zt_im = copyImage(im); for(p=0;p>im->planes;p++) { ptr = zt_im->data[p][0][0]; bitmask = 1< plane_size;r--;) { if ( *ptr & bitmask ) *ptr++ = 255; else { *ptr = ((*ptr>>(CODE_MAX_BPN+1))<<6); ptr++; } /** 256 is on 128 is isolated 64 is child 0 is root ****/ ptr[-1] -= 0x80; } } writeImageFile("zerotree.raw",zt_im); freeImage(zt_im); } #endif /** end zero-tree writing **/ for (l = levels; l > 0; l--) { sizeX = (im->width) >> l; sizeY = (im->height) >> l; for(p=0;p planes;p++) { rows = im->data[p]; encoder->encodeBandZT(encoder,rows[0] + sizeX, sizeX, sizeY,bits,im->width,rows); encoder->encodeBandZT(encoder,rows[sizeY], sizeX, sizeY,bits,im->width,rows); encoder->encodeBandZT(encoder,rows[sizeY]+sizeX,sizeX, sizeY,bits,im->width,rows); } } } sign_coder = initSigns(encoder->arith); for(p=0;p planes;p++) { rows = im->data[p]; for (l = levels; l > 0; l--) { sizeX = (im->width) >> l; sizeY = (im->height) >> l; encodeSigns(sign_coder,rows[0] + sizeX , sizeX, sizeY, im->width,rows[0] + (sizeX>>1)); encodeSigns(sign_coder,rows[sizeY] , sizeX, sizeY, im->width,rows[(sizeY>>1)]); encodeSigns(sign_coder,rows[sizeY]+sizeX, sizeX, sizeY, im->width,rows[(sizeY>>1)]+ (sizeX>>1)); } } freeSigns(sign_coder); } void decodeImageZT(coder * decoder,image *im,int levels) { int l,sizeX,sizeY,x,y,*dp; int **rows; int top_bitpn,bits,p; void *sign_coder; top_bitpn = cu_getExpanding_ari(decoder->arith,16,8); for(bits = top_bitpn;bits>=1;bits--) { for (l = levels; l > 0; l--) { for(p=0;p planes;p++) { rows = im->data[p]; sizeX = (im->width) >> l; sizeY = (im->height) >> l; decoder->decodeBandZT(decoder,rows[0] + sizeX, sizeX, sizeY,bits,im->width,rows); decoder->decodeBandZT(decoder,rows[sizeY], sizeX, sizeY,bits,im->width,rows); decoder->decodeBandZT(decoder,rows[sizeY]+sizeX,sizeX, sizeY,bits,im->width,rows); } } } sign_coder = initSigns(decoder->arith); for(p=0;p planes;p++) { rows = im->data[p]; for (l = levels; l > 0; l--) { sizeX = (im->width) >> l; sizeY = (im->height) >> l; decodeSigns(sign_coder,rows[0] + sizeX , sizeX, sizeY, im->width,rows[0] + (sizeX>>1)); decodeSigns(sign_coder,rows[sizeY] , sizeX, sizeY, im->width,rows[(sizeY>>1)]); decodeSigns(sign_coder,rows[sizeY]+sizeX, sizeX, sizeY, im->width,rows[(sizeY>>1)]+ (sizeX>>1)); } } freeSigns(sign_coder); /** global post-pass : restore signs * (<> decodeSigns could do this for us, but that would require him to * do an if() when he builds contexts) **/ for(p=0;p planes;p++) { rows = im->data[p]; sizeX = (im->width) >> levels; sizeY = (im->height) >> levels; for(y=0;y height;y++) { dp = rows[y]; if ( y < sizeY ) { x = sizeX; dp += sizeX; } else x = 0; for(;x width;x++) { if ( *dp & 1 ) *dp++ = - ((*dp)>>1); else *dp++ >>= 1; } } } }