ffmpeg源码分析--16.bmp格式分析及raw与bmp的相互转换

来源:互联网 发布:dubbo 视频教程 源码 编辑:程序博客网 时间:2024/05/18 01:09
1.关于bmp的头
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,表示都重要。


1.3 bmp的header分析
以下是从一张240 x 320 x 32用二进制分析出来的
  1. 0000000: 424d 36b0 0400 0000 0000 3600 0000 2800 BM6.......6...(.
  2. 0000010: 0000 f000 0000 4001 0000 0100 2000 0000 ......@..... ...
  3. 0000020: 0000 00b0 0400 0000 0000 0000 0000 0000 ................
  4. 0000030: 0000 0000 0000                          ......

  5. 14个字节的BITMAPFILEHEADER
  6. bfType   2B--> 424d即文件的类型,该值必需是0x4D42,也就是字符'BM' 
  7. bfSize   4B--> 36b0 0400 --> 0x0004b036即文件的大小是307254字节=240*320*4+14+40
  8. bfResv   2B--> 0000 -->必须设置为0
  9. bfResv   2B--> 0000 -->必须设置为0
  10. bfOffset 4B--> 3600 0000 -->0x36=54即从文件头开始到实际的图象数据之间的字节的偏移量是54=14+40

  11. 40个字节的BITMAPINFOHEADER:
  12. biSize          4B-->2800 0000 -->0x28--> 40即BITMAPINFOHEADER结构所需要的字数是40
  13. biWidth         4B-->f000 0000 -->0xf0即图像的宽度是0xf0=240象素
  14. biHeight        4B-->4001 0000 -->0x0140即图像的高度是0x140=320象素
  15. biPlanes        2B-->0100      -->为目标设备说明位面数,其值将总是被设为1。
  16. biBitCount      2B-->2000      -->比特数/象素,即32bit一个象素
  17. biCompres       4B-->0000 0000 -->0代表没有压缩
  18. biSizeImage     4B-->00b0 0400 -->0x0004b000=307200-->图像中的数据大小,即去掉头之后的图像数据大小
  19. biXPelsPerMeter 4B-->0000 0000 -->水平分辨率,用象素/米表示
  20. biYPelsPerMeter 4B-->0000 0000 -->垂直分辨率,用象素/米表示
  21. biClrUsed       4B-->0000 0000 -->说明位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)。
  22. biClrImportant  4B-->0000 0000 -->说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。

知道这些内容了就可以把一个raw的数据写成bmp格式的图像文件
注意: BMP存储的图像数据是--> 从左下角的像素开始 到最后的右上角像素
二.rgb的raw图像与bmp之间的相互转化
2.1 将rgb的raw图像转为bmp
原先只是以为加个bmp头就可以了,没想到里面还有小细节需要注意的:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4. #pragma pack(1)                           //结构体要按字节对齐
  5. typedef struct __BITMAPFILEHEADER__
  6. {
  7.     u_int16_t bfType;
  8.     u_int32_t bfSize;
  9.     u_int16_t bfReserved1;
  10.     u_int16_t bfReserved2;
  11.     u_int32_t bfOffBits;
  12. }BITMAPFILEHEADER; 

  13. typedef struct __BITMAPINFOHEADER 
  14. { 
  15.     u_int32_t biSize; 
  16.     u_int32_t biWidth; 
  17.     u_int32_t biHeight; 
  18.     u_int16_t biPlanes; 
  19.     u_int16_t biBitCount; 
  20.     u_int32_t biCompression; 
  21.     u_int32_t biSizeImage; 
  22.     u_int32_t biXPelsPerMeter; 
  23.     u_int32_t biYPelsPerMeter; 
  24.     u_int32_t biClrUsed; 
  25.     u_int32_t biClrImportant; 
  26. }BITMAPINFOHEADER; 

  27. #define BYTE_PER_PIX 3
  28. int create_bmp_header(BITMAPFILEHEADER* bmphead, BITMAPINFOHEADER* infohead, int w, int h)
  29. {
  30.     bmphead->bfType = 0x4D42; //must be 0x4D42='BM'
  31.     bmphead->bfSize= w*h*BYTE_PER_PIX+14+40;
  32.     bmphead->bfReserved1= 0x00;
  33.     bmphead->bfReserved2= 0x00;
  34.     bmphead->bfOffBits = 14+40;

  35.     infohead->biSize = sizeof(BITMAPINFOHEADER);
  36.     infohead->biWidth = w; 
  37.     infohead->biHeight = -h;    //特别注意:引自参考文章"BMP图片从最后一个点开始扫描,显示时图片是倒着的,所以用-height,这样图片就正了"
  38.     infohead->biPlanes = 1;
  39.     infohead->biBitCount = BYTE_PER_PIX*8;
  40.     infohead->biCompression= 0;
  41.     infohead->biSizeImage= w*h*BYTE_PER_PIX;//640 * 480 * 3;
  42.     infohead->biXPelsPerMeter= 0x0;
  43.     infohead->biYPelsPerMeter= 0x0;
  44.     infohead->biClrUsed = 0;
  45.     infohead->biClrImportant = 0;
  46.     return 0;
  47. }

  48. int main ( int argc, char *argv[] )
  49. {
  50.     char* pbuf=NULL;
  51.     char* pRGBbuf=NULL;
  52.     int w = 640;
  53.     int h = 480;
  54.     char raw_file[] = "./640_480.raw";
  55.     char bmp_file[] = "./out.bmp";
  56.     FILE * raw_fp = NULL;
  57.     FILE * bmp_fp = NULL;
  58.     int i;
  59.     char t_ch;

  60.     BITMAPFILEHEADER bmphead;
  61.     BITMAPINFOHEADER infohead;
  62.     
  63.     pbuf = (char*)malloc(w*h*BYTE_PER_PIX*sizeof(char));
  64.     pRGBbuf = (char*)malloc(w*h*BYTE_PER_PIX*4*sizeof(char));

  65.     printf("sizeof(header)=%d\n",sizeof(bmphead));
  66.     printf("sizeof(info)=%d\n",sizeof(infohead));
  67.     //prepare for bmp write 
  68.     if (NULL == (raw_fp = fopen(raw_file,"rb")))
  69.     {
  70.         printf("error: %s not found\n",raw_file);
  71.         return -1;
  72.     }

  73.     if (NULL == (bmp_fp = fopen(bmp_file,"wb")))
  74.     {
  75.         printf("error: %s not found\n",bmp_file);
  76.         return -1;
  77.     }

  78.     create_bmp_header(&bmphead, &infohead, w, h);
  79.     fwrite(&bmphead, 14, 1, bmp_fp);
  80.     fwrite(&infohead, 40, 1, bmp_fp);
  81.     
  82.     fread(pbuf, w*h*BYTE_PER_PIX, 1, raw_fp);
  83.     for(i=0; i<w*h*BYTE_PER_PIX; i+=BYTE_PER_PIX)  //特别注意,这儿的BGR转RGB
  84.     {
  85.         t_ch = pbuf[i];
  86.         pbuf[i] = pbuf[i+2];
  87.         pbuf[i+2] = t_ch;
  88.     }
  89.     fwrite(pbuf, w*h*BYTE_PER_PIX, 1, bmp_fp);

  90.     free(pbuf);
  91.     fclose(raw_fp);
  92.     fclose(bmp_fp);
  93.     printf("over\n");
  94.     return EXIT_SUCCESS;
  95. }

2.3 将bmp转为raw图像
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <math.h>
  5. #pragma pack(1)
  6. typedef struct __BITMAPFILEHEADER__
  7. {
  8.     u_int16_t bfType;
  9.     u_int32_t bfSize;
  10.     u_int16_t bfReserved1;
  11.     u_int16_t bfReserved2;
  12.     u_int32_t bfOffBits;
  13. }BITMAPFILEHEADER; 

  14. typedef struct __BITMAPINFOHEADER 
  15. { 
  16.     u_int32_t biSize; 
  17.     u_int32_t biWidth; 
  18.     u_int32_t biHeight; 
  19.     u_int16_t biPlanes; 
  20.     u_int16_t biBitCount; 
  21.     u_int32_t biCompression; 
  22.     u_int32_t biSizeImage; 
  23.     u_int32_t biXPelsPerMeter; 
  24.     u_int32_t biYPelsPerMeter; 
  25.     u_int32_t biClrUsed; 
  26.     u_int32_t biClrImportant; 
  27. }BITMAPINFOHEADER; 

  28. int translate_bmp2raw(FILE* raw_fp, FILE* bmp_fp)
  29. {
  30.     int i, len;
  31.     int w, h, bpp; //bpp-->byte_per_pix
  32.     char* p_temp = NULL;
  33.     BITMAPFILEHEADER bmphead;
  34.     BITMAPINFOHEADER infohead;

  35.     if( (NULL==raw_fp) || (NULL==bmp_fp))
  36.         return -1;
  37.     len = sizeof(bmphead)+sizeof(infohead);
  38.     printf("len=%d\n",len);
  39.     p_temp = (char*)malloc(len*sizeof(char));
  40.     if(p_temp == NULL)
  41.     {
  42.         printf("malloc error\n");
  43.         return -1;
  44.     }
  45.     fread(p_temp, len, 1, bmp_fp);
  46.     memcpy(&bmphead, p_temp, sizeof(bmphead));
  47.     memcpy(&infohead, p_temp+sizeof(bmphead), sizeof(infohead));
  48.     if(bmphead.bfType != 0x4D42) //must be 0x4D42='BM'
  49.     {
  50.         printf("not a bmp file\n");
  51.         return -1;
  52.     }
  53.     if(infohead.biBitCount < 24)
  54.     {
  55.         printf("error: now bitCount=%d < 24bit\n", infohead.biBitCount);
  56.         return -1;
  57.     }
  58.     free(p_temp);
  59.     w = infohead.biWidth;
  60.     h = infohead.biHeight;
  61.     bpp = infohead.biBitCount/8;
  62.     printf("w=%d,h=%d,bitcount=%d\n", w, h, bpp);
  63.     p_temp = (char*)malloc(w*h*bpp);
  64.     if(p_temp == NULL)
  65.     {
  66.         printf("malloc w*h*bpp error\n");
  67.         return -1;
  68.     }
  69.     fread(p_temp, w*h*bpp, 1, bmp_fp);
  70.     fwrite(p_temp, w*h*bpp, 1, raw_fp);
  71.     free(p_temp);
  72.     return 0;
  73. }

  74. int main ( int argc, char *argv[] )
  75. {
  76.     char* pbuf=NULL;
  77.     char bmp_file[] = "./240_320.bmp";
  78.     char raw_file[] = "./240_320.yuv";
  79.     FILE * raw_fp = NULL;
  80.     FILE * bmp_fp = NULL;

  81.     if (NULL == (bmp_fp = fopen(bmp_file,"rb")))
  82.     {
  83.         printf("error: %s not found\n",bmp_file);
  84.         return -1;
  85.     }

  86.     if (NULL == (raw_fp = fopen(raw_file,"wb")))
  87.     {
  88.         printf("error: %s not found\n",raw_file);
  89.         return -1;
  90.     }
  91.     
  92.     translate_bmp2raw(raw_fp, bmp_fp);

  93.     fclose(raw_fp);
  94.     fclose(bmp_fp);
  95.     printf("over\n");
  96.     return EXIT_SUCCESS;
  97. }

注意1:刚开始生成的bmp里面图像都是倒着的,参考下面的文章
《将rgb图像数据保存为BMP格式图片的方法》
http://blog.csdn.net/chyxwzn/article/details/8443883
才知道BMP图片从最后一个点开始扫描,显示时图片是倒着的,所以用-height,这样图片就正了  
注意2:刚开始生成的bmp里面图像BRG转一下RGB才能正常显示
所以需要加一个转换RB转换
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 地板买的太暗了怎么办 木地板贴好后发现颜色不好看怎么办 鞋上鞋扣老是开怎么办 虚拟机的win10蓝屏重启怎么办 fs免拆模板专利怎么办 新买的床咯吱响怎么办 实木床一动就响怎么办 cad图纸是斜的怎么办 老房子土墙腻子老掉怎么办 生完孩子子宫大怎么办 刚开的店没人怎么办 刚开业的店没人怎么办 美容店没人进店怎么办 新店开业招不到营业员怎么办 无意开通了花呗怎么办? 花呗灰色用不了怎么办 花呗逾期用不了怎么办 店铺花呗关闭了怎么办 花呗无法使用了怎么办 借呗自动关闭了怎么办 蚂蚁花呗无法开通怎么办 花呗本月还不了怎么办 蚂蚁借呗没钱还怎么办 淘宝账号被限制登录怎么办 辱骂买家被投诉骚扰怎么办 淘宝卖家骚扰买家怎么办 被淘宝卖家电话骚扰怎么办 闲鱼卖东西买家退货运费怎么办 淘宝被恶意拍单怎么办 炒作信用度评价被删除怎么办 删除淘宝评价之后卖家不返现怎么办 美团客户给差评怎么办 淘宝卖家评价差怎么办 淘宝卖家发货未揽收怎么办 周不过5我超过了怎么办 淘宝申请退款后卖家不确认怎么办 淘宝直通车b类扣12分怎么办 淘宝店铺被买家投诉怎么办 淘宝店铺遭买家投诉怎么办 淘宝店铺被买家恶意投诉怎么办 苹果手机无法识别指纹怎么办