数据压缩实验二:bmp转yuv格式实验报告
2017-03-23 19:26
387 查看
一:实验基本原理
1.BMP文件格式
典型的 BMP 图像文件由四部分组成:
( 1) 位图头文件数据结构,它包含 BMP 图像文件的类型、显示内容等信息;
( 2) 位图信息数据结构,它包含有 BMP 图像的宽、高、压缩方法,以及定义颜色等信息;
( 3) 调色板,这个部分是可选的,有些位图需要调色板,有些位图,比如真彩色图( 24位的 BMP)就不需要调色板;
( 4) 位图数据,这部分的内容根据 BMP 位图使用的位数不同而不同,在 24 位图中直接使用 RGB,而其他的小于 24 位的使用调色板中颜色索引值。
位图文件头主要包括:
U=-0.1684R-0.3316G+0.5B
V=0.5R-0.4187G-0.0813B
二:实验的基本流程:
1.命令行参数的设置:工程->设置->调试
这里将5张不同的图片写入一张yuv文件中,所以选择输入5张bmp图片。
2.程序初始化(打开两个文件、定义变量和缓冲区等)
这里开辟了4个缓冲区,分别为rgbbuf、ybuf、ubuf和vbuf。
3.读取BMP文件,抽取或生成RGB数据写入缓冲区
4.调用RGB2YUV的函数实现RGB到YUV数据的转换
5.写YUV文件
6.程序收尾工作(关闭文件,释放缓冲区)
三:关键代码及其分析
main函数所有代码:
RGB2YUV函数代码在实验一中已有给出,这里不再赘述。
三:实验结果及其分析
原始的五张24位bmp图像:
写入图像后的yuv文件:
错误以及调试:
1:这段程序如果存在,图像颜色不正常显示,而是显示如下:
错误原因以及调试:
未知
2.插入多组图像数据时只显示最后张图像
错误原因以及调试:
四:实验结论
bmp转yuv可以通过抽取bmp中的图像数据并保存到rgb缓存中,再调用rgb转yuv函数的方法来实现。可以通过循环写入和多图写入的方法来实现一个yuv文件的一图多帧和多图存放。
1.BMP文件格式
典型的 BMP 图像文件由四部分组成:
( 1) 位图头文件数据结构,它包含 BMP 图像文件的类型、显示内容等信息;
( 2) 位图信息数据结构,它包含有 BMP 图像的宽、高、压缩方法,以及定义颜色等信息;
( 3) 调色板,这个部分是可选的,有些位图需要调色板,有些位图,比如真彩色图( 24位的 BMP)就不需要调色板;
( 4) 位图数据,这部分的内容根据 BMP 位图使用的位数不同而不同,在 24 位图中直接使用 RGB,而其他的小于 24 位的使用调色板中颜色索引值。
位图文件头主要包括:
typedef struct tagBITMAPFILEHEADER { WORD bfType; /* 说明文件的类型 */ DWORD bfSize; /* 说明文件的大小,用字节为单位 */ WORD bfReserved1; /* 保留,设置为 0 */ WORD bfReserved2; /* 保留,设置为 0 */ DWORD bfOffBits; /* 说明从 BITMAPFILEHEADER 结构开始到实际的图像数据之间的字节偏移量 */ } BITMAPFILEHEADER;位图信息头主要包括:
typedef struct tagBITMAPINFOHEADER { DWORD biSize; /* 说明结构体所需字节数 */ LONG biWidth; /* 以像素为单位说明图像的宽度 */ LONG biHeight; /* 以像素为单位说明图像的高速 */ WORD biPlanes; /* 说明位面数,必须为 1 */ WORD biBitCount; /* 说明位数/像素, 1、 2、 4、 8、 24 */ DWORD biCompression; /* 说明图像是否压缩及压缩类型 BI_RGB, BI_RLE8, BI_RLE4,BI_BITFIELDS */ DWORD biSizeImage; /* 以字节为单位说明图像大小,必须是 4 的整数倍*/ LONG biXPelsPerMeter; /*目标设备的水平分辨率,像素/米 */ LONG biYPelsPerMeter; /*目标设备的垂直分辨率,像素/米 */ DWORD biClrUsed; /* 说明图像实际用到的颜色数,如果为 0,则颜色数为 2 的 biBitCount次方 */ DWORD biClrImportant; /*说明对图像显示有重要影响的颜色索引的数目,如果是 0,表示都重要。 */ } BITMAPINFOHEADER;调色板:
typedef struct tagRGBQUAD { BYTE rgbBlue; /*指定蓝色分量*/ BYTE rgbGreen; /*指定绿色分量*/ BYTE rgbRed; /*指定红色分量*/ BYTE rgbReserved; /*保留,指定为 0*/ } RGBQUAD;2.RGB到YUV文件的转换公式
U=-0.1684R-0.3316G+0.5B
V=0.5R-0.4187G-0.0813B
二:实验的基本流程:
1.命令行参数的设置:工程->设置->调试
这里将5张不同的图片写入一张yuv文件中,所以选择输入5张bmp图片。
2.程序初始化(打开两个文件、定义变量和缓冲区等)
这里开辟了4个缓冲区,分别为rgbbuf、ybuf、ubuf和vbuf。
3.读取BMP文件,抽取或生成RGB数据写入缓冲区
4.调用RGB2YUV的函数实现RGB到YUV数据的转换
5.写YUV文件
6.程序收尾工作(关闭文件,释放缓冲区)
三:关键代码及其分析
main函数所有代码:
#include<stdio.h> #include<windows.h> #include<stdlib.h> #include <malloc.h> #include "rgb2yuv.h" #define u_int8_t unsigned __int8 #define u_int unsigned __int32 #define u_int32_t unsigned __int32 int main(int argc,char *argv[]) { for(int m=0;m<5;m++)//这里的循环是为了多次写入不同图像数据 { //定义变量 char* bmpFileName = NULL; char* yuvFileName = NULL; bmpFileName = argv[1+m]; yuvFileName = argv[6]; u_int8_t* rgbBuf = NULL; u_int8_t* yBuf = NULL; u_int8_t* uBuf = NULL; u_int8_t* vBuf = NULL; int width,height; int i; int N=atoi(agv[7]); bool flip = false;//因为bmp中图像数据是倒序排放,rgb转yuv时,需要设置为倒序读取 u_int32_t videoFramesWritten = 0; //打开文件 FILE *bmpFile= fopen(bmpFileName, "rb"); if (bmpFile == NULL) { printf("can not find bmp file\n"); exit(1); } else { printf("The input bmp file is %s\n", bmpFileName); } FILE *yuvFile= fopen(yuvFileName, "ab");//有五组不同的图像数据写入,因此设置打开格式为“追加” if (yuvFile == NULL) { printf("can not find yuv file\n"); exit(1); } //读取文件头和信息头 BITMAPFILEHEADER File_header; BITMAPINFOHEADER Info_header; 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); } if(fread(&Info_header,sizeof(BITMAPINFOHEADER),1,bmpFile) != 1) { printf("read info header error!"); exit(0); } //开辟rgb缓冲区 width=(int)(Info_header.biWidth); height=(int)(Info_header.biHeight); rgbBuf = (u_int8_t*)malloc(width*height* 3); yBuf = (u_int8_t*)malloc(width*height); uBuf = (u_int8_t*)malloc((width*height) / 4); vBuf = (u_int8_t*)malloc((width*height) / 4); //这段代码先隐去,稍后再议 /* if(fread(rgbBuf,sizeof(bmpFile),1,bmpFile) != 1) { printf("read bmp 4000 file data error!"); exit(0); } */ //调用rgb转换成yuv函数 while (fread(rgbBuf, 1, width * height * 3, bmpFile)) { if(RGB2YUV (width, height,rgbBuf, yBuf,uBuf, vBuf, flip)) { printf("error"); return 0; } //溢出处理 for ( i = 0; i < width*height; i++) { if (yBuf[i] < 16) yBuf[i] = 16; if (yBuf[i] > 235) yBuf[i] = 235; } for ( i = 0; i < width*height/4; i++) { if (uBuf[i] < 16) uBuf[i] = 16; if (uBuf[i] > 240) uBuf[i] = 240; if (vBuf[i] < 16) vBuf[i] = 16; if (vBuf[i] > 240) vBuf[i] = 240; } //每张图片循环N帧,所以重复写入N组数据,N在命令行中设置 for(i=0;i<N;i++) { fwrite(yBuf, 1, width*height, yuvFile); fwrite(uBuf, 1, (width*height) / 4, yuvFile); fwrite(vBuf, 1, (width*height) / 4, yuvFile); ++videoFramesWritten; } } printf("\n%u %ux%u video frames written\n", videoFramesWritten, width,height); //释放缓冲区 free(rgbBuf); free(yBuf); free(uBuf); free(vBuf); //关闭打开的文件 fclose(bmpFile); fclose(yuvFile); } return(0); }
RGB2YUV函数代码在实验一中已有给出,这里不再赘述。
三:实验结果及其分析
原始的五张24位bmp图像:
写入图像后的yuv文件:
1:这段程序如果存在,图像颜色不正常显示,而是显示如下:
/* if(fread(rgbBuf,sizeof(bmpFile),1,bmpFile) != 1) { printf("read bmp file data error!"); exit(0); } */
错误原因以及调试:
未知
2.插入多组图像数据时只显示最后张图像
错误原因以及调试:
FILE *yuvFile= fopen(yuvFileName, "ab"); { printf("can not find yuv file\n"); exit(1); }错误原因:上面代码中的打开方式若设置为“wb”,则文件打开方式为重新写入并覆盖原数据而不是在其后追加了。
四:实验结论
bmp转yuv可以通过抽取bmp中的图像数据并保存到rgb缓存中,再调用rgb转yuv函数的方法来实现。可以通过循环写入和多图写入的方法来实现一个yuv文件的一图多帧和多图存放。
相关文章推荐
- 数据压缩第二次实验报告——用C语言实现bmp to yuv的图片格式转化
- 数据压缩第一次实验报告(rgb与yuv的转换)
- 数据压缩实验二:bmp转yuv格式实验报告
- 数据压缩原理与应用 图像文件的读写和转换(BMP2YUV)实验报告
- 数据压缩实验二 图像文件的读写和转换(bmp转yuv)
- 数据压缩原理实验1_实验报告
- 数据压缩实验一:yuv转rgb
- 数据压缩原理与应用之彩色空间转换 实验报告1
- 普通摄像头的数据输出格式YUV与mjpeg之间联系、DCT离散余弦变换去噪跟压缩
- 数据压缩原理实验5_实验报告
- 数据压缩原理实验6_实验报告
- 数据压缩实验一实验报告
- 数据压缩原理实验2_实验报告
- 数据压缩实验一:YUV转RGB
- 数据压缩原理实验4_实验报告
- 数据压缩实验一:yuv转rgb格式实验报告
- 数据压缩实验二:bmp2yuv
- BMP转YUV实验报告
- 普通摄像头的数据输出格式YUV与mjpeg之间联系、DCT离散余弦变换去噪跟压缩
- 数据压缩原理实验3_实验报告