DPCM编码原理及代码实现

目录

  • 一、DPCM编码
  • 二、DPCM编码原理
  • 三、DPCM编码器
  • 四、DPCM解码器
  • 五、DPCM代码实现
  • 六、代码结果

一、DPCM编码

DPCM编码,英文名称Differential pulse-code modulation,是一种信号编码器,它以脉冲编码调制(PCM)为基础,基于信号样本的预测添加了一些功能。DPCM的输入信号可以是模拟信号,也可以是数字信号。

二、DPCM编码原理

DPCM并不是对每个抽样值进行独立编码,而是对根据前一个抽样值的预测值与当前抽样值的差值进行编码。因为相邻抽样值之间相关性较大,因此预测值与抽样值会很接近,其差值也会很小,因此对这个小的差值进行编码可以很有效的压缩数据量。

三、DPCM编码器

DPCM编码器:

DPCM编码原理及代码实现_第1张图片

四、DPCM解码器

DPCM解码器:

DPCM编码原理及代码实现_第2张图片

五、DPCM代码实现

#include 
#include 
#include 
#include 
int main()
{
	unsigned int width = 256;
	unsigned int height = 256;
	
	// 读取文件 
	char *yuvtest = NULL;
	char *newyuvtest = NULL;
	FILE* yuvFile = NULL;
	FILE* newyuvFile = NULL;
	char *pname = NULL;
	FILE* pFile = NULL;
    
    unsigned char* yuvbuffer = NULL;
	unsigned char* ubuffer = NULL;
	unsigned char* vbuffer = NULL;
    unsigned char * pbuffer = NULL;
	float* dbuffer = NULL;
	unsigned char* rbuffer = NULL;
    
	yuvtest = "···/test.yuv";
	newyuvtest = "···/testrebuild.yuv";
	pname= "···/error.yuv";
	yuvFile = fopen(yuvtest, "rb");
	if (!yuvFile)
		printf("YUV测试文件打开失败\n");
	else
		printf("成功打开YUV测试文件\n");
	newyuvFile = fopen(newyuvtest, "wb");
	if (!newyuvFile)
		printf("重建YUV文件打开失败\n");
	else
		printf("重建YUV文件打开成功\n");
	pFile = fopen(pname, "wb");
	if (!pFile)
		printf("误差文件打开失败\n");
	else
		printf("误差文件打开成功\n");
		
	
	yuvbuffer = (unsigned char*)malloc(width*height);
	ubuffer = (unsigned char*)malloc(width*height / 4);
	vbuffer = (unsigned char*)malloc(width*height / 4);
	pbuffer = (unsigned char*)malloc(width*height);//预测误差的量化值
	rbuffer = (unsigned char*)malloc(width*height);//重现图像
	dbuffer = (float*)malloc(width*height*4);//输入预测误差
	unsigned char* dobuffer = (unsigned char*)malloc(width*height * 4);
	
	if (yuvbuffer == NULL || ubuffer == NULL || vbuffer == NULL || pbuffer == NULL)
	{
		printf("ERROR");
	}
 
	fread(yuvbuffer, 1, width * height * 1, yuvFile);
 
	for (int i = 0; i < height; i++) {
		for (int j = 0; j < width; j++) {
			if (j == 0) {
				pbuffer[i*width + j] = 0;
				rbuffer[i*width + j] = yuvbuffer[i*width + j];
				dbuffer[i*width + j] = 0;
			}
			else {
				dbuffer[(i*width + j)] = float(yuvbuffer[i*width + j]) - float(rbuffer[i*width + j - 1]);
				if (dbuffer[ (i*width + j)] >= 0) {
					pbuffer[i*width + j] = floor(dbuffer[(i*width + j)] + 0.5);
					rbuffer[i*width + j] = rbuffer[i*width + j - 1] + pbuffer[i*width + j] * 1;
				}
				else {
					pbuffer[i*width + j] = floor(fabs(float(dbuffer[i*width + j]) + 0.5));
					rbuffer[i*width + j] = rbuffer[i*width + j - 1] - pbuffer[i*width + j] * 1;
				}
			}
		}
	}
    
    //计算误差
	int sum=0;
	for (int i = 0; i < height; i++) {
 
		for (int j = 0; j < width; j++) {
			sum += abs(pbuffer[i*width + j]);
		}
	}
	float MSE = float(sum) / float(width*height);
	float PSNR = 10 * log10(65025 / MSE);
	printf("PSNR=%f", PSNR);
	
	// 写入重建YUV文件和预测误差文件 
	for (int i = 0; i < width*height / 4; i++) {
		ubuffer[i] = 128;
		vbuffer[i] = 128;
	}
	fwrite(rbuffer, 1, width*height, newyuvFile);
	fwrite(ubuffer, 1, width*height / 4, newyuvFile);
	fwrite(vbuffer, 1, width*height / 4, newyuvFile);
	
	for (int i = 0; i < width*height ; i++) {
		dobuffer[i] = (unsigned char)(dbuffer[i])+128;
	}
	fwrite(dobuffer, 1, width*height, pFile);
	fwrite(ubuffer, 1, width*height / 4, pFile);
	fwrite(vbuffer, 1, width*height / 4, pFile);
	
	fclose(newyuvFile);
	fclose(yuvFile);
	fclose(pFile);
 
	return 0;
}

六、代码结果

原图像:

DPCM编码原理及代码实现_第3张图片

重建图像:

DPCM编码原理及代码实现_第4张图片

误差图像:

DPCM编码原理及代码实现_第5张图片

你可能感兴趣的:(CUC数据压缩原理与应用作业,图像处理)