ffmpeg源码分析--16.bmp格式分析及raw与bmp的相互转换
来源:互联网 发布:dubbo 视频教程 源码 编辑:程序博客网 时间:2024/05/18 01:09
1.1 bmp头由两部分组成
包含14个字节的BITMAPFILEHEADER及40个字节的BITMAPINFOHEADER
1.2 以下两个表引自 《BMP 头文件格式》
http://blog.csdn.net/searchsun/article/details/4787472
BITMAPFILEHEADER:
bfType
说明文件的类型,该值必需是0x4D42,也就是字符'BM'。
bfSize
说明该位图文件的大小,用字节为单位
bfReserved1
保留,必须设置为0
bfReserved2
保留,必须设置为0
bfOffBits
说明从文件头开始到实际的图象数据之间的字节的偏移量。这个参数是非常有用的,因为位图信息头和调色板的长度会根据不同情况而变化,所以你可以用这个偏移值迅速的从文件中读取到位数据。
BITMAPINFOHEADER:
biSize
说明BITMAPINFOHEADER结构所需要的字数。
biWidth
说明图象的宽度,以象素为单位。
biHeight
说明图象的高度,以象素为单位。注:这个值除了用于描述图像的高度之外,它还有另一个用处,就是指明该图像是倒向的位图,还是正向的位图。如果该值是一个正数,说明图像是倒向的,如果该值是一个负数,则说明图像是正向的。大多数的BMP文件都是倒向的位图,也就是时,高度值是一个正数。
biPlanes
为目标设备说明位面数,其值将总是被设为1。
biBitCount
说明比特数/象素,其值为1、4、8、16、24、或32。但是由于我们平时用到的图像绝大部分是24位和32位的,所以我们讨论这两类图像。
biCompression
说明图象数据压缩的类型,同样我们只讨论没有压缩的类型:BI_RGB。
biSizeImage
说明图象的大小,以字节为单位。当用BI_RGB格式时,可设置为0。
biXPelsPerMeter
说明水平分辨率,用象素/米表示。
biYPelsPerMeter
说明垂直分辨率,用象素/米表示。
biClrUsed
说明位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)。
biClrImportant
说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。
以下是从一张240 x 320 x 32用二进制分析出来的
- 0000000: 424d 36b0 0400 0000 0000 3600 0000 2800 BM6.......6...(.
- 0000010: 0000 f000 0000 4001 0000 0100 2000 0000 ......@..... ...
- 0000020: 0000 00b0 0400 0000 0000 0000 0000 0000 ................
- 0000030: 0000 0000 0000 ......
- 14个字节的BITMAPFILEHEADER:
- bfType 2B--> 424d即文件的类型,该值必需是0x4D42,也就是字符'BM'
- bfSize 4B--> 36b0 0400 --> 0x0004b036即文件的大小是307254字节=240*320*4+14+40
- bfResv 2B--> 0000 -->必须设置为0
- bfResv 2B--> 0000 -->必须设置为0
- bfOffset 4B--> 3600 0000 -->0x36=54即从文件头开始到实际的图象数据之间的字节的偏移量是54=14+40
- 40个字节的BITMAPINFOHEADER:
- biSize 4B-->2800 0000 -->0x28--> 40即BITMAPINFOHEADER结构所需要的字数是40
- biWidth 4B-->f000 0000 -->0xf0即图像的宽度是0xf0=240象素
- biHeight 4B-->4001 0000 -->0x0140即图像的高度是0x140=320象素
- biPlanes 2B-->0100 -->为目标设备说明位面数,其值将总是被设为1。
- biBitCount 2B-->2000 -->比特数/象素,即32bit一个象素
- biCompres 4B-->0000 0000 -->0代表没有压缩
- biSizeImage 4B-->00b0 0400 -->0x0004b000=307200-->图像中的数据大小,即去掉头之后的图像数据大小
- biXPelsPerMeter 4B-->0000 0000 -->水平分辨率,用象素/米表示
- biYPelsPerMeter 4B-->0000 0000 -->垂直分辨率,用象素/米表示
- biClrUsed 4B-->0000 0000 -->说明位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)。
- biClrImportant 4B-->0000 0000 -->说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。
注意: BMP存储的图像数据是--> 从左下角的像素开始 到最后的右上角像素
二.rgb的raw图像与bmp之间的相互转化
2.1 将rgb的raw图像转为bmp
原先只是以为加个bmp头就可以了,没想到里面还有小细节需要注意的:
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #pragma pack(1) //结构体要按字节对齐
- typedef struct __BITMAPFILEHEADER__
- {
- u_int16_t bfType;
- u_int32_t bfSize;
- u_int16_t bfReserved1;
- u_int16_t bfReserved2;
- u_int32_t bfOffBits;
- }BITMAPFILEHEADER;
- typedef struct __BITMAPINFOHEADER
- {
- u_int32_t biSize;
- u_int32_t biWidth;
- u_int32_t biHeight;
- u_int16_t biPlanes;
- u_int16_t biBitCount;
- u_int32_t biCompression;
- u_int32_t biSizeImage;
- u_int32_t biXPelsPerMeter;
- u_int32_t biYPelsPerMeter;
- u_int32_t biClrUsed;
- u_int32_t biClrImportant;
- }BITMAPINFOHEADER;
- #define BYTE_PER_PIX 3
- int create_bmp_header(BITMAPFILEHEADER* bmphead, BITMAPINFOHEADER* infohead, int w, int h)
- {
- bmphead->bfType = 0x4D42; //must be 0x4D42='BM'
- bmphead->bfSize= w*h*BYTE_PER_PIX+14+40;
- bmphead->bfReserved1= 0x00;
- bmphead->bfReserved2= 0x00;
- bmphead->bfOffBits = 14+40;
- infohead->biSize = sizeof(BITMAPINFOHEADER);
- infohead->biWidth = w;
- infohead->biHeight = -h; //特别注意:引自参考文章"BMP图片从最后一个点开始扫描,显示时图片是倒着的,所以用-height,这样图片就正了"
- infohead->biPlanes = 1;
- infohead->biBitCount = BYTE_PER_PIX*8;
- infohead->biCompression= 0;
- infohead->biSizeImage= w*h*BYTE_PER_PIX;//640 * 480 * 3;
- infohead->biXPelsPerMeter= 0x0;
- infohead->biYPelsPerMeter= 0x0;
- infohead->biClrUsed = 0;
- infohead->biClrImportant = 0;
- return 0;
- }
- int main ( int argc, char *argv[] )
- {
- char* pbuf=NULL;
- char* pRGBbuf=NULL;
- int w = 640;
- int h = 480;
- char raw_file[] = "./640_480.raw";
- char bmp_file[] = "./out.bmp";
- FILE * raw_fp = NULL;
- FILE * bmp_fp = NULL;
- int i;
- char t_ch;
- BITMAPFILEHEADER bmphead;
- BITMAPINFOHEADER infohead;
-
- pbuf = (char*)malloc(w*h*BYTE_PER_PIX*sizeof(char));
- pRGBbuf = (char*)malloc(w*h*BYTE_PER_PIX*4*sizeof(char));
- printf("sizeof(header)=%d\n",sizeof(bmphead));
- printf("sizeof(info)=%d\n",sizeof(infohead));
- //prepare for bmp write
- if (NULL == (raw_fp = fopen(raw_file,"rb")))
- {
- printf("error: %s not found\n",raw_file);
- return -1;
- }
- if (NULL == (bmp_fp = fopen(bmp_file,"wb")))
- {
- printf("error: %s not found\n",bmp_file);
- return -1;
- }
- create_bmp_header(&bmphead, &infohead, w, h);
- fwrite(&bmphead, 14, 1, bmp_fp);
- fwrite(&infohead, 40, 1, bmp_fp);
-
- fread(pbuf, w*h*BYTE_PER_PIX, 1, raw_fp);
- for(i=0; i<w*h*BYTE_PER_PIX; i+=BYTE_PER_PIX) //特别注意,这儿的BGR转RGB
- {
- t_ch = pbuf[i];
- pbuf[i] = pbuf[i+2];
- pbuf[i+2] = t_ch;
- }
- fwrite(pbuf, w*h*BYTE_PER_PIX, 1, bmp_fp);
- free(pbuf);
- fclose(raw_fp);
- fclose(bmp_fp);
- printf("over\n");
- return EXIT_SUCCESS;
- }
2.3 将bmp转为raw图像
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <math.h>
- #pragma pack(1)
- typedef struct __BITMAPFILEHEADER__
- {
- u_int16_t bfType;
- u_int32_t bfSize;
- u_int16_t bfReserved1;
- u_int16_t bfReserved2;
- u_int32_t bfOffBits;
- }BITMAPFILEHEADER;
- typedef struct __BITMAPINFOHEADER
- {
- u_int32_t biSize;
- u_int32_t biWidth;
- u_int32_t biHeight;
- u_int16_t biPlanes;
- u_int16_t biBitCount;
- u_int32_t biCompression;
- u_int32_t biSizeImage;
- u_int32_t biXPelsPerMeter;
- u_int32_t biYPelsPerMeter;
- u_int32_t biClrUsed;
- u_int32_t biClrImportant;
- }BITMAPINFOHEADER;
- int translate_bmp2raw(FILE* raw_fp, FILE* bmp_fp)
- {
- int i, len;
- int w, h, bpp; //bpp-->byte_per_pix
- char* p_temp = NULL;
- BITMAPFILEHEADER bmphead;
- BITMAPINFOHEADER infohead;
- if( (NULL==raw_fp) || (NULL==bmp_fp))
- return -1;
- len = sizeof(bmphead)+sizeof(infohead);
- printf("len=%d\n",len);
- p_temp = (char*)malloc(len*sizeof(char));
- if(p_temp == NULL)
- {
- printf("malloc error\n");
- return -1;
- }
- fread(p_temp, len, 1, bmp_fp);
- memcpy(&bmphead, p_temp, sizeof(bmphead));
- memcpy(&infohead, p_temp+sizeof(bmphead), sizeof(infohead));
- if(bmphead.bfType != 0x4D42) //must be 0x4D42='BM'
- {
- printf("not a bmp file\n");
- return -1;
- }
- if(infohead.biBitCount < 24)
- {
- printf("error: now bitCount=%d < 24bit\n", infohead.biBitCount);
- return -1;
- }
- free(p_temp);
- w = infohead.biWidth;
- h = infohead.biHeight;
- bpp = infohead.biBitCount/8;
- printf("w=%d,h=%d,bitcount=%d\n", w, h, bpp);
- p_temp = (char*)malloc(w*h*bpp);
- if(p_temp == NULL)
- {
- printf("malloc w*h*bpp error\n");
- return -1;
- }
- fread(p_temp, w*h*bpp, 1, bmp_fp);
- fwrite(p_temp, w*h*bpp, 1, raw_fp);
- free(p_temp);
- return 0;
- }
- int main ( int argc, char *argv[] )
- {
- char* pbuf=NULL;
- char bmp_file[] = "./240_320.bmp";
- char raw_file[] = "./240_320.yuv";
- FILE * raw_fp = NULL;
- FILE * bmp_fp = NULL;
- if (NULL == (bmp_fp = fopen(bmp_file,"rb")))
- {
- printf("error: %s not found\n",bmp_file);
- return -1;
- }
- if (NULL == (raw_fp = fopen(raw_file,"wb")))
- {
- printf("error: %s not found\n",raw_file);
- return -1;
- }
-
- translate_bmp2raw(raw_fp, bmp_fp);
- fclose(raw_fp);
- fclose(bmp_fp);
- printf("over\n");
- return EXIT_SUCCESS;
- }
注意1:刚开始生成的bmp里面图像都是倒着的,参考下面的文章
《将rgb图像数据保存为BMP格式图片的方法》
http://blog.csdn.net/chyxwzn/article/details/8443883
才知道BMP图片从最后一个点开始扫描,显示时图片是倒着的,所以用-height,这样图片就正了
注意2:刚开始生成的bmp里面图像BRG转一下RGB才能正常显示
所以需要加一个转换RB转换
- ffmpeg源码分析--16.bmp格式分析及raw与bmp的相互转换
- BMP格式的分析
- BCB实现BMP图片的RGB分解,BMP与JPG格式的相互转换
- Raw格式转换为Bmp格式
- BMP格式分析
- BMP格式实例分析
- OpenCV的IplImage与BMP相互转换
- BMP与IplImage相互转换
- BMP与IplImage相互转换
- BMP与IplImage相互转换
- BMP与IplImage相互转换
- IplImage与BMP相互转换
- BMP与IplImage相互转换
- BMP与PPM格式的转换
- BMP格式图片文件分析
- BMP格式图片文件分析
- OPENCV应用中BMP与IPLIAMGE图像格式的相互转换及源代码
- 位图(BMP)文件头格式及数据分析
- 你好!博客
- 一个TeeChart插件中添加多条曲线的方法
- ROS进二阶学习笔记(1) TF 学习笔记3 -- TF Listener 编写 (Python)and Adding frame(Python)
- biliobs 编译问题
- Youki的Matlab命名规则
- ffmpeg源码分析--16.bmp格式分析及raw与bmp的相互转换
- JS函数与面向对象
- JavaScript懒加载代码
- java面试题--java基础--2
- opengl学习---1.ubuntu下搭建opengl开发环境及demo
- 长时间停留在calculating requirements and dependencies 的解决方案
- Android生命周期巩固笔记
- opengl学习---2.学习opengl的一些代码
- ue4 Xml文件读取小结