实验四 DPCM编码
来源:互联网 发布:淘宝售假仅退款不退货 编辑:程序博客网 时间:2024/06/05 21:06
一、实验原理
DPCM是差分预测编码调制的缩写,是比较典型的预测编码系统。在DPCM中,需要注意的是预测器输入的是预测器的输入是已经编码的样本。因为在解码端,同样无法得到原始样本,只能得到存在误差的样本。因此,在DPCM编码器中实际内嵌了一个解码器,如编码器中虚线框中所示。
在一个DPCM系统中,有两个因素需要设计:预测器与量化器。理想情况下,预测器和量化器应该联合设计。但在实际中,采用一种次优的设计方法:分别进行线性预测器和量化器的优化设计。下图则为DPCM编码端与解码端的图示:
二、部分代码及注释
本次实验采用了实验二bmp to yuv的程序,因为在编写实验二时只编写了24位bmp的转化,本次实验素材为多位在参考了网上部分程序后对整个程序重新采用了结构体编写(全部程序参见附录)。本次实验的dpcm部分作为一个子函数加入函数程序中,下面为程序中主要添加的代码,在结构体以及初始化函数中的详细更改参见附录。
main.c
if(yuv.DO_DPC(yuv.Y,yuvFile2,yuvFile3, bmp.width, bmp.height)) printf("dpcm YUV file successful!\n\n"); else {printf("dpcm YUV file failed!\n\n");}
bpcm2yuv.cpp(子函数)中添加的部分。
bool DO_DPCM(void * yBuf, FILE * quanBuf, FILE *rebuildBuf, unsigned int width, unsigned int height){ unsigned char *y_buffer = NULL; unsigned char *quan_buffer = NULL; unsigned char *rebuild_buffer = NULL; int immediate = 0; int i = 0; int j = 0; y_buffer = (unsigned char *)yBuf;//定义指针指向原始图像缓冲区 quan_buffer = (unsigned char *)malloc(width*height*sizeof(unsigned char));//定义指针指向预测误差图像缓冲区 rebuild_buffer = (unsigned char *)malloc(width*height*sizeof(unsigned char));//定义指针指向重建图像缓冲区 for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { if (j == 0) { /*immediate先是为量化后的预测误差。 后用来存放反量化后的预测误差。*/ immediate = ((int)*(y_buffer+i*width+j) - 128)/2+128; *(quan_buffer+i*width+j) = (unsigned char)immediate; immediate = (*(quan_buffer+i*width+j) - 128) * 2+128; *(rebuild_buffer+i*width+j) = (unsigned char)immediate; //y_buffer++; //quan_buffer++; //rebuild_buffer++; } else { immediate = (*(y_buffer+i*width+j) - *(rebuild_buffer+i*width+j-1))/2+128; *(quan_buffer+i*width+j) = (unsigned char)immediate; immediate = (*(quan_buffer+i*width+j) - 128) * 2 + *(rebuild_buffer+i*width+j - 1); *(rebuild_buffer+i*width+j) =(unsigned char)immediate; // y_buffer++; //quan_buffer++; //rebuild_buffer++; } } printf("i:%d",i);//调试代码用 } //FILE *rebuild_bufferfile; //FILE *quanBuffile; for(i=0;i<width*height/4;i++) { *(yuv.U+i)=128; *(yuv.V+i)=128; } fwrite(rebuild_buffer,1,width*height,rebuildBuf); fwrite(yuv.U,1,width*height/4,rebuildBuf); fwrite(yuv.V,1,width*height/4,rebuildBuf); fwrite(quan_buffer,1,width*height,quanBuf); fwrite(yuv.U,1,width*height/4,quanBuf); fwrite(yuv.V,1,width*height/4,quanBuf);//以上将预测误差图像和重建图像写入文件 free(quan_buffer); free(rebuild_buffer);//释放空间 return true;//返回1在主函数中判断是否完成了dpcm}
三、实验结果及分析
注:每幅图像按照原始bmp图、转换后的yuv图(图片名称#0··1)、差值图(图片名称#0··2)、重建后的yuv图排列(图片名称#0··3)。
符号概率密度图:
按照Camman Clown Fruit Lena Noise Odie Zone每幅图的原始图、预测误差图排序
分析:图像的相邻像素相关度越高量化误差越小,系统的压缩性能越好。
附录:实验全部程序(重新采用结构体编写)
bmp2yuv.h
bool RGB2YUV(unsigned long w,unsigned long h,unsigned char * rgbData,unsigned char * y,unsigned char * u,unsigned char *v);bool DO_DPCM(void * yBuf, FILE * quanBuf, FILE *rebuildBuf, unsigned int width, unsigned int height);FILE *OpenBmp(const char *,const char *);bool ReadBmp(FILE *);bool CloseBmp(FILE *);FILE * OpenYuv(const char *,const char *);bool WriteYuv(FILE *);bool CloseYuv(FILE *);
glabal.h
typedef struct{ BITMAPFILEHEADER file_header; BITMAPINFOHEADER info_header; unsigned long width,height; BYTE *rgbData; FILE* (* BMPopen)(const char *,const char *); bool (* BMPread)(FILE *); bool (* Convert2Yuv)(unsigned long,unsigned long,unsigned char*,unsigned char*,unsigned char*,unsigned char *); bool (* BMPclose)(FILE *);}BMPSTRUCT;typedef struct{ BYTE *Y,*U,*V; FILE* (* YUVopen)(const char *,const char *); bool (* YUVwrite)(FILE *); bool (* DO_DPC)(void *, FILE * , FILE *, unsigned int, unsigned int ); bool (* YUVclose)(FILE *);}YUVSTRUCT;
main.c
#include <stdio.h>#include <windows.h>#include "global.h"#include "bmp2yuv.h"BMPSTRUCT bmp;YUVSTRUCT yuv;void init();void release();void main(int argc,char *argv[]){ FILE *bmpFile = NULL; FILE *nbmpFile = NULL; FILE *yuvFile1 = NULL; FILE *yuvFile2 = NULL; FILE *yuvFile3 = NULL; init();//初始化 bmpFile = fopen(argv[1], "rb");//// bmpFile = fopen(argv[1], "ab");// // open bmp & yuv file //if((bmpFile = bmp.BMPopen(argv[1],"rb")) == NULL) if(bmpFile == NULL) { printf("bmp file open failed!\n\n"); exit(0); } if ((yuvFile1 = yuv.YUVopen(argv[2],"wb")) == NULL) { printf("yuv file failed!\n\n"); exit(0); } if ((yuvFile2 = yuv.YUVopen(argv[3],"wb")) == NULL) { printf("yuv file failed!\n\n"); exit(0); } if ((yuvFile3 = yuv.YUVopen(argv[4],"wb")) == NULL) { printf("yuv file failed!\n\n"); exit(0); } // end open bmp & yuv file if(!bmp.BMPread(bmpFile))// read file & info header & rgb data exit(0); //rgb2yuv if(bmp.Convert2Yuv(bmp.width,bmp.height,bmp.rgbData,yuv.Y,yuv.U,yuv.V)) printf("rgb2yuv successful!\n\n"); else exit(0); //write yuv file if(yuv.YUVwrite(yuvFile1)) printf("write YUV file successful!\n\n"); else {printf("write YUV file failed!\n\n");} if(yuv.DO_DPC(yuv.Y,yuvFile2,yuvFile3, bmp.width, bmp.height)) printf("dpcm YUV file successful!\n\n"); else {printf("dpcm YUV file failed!\n\n");} //close yuv & bmp file yuv.YUVclose(yuvFile1); bmp.BMPclose(bmpFile); //release buffer release(); }void init(){ bmp.rgbData = NULL; bmp.BMPopen = OpenBmp; bmp.BMPread = ReadBmp; bmp.Convert2Yuv = RGB2YUV; bmp.BMPclose = CloseBmp; yuv.Y = NULL; yuv.U = NULL; yuv.V = NULL; yuv.YUVopen = OpenYuv; yuv.YUVwrite = WriteYuv; yuv.DO_DPC = DO_DPCM; yuv.YUVclose = CloseYuv;}void release(){ if(bmp.rgbData) free(bmp.rgbData); if(yuv.Y) free(yuv.Y); if(yuv.U) free(yuv.U); if(yuv.V) free(yuv.V);}
bmp2yuv.cpp
#include <stdio.h>#include <windows.h>#include <math.h>#include "global.h"#include "bmp2yuv.h"extern BMPSTRUCT bmp;extern YUVSTRUCT yuv;bool MakePalette(FILE * pFile,BITMAPFILEHEADER &file_h,BITMAPINFOHEADER & info_h,RGBQUAD *pRGB_out);void ReadRGB(FILE * pFile,BITMAPFILEHEADER & file_h,BITMAPINFOHEADER & info_h,unsigned char * rgbDataOut){ unsigned long Loop,iLoop,jLoop,width,height,w,h; unsigned char mask,*Index_Data,* Data; if (((info_h.biWidth/8*info_h.biBitCount)%4) == 0) w = info_h.biWidth; else w = (info_h.biWidth*info_h.biBitCount+31)/32*4; if ((info_h.biHeight%2) == 0) h = info_h.biHeight; else h = info_h.biHeight + 1; width = w/8*info_h.biBitCount; height = h; Index_Data = (unsigned char *)malloc(height*width); Data = (unsigned char *)malloc(height*width); fseek(pFile,file_h.bfOffBits,0); if(fread(Index_Data,height*width,1,pFile) != 1) { printf("read file error!\n\n"); exit(0); } for ( iLoop = 0;iLoop < height;iLoop ++) for (jLoop = 0;jLoop < width;jLoop++) { Data[iLoop*width+jLoop] = Index_Data[(height-iLoop-1)*width+jLoop]; } switch(info_h.biBitCount) { case 24: memcpy(rgbDataOut,Data,height*width); if(Index_Data) free(Index_Data); if(Data) free(Data); return; case 16: if(info_h.biCompression == BI_RGB) { for (Loop = 0;Loop < height * width;Loop +=2) { *rgbDataOut = (Data[Loop]&0x1F)<<3; *(rgbDataOut + 1) = ((Data[Loop]&0xE0)>>2) + ((Data[Loop+1]&0x03)<<6); *(rgbDataOut + 2) = (Data[Loop+1]&0x7C)<<1; rgbDataOut +=3; } } if(Index_Data) free(Index_Data); if(Data) free(Data); return; default: RGBQUAD *pRGB = (RGBQUAD *)malloc(sizeof(RGBQUAD)*(unsigned char)pow(float(2),info_h.biBitCount)); int temp = sizeof(pRGB); if(!MakePalette(pFile,file_h,info_h,pRGB)) printf("No palette!\n\n"); for (Loop=0;Loop<height*width;Loop++) { switch(info_h.biBitCount) { case 1: mask = 0x80; break; case 2: mask = 0xC0; break; case 4: mask = 0xF0; break; case 8: mask = 0xFF; } int shiftCnt = 1; while (mask) { unsigned char index = mask == 0xFF ? Data[Loop] : ((Data[Loop] & mask)>>(8 - shiftCnt * info_h.biBitCount)); * rgbDataOut = pRGB[index].rgbBlue; * (rgbDataOut+1) = pRGB[index].rgbGreen; * (rgbDataOut+2) = pRGB[index].rgbRed; if(info_h.biBitCount == 8) mask =0; else mask >>= info_h.biBitCount; rgbDataOut+=3; shiftCnt ++; } } if(Index_Data) free(Index_Data); if(Data) free(Data);// if(pRGB)// free(pRGB); }}bool MakePalette(FILE * pFile,BITMAPFILEHEADER &file_h,BITMAPINFOHEADER & info_h,RGBQUAD *pRGB_out){ if ((file_h.bfOffBits - sizeof(BITMAPFILEHEADER) - info_h.biSize) == sizeof(RGBQUAD)*pow(float(2),info_h.biBitCount)) { fseek(pFile,sizeof(BITMAPFILEHEADER)+info_h.biSize,0); fread(pRGB_out,sizeof(RGBQUAD),(unsigned int)pow(float(2),info_h.biBitCount),pFile); return true; } else return false;}float RGBYUV02990[256],RGBYUV05870[256],RGBYUV01140[256];float RGBYUV01684[256],RGBYUV03316[256];float RGBYUV04187[256],RGBYUV00813[256];void initLookupTable();bool RGB2YUV(unsigned long w,unsigned long h,unsigned char * rgbData,unsigned char * y,unsigned char * u,unsigned char *v){ initLookupTable();//初始化查找表 unsigned char *ytemp = NULL; unsigned char *utemp = NULL; unsigned char *vtemp = NULL; utemp = (unsigned char *)malloc(w*h); vtemp = (unsigned char *)malloc(w*h); unsigned long i,nr,ng,nb,nSize; //对每个像素进行 rgb -> yuv的转换 for (i=0,nSize=0;nSize<w*h*3;nSize+=3) { nb = rgbData[nSize]; ng = rgbData[nSize+1]; nr = rgbData[nSize+2]; y[i] = (unsigned char)(RGBYUV02990[nr]+RGBYUV05870[ng]+RGBYUV01140[nb]); utemp[i] = (unsigned char)(-RGBYUV01684[nr]-RGBYUV03316[ng]+nb/2+128); vtemp[i] = (unsigned char)(nr/2-RGBYUV04187[ng]-RGBYUV00813[nb]+128); i++; } //对u信号及v信号进行采样 int k = 0; for (i=0;i<h;i+=2) for(unsigned long j=0;j<w;j+=2) { u[k]=(utemp[i*w+j]+utemp[(i+1)*w+j]+utemp[i*w+j+1]+utemp[(i+1)*w+j+1])/4; v[k]=(vtemp[i*w+j]+vtemp[(i+1)*w+j]+vtemp[i*w+j+1]+vtemp[(i+1)*w+j+1])/4; k++; } //对y、u、v 信号进行抗噪处理 for (i=0;i<w*h;i++) { if(y[i]<16) y[i] = 16; if(y[i]>235) y[i] = 235; } for(i=0;i<h*w/4;i++) { if(u[i]<16) u[i] = 16; if(v[i]<16) v[i] = 16; if(u[i]>240) u[i] = 240; if(v[i]>240) v[i] = 240; } if(utemp) free(utemp); if(vtemp) free(vtemp); return true;}void initLookupTable(){ for (int i=0;i<256;i++) { RGBYUV02990[i] = (float)0.2990 * i; RGBYUV05870[i] = (float)0.5870 * i; RGBYUV01140[i] = (float)0.1140 * i; RGBYUV01684[i] = (float)0.1684 * i; RGBYUV03316[i] = (float)0.3316 * i; RGBYUV04187[i] = (float)0.4187 * i; RGBYUV00813[i] = (float)0.0813 * i; }}FILE *OpenBmp(const char *strFileName,const char *strMode){ return fopen(strFileName,strMode);}FILE *OpenYuv(const char *strFileName,const char *strMode){ return fopen(strFileName,strMode);}bool ReadBmp(FILE *bmpFile){ if(fread(&bmp.file_header,sizeof(BITMAPFILEHEADER),1,bmpFile) != 1) { printf("read file header error!\n\n"); return false; } if (bmp.file_header.bfType != 0x4D42) { printf("Not bmp file!\n\n"); return false; } if(fread(&bmp.info_header,sizeof(BITMAPINFOHEADER),1,bmpFile) != 1) { printf("read info header error!\n\n"); return false; } if (((bmp.info_header.biWidth/8*bmp.info_header.biBitCount)%4) == 0) bmp.width = bmp.info_header.biWidth; else bmp.width = (bmp.info_header.biWidth*bmp.info_header.biBitCount+31)/32*4; if ((bmp.info_header.biHeight%2) == 0) bmp.height = bmp.info_header.biHeight; else bmp.height = bmp.info_header.biHeight + 1; bmp.rgbData = (unsigned char *)malloc(bmp.height*bmp.width*3); memset(bmp.rgbData,0,bmp.height*bmp.width*3); yuv.Y = (unsigned char * )malloc(bmp.height*bmp.width); yuv.U = (unsigned char * )malloc((bmp.height*bmp.width)/4); yuv.V = (unsigned char * )malloc((bmp.height*bmp.width)/4); printf("This is a %d bits image!\n",bmp.info_header.biBitCount); printf("\nbmp size: \t%d X %d\n\n",bmp.info_header.biWidth,bmp.info_header.biHeight); ReadRGB(bmpFile,bmp.file_header,bmp.info_header,bmp.rgbData); return true;}bool WriteYuv(FILE *outFile){ unsigned int size = bmp.width*bmp.height; if(fwrite(yuv.Y,1,size,outFile) != size) return false; if (fwrite(yuv.U,1,size/4,outFile) != size/4) return false; if(fwrite(yuv.V,1,size/4,outFile) != size/4) return false; return true;}bool DO_DPCM(void * yBuf, FILE * quanBuf, FILE *rebuildBuf, unsigned int width, unsigned int height){ unsigned char *y_buffer = NULL; unsigned char *quan_buffer = NULL; unsigned char *rebuild_buffer = NULL; int immediate = 0; int i = 0; int j = 0; y_buffer = (unsigned char *)yBuf;//定义指针指向原始图像缓冲区 quan_buffer = (unsigned char *)malloc(width*height*sizeof(unsigned char));//定义指针指向预测误差图像缓冲区并开辟空间 rebuild_buffer = (unsigned char *)malloc(width*height*sizeof(unsigned char));//定义指针指向重建图像缓冲区并开辟空间 for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { if (j == 0) { /*immediate先是为量化后的预测误差。 后用来存放反量化后的预测误差。*/ immediate = ((int)*(y_buffer+i*width+j) - 128)/2+128; *(quan_buffer+i*width+j) = (unsigned char)immediate; immediate = (*(quan_buffer+i*width+j) - 128) * 2+128; *(rebuild_buffer+i*width+j) = (unsigned char)immediate; //y_buffer++; //quan_buffer++; //rebuild_buffer++; } else { immediate = (*(y_buffer+i*width+j) - *(rebuild_buffer+i*width+j-1))/2+128; *(quan_buffer+i*width+j) = (unsigned char)immediate; immediate = (*(quan_buffer+i*width+j) - 128) * 2 + *(rebuild_buffer+i*width+j - 1); *(rebuild_buffer+i*width+j) =(unsigned char)immediate; // y_buffer++; //quan_buffer++; //rebuild_buffer++; } } printf("i:%d",i); } //FILE *rebuild_bufferfile; //FILE *quanBuffile; for(i=0;i<width*height/4;i++) { *(yuv.U+i)=128; *(yuv.V+i)=128; } fwrite(rebuild_buffer,1,width*height,rebuildBuf); fwrite(yuv.U,1,width*height/4,rebuildBuf); fwrite(yuv.V,1,width*height/4,rebuildBuf); fwrite(quan_buffer,1,width*height,quanBuf); fwrite(yuv.U,1,width*height/4,quanBuf); fwrite(yuv.V,1,width*height/4,quanBuf); free(quan_buffer); free(rebuild_buffer); return true;}bool CloseYuv(FILE * file){ if(file) { fclose(file); return true; } return false;}bool CloseBmp(FILE *file){ if(file) { fclose(file); return true; } return false;}
阅读全文
0 0
- 实验四-dpcm编码
- 实验四 DPCM编码
- 实验四 DPCM编码
- 实验四:DPCM编码
- 数据压缩实验四:DPCM编码
- 数据压缩实验四:DPCM编码
- 实验四——DPCM编码
- 【实验五】DPCM编码
- 实验4 DPCM编码
- 【数据压缩】实验四 DPCM
- 数据压缩实验4-DPCM编码
- 数据压缩实验四--dpcm压缩系统
- DPCM编码
- DPCM编码
- 实验四 DPCM 压缩系统的实现和分析
- 数据压缩实验四:DPCM 压缩系统的实现和分析
- 数据压缩实验四 DPCM压缩系统的实现与分析
- 《数据压缩》实验报告四·DPCM编解码
- ajax的三种方式请求
- Android AbsoluteLayout(绝对)、RelativeLayout(相对)、RTL(RightToLeth)(布局小结二)
- 微信小程序例子——获取微信群唯一标识openGId
- [JAVA学习笔记-96]ThreadLocal
- UBUNTU16.10系统,显卡GTX1070,鼠标一直在左上角
- 实验四 DPCM编码
- download
- Python语法第3讲:数组
- Windows无法格式化改卷,改卷已脱机, 请尝试首先向改卷分配驱动器号或路径使其联机
- loadrunner GUI界面性能测试
- php 替换敏感字符串
- 数据库最常见的10个安全问题
- 接着很久以前的贪吃蛇
- [JAVA学习笔记-97]ActiveObject模式的Scheduler的关键实现