cdfstat.c
来自「一个简单而且快速的无损压缩算法。包含源代码实现」· C语言 代码 · 共 710 行 · 第 1/2 页
C
710 行
/* ustawia parametry modelu: ncodes, searchstart, modelrows i finalbuckets*/
/* oraz parametry nicjalizacji modelu dla statfillstructures(): repfirst/next, mulsize i evoluted */
void findmodelparams(const int bpp, const int evol)
{
unsigned int
bsize, /* rozmiar kubelka - liczba kontekstow*/
bstart, bend, /* poczatek i koniec kubelka zakres: 0 do levels-1*/
repcntr; /* ewolucja kubelkow licznik pom. */
assert((bpp<=16) && (bpp>0));
_bpp=bpp; /* ustawione */
if (bpp>8)
ncounters=16;
else
ncounters=8;
levels=0x1<<bpp; /* ustaw levels */
b_lo_ptrs=0; /* ==0 znaczy ze jeszcze nie ustawione */
switch (evol) /* ustaw repfirst firstsize repnext mulsize */
{
case 1: /* od inicjalizacji: 1 1 1 2 2 4 4 8 8 ... */
repfirst=3; firstsize=1; repnext=2; mulsize=2; break;
case 3: /* od inicjalizacji: 1 2 4 8 16 32 64 ... */
repfirst=1; firstsize=1; repnext=1; mulsize=2; break;
case 5: /* od inicjalizacji: 1 4 16 64 256 1024 4096 16384 65536 */
repfirst=1; firstsize=1; repnext=1; mulsize=4; break;
case 6: /* od inicjalizacji: jeden kubelek bez podzialow */
repfirst=1; firstsize=levels; repnext=-1; mulsize=-1; break;
case 0: /* obsolete */
case 2: /* obsolete */
case 4: /* obsolete */
assert(0);
exitit("findmodelparams(): evol value obsolete!!!", 100);
default:
assert(0);
exitit("findmodelparams(): evol out of range!!!", 100);
}
nbuckets=0;
repcntr=repfirst+1; /* generujemy pierwszy kubelek */
bsize=firstsize;
do /* generujemy kolejne kubelki */
{
if (nbuckets) /* poczatek kubelka */
bstart=bend+1;
else
bstart=0;
if (!--repcntr) /* rozmiar kubelka */
{
repcntr=repnext;
bsize*=mulsize;
}
bend=bstart+bsize-1; /* koniec kubelka */
if (bend+bsize>=levels) /* jezeli nastepny kubelek mialbyby byc mniejszy od tego */
bend=levels-1; /* to je polacz */
if (!b_lo_ptrs) /* jeszcze nie ustalono dlugosci tablic indeksow? */
{
if (bend==levels-1) /* ten kubelek jest ostatni - wszystkie beda w pierwszej tablicy*/
b_lo_ptrs=levels;
else if (bsize>=256) /* ten kubelek moze byc w drugiej tablicy */
{
b_lo_ptrs=bstart;
assert(bstart); /* poprzedni istnieje */
}
}
nbuckets++;
}
while (bend < levels-1);
b_hi_ptrs=(255+levels-b_lo_ptrs)>>8; /* czyli ceil((levels-b_lo_ptrs)/256) */
}
/* na podstawie zm. glob. wypelnia model */
/* liczniki sa zerowane przy alokacji przez caloc()*/
void statfillstructures()
{
unsigned int
bsize, /* rozmiar kubelka - liczba kontekstow*/
bstart, /* poczatek i koniec kubelka zakres: 0 do levels-1*/
bend, /* koniec kubelka */
repcntr, /* ewolucja kubelkow licznik pom. */
bnumber; /* numer kolejny kubelka */
COUNTER * freecounter=pc; /* poczatek wolnego miejsca w tablicy licznikow */
bnumber=0;
repcntr=repfirst+1; /* generujemy pierwszy kubelek */
bsize=firstsize;
do /* generujemy kolejne kubelki */
{
if (bnumber) /* poczatek kubelka */
bstart=bend+1;
else
bstart=0;
if (!--repcntr) /* rozmiar kubelka */
{
repcntr=repnext;
bsize*=mulsize;
}
bend=bstart+bsize-1; /* koniec kubelka */
if (bend+bsize>=levels) /* jezeli nastepny kubelek mialbyby byc mniejszy od tego */
bend=levels-1; /* to je polacz */
pb[bnumber].bestcode=_bpp-1;
pb[bnumber].pcounters=freecounter;
freecounter+=ncounters;
if (bstart<b_lo_ptrs) /* kubelek w czesci lo */
{
unsigned int i;
assert(bend<b_lo_ptrs);
for(i=bstart; i<=bend; i++)
b_ptr_lo[i]=pb+bnumber;
}
else /* w czesci hi */
{
unsigned int i,iend;
assert(bend>=b_lo_ptrs);
i=(bstart-b_lo_ptrs)>>8;
iend=(bend-b_lo_ptrs)>>8;
for(;i<=iend; i++)
b_ptr_hi[i]=pb+bnumber;
}
bnumber++;
}
while (bend < levels-1);
assert(freecounter-pc==nbuckets*ncounters);
return;
}
/* parametry, przydzial pamieci i wypelnienie */
void statinitmodel(const int bpp, const int evol, const int init8bpp)
{
assert(!pb);
assert(!pc);
assert(bpp>=1);
assert(bpp<=16);
findmodelparams(bpp, evol);
if(init8bpp)
{
assert(!b_hi_ptrs);
assert(b_lo_ptrs==(0x1U<<_bpp));
}
assert(b_lo_ptrs);
b_ptr_lo=(p_s_bucket *)clamalloc(b_lo_ptrs * sizeof(p_s_bucket));
if (!b_ptr_lo)
exitit("no memory for model allocation", 4);
if(b_hi_ptrs) /* to moze byc ==0 */
{
b_ptr_hi=(p_s_bucket *)clamalloc(b_hi_ptrs * sizeof(p_s_bucket));
if (!b_ptr_hi)
exitit("no memory for model allocation", 4);
}
pb=(s_bucket *)clamalloc( (size_t)nbuckets * sizeof(s_bucket) );
if (!pb)
exitit("no memory for model allocation", 4);
/* alokujemy i zerujemy liczniki - nie malloc a calloc */
pc=(COUNTER *)clacalloc( (size_t)nbuckets, sizeof(COUNTER) * MAXNUMCODES );
if (!pc)
exitit("no memory for model allocation", 4);
statfillstructures();
}
/* zwolnienie pamieci */
void statfreemodel()
{
assert(pb);
assert(pc);
clafree(pc);
pc=NULL;
clafree(pb);
pb=NULL;
if(b_hi_ptrs)
clafree(b_ptr_hi);
clafree(b_ptr_lo);
}
/* funkcje eksportowane */
void statinitcoder(const int bpp, const int maxclen,
const int evol, const int init8bpp)
{
assert(bpp<=MAXNUMCODES);
statinitmodel(bpp, evol, init8bpp);
familyinit(bpp, maxclen);
stabrand();
wmidx=wmistart;
set_wm_trigger(wmidx);
wmileft=wminext;
waitcnt=0;
}
void statfreecoder()
{
statfreemodel();
familyfree();
}
void statinitdecoder(const int bpp, const int maxclen, const int evol, const int width, struct bitinstatus *bs)
{
assert(bpp<=MAXNUMCODES);
statinitmodel(bpp, evol, 0);
familyinit(bpp, maxclen);
stabrand();
wmidx=wmistart;
set_wm_trigger(wmidx);
wmileft=wminext;
waitcnt=0;
bitinstatusinit(bs);
}
void statfreedecoder()
{
statfreemodel();
familyfree();
}
/* przeprowadz kompresje zmieniajac wmidx, wskaznik do tablicy pikseli i jej dlugosc */
/* zwroc 0-ok, 1-blad */
void statcompressrow(PIXEL context, const PIXEL * uncompressedrow, unsigned int width,
BYTE * compressedrow, unsigned int * fullbytes, unsigned int * bitsused)
{
while ((wmimax > (int)wmidx) && (wmileft<=width)) /*podzial w buforze */
{
if (wmileft)
{
statcompressrowwm(context, uncompressedrow, wmileft, bppmask[wmidx],
compressedrow, fullbytes, bitsused);
context=*(uncompressedrow+wmileft-1);
uncompressedrow+=wmileft;
width-=wmileft;
}
wmidx++;
set_wm_trigger(wmidx);
wmileft=wminext;
}
if (width)
{
statcompressrowwm(context, uncompressedrow, width, bppmask[wmidx],
compressedrow, fullbytes, bitsused);
if (wmimax > (int)wmidx)
wmileft-=width;
}
assert((int)wmidx<=wmimax);
assert(wmidx<=32);
assert(wminext>0);
}
void statcompressrow8bpp(BYTE context, const BYTE * uncompressedrow, unsigned int width,
BYTE * compressedrow, unsigned int * fullbytes, unsigned int * bitsused)
{
while ((wmimax > (int)wmidx) && (wmileft<=width)) /*podzial w buforze */
{
if (wmileft)
{
statcompressrowwm8bpp(context, uncompressedrow, wmileft, bppmask[wmidx],
compressedrow, fullbytes, bitsused);
context=*(uncompressedrow+wmileft-1);
uncompressedrow+=wmileft;
width-=wmileft;
}
wmidx++;
set_wm_trigger(wmidx);
wmileft=wminext;
}
if (width)
{
statcompressrowwm8bpp(context, uncompressedrow, width, bppmask[wmidx],
compressedrow, fullbytes, bitsused);
if (wmimax > (int)wmidx)
wmileft-=width;
}
assert((int)wmidx<=wmimax);
assert(wmidx<=32);
assert(wminext>0);
}
/* przeprowadz dekompresje zmieniajac wmidx, wskaznik do tablicy pikseli i jej dlugosc */
/* zwroc 0-ok, 1-blad */
int statdecompressrow(PIXEL context, PIXEL * uncompressedrow, unsigned int width, struct bitinstatus *bs)
{
int result;
while ((wmimax > (int)wmidx) && (wmileft<=width)) /*podzial w buforze */
{
if (wmileft)
{
result=statdecompressrowwm(context, uncompressedrow, wmileft, bppmask[wmidx], bs);
context=*(uncompressedrow+wmileft-1);
uncompressedrow+=wmileft;
width-=wmileft;
}
wmidx++;
set_wm_trigger(wmidx);
wmileft=wminext;
}
if (width)
{
result=statdecompressrowwm(context, uncompressedrow, width, bppmask[wmidx], bs);
if (wmimax > (int)wmidx)
wmileft-=width;
}
assert((int)wmidx<=wmimax);
assert(wmidx<=32);
assert(wminext>0);
return result;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?