一.实验原理:BMP文件的结构
(1)位图文件头的结构`
typedef struct tagBITMAPFILEHEADER {
WORD bfType;/*说明文件的类型*/
DWORD bfSize;/*说明文件的大小,用字节为单位*/
/*注意此处的字节序问题*/
WORD bfReserved1; /* 保留,设置为0 */
WORD bfReserved2; /* 保留,设置为0 */
DWORD bfOffBits; /* 说明从BITMAPFILEHEADER结构开始到实际的图像数据之间的字节偏移量 */
} BITMAPFILEHEADER;
(2)位图信息头的内容
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;
(3)调色板包含的内容:
`图像位深度小于等于8bit时调用调色板,调色板中不保存每个像素的RGB值,而是将颜色信息制成表格,通过索引来确定像素的RGB值。比如图像位深度为8bit时,表格中则有2^8 256个数值。
二.实验流程:
1.程序初始化(打开两个文件、定义变量和缓冲区等
2. 读取BMP文件,抽取或生成RGB数据写入缓冲区读位图文件头:判断是否可读出、判断是否是BMP文件判断像素的实际点阵数开辟缓冲区,读数据,倒序存放根据每像素位数的不同,执行不同的操作:
8bit以下:构造调色板位与移位取像素数据查调色板写RGB缓冲区
16bit:位与移位取像素数据转换8bit彩色分量写RGB缓冲区
24bit:直接取像素数据写RGB缓冲区
3.调用RGB2YUV的函数实现RGB到YUV数据的转换
4.写YUV文件
5.程序收尾工作(关闭文件,释放缓冲区)
三.实验代码:
main.cpp部分:
ReadRGB.cpp:
四.实验结果及分析
实验效果:
五.错误分析
*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;
在这段代码中一开始使用的是rgbbuf指针,在执行完这段循环后,rgbbuf已经指向了图像的最后,在接下来调用YUV2RGB函数是,仍要使用rgbbuf,因此此时的rgbbuf已经超出了开空间的范围,在运行时出现了错误。因此通过rgb=rgbbuf,将这段代码中的rgbbuf改为rgb,来使得rgbbuf指向的值改变的同时,rgbbuf指向的地址值不变。
收获:学习到了结构体、结构体指针的使用方法,掌握了bmp文件的格式和bmp如何转换成yuv的办法。