数据压缩 实验四 DPCM压缩系统的实现和分析
来源:互联网 发布:我的老婆是警花知君txt 编辑:程序博客网 时间:2024/06/08 10:25
实验原理
DPCM是差分预测编码调制的缩写,是比较典型的预测编码系统。在DPCM系统中,需要注意的是预测器的输入是已经解码以后的样本。之所以不用原始样本来做预测,是因为在解码端无法得到原始样本,只能得到存在误差的样本。因此,在DPCM编码器中实际内嵌了一个解码器,如编码器虚线框中所示。
DPCM是差分预测编码调制的缩写,是比较典型的预测编码系统。在DPCM系统中,需要注意的是预测器的输入是已经解码以后的样本。之所以不用原始样本来做预测,是因为在解码端无法得到原始样本,只能得到存在误差的样本。因此,在DPCM编码器中实际内嵌了一个解码器,如编码器中虚线框中所示。
在一个DPCM系统中,有两个因素需要设计:预测器和量化器。理想情况下,预测器和量化器应进行联合优化。实际中,采用一种次优的设计方法:分别进行线性预测器和量化器的优化设计。
代码分析
main.cpp
#include<stdio.h>#include<stdlib.h>#include<malloc.h>#include<Windows.h>#include<math.h>#include"DPCM.h"#define u_int8_t unsigned __int8#define u_int unsigned __int32#define u_int32_t unsigned __int32BITMAPFILEHEADER File_header;BITMAPINFOHEADER Info_header;int main(int argc, char** argv){ bool flip = FALSE; //BMP图像倒序存储数据 需要翻转 char* bmpFileName = NULL; //输入 char* yuvFileName = NULL; //输出 char* deviationFileName = NULL; //误差 char* rebuildFileName = NULL; //重建 FILE* bmpFile = NULL; FILE* yuvFile = NULL; FILE* deviationFile = NULL; FILE* rebuildFile = NULL; u_int8_t* rgbBuf = NULL; u_int8_t* yBuf = NULL; u_int8_t* uBuf = NULL; u_int8_t* vBuf = NULL; u_int8_t* deviationBuf = NULL; u_int8_t* rebuildBuf = NULL; u_int frameWidth, frameHeight; //宽高 int i = 0, j = 0; bmpFileName = argv[1]; //输入 yuvFileName = argv[2]; //输出 deviationFileName = argv[3]; //误差 rebuildFileName = argv[4]; //重建 /////read files///// bmpFile = fopen(bmpFileName, "rb"); if (bmpFile == NULL) { printf("cannot find bmp file\n"); exit(1); } else { printf("The input bmp file is %s\n", bmpFileName); } yuvFile = fopen(yuvFileName, "wb"); if (yuvFile == NULL) { printf("cannot find yuv file\n"); exit(1); } else { printf("The output yuv file is %s\n", yuvFileName); } deviationFile = fopen(deviationFileName, "wb"); if (deviationFile == NULL) { printf("cannot find deviation file\n"); exit(1); } else { printf("The output deviation file is %s\n", deviationFileName); } rebuildFile = fopen(rebuildFileName, "wb"); if (rebuildFile == NULL) { printf("cannot find rebuild file\n"); exit(1); } else { printf("The output rebuild file is %s\n", rebuildFileName); } printf("\n"); /////read BMP fileheader & infoheader///// if (fread(&File_header, sizeof(BITMAPFILEHEADER), 1, bmpFile) != 1) { printf("read file header error!"); exit(0); } if (File_header.bfType != 0x4D42) { printf("Not bmp file!"); exit(0); } else { printf("this is a bmp file.\n"); } if (fread(&Info_header, sizeof(BITMAPINFOHEADER), 1, bmpFile) != 1) { printf("read info header error!"); exit(0); } printf("bitcount==%d\n", (unsigned char)Info_header.biBitCount); /////end read header///// frameWidth = Info_header.biWidth; //宽高赋值 frameHeight = Info_header.biHeight; /////开缓存区///// rgbBuf = (u_int8_t *)malloc(sizeof(u_int8_t)*frameHeight*frameWidth * 3); memset(rgbBuf, 0, frameHeight*frameWidth * 3); yBuf = (u_int8_t*)malloc(sizeof(u_int8_t)*frameHeight*frameWidth); uBuf = (u_int8_t*)malloc(sizeof(u_int8_t)*frameHeight*frameWidth / 4); vBuf = (u_int8_t*)malloc(sizeof(u_int8_t)*frameHeight*frameWidth / 4); deviationBuf = (u_int8_t*)malloc(sizeof(u_int8_t)*frameHeight*frameWidth); rebuildBuf = (u_int8_t*)malloc(sizeof(u_int8_t)*frameHeight*frameWidth); ReadRGB(rgbBuf, bmpFile, File_header, Info_header); if (RGB2YUV(frameWidth, frameHeight, rgbBuf, yBuf, uBuf, vBuf, flip)) { printf("Color transferring failed"); return 0; } printf("framewidth==%d,frameheight==%d.\n", frameWidth, frameHeight); //输出图像宽高 DO_DPCM(yBuf, deviationBuf, rebuildBuf,frameWidth,frameHeight); //进行DPCM编码 fwrite(yBuf, 1, frameWidth * frameHeight, yuvFile); //写输出文件 fwrite(deviationBuf, 1, frameHeight*frameWidth, deviationFile); fwrite(rebuildBuf, 1, frameHeight*frameWidth, rebuildFile); /////关缓存///// if (rgbBuf != NULL) free(rgbBuf); if (yBuf != NULL) free(yBuf); if (uBuf != NULL) free(uBuf); if (vBuf != NULL) free(vBuf); if (deviationBuf != NULL) free(deviationBuf); if (rebuildBuf != NULL) free(rebuildBuf); /////关文件///// if (bmpFile != NULL) fclose(bmpFile); if (yuvFile != NULL) fclose(yuvFile); if(deviationFile != NULL) fclose(deviationFile); if(rebuildFile != NULL) fclose(rebuildFile); system("pause"); return 0;}
DPCM.cpp
#include<Windows.h>#include<stdio.h>#include<math.h>#include"DPCM.h"static float RGBYUV02990[256], RGBYUV05870[256], RGBYUV01140[256];static float RGBYUV01684[256], RGBYUV03316[256];static float RGBYUV04187[256], RGBYUV00813[256];bool MakePalette(FILE * pFile, BITMAPFILEHEADER &file_h, BITMAPINFOHEADER & info_h, RGBQUAD *pRGB_out){ /*若图像开始位置与INFOHEADER结束处位置,还有pow(2, info_h.biBitCount)个 结构体RGBQUAQ的空间(颜色数为2的biBitCount次方,调色板为数组),则说明 该bmp图像有调色板。*/ if ((file_h.bfOffBits - sizeof(BITMAPFILEHEADER) - info_h.biSize) == sizeof(RGBQUAD)*pow(2.0, info_h.biBitCount)) { fseek(pFile, sizeof(BITMAPFILEHEADER) + info_h.biSize, 0); fread(pRGB_out, sizeof(RGBQUAD), (unsigned int)pow(2.0, info_h.biBitCount), pFile); return true; } else return false;}void ReadRGB(unsigned char * rgbbuf, FILE *bmpfile, BITMAPFILEHEADER &file_h, BITMAPINFOHEADER & info_h){ u_int Width = 0, Height = 0; long Loop = 0; unsigned char *bmpbuf = NULL; unsigned char *rgb = NULL; unsigned char mask = 0; int deltaw = 0; rgb = rgbbuf; if (((info_h.biWidth * info_h.biBitCount / 8) % 4) == 0) Width = info_h.biWidth*info_h.biBitCount / 8; else Width = (info_h.biWidth * info_h.biBitCount + 31) / 32 * 4; if ((info_h.biHeight % 2) == 0) Height = info_h.biHeight; else Height = info_h.biHeight + 1; deltaw = Width - info_h.biWidth * info_h.biBitCount / 8; bmpbuf = (unsigned char *)malloc(sizeof(unsigned char)*Height*Width); printf("word_width :%d , word_height: %d \n", Width, Height); RGBQUAD *pRGB = (RGBQUAD *)malloc(sizeof(RGBQUAD) * (unsigned int)pow(2.0, (double)info_h.biBitCount)); if (!MakePalette(bmpfile, file_h, info_h, pRGB)) { printf("No palette!\n"); //没有调色板 } fread(bmpbuf, 1, Height*Width, bmpfile); if (info_h.biBitCount == 24) //24位bmp { for (Loop = 0; Loop<Height*Width; Loop++) { if (deltaw != 0) { if (deltaw == 1) { if ((Loop + 1) % Width == 0) continue; } else if (deltaw == 2) { if ((Loop + 1) % Width == 0 || (Loop + 2) % Width == 0) continue; } else { if ((Loop + 1) % Width == 0 || (Loop + 2) % Width == 0 || (Loop + 3) % Width == 0) continue; } } *rgb = *(bmpbuf + Loop); rgb++; } } else if (info_h.biBitCount == 16) //16位bmp { for (Loop = 0; Loop < Height * Width; Loop += 2) { *rgb = (bmpbuf[Loop] & 0x1F) << 3; *(rgb + 1) = ((bmpbuf[Loop] & 0xE0) >> 2) + ((bmpbuf[Loop + 1] & 0x03) << 6); *(rgb + 2) = (bmpbuf[Loop + 1] & 0x7C) << 1; rgb += 3; } } else if (info_h.biBitCount == 32) //32位bmp { for (Loop = 0; Loop < info_h.biWidth*info_h.biHeight; Loop++) { *(rgb + 3 * Loop) = *(bmpbuf + 4 * Loop); *(rgb + 3 * Loop + 1) = *(bmpbuf + 4 * Loop + 1); *(rgb + 3 * Loop + 2) = *(bmpbuf + 4 * Loop + 2); } } else //其他位bmp { for (Loop = 0; Loop < Height*Width; Loop++) { if (deltaw != 0) { if (deltaw == 1) { if ((Loop + 1) % Width == 0) continue; } else if (deltaw == 2) { if ((Loop + 1) % Width == 0 || (Loop + 2) % Width == 0) continue; } else { if ((Loop + 1) % Width == 0 || (Loop + 2) % Width == 0 || (Loop + 3) % Width == 0) continue; } } switch (info_h.biBitCount) //蒙版 { case 1: mask = 0x80; //10000000 break; case 2: mask = 0xC0; //11000000 break; case 4: mask = 0xF0; //11110000 break; case 8: mask = 0xFF; //11111111 break; } int shiftCnt = 1; while (mask) { /*根据从数据中提取出的索引号index,以index为调色板数组下标去查询 数据中每info_h.biBitCount位所代表的颜色。 while 循环的次数: 1bit 图像 每字节循环8次 2bit 图像 每字节循环4次 4bit 图像 每字节循环2次 8bit 图像 每字节循环1次。 */ unsigned char index = mask == 0xFF ? bmpbuf[Loop] : ((bmpbuf[Loop] & mask) >> (8 - shiftCnt *info_h.biBitCount)); *rgb = pRGB[index].rgbBlue; *(rgb + 1) = pRGB[index].rgbGreen; *(rgb + 2) = pRGB[index].rgbRed; if (info_h.biBitCount == 8) mask = 0; else mask >>= info_h.biBitCount; rgb += 3; shiftCnt++; } } } if (pRGB != NULL) free(pRGB); if (bmpbuf != NULL) free(bmpbuf);}int RGB2YUV(int x_dim, int y_dim, void *bmp, void *y_out, void *u_out, void *v_out, int flip){ static int init_done = 0; long i, j, size; float yf, uf, vf; unsigned char *r, *g, *b; unsigned char *y, *u, *v; unsigned char *pu1, *pu2, *pv1, *pv2, *psu, *psv; unsigned char *y_buffer, *u_buffer, *v_buffer; unsigned char *sub_u_buf, *sub_v_buf; if (init_done == 0) { InitLookupTable(); init_done = 1; } if ((x_dim % 2) || (y_dim % 2)) return 1; size = x_dim * y_dim; y_buffer = (unsigned char *)y_out; sub_u_buf = (unsigned char *)u_out; sub_v_buf = (unsigned char *)v_out; u_buffer = (unsigned char *)malloc(size * sizeof(unsigned char)); v_buffer = (unsigned char *)malloc(size * sizeof(unsigned char)); if (!(u_buffer && v_buffer)) { if (u_buffer) free(u_buffer); if (v_buffer) free(v_buffer); return 2; } b = (unsigned char *)bmp; y = y_buffer; u = u_buffer; v = v_buffer; /////RGB to YUV///// if (!flip) { for (j = 0; j < y_dim; j++) { y = y_buffer + (y_dim - j - 1) * x_dim; u = u_buffer + (y_dim - j - 1) * x_dim; v = v_buffer + (y_dim - j - 1) * x_dim; for (i = 0; i < x_dim; i++) { g = b + 1; r = b + 2; yf = (RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]); uf = (-RGBYUV01684[*r] - RGBYUV03316[*g] + (*b) / 2 + 128); vf = ((*r) / 2 - RGBYUV04187[*g] - RGBYUV00813[*b] + 128); *y = (unsigned char)(yf>16 ? (yf>235 ? 235 : (unsigned char)yf) : 16); *u = (unsigned char)(uf>16 ? (uf>240 ? 240 : (unsigned char)uf) : 16); *v = (unsigned char)(vf>16 ? (vf>240 ? 240 : (unsigned char)vf) : 16); b += 3; y++; u++; v++; } } } else { for (i = 0; i < size; i++) { g = b + 1; r = b + 2; *y = (unsigned char)(RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]); *u = (unsigned char)(-RGBYUV01684[*r] - RGBYUV03316[*g] + (*b) / 2 + 128); *v = (unsigned char)((*r) / 2 - RGBYUV04187[*g] - RGBYUV00813[*b] + 128); b += 3; y++; u++; v++; } } for (j = 0; j < y_dim / 2; j++) { psu = sub_u_buf + j * x_dim / 2; psv = sub_v_buf + j * x_dim / 2; pu1 = u_buffer + 2 * j * x_dim; pu2 = u_buffer + (2 * j + 1) * x_dim; pv1 = v_buffer + 2 * j * x_dim; pv2 = v_buffer + (2 * j + 1) * x_dim; for (i = 0; i < x_dim / 2; i++) { *psu = (*pu1 + *(pu1 + 1) + *pu2 + *(pu2 + 1)) / 4; *psv = (*pv1 + *(pv1 + 1) + *pv2 + *(pv2 + 1)) / 4; psu++; psv++; pu1 += 2; pu2 += 2; pv1 += 2; pv2 += 2; } } free(u_buffer); free(v_buffer); return 0;}void InitLookupTable(){ int i; for (i = 0; i < 256; i++) RGBYUV02990[i] = (float)0.2990 * i; for (i = 0; i < 256; i++) RGBYUV05870[i] = (float)0.5870 * i; for (i = 0; i < 256; i++) RGBYUV01140[i] = (float)0.1140 * i; for (i = 0; i < 256; i++) RGBYUV01684[i] = (float)0.1684 * i; for (i = 0; i < 256; i++) RGBYUV03316[i] = (float)0.3316 * i; for (i = 0; i < 256; i++) RGBYUV04187[i] = (float)0.4187 * i; for (i = 0; i < 256; i++) RGBYUV00813[i] = (float)0.0813 * i;}void DO_DPCM(void * yBuf, void * deviationBuf, void *rebuildBuf, unsigned int width, unsigned int height){ unsigned char *ybuffer = NULL; unsigned char *deviationbuffer = NULL; unsigned char *rebuildbuffer = NULL; int deviation = 0; int i = 0, j = 0; ybuffer = (unsigned char *)yBuf; //原始图像缓冲区 deviationbuffer = (unsigned char *)deviationBuf; //误差图像缓冲区 rebuildbuffer = (unsigned char *)rebuildBuf; //重建图像缓冲区 for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { /*256级的灰度图像,预测值范围为[-255,255], 8bit量化则除以2,将预测值范围变为[-127,127], 再加128后可转到正常灰度显示 */ if (j == 0)//对第一个像素进行误差预测 { deviation = (*ybuffer - 128)/2+128;//量化后的预测误差 *deviationbuffer = (unsigned char)deviation; deviation = (*deviationbuffer - 128)*2+128;//反量化后的预测误差 *rebuildbuffer = (unsigned char)deviation; ybuffer++; deviationbuffer++; rebuildbuffer++; } else//对其余像素进行误差预测 { deviation = (*ybuffer - *(rebuildbuffer-1))/2+128;//量化后的预测误差 *deviationbuffer = (unsigned char)deviation; deviation = (*deviationbuffer - 128)*2 + *(rebuildbuffer - 1);//反量化后的预测误差 *rebuildbuffer = (unsigned char)deviation; ybuffer++; deviationbuffer++; rebuildbuffer++; } } }}
压缩性能比较:
预测误差图像都为明显的灰色,电平集中分布在128附近,量化过程中将量化误差抬升128电平所以表明实际预测误差值集中分布在 0 左右,证明对于正常图像,相邻像素之间存在很强的关联性,利用相关性对像素量化后进行压缩压缩比会很理想。
阅读全文
0 0
- 数据压缩实验四:DPCM 压缩系统的实现和分析
- 数据压缩实验四 DPCM 压缩系统的实现和分析
- 数据压缩 实验四 DPCM压缩系统的实现和分析
- 数据压缩 实验四 DPCM压缩系统的实现和分析
- 数据压缩实验四 DPCM压缩系统的实现与分析
- 数据压缩实验四——DPCM压缩系统的实现和分析
- 数据压缩原理与应用 实验四 DPCM 压缩系统的实现和分析
- 数据压缩原理 实验四 DPCM压缩系统的实现和分析
- 实验四 DPCM 压缩系统的实现和分析
- 实验四 DPCM压缩系统的实现和分析
- 实验四 DPCM压缩系统的实现和分析
- 【数据压缩】DPCM 压缩系统的实现和分析
- 数据压缩实验四--dpcm压缩系统
- DPCM 压缩系统的实现和分析
- DPCM 压缩系统的实现和分析
- DPCM 压缩系统的实现和分析
- 【数据压缩】实验四 DPCM
- 数据压缩实验四:DPCM编码
- php魔术函数__autoload
- STM32(1)
- 关于c++面向对象重债覆盖隐藏和虚函数表
- 读取CSV XLSX XLS文件
- java动态规划最小路径和
- 数据压缩 实验四 DPCM压缩系统的实现和分析
- getlasterrror用法
- JS-7-new
- 表格添加、删除某一行
- 一个简单的零配置命令行HTTP服务器
- Linux 数据压缩与归档
- NPC问题
- AC自动机模板【洛谷3796】
- Shell Sort