一.实验原理
DPCM是差分预测编码调制的缩写,是比较典型的系统。在DPCM系统中,需要注意的是预测器的输入是已经解码以后的样本。之所以不用原始值来做预测,是因为在解码端无法得到原始样本,只能用存在误差的解码之后的数据,因此DPCM编码器中实际内嵌了一个解码器。
在一个 DPCM系统中,有两个因素需要设计:预测器 和量化。理想情况下系统中,预测器和量化采取联合优化的方式。而在实际的系统中采用的是次优方式:分别进行线性预测器和量化器的优化设计。
信源的相邻符号通常是相关的,预测编码就是利用信源相邻符合之间的相关性来进行压缩,根据某一模型利用以往的样本值对新样本进行预测,然后将样本的实际值与其预测值相减得到一个误差值,最后对这一误差值进行编码,如果模型足够好,且样本序列在时间上相关性较强,则误差信号的幅度将远远小于原始信号,从而得到较大的数据压缩。
二.实验框图
虚线方框中的内容就为编码器中内嵌的解码器。
三.DPCM+量化使信号产生的三种失真
(1)粒状噪声(Granular noise):平坦区域的随机噪声
对于小信号的量化区间过于大了,减小小信号的量化区间可以解决此类的问题,一般采用的是非均匀量化或者是压缩扩张法,即所谓的“小信号细量化,大信号粗量化”。
(2)Edge busyness:抖动的边缘
平坦区向斜率过载区过渡产生的信号失真。
(3)斜率过载(Slope overload):边缘模糊
信号的量化区间过于小了,需要增大信号的量化区间。
四.代码分析
main主函数
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <math.h>
#include "dpcm.h"
#include <windows.h>
#define u_int8_t unsigned __int8
#define u_int unsigned __int32
#define u_int32_t unsigned __int32
#pragma pack(1)
BITMAPFILEHEADER File_header;
BITMAPINFOHEADER Info_header;
long frameWidth ; /* --width=<uint> */
long frameHeight ; /* --height=<uint> */
unsigned char rectify(unsigned char x)
{
if (x<0) x=0;
if (x>255) x=255;
return x;
}
int BMP2YUV(char *url,char *url_out1,char *url_out2,int num)
{
FILE *bmpFile=NULL;
FILE *pFile=NULL;//存储重建图像值
FILE *eFile=NULL;//存储差值
bool flip = TRUE;/* --flip */
unsigned int i;
unsigned char* bmpBuf = NULL;
unsigned char* pBuf = NULL;//存储重建图像值
//int eBuf;
unsigned char* eBuf_p = NULL;//存储差值
unsigned char* yBuf = NULL;//仅对亮度进行预测编码
unsigned char* uBuf = NULL;
unsigned char* vBuf = NULL;
u_int32_t videoFramesWritten = 0;
bmpFile=fopen(url,"rb+");
pFile=fopen(url_out1,"wb+");
eFile=fopen(url_out2,"wb+");
//判断文件头是否读取正确
if(fread(&File_header,sizeof(BITMAPFILEHEADER),1,bmpFile) != 1)
{
printf("read file header error!");
exit(0);
}
//判断是否为bmp文件
if (File_header.bfType != 0x4D42)
{
printf("Not bmp file!");
exit(0);
}
else
{ printf("this is a bmp\n");
}
//判断信息头是否读取正确
if(fread(&Info_header,sizeof(BITMAPINFOHEADER),1,bmpFile) != 1)
{
printf("read info header error!");
exit(0);
}
// end read header
//判断长宽高是否读取正确,并赋值
if (((Info_header.biWidth/8*Info_header.biBitCount)%4) == 0)
frameWidth= Info_header.biWidth;
else
frameWidth = (Info_header.biWidth*Info_header.biBitCount+31)/32*4;
if ((Info_header.biHeight%2) == 0)
frameHeight = Info_header.biHeight;
else
frameHeight = Info_header.biHeight + 1;
printf("The width is %d\n",frameWidth);
printf("The height is %d\n",frameHeight);
/* open the BMP file */
if (bmpFile == NULL)
{
printf("cannot find bmp file\n");
exit(1);
}
else
{
printf("The input bmp file is open\n"/*, bmpFileName*/);
}
/* open the pfile */
if (pFile == NULL)
{
printf("cannot find p file\n");
exit(1);
}
else
{
printf("The out