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