⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cdf.c

📁 一个简单而且快速的无损压缩算法。包含源代码实现
💻 C
字号:
/* program do kompresji - dekompresji obrazow */

#include "cdftypes.h"
#include "taskparams.h"
#include "cdfcmdline.h"
#include "exitit.h"
#include "cdfpred.h"
#include "cfamily.h"
#include "cdfstat.h"
#include "headers.h"
#include "bigendian.h"
#include "clalloc.h"

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


void decompression(FILE *infile, FILE *outfile)
{
	int fileBYTESpp;
	BYTE *filerow, *compressedrow;
	int compressedrowlen=4*(width+1);
	int eof=0;
	PIXEL context, *prevrow, *currow, *decorelatedrow;
	int row;
	struct bitinstatus bs;		/* struktura stanu dla wejscia bitowego */

	if (bpp<9)
		fileBYTESpp=1;
	else 
		fileBYTESpp=2;

	context=0;

	if (!(compressedrow=(BYTE *)clamalloc(compressedrowlen)))
		exitit("error compressedrow buffer allocation", 4);
	if (!(filerow=(BYTE *)clamalloc(width*fileBYTESpp)))
		exitit("error filerow buffer allocation", 4);
	if (!(prevrow=(PIXEL *)clamalloc(width*sizeof(PIXEL))))
		exitit("error pervrow buffer allocation", 4);
	if (!(currow=(PIXEL *)clamalloc(width*sizeof(PIXEL))))
		exitit("error currow buffer allocation", 4);
	if (!(decorelatedrow=(PIXEL *)clamalloc(width*sizeof(PIXEL))))
		exitit("error decorelatedrow buffer allocation", 4);

	if(!decoronly)
	{	
		eof=(compressedrowlen!=fread((void *)compressedrow, 1, compressedrowlen, infile));
		bs.readptr=compressedrow;
		statinitdecoder(bpp, maxclen, evol, width, &bs);
	}

	for (row=0; row<height; row++)
	{	
		PIXEL *helprowptr;

		if (decoronly)
		{
			if (width!=fread((void *)decorelatedrow, sizeof(PIXEL), width, infile))
				exitit("error reading decorelated pixels from infile", 4);
		}
		else
		{
			int usedbytes;
			if (statdecompressrow(context, decorelatedrow, width, &bs))
				exitit("error decompressing (statdecompressrow())", 4);
			usedbytes=bs.readptr-compressedrow;
			assert(usedbytes<=compressedrowlen);
			if (!eof)
			{
				memmove(compressedrow, compressedrow+usedbytes, compressedrowlen-usedbytes);
				bs.readptr=compressedrow;
				eof=(usedbytes!=fread((void *)(compressedrow+(compressedrowlen-usedbytes))
									   , 1, usedbytes, infile));
			}
		}

		context=*decorelatedrow;

		corelaterow(prevrow, currow, row, width, bpp, pred, decorelatedrow);

		BEpixelrowtorawrow(filerow, currow, width, fileBYTESpp);	
		if (width!=fwrite((void *)filerow, fileBYTESpp, width, outfile))	
			exitit("error writting pixels to outfile", 4);	

		helprowptr=prevrow;
		prevrow=currow;
		currow=helprowptr;
	}

	if(!decoronly)
		statfreedecoder();

	clafree(decorelatedrow);
	clafree(currow);
	clafree(prevrow);
	clafree(filerow);
	clafree(compressedrow);
}


void compression(FILE *infile, FILE *outfile)
{
	int fileBYTESpp;
	PIXEL context;  // kontekst dla pierwszego piksela currow
	int row;	// numer aktualnie przetwarzanego wiersza
	unsigned int bitsused;	// ile bitow zapisanych (przez encodecodewords) w ostatnim niepelnym bajcie comprssedrow
	int needconvert; /* czy bajty z pliku trzeba konwertowac na piksele */

	BYTE *filerow;	// pomocniczy bufor na wiersz odczytany z pliku jezeli potrzebna konwertsja na wlasciwy endian
	PIXEL *prevrow, // poprzedni wiersz
		  *currow,  // aktualny wiersz
		  *decorelatedrow;	// wiersz po dekorelacji
	BYTE  *compressedrow;	  // precompressedrow zakodowany bitowo (rezerwujemy po 4 bajty na piksel + 4 bajty zapasu)

	if(!decoronly)
		statinitcoder(bpp, maxclen, evol, 0);

	if (bpp<9)
		fileBYTESpp=1;
	else 
		fileBYTESpp=2;

	needconvert=(fileBYTESpp!=sizeof(PIXEL)) || (fileBYTESpp>1 && !BEmachine());

	if (!(compressedrow=(BYTE *)clamalloc(4*(width+1))))
		exitit("error compressedrow buffer allocation", 4);
	if (!(prevrow=(PIXEL *)clamalloc(width*sizeof(PIXEL))))
		exitit("error pervrow buffer allocation", 4);
	if (!(currow=(PIXEL *)clamalloc(width*sizeof(PIXEL))))
		exitit("error currow buffer allocation", 4);
	if (!(decorelatedrow=(PIXEL *)clamalloc(width*sizeof(PIXEL))))
		exitit("error decorelatedrow buffer allocation", 4);
	if(needconvert)
		if (!(filerow=(BYTE *)clamalloc(width*fileBYTESpp)))
			exitit("error filerow buffer allocation", 4);

	context=0;
	bitsused=0;

	for (row=0; row<height; row++)
	{	
		PIXEL *helprowptr;

		helprowptr=prevrow;
		prevrow=currow;
		currow=helprowptr;

		if(needconvert)
		{
			if (width!=fread((void *)filerow, fileBYTESpp, width, infile))
				exitit("error reading pixels from infile", 4);
			BErawrowtopixelrow(filerow, currow, width, fileBYTESpp);
		}
		else
			if (width!=fread((void *)currow, fileBYTESpp, width, infile))
				exitit("error reading pixels from infile", 4);

		decorelaterow(prevrow, currow, row, width, bpp, pred, decorelatedrow);

		if (decoronly)
		{
			if (width!=fwrite((void *)decorelatedrow, sizeof(PIXEL), width, outfile))
				exitit("error writting decorelated pixels to outfile", 4);
		}
		else
		{
			unsigned int fullbytes=0;
			statcompressrow(context, decorelatedrow, width, 
							compressedrow, &fullbytes, &bitsused);
			if (fullbytes!=fwrite((void *)compressedrow, 1, fullbytes, outfile))
				exitit("error writting compressed pixels to outfile", 4);
			if (bitsused) /* bitsused jest z zakresu 0-31 */
				*(unsigned int *)compressedrow=*(unsigned int *)(compressedrow+fullbytes);
		}

		context=*decorelatedrow;
	}

	if(!decoronly)
	{
		if (bitsused)			/* jezeli trzeba to zapisz ostatni bajt skompresowanego obrazka*/
			if (1!=fwrite((void *)compressedrow, (bitsused+7)/8, 1, outfile))
				exitit("error writting compressed pixels to outfile", 4);
		statfreecoder();	/* zwolnij struktury */
	}

	if(needconvert)
		clafree(filerow);
	clafree(decorelatedrow);
	clafree(currow);
	clafree(prevrow);
	clafree(compressedrow);
}


void compression8bpp(FILE *infile, FILE *outfile)
{
	BYTE context;  // kontekst dla pierwszego piksela currow
	int row;	// numer aktualnie przetwarzanego wiersza
	unsigned int bitsused;	// ile bitow zapisanych (przez encodecodewords) w ostatnim niepelnym bajcie comprssedrow

	BYTE *prevrow, // poprzedni wiersz
		  *currow,  // aktualny wiersz
		  *decorelatedrow;	// wiersz po dekorelacji
	BYTE  *compressedrow;	  // precompressedrow zakodowany bitowo (rezerwujemy po 4 bajty na piksel + 4 bajty zapasu)

	assert(bpp<=8);

	decorelateinit8bpp(bpp); /* dekorelacja nie wymaga zwolnienia */
	if(!decoronly)
		statinitcoder(bpp, maxclen, evol, 1);

	if (!(compressedrow=(BYTE *)clamalloc(4*(width+1))))
		exitit("error compressedrow buffer allocation", 4);
	if (!(prevrow=(BYTE *)clamalloc(width)))
		exitit("error pervrow buffer allocation", 4);
	if (!(currow=(BYTE *)clamalloc(width)))
		exitit("error currow buffer allocation", 4);
	if (!(decorelatedrow=(BYTE *)clamalloc(width)))
		exitit("error decorelatedrow buffer allocation", 4);

	context=0;
	bitsused=0;

	for (row=0; row<height; row++)
	{	
		BYTE *helprowptr;

		helprowptr=prevrow;
		prevrow=currow;
		currow=helprowptr;

		if (width!=fread((void *)currow, 1, width, infile))
			exitit("error reading pixels from infile", 4);

		decorelaterow8bpp(prevrow, currow, row, width, bpp, pred, decorelatedrow);

		if (decoronly)
		{
			if (width!=fwrite((void *)decorelatedrow, 1, width, outfile))
				exitit("error writting decorelated pixels to outfile", 4);
		}
		else
		{
			unsigned int fullbytes=0;
			statcompressrow8bpp(context, decorelatedrow, width, 
							compressedrow, &fullbytes, &bitsused);
			if (fullbytes!=fwrite((void *)compressedrow, 1, fullbytes, outfile))
				exitit("error writting compressed pixels to outfile", 4);
			if (bitsused) /* bitsused jest z zakresu 0-31 */
				*(unsigned int *)compressedrow=*(unsigned int *)(compressedrow+fullbytes);
		}

		context=*decorelatedrow;
	}

	if(!decoronly)
	{
		if (bitsused)			/* jezeli trzeba to zapisz ostatni bajt skompresowanego obrazka*/
			if (1!=fwrite((void *)compressedrow, (bitsused+7)/8, 1, outfile))
				exitit("error writting compressed pixels to outfile", 4);
		statfreecoder();	/* zwolnij struktury */
	}

	clafree(decorelatedrow);
	clafree(currow);
	clafree(prevrow);
	clafree(compressedrow);
}


int main(const int argc, char **argv)
{
	FILE *infile, *outfile;

	if (CheckAssumptions())
		exitit("internal error: CheckAssumptions() fail. Chceck compiler options and macros.", 100);

	processcmdline(argc, argv);

	if (echo) 
		printf("\n" PROGNAME);
	if (echo) 
		printf("\nBEmachine() = %d", BEmachine());

	infile=fopen(infilename, "rb");
	if (!infile)
		exitit("error openning infile", 2);
	if (f_compress)
		readPGMP5header(infile);
	else
		readCDFheader(infile);

	if (echo) 
		printparams();

	testparams();

	outfile=fopen(outfilename, "wb");
	if (!outfile)
		exitit("error openning outfile", 2);
	if (!noheader)
	{
		if (f_compress)
			writeCDFheader(outfile);
		else
			writePGMP5header(outfile);
	}

	if (f_compress)
	{
		if (bpp<=8 && !generic8bpp)
			compression8bpp(infile, outfile);
		else
			compression(infile, outfile);
	}
	else
		decompression(infile, outfile);

	fclose(infile);
	fclose(outfile);

	if (echo) 
		printf("\n\nFinished!\n");

	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -