www.pudn.com > sfalic-03-src.rar.rar > cdfpred.c
#include "cdftypes.h" #include "cdfpred.h" #include "bppmask.h" #include "assert.h" #include/* zwroc mediane */ #define MEDIAN(A, B, C) \ ( (B)>=(C) ? \ (C)>=(A) ? (C) : (A)>=(B) ? (B) : (A) : \ (C)<=(A) ? (C) : (A)<=(B) ? (B) : (A) \ ) \ /* automatyczne tlumaczenie rozkladu U na L, wypelniane przez decorelateinit() dla 8bpp i mniej*/ static unsigned int xlatU2L[256]; /* kompresja kodu zrodlowego */ #define PIXEL_A ((unsigned int)currow[i-1]) #define PIXEL_B ((unsigned int)prevrow[i]) #define PIXEL_C ((unsigned int)prevrow[i-1]) /* pomocnicze do dekorelowania pojedynczych pikseli */ /* 0 */ static void decorelate_onepixel_0(const PIXEL * const currow, PIXEL * const decorelatedrow, const unsigned int pixelbitmask) { const unsigned int s=*currow; if (s<=(pixelbitmask>>1)) *decorelatedrow=s<<1; else *decorelatedrow=((pixelbitmask-s)<<1)+1; } static void decorelate_onepixel_0_8bpp(const BYTE * const currow, BYTE * const decorelatedrow, const unsigned int pixelbitmask) { const unsigned int s=*currow; *decorelatedrow=xlatU2L[s]; } static void decorelate_onepixel_2(const PIXEL * const prevrow, const PIXEL * const currow, PIXEL * const decorelatedrow, const unsigned int pixelbitmask) { const unsigned int s=(unsigned)( (int)(*currow) - (int)(*prevrow) ) & pixelbitmask; if (s<=(pixelbitmask>>1)) *decorelatedrow=s<<1; else *decorelatedrow=((pixelbitmask-s)<<1)+1; } static void decorelate_onepixel_2_8bpp(const BYTE * const prevrow, const BYTE * const currow, BYTE * const decorelatedrow, const unsigned int pixelbitmask) { const unsigned int s=(unsigned)( (int)(*currow) - (int)(*prevrow) ) & pixelbitmask; *decorelatedrow=xlatU2L[s]; } /* dekorelowanie calych wierszy */ /* 0 */ static void decorelate_0(const PIXEL currow[], const unsigned int rowlen, const int bpp, PIXEL decorelatedrow[]) { const unsigned int pixelbitmask=bppmask[bpp]; const unsigned int pixelbitmaskshr=pixelbitmask>>1; unsigned int i; for (i=0; i >1; unsigned int i; for (i=0; i >1; unsigned int i; assert(rowlen); // osobne wywolanie dla pierwszego piksela, bo on nie ma lewego sasiada i komplikowalby ponizsza petle - nie daloby sie zrobic unrolling decorelate_onepixel_0(currow, decorelatedrow, pixelbitmask); for (i=1; i >1; unsigned int i; assert(rowlen); // osobne wywolanie dla pierwszego piksela, bo on nie ma lewego sasiada i komplikowalby ponizsza petle - nie daloby sie zrobic unrolling decorelate_onepixel_0_8bpp(currow, decorelatedrow, pixelbitmask); for (i=1; i >1; unsigned int i; for (i=0; i >1; unsigned int i; for (i=0; i >1; unsigned int i; assert(rowlen); // osobne wywolanie dla pierwszego piksela, bo on nie ma lewego sasiada i komplikowalby ponizsza petle - nie daloby sie zrobic unrolling decorelate_onepixel_2(prevrow, currow, decorelatedrow, pixelbitmask); for (i=1; i >1; unsigned int i; assert(rowlen); // osobne wywolanie dla pierwszego piksela, bo on nie ma lewego sasiada i komplikowalby ponizsza petle - nie daloby sie zrobic unrolling decorelate_onepixel_2_8bpp(prevrow, currow, decorelatedrow, pixelbitmask); for (i=1; i >1; unsigned int i; assert(rowlen); // osobne wywolanie dla pierwszego piksela, bo on nie ma lewego sasiada i komplikowalby ponizsza petle - nie daloby sie zrobic unrolling decorelate_onepixel_2(prevrow, currow, decorelatedrow, pixelbitmask); for (i=1; i pixelbitmask) p=pixelbitmask; { const unsigned int s=(unsigned)( (int)currow[i] - p ) & pixelbitmask; if (s<=pixelbitmaskshr) decorelatedrow[i]=s<<1; else decorelatedrow[i]=((pixelbitmask-s)<<1)+1; } } } static void decorelate_4_8bpp(const BYTE prevrow[], const BYTE currow[], const unsigned int rowlen, const int bpp, BYTE decorelatedrow[]) { const unsigned int pixelbitmask=bppmask[bpp]; const unsigned int pixelbitmaskshr=pixelbitmask>>1; unsigned int i; assert(rowlen); // osobne wywolanie dla pierwszego piksela, bo on nie ma lewego sasiada i komplikowalby ponizsza petle - nie daloby sie zrobic unrolling decorelate_onepixel_2_8bpp(prevrow, currow, decorelatedrow, pixelbitmask); for (i=1; i pixelbitmask) p=pixelbitmask; { const unsigned int s=(unsigned)( (int)currow[i] - p ) & pixelbitmask; decorelatedrow[i]=xlatU2L[s]; } } } /* a+(b-c)/2 */ static void decorelate_5(const PIXEL prevrow[], const PIXEL currow[], const unsigned int rowlen, const int bpp, PIXEL decorelatedrow[]) { const unsigned int pixelbitmask=bppmask[bpp]; const unsigned int pixelbitmaskshr=pixelbitmask>>1; unsigned int i; assert(rowlen); // osobne wywolanie dla pierwszego piksela, bo on nie ma lewego sasiada i komplikowalby ponizsza petle - nie daloby sie zrobic unrolling decorelate_onepixel_2(prevrow, currow, decorelatedrow, pixelbitmask); for (i=1; i >1) ) ; if (p<0) p=0; else if ((unsigned)p>pixelbitmask) p=pixelbitmask; { const unsigned int s=(unsigned)( (int)currow[i] - p ) & pixelbitmask; if (s<=pixelbitmaskshr) decorelatedrow[i]=s<<1; else decorelatedrow[i]=((pixelbitmask-s)<<1)+1; } } } static void decorelate_5_8bpp(const BYTE prevrow[], const BYTE currow[], const unsigned int rowlen, const int bpp, BYTE decorelatedrow[]) { const unsigned int pixelbitmask=bppmask[bpp]; const unsigned int pixelbitmaskshr=pixelbitmask>>1; unsigned int i; assert(rowlen); // osobne wywolanie dla pierwszego piksela, bo on nie ma lewego sasiada i komplikowalby ponizsza petle - nie daloby sie zrobic unrolling decorelate_onepixel_2_8bpp(prevrow, currow, decorelatedrow, pixelbitmask); for (i=1; i >1) ) ; if (p<0) p=0; else if ((unsigned)p>pixelbitmask) p=pixelbitmask; { const unsigned int s=(unsigned)( (int)currow[i] - p ) & pixelbitmask; decorelatedrow[i]=xlatU2L[s]; } } } /* b+(a-c)/2 */ static void decorelate_6(const PIXEL prevrow[], const PIXEL currow[], const unsigned int rowlen, const int bpp, PIXEL decorelatedrow[]) { const unsigned int pixelbitmask=bppmask[bpp]; const unsigned int pixelbitmaskshr=pixelbitmask>>1; unsigned int i; assert(rowlen); // osobne wywolanie dla pierwszego piksela, bo on nie ma lewego sasiada i komplikowalby ponizsza petle - nie daloby sie zrobic unrolling decorelate_onepixel_2(prevrow, currow, decorelatedrow, pixelbitmask); for (i=1; i >1) ); if (p<0) p=0; else if ((unsigned)p>pixelbitmask) p=pixelbitmask; { const unsigned int s=(unsigned)( (int)currow[i] - p ) & pixelbitmask; if (s<=pixelbitmaskshr) decorelatedrow[i]=s<<1; else decorelatedrow[i]=((pixelbitmask-s)<<1)+1; } } } static void decorelate_6_8bpp(const BYTE prevrow[], const BYTE currow[], const unsigned int rowlen, const int bpp, BYTE decorelatedrow[]) { const unsigned int pixelbitmask=bppmask[bpp]; const unsigned int pixelbitmaskshr=pixelbitmask>>1; unsigned int i; assert(rowlen); // osobne wywolanie dla pierwszego piksela, bo on nie ma lewego sasiada i komplikowalby ponizsza petle - nie daloby sie zrobic unrolling decorelate_onepixel_2_8bpp(prevrow, currow, decorelatedrow, pixelbitmask); for (i=1; i >1) ); if (p<0) p=0; else if ((unsigned)p>pixelbitmask) p=pixelbitmask; { const unsigned int s=(unsigned)( (int)currow[i] - p ) & pixelbitmask; decorelatedrow[i]=xlatU2L[s]; } } } /* (a+b)/2 */ static void decorelate_7(const PIXEL prevrow[], const PIXEL currow[], const unsigned int rowlen, const int bpp, PIXEL decorelatedrow[]) { const unsigned int pixelbitmask=bppmask[bpp]; const unsigned int pixelbitmaskshr=pixelbitmask>>1; unsigned int i; assert(rowlen); // osobne wywolanie dla pierwszego piksela, bo on nie ma lewego sasiada i komplikowalby ponizsza petle - nie daloby sie zrobic unrolling decorelate_onepixel_2(prevrow, currow, decorelatedrow, pixelbitmask); for (i=1; i >1) ) & pixelbitmask; if (s<=pixelbitmaskshr) decorelatedrow[i]=s<<1; else decorelatedrow[i]=((pixelbitmask-s)<<1)+1; } } static void decorelate_7_8bpp(const BYTE prevrow[], const BYTE currow[], const unsigned int rowlen, const int bpp, BYTE decorelatedrow[]) { const unsigned int pixelbitmask=bppmask[bpp]; const unsigned int pixelbitmaskshr=pixelbitmask>>1; unsigned int i; assert(rowlen); // osobne wywolanie dla pierwszego piksela, bo on nie ma lewego sasiada i komplikowalby ponizsza petle - nie daloby sie zrobic unrolling decorelate_onepixel_2_8bpp(prevrow, currow, decorelatedrow, pixelbitmask); for (i=1; i >1) ) & pixelbitmask; decorelatedrow[i]=xlatU2L[s]; } } /* .75a+.75b-.5c */ static void decorelate_8(const PIXEL prevrow[], const PIXEL currow[], const unsigned int rowlen, const int bpp, PIXEL decorelatedrow[]) { const unsigned int pixelbitmask=bppmask[bpp]; const unsigned int pixelbitmaskshr=pixelbitmask>>1; unsigned int i; assert(rowlen); // osobne wywolanie dla pierwszego piksela, bo on nie ma lewego sasiada i komplikowalby ponizsza petle - nie daloby sie zrobic unrolling decorelate_onepixel_2(prevrow, currow, decorelatedrow, pixelbitmask); for (i=1; i >2 ; if (p<0) p=0; else if ((unsigned)p>pixelbitmask) p=pixelbitmask; { const unsigned int s=(unsigned)( (int)currow[i] - p ) & pixelbitmask; if (s<=pixelbitmaskshr) decorelatedrow[i]=s<<1; else decorelatedrow[i]=((pixelbitmask-s)<<1)+1; } } } static void decorelate_8_8bpp(const BYTE prevrow[], const BYTE currow[], const unsigned int rowlen, const int bpp, BYTE decorelatedrow[]) { const unsigned int pixelbitmask=bppmask[bpp]; const unsigned int pixelbitmaskshr=pixelbitmask>>1; unsigned int i; assert(rowlen); // osobne wywolanie dla pierwszego piksela, bo on nie ma lewego sasiada i komplikowalby ponizsza petle - nie daloby sie zrobic unrolling decorelate_onepixel_2_8bpp(prevrow, currow, decorelatedrow, pixelbitmask); for (i=1; i >2 ; if (p<0) p=0; else if ((unsigned)p>pixelbitmask) p=pixelbitmask; { const unsigned int s=(unsigned)( (int)currow[i] - p ) & pixelbitmask; decorelatedrow[i]=xlatU2L[s]; } } } /* median(a, b, c) */ static void decorelate_9(const PIXEL prevrow[], const PIXEL currow[], const unsigned int rowlen, const int bpp, PIXEL decorelatedrow[]) { const unsigned int pixelbitmask=bppmask[bpp]; const unsigned int pixelbitmaskshr=pixelbitmask>>1; unsigned int i; assert(rowlen); // osobne wywolanie dla pierwszego piksela, bo on nie ma lewego sasiada i komplikowalby ponizsza petle - nie daloby sie zrobic unrolling decorelate_onepixel_2(prevrow, currow, decorelatedrow, pixelbitmask); for (i=1; i >1; unsigned int i; assert(rowlen); // osobne wywolanie dla pierwszego piksela, bo on nie ma lewego sasiada i komplikowalby ponizsza petle - nie daloby sie zrobic unrolling decorelate_onepixel_2_8bpp(prevrow, currow, decorelatedrow, pixelbitmask); for (i=1; i =MINpred); assert(rowlen>0); assert(row>=0); if (pred==-1) /* copy */ { memcpy(decorelatedrow, currow, sizeof(PIXEL)*rowlen); return; } if (row==0 && pred!=0) /* dla wiersza zerowego wszystkie predyktory, oprocz 0, przechodza w 1 */ pred=1; switch (pred) { case 0: decorelate_0(currow, rowlen, bpp, decorelatedrow); return; case 1: decorelate_1(currow, rowlen, bpp, decorelatedrow); return; case 2: decorelate_2(prevrow, currow, rowlen, bpp, decorelatedrow); return; case 3: decorelate_3(prevrow, currow, rowlen, bpp, decorelatedrow); return; case 4: decorelate_4(prevrow, currow, rowlen, bpp, decorelatedrow); return; case 5: decorelate_5(prevrow, currow, rowlen, bpp, decorelatedrow); return; case 6: decorelate_6(prevrow, currow, rowlen, bpp, decorelatedrow); return; case 7: decorelate_7(prevrow, currow, rowlen, bpp, decorelatedrow); return; case 8: decorelate_8(prevrow, currow, rowlen, bpp, decorelatedrow); return; case 9: decorelate_9(prevrow, currow, rowlen, bpp, decorelatedrow); return; default: assert(0); } } void decorelaterow8bpp(const BYTE *prevrow, const BYTE *currow, int row, int rowlen, int bpp, int pred, BYTE *decorelatedrow) { assert(bpp<=8); assert(pred<=MAXpred && pred>=MINpred); assert(rowlen>0); assert(row>=0); if (pred==-1) /* copy */ { memcpy(decorelatedrow, currow, rowlen); return; } if (row==0 && pred!=0) /* dla wiersza zerowego wszystkie predyktory, oprocz 0, przechodza w 1 */ pred=1; switch (pred) { case 0: decorelate_0_8bpp(currow, rowlen, bpp, decorelatedrow); return; case 1: decorelate_1_8bpp(currow, rowlen, bpp, decorelatedrow); return; case 2: decorelate_2_8bpp(prevrow, currow, rowlen, bpp, decorelatedrow); return; case 3: decorelate_3_8bpp(prevrow, currow, rowlen, bpp, decorelatedrow); return; case 4: decorelate_4_8bpp(prevrow, currow, rowlen, bpp, decorelatedrow); return; case 5: decorelate_5_8bpp(prevrow, currow, rowlen, bpp, decorelatedrow); return; case 6: decorelate_6_8bpp(prevrow, currow, rowlen, bpp, decorelatedrow); return; case 7: decorelate_7_8bpp(prevrow, currow, rowlen, bpp, decorelatedrow); return; case 8: decorelate_8_8bpp(prevrow, currow, rowlen, bpp, decorelatedrow); return; case 9: decorelate_9_8bpp(prevrow, currow, rowlen, bpp, decorelatedrow); return; default: assert(0); } } void decorelateinit8bpp(int bpp) { const unsigned int pixelbitmask=bppmask[bpp]; const unsigned int pixelbitmaskshr=pixelbitmask>>1; unsigned int s; assert(bpp<=8); for (s=0; s<=pixelbitmask; s++) if (s<=pixelbitmaskshr) xlatU2L[s]=s<<1; else xlatU2L[s]=((pixelbitmask-s)<<1)+1; } static PIXEL xlatL2U(register PIXEL s, register const unsigned int pixelbitmask) { if (s & 0x01) return pixelbitmask-(s>>1); return s>>1; } /* do zoptymalizowania po zoptymalizowaniu decorelate_* i sprawdzeniu, ze nadal odtwarzalne przez ta funkcje */ void corelaterow(const PIXEL *prevrow, PIXEL *currow, int row, int rowlen, int bpp, int pred, const PIXEL *decorelatedrow) { int a, /*b,*/ c; /* piksele L, G, LG */ /*s,*/ /* symbol residuum */ /*p,*/ /* wartosc predyktora */ /*x;*/ /* odtworzony piksel */ unsigned int pixelbitmask; assert(pred<=MAXpred && pred>=MINpred); assert(rowlen>0); assert(row>=0); if (pred==-1) /* copy */ { while(rowlen--) *currow++=*decorelatedrow++; return; } if (row==0 && pred!=0) /* dla wiersza zerowego wszystkie predyktory, oprocz 0, przechodza w 1 */ pred=1; pixelbitmask=bppmask[bpp]; if (pred>1) a=c=*prevrow; /* 0 i 1 nie wyk. prev_row */ else a=0; while (rowlen--) { const int b=*prevrow++; int p, x; const int s=xlatL2U(*decorelatedrow++, pixelbitmask); switch (pred) { case 0: p=0; break; case 1: p=a; break; case 2: p=b; break; case 3: p=c; break; case 4: p=a+b-c; break; case 5: p=(2*a+b-c)/2; break; /* a+(b-c)/2 bylo zle !!! */ case 6: p=(2*b+a-c)/2; break; /* b+(a-c)/2 bylo zle !!! */ case 7: p=(a+b)/2; break; case 8: p=(3*a+3*b-2*c)/4; break; case 9: p=MEDIAN(a, b, c); break; default: assert(0); } if (p<0) p=0; else if ((unsigned)p>pixelbitmask) p=pixelbitmask; x=(s+p) & pixelbitmask; *currow++=(PIXEL)x; a=x; c=b; } }