?? cdfstat.c
字號(hào):
/* kod podzielony na 2 czesci, gorna do zoptymalizowana, dolna nie-krytyczna */
/* funkcje krytyczne dla predkosci, nie eksportowane */
#include "tabrand.h"
#include "cdfstat.h"
#include "cfamily.h"
#include <assert.h>
#include "encodecodeword.h"
/* uzywane w findbucket() */
static p_s_bucket * b_ptr_lo; /* tablica wskaznikow na kubelki - czesc lo */
static p_s_bucket * b_ptr_hi; /* tablica wskaznikow na kubelki - czesc hi */
static unsigned int
b_lo_ptrs; /* rozmiar tablicy b_lo_ptrs */
static unsigned int
b_hi_ptrs;
/* uzywane w updatemodel() */
static unsigned int
wm_trigger; /* prog dla polowienia licznikow, jezeli trigger z taskparams<>0 */
/* to wm_trigger=trigger, else wm_trigger wyznaczany funkcja set_wm_trigger dla evol i wm */
/* uzywany w statdecompressrow() i statcompressrow() */
static unsigned int
waitcnt; /* globalny licznik pominiec aktualizacji modelu */
static unsigned int
_bpp; /* lokalna kopia bpp z taskparams */
/*zwraca wskaznik do kubelka, ktory zawiera kontekst val */
static s_bucket * findbucket(const unsigned int val)
{
assert(val<(0x1U<<_bpp));
if (val<b_lo_ptrs)
return b_ptr_lo[val];
else
return b_ptr_hi[(val-b_lo_ptrs)>>8];
}
/* aktualizacja kubelka modelu na podstawie zakodowanego symbolu curval */
static void updatemodel(s_bucket * const bucket, const unsigned int curval,
const unsigned int bpp)
{
COUNTER * const pcounters=bucket->pcounters;
unsigned int i;
unsigned int bestcode;
unsigned int bestcodelen;
/* uaktualnij liczniki i wyznacz wartosc i indeks najmniejszego */
/* zaczynajac od najwiekszego indeksu -- bpp==ncodes*/
bestcode=bpp-1;
bestcodelen=( pcounters[bestcode]+=GolombCodeLen(curval, bestcode) );
for (i=bpp-2; i<bpp; i--) /* UWAGA: warunek i<bpp dla signed int i bylby i>=0 !!! */
{
const unsigned int ithcodelen=( pcounters[i]+=GolombCodeLen(curval, i) );
if (ithcodelen<bestcodelen)
{
bestcode=i;
bestcodelen=ithcodelen;
}
}
bucket->bestcode=bestcode; /* zapamietaj wyznaczony */
if(bestcodelen>wm_trigger) /* czy polowic liczniki? */
for (i=0; i<bpp; i++) /* polowimy */
pcounters[i]>>=1;
}
/* dla stalego waitmask przeprowadz kompresje */
/* argumenty: kontekst pierwszego piksela, tablica pikseli, dlugosc tablicy, waitmask */
/* tablica na bitowo zapisane slowa kodowe i jej zmienne stanu */
static void statcompressrowwm(const PIXEL firstcontext, const PIXEL uncompressedrow[],
const unsigned int width, const unsigned int waitmask,
BYTE compressedrow[],
unsigned int * const fullbytes, unsigned int * const bitsused)
{
unsigned int i;
unsigned int stopidx; /* piksel na ktorym zatrzymuje sie petla wewnetrzna */
ENCODE_START(compressedrow, fullbytes, bitsused)
assert(width);
{ /* element zerowy */
unsigned int codeword, codewordlen ;
GolombCoding(uncompressedrow[0],
findbucket(firstcontext)->bestcode,
&codeword, &codewordlen);
ENCODE(codeword, codewordlen)
if (waitcnt)
waitcnt--;
else
{
waitcnt=(tabrand() & waitmask);
updatemodel(findbucket(firstcontext),
uncompressedrow[0] , _bpp);
}
}
i=1;
stopidx=i+waitcnt;
while (stopidx<width) /* kodujemy grupe pikseli i aktualizujemy model po ostatnim z grupy */
{
for (; i<=stopidx; i++)
{
unsigned int codeword, codewordlen ;
GolombCoding(uncompressedrow[i],
findbucket(uncompressedrow[i-1])->bestcode,
&codeword, &codewordlen);
ENCODE(codeword, codewordlen)
}
updatemodel(findbucket(uncompressedrow[stopidx-1]),
uncompressedrow[stopidx] , _bpp);
stopidx=i+(tabrand() & waitmask);
}
for (; i<width; i++) /* ewentualna ostatnia grupa pikseli, po ktorej nie ma aktualizacji */
{
unsigned int codeword, codewordlen ;
GolombCoding(uncompressedrow[i],
findbucket(uncompressedrow[i-1])->bestcode,
&codeword, &codewordlen);
ENCODE(codeword, codewordlen)
}
ENCODE_STOP(compressedrow, fullbytes, bitsused)
waitcnt=stopidx-width;
}
/* powyzsze w wariancie dla do 8 bpp */
static s_bucket * findbucket8bpp(const unsigned int val)
{
assert(val<(0x1U<<_bpp));
return b_ptr_lo[val];
}
static void updatemodel8bpp(s_bucket * const bucket, const unsigned int curval,
const unsigned int bpp)
{
COUNTER * const pcounters=bucket->pcounters;
unsigned int i;
unsigned int bestcode;
unsigned int bestcodelen;
/* uaktualnij liczniki i wyznacz wartosc i indeks najmniejszego */
/* zaczynajac od najwiekszego indeksu -- bpp==ncodes*/
bestcode=bpp-1;
bestcodelen=( pcounters[bestcode]+=GolombCodeLen(curval, bestcode) );
for (i=bpp-2; i<bpp; i--) /* UWAGA: warunek i<bpp dla signed int i bylby i>=0 !!! */
{
const unsigned int ithcodelen=( pcounters[i]+=GolombCodeLen(curval, i) );
if (ithcodelen<bestcodelen)
{
bestcode=i;
bestcodelen=ithcodelen;
}
}
bucket->bestcode=bestcode; /* zapamietaj wyznaczony */
if(bestcodelen>wm_trigger) /* czy polowic liczniki? */
for (i=0; i<bpp; i++) /* polowimy */
pcounters[i]>>=1;
}
static void statcompressrowwm8bpp(const BYTE firstcontext, const BYTE uncompressedrow[],
const unsigned int width, const unsigned int waitmask,
BYTE compressedrow[],
unsigned int * const fullbytes, unsigned int * const bitsused)
{
unsigned int i;
unsigned int stopidx; /* piksel na ktorym zatrzymuje sie petla wewnetrzna */
ENCODE_START(compressedrow, fullbytes, bitsused)
assert(width);
{ /* element zerowy */
unsigned int codeword, codewordlen ;
GolombCoding(uncompressedrow[0],
findbucket8bpp(firstcontext)->bestcode,
&codeword, &codewordlen);
ENCODE(codeword, codewordlen)
if (waitcnt)
waitcnt--;
else
{
waitcnt=(tabrand() & waitmask);
updatemodel8bpp(findbucket8bpp(firstcontext),
uncompressedrow[0] , _bpp);
}
}
i=1;
stopidx=i+waitcnt;
while (stopidx<width) /* kodujemy grupe pikseli i aktualizujemy model po ostatnim z grupy */
{
for (; i<=stopidx; i++)
{
unsigned int codeword, codewordlen ;
GolombCoding(uncompressedrow[i],
findbucket8bpp(uncompressedrow[i-1])->bestcode,
&codeword, &codewordlen);
ENCODE(codeword, codewordlen)
}
updatemodel8bpp(findbucket8bpp(uncompressedrow[stopidx-1]),
uncompressedrow[stopidx] , _bpp);
stopidx=i+(tabrand() & waitmask);
}
for (; i<width; i++) /* ewentualna ostatnia grupa pikseli, po ktorej nie ma aktualizacji */
{
unsigned int codeword, codewordlen ;
GolombCoding(uncompressedrow[i],
findbucket8bpp(uncompressedrow[i-1])->bestcode,
&codeword, &codewordlen);
ENCODE(codeword, codewordlen)
}
ENCODE_STOP(compressedrow, fullbytes, bitsused)
waitcnt=stopidx-width;
}
/* obszar nie-krytyczny */
#include "cfamily.h"
#include "cdftypes.h"
#include "exitit.h"
#include "bppmask.h"
#include "ceillog2.h"
#include "taskparams.h"
#include "clalloc.h"
static COUNTER * pc=NULL; /* pomocniczy do dealokacji i alokacji tablic licznikow (hurtem) */
static s_bucket * pb=NULL; /* tablica kubelkow */
/* ustawiane przez findmodelparams(), uzywane przez statfillstructures() */
static unsigned int
repfirst, /* ile kubelkow takich jak pierwszy */
firstsize, /* rozmiar pierwszego kubelka */
repnext, /* po ile razy powtarzac kolejne rozmiary */
mulsize, /* skok wielkosci rozmiaru */
levels; /* liczba poziomow jasnosci piksela */
static unsigned int
nbuckets; /* liczba kubelkow */
static unsigned int
ncounters; /* liczba licznikow alokowanych dla kubelka */
static unsigned int
wmidx, /* aktualny index waitmask */
wmileft; /* ile jeszcze symboli zakodowac z aktualnym wmidx */
static const unsigned short besttrigtab[4][11]={ /* tablica wartosci do wyznaczenia wm_trigger przez set_wm_trigger() */
/*w komentatrzach evol */
/* 1 */ { 550, 900, 800, 700, 500, 350, 300, 200, 180, 180, 160 },
/* 3 */ { 110, 550, 900, 800, 550, 400, 350, 250, 140, 160, 140 },
/* 5 */ { 100, 120, 550, 900, 700, 500, 400, 300, 220, 250, 160 },
/* 6 */ { 30, 30, 30, 30, 30, 250, 400, 400, 300, 220, 220 }
};
/* dla stalego waitmask przeprowadz de kompresje, wskaznik do tablicy pikseli i jej dlugosc */
/* zwroc 0-ok, 1-blad */
static int statdecompressrowwm(PIXEL context, PIXEL * uncompressedrow,
const unsigned int width, const unsigned int waitmask,
struct bitinstatus *bs)
{
unsigned int
_waitcnt=waitcnt;
struct bitinstatus
_bs=*bs;
unsigned int i;
for (i=0; i<width; i++)
{
s_bucket * const bucket=findbucket(context);
context=uncompressedrow[i]=GolombDecoding(bucket->bestcode, &_bs);
if (_waitcnt)
_waitcnt--;
else
{
_waitcnt=(tabrand() & waitmask);
updatemodel(bucket, context, _bpp);
}
}
waitcnt=_waitcnt;
*bs=_bs;
return 0;
}
/* ustaw wm_trigger dla danego waitmask */
void set_wm_trigger(unsigned int wm)
{
if (trigger)
{
wm_trigger=trigger;
return;
}
if (wm>10)
wm=10;
assert(evol<7);
wm_trigger=besttrigtab[evol/2][wm];
assert(wm_trigger<=2000);
assert(wm_trigger>=1);
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -