codeimage.c

来自「傅立叶变换和小波变换是图像压缩的重要工具。该代大戏是利用小波变换进行图像压缩。」· C语言 代码 · 共 219 行

C
219
字号

#include "codeimage.h"
#include "mathutil.h"
#include "wavelet.h"
#include "decoder.h"
#include <crblib/imutil.h>
#include <crblib/tsc.h>
#include "yuv.h"
#include <math.h>

//#define DO_TSC

uint writeHeader(ubyte *buf,float quantizer);
uint readHeader( ubyte *buf,float *pquantizer);

#define MIN_Q_STEP		(0.25f)
#define MAX_QUANTIZER	(128.f)

struct CodeImager
{
	float * fPlanes[3];
	Wavelet * wave;
	int width,height;
};

CodeImager * CodeImager_Create(int w,int h)
{
CodeImager * ci;
int p;

	ci = new(CodeImager);

	ci->width = w;
	ci->height = h;

	for(p=0;p<3;p++)
	{
		ci->fPlanes[p] = malloc(sizeof(float)*(w*(h + 2)));
		assert(ci->fPlanes[p]);
	}

	ci->wave = Wavelet_Create(ci->fPlanes,w,h);
	assert(ci->wave);

return ci;
};

void CodeImager_Destroy(CodeImager * ci)
{
int p;

	Wavelet_Destroy(ci->wave);

	for(p=0;p<3;p++)
		free(ci->fPlanes[p]);

	destroy(ci);
}

/*}{****** encode *******/

float CodeImager_Encode(CodeImager * ci,Image *im,ubyte *compBuf,int *pCompLen,uint targetLen,
							CodeImager * decoder,Image *decIm)
{
int planeLen,cnt;
uint compLen,headerLen;
ubyte *compPtr;
int width,height;
float Q,Qstep;

	width  = im->width;
	height = im->height;

	assert( width  == ci->width );
	assert( height == ci->height );

	// im to float planes

	planeLen = width * height;

	{
	float *fptr0,*fptr1,*fptr2;
	ubyte *iptr;
		fptr0 = ci->fPlanes[0];
		fptr1 = ci->fPlanes[1];
		fptr2 = ci->fPlanes[2];
		iptr = im->BGRplane;
		for(cnt=planeLen;cnt--;)
		{
			BGRb_to_YUVf(iptr,fptr2++,fptr1++,fptr0++); iptr += 3;
		}
	}

	Image_DownSampFPlane(ci->fPlanes[0],width,height);
	Image_DownSampFPlane(ci->fPlanes[1],width,height);

	Wavelet_Transform(ci->wave);

	Qstep = MAX_QUANTIZER * 0.5f;
	Q = 1.0f + Qstep*2;

	if ( targetLen )
		targetLen += (int)(planeLen * 0.001f);

	ci->wave->speculative = true;

	while(Qstep >= MIN_Q_STEP)
	{
		assert( Q > Qstep );

		Wavelet_Quantize(ci->wave,Q - Qstep);
			
		Wavelet_CodeToPackets(ci->wave);

		compLen = Wavelet_CompLen(ci->wave);

		//printf("quant = %2.2f -> %2.2f kbytes\n",(Q - Qstep),compLen*(1.0f/1024.0f));

		if ( compLen <= targetLen )
		{
			Q -= Qstep;
		}

		Qstep *= 0.5f;
	}

	ci->wave->speculative = false;

	Wavelet_Quantize(ci->wave,Q);

	printf("chose quantizer = %f; dpcm loss = %d\n",Q,ci->wave->dpcmLoss);
			
	Wavelet_CodeToPackets(ci->wave);

	compLen = Wavelet_CompLen(ci->wave);

	compPtr = compBuf;

	// write header info to compBuf

	headerLen = writeHeader(compPtr,Q);

	compPtr += headerLen;

	// write packets to compBuf

	Wavelet_WritePacketsToBuf(ci->wave,compPtr);

	*pCompLen = compLen + headerLen;

	ci->wave->uses ++;

	if ( decoder )
	{
	float mse,rmse;
		CodeImager_Decode(decoder,decIm,compBuf,*pCompLen,NULL);

		mse = Image_DifferenceMSE(im,decIm);

		rmse = fsqrt(mse);
		printf("mse = %1.3f, rmse = %1.3f, psnr = %2.2f\n",mse,rmse,20*log10(256.0/rmse));

		return rmse;
	}

	return 0.0f;
}

/*}{****** decode *******/

void CodeImager_Decode(CodeImager * ci,Image * im,ubyte *compBuf,int compLen,
							Driver_Window * Window)
{
ubyte * compPtr;
int headerLen;
float Q;

	compPtr = compBuf;
	headerLen = readHeader(compPtr,&Q);
	compPtr += headerLen;
	compLen -= headerLen;

	assert(im);

	DecodeIt(ci->wave,compPtr,im->BGRplane,ci->fPlanes,im->width,im->height,Q,Window);
	
	ci->wave->uses ++;
}

/*}{****** header IO *******/

uint writeHeader(ubyte *buf,float quantizer)
{
int x;

	// must write quant in the full 16 bits

	assert( quantizer >= 2.f );
	quantizer -= 2.f;

	assert( quantizer < MAX_QUANTIZER );
	x = (int)(quantizer * 65536.0f / MAX_QUANTIZER);
	assert( x < 65536 );

	*((uword *)buf) = x;

return 2;
}

uint readHeader( ubyte *buf,float *pquantizer)
{
int x;

	x = *((uword *)buf);

	*pquantizer = (x * MAX_QUANTIZER / 65536.0f) + 2.0f;

return 2;
}

⌨️ 快捷键说明

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