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 + -
显示快捷键?