登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

面包会有的

... ...

 
 
 

日志

 
 

C++写BMP位图,主流USB视频摄像头的媒体格式为RGB24和I420,如何把这些数据变成BMP位图存下来呢  

2011-04-12 01:22:04|  分类: VC++ |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

主流USB视频摄像头的媒体格式为RGB24和I420,如何把这些数据变成BMP位图存下来呢?请看本文。

首先,我们了解一下BMP的格式,BMP有四部分组成,用表格表示如下:

1. 文件信息头

2. 位图信息头

3. 调色板

4. 位图数据

第一部分,文件信息头的格式如下:

typedef struct tagBITMAPFILEHEADER {

        WORD    bfType;

        DWORD   bfSize;

        WORD    bfReserved1;

        WORD    bfReserved2;

        DWORD   bfOffBits;

} BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;

共有14个字节,其中bfType为文件类型,BMP的类型为0×4d42,也就是字母m和b;bfSize是文件大小,为1,2,3,4部分大小的总和;bfReserved1和bfReserved2为1,2,3部分大小的总和。

第二部分,位图信息头,定义如下:

typedef struct tagBITMAPINFOHEADER{

        DWORD      biSize;

        LONG       biWidth;

        LONG       biHeight;

        WORD       biPlanes;

        WORD       biBitCount;

        DWORD      biCompression;

        DWORD      biSizeImage;

        LONG       biXPelsPerMeter;

        LONG       biYPelsPerMeter;

        DWORD      biClrUsed;

        DWORD      biClrImportant;

} BITMAPINFOHEADER, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;

总共40个字节,字段比较多,可以查看MSDN中的说明,对于RGB24的位图,这个结构体一般定义如下:

BITMAPINFOHEADER bih;

       bih.biSize = sizeof(BITMAPINFOHEADER);

       bih.biWidth = width;

       bih.biHeight = height;

       bih.biPlanes = 1;

       bih.biBitCount = 24;

       bih.biCompression = 0;

       bih.biSizeImage = size;

       bih.biXPelsPerMeter = 0;

       bih.biYPelsPerMeter = 0;

       bih.biClrUsed = 0;

       bih.biClrImportant = 0;

第三部分是调色板信息,定义如下:

typedef struct tagRGBQUAD {

        BYTE    rgbBlue;

        BYTE    rgbGreen;

        BYTE    rgbRed;

        BYTE    rgbReserved;

} RGBQUAD;

这部分用来表示RGB各色的强度,一般情况我们不把这一部分写到文件中。

第四部分就是真正的数据,比如宽度和高度分别是320和240,这部分数据的长度应该为320*240*3(每个像素点上有3个字节,分别用来表示b,g,r的颜色)。

根据对BMP格式的说明,我们可以轻易的写出一个生成BMP图像的函数,如下所示:

// pData为rgb24数据,width为位图宽度,height为位图高度,filename为位图文件的名字

void Snapshot( BYTE * pData, int width, int height, const char * filename )

{

       int size = width*height*3; // 每个像素点3个字节

       // 位图第一部分,文件信息

       BITMAPFILEHEADER bfh;

       bfh.bfType = 0×4d42; //bm

       bfh.bfSize = size // data size

              + sizeof( BITMAPFILEHEADER ) // first section size

              + sizeof( BITMAPINFOHEADER ) // second section size

              ;

       bfh.bfReserved1 = 0; // reserved

       bfh.bfReserved2 = 0; // reserved

       bfh.bfOffBits = bfh.bfSize - size;

       // 位图第二部分,数据信息

       BITMAPINFOHEADER bih;

       bih.biSize = sizeof(BITMAPINFOHEADER);

       bih.biWidth = width;

       bih.biHeight = height;

       bih.biPlanes = 1;

       bih.biBitCount = 24;

       bih.biCompression = 0;

       bih.biSizeImage = size;

       bih.biXPelsPerMeter = 0;

       bih.biYPelsPerMeter = 0;

       bih.biClrUsed = 0;

       bih.biClrImportant = 0;

      

       FILE * fp = fopen( filename, “wb” );

       if( !fp ) return;

       fwrite( &bfh, 1, sizeof(BITMAPFILEHEADER), fp );

       fwrite( &bih, 1, sizeof(BITMAPINFOHEADER), fp );

       fwrite( pData, 1, size, fp );

       fclose( fp );

}

如果要对摄像头采集到的数据进行截图,这里可以直接把数据送给这个函数,就可以生成一张位图了。当然也可以自己生成一段数据,用图片的形式保存下来。下面我将给一个例子,说明怎么生成位图,本例中说明了如何生成一个320*240的图像,黑色的背景,中部有一个100*100的矩形,代码如下:

void GenerateBMP()

{

       int i=0, j=0;

       struct {

              BYTE b;

              BYTE g;

              BYTE r;

       } pRGB[240][320]; // 定义位图数据

       memset( pRGB, 0, sizeof(pRGB) ); // 设置背景为黑色

       // 在中间画一个100*100的矩形

       for( int i=70;i<170;i++ ){

              for( int j=110;j<210;j++ ){

                     pRGB[i][j].r = 0xff;

              }

       }

       // 生成BMP图片

       Snapshot( (BYTE *)pRGB, 320, 240, “C:\\rgb.bmp” );

}

生成图片如下所示:

C++写BMP位图,主流USB视频摄像头的媒体格式为RGB24和I420,如何把这些数据变成BMP位图存下来呢 - 加菲 -  .

上面所说的都是对于RGB24的数据,对于I420,可以先转换成RGB24,然后在生成位图。

BMP的数据量是很大的,没有经过任何的压缩,我们可以计算一下,对于一副320*240的图像,图片的大小是320*240*3 = 230400 bytes = 225 Kbytes,普通电脑一副屏幕截图就要1024*768*3=2.3M。所以我们要用一些流行的算法对图片进行压缩才便于存储,

  评论这张
 
阅读(3184)| 评论(2)

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018