www.pudn.com > sfalic-03-src.rar.rar > cdfstat.c


/* 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  
 
#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>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=0 !!! */ 
	{ 
		const unsigned int ithcodelen=( pcounters[i]+=GolombCodeLen(curval, i) ); 
 
		if (ithcodelenbestcode=bestcode; /* zapamietaj wyznaczony */ 
 
	if(bestcodelen>wm_trigger)	/* czy polowic liczniki? */ 
		for (i=0; 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 (stopidxbestcode,  
						&codeword, &codewordlen); 
			ENCODE(codeword, codewordlen) 
		} 
 
		updatemodel(findbucket(uncompressedrow[stopidx-1]),  
						uncompressedrow[stopidx] , _bpp); 
		stopidx=i+(tabrand() & waitmask); 
	} 
 
	for (; ibestcode,  
					&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=0 !!! */ 
	{ 
		const unsigned int ithcodelen=( pcounters[i]+=GolombCodeLen(curval, i) ); 
 
		if (ithcodelenbestcode=bestcode; /* zapamietaj wyznaczony */ 
 
	if(bestcodelen>wm_trigger)	/* czy polowic liczniki? */ 
		for (i=0; 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 (stopidxbestcode,  
						&codeword, &codewordlen); 
			ENCODE(codeword, codewordlen) 
		} 
 
		updatemodel8bpp(findbucket8bpp(uncompressedrow[stopidx-1]),  
						uncompressedrow[stopidx] , _bpp); 
		stopidx=i+(tabrand() & waitmask); 
	} 
 
	for (; ibestcode,  
					&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; ibestcode, &_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); 
} 
 
 
/* 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<=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); 
 
			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; 
}