标签:
BMP文件渊源流长,虽然对JPG、PNG等格式图像文件来说,确实有点土,但是毕竟BMP文件格式相对简单,容易理解,至于BMP众多的位图格式也不能责怪微软,主要是早期谁也没料到图片技术会发展的这么快,而且每次升级还要兼容,所以只能如此了(有点麻烦但并不复杂)。天缘撰写本文以便留档和各位编程爱好者参考。 BMP位图文件的结构主要由:BMP文件头、位图信息头、颜色表和图形数据四个部分组成,对于24位、32位则没有色彩表字段,低位图则存在色彩索引表。 一、BMP的文件头结构 BMP文件头数据结构包含有BMP文件类型标志、文件大小和位图数据的起始位置等信息。 其结构定义如下: typedef strUCt tagBITMAPFILEHEADER { WORD bfType; DWORD bfSize; WORD bfReserved1; // 保留字,必须为0 WORD bfReserved2; // 保留字,必须为0 DWORD bfOffBits; } BITMAPFILEHEADER; bfType——为位图文件类型,必须为BM,转化为十六进制码就是0x4d42(小端约定,关于大端和小端概念请参考稍后的天缘文章) bfSize——位图文件的大小,以字节为单位,表示整个bmp文件的大小,包括2个头段和位图数据区,计算方法如下: sizeof(BITMAPFILEHEADER)+ sizeof(BITMAPINFOHEADER)+ (biWidth* biBitCount+31)/8*biHeight 可能很多网友对公式中的后半段很疑惑,为什么那样计算数据区的大小,这是因为Windows还规定图像文件中一个扫描行所占的字节数必须是4的倍数,不足部分要以0填充,所以数据区的大小不能使用简单的(biWidth*biBitCount*biHeight)/8计算总字节数,而应当折算每行的BIT数,分子中的加31(因为4字节补齐就是32位补齐)就是为了防止一个扫描行多一位或少一位而做的进位(+31)取整(/8)操作。 bfOffBits—— 位图数据的起始位置,也就是数据区的起始位置,基点是位图数据区相对文件头部的偏移量,单位为字节。 二、BMP位图信息头结构 BMP位图信息头结构主要用于说明位图的尺寸、压缩类型等重要信息。其结构如下: typedef struct tagBITMAPINFOHEADER{ DWORD biSize; //本结构所占字节数,实际上该结构占用40个字节,但Windows每次还是需要您亲自添上 LONG biWidth; //位图的宽度,单位为像素 LONG biHeight; //位图的高度,单位为像素 WORD biPlanes; //目标设备的平面数,约定必须为1 WORD biBitCount//每个像素所需的位数,必须是1(双色)、 4(16色)、8(256色)、24(真彩色)或32(32位真彩)之一 DWORD biCompression; //位图压缩类型,必须是0(不压缩)、1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一 DWORD biSizeImage; //位图的大小,以字节为单位,对于BI_RGB必须设置为0,对于压缩文件请参考MSDN LONG biXPelsPerMeter; //水平分辨率,每米像素数,一般不用关心,设为0 LONG biYPelsPerMeter; //垂直分辨率,每米像素数,一般不用关心,设为0 DWORD biClrUsed;//位图实际使用的颜色表中的颜色数,一般不用关心,设为0 DWORD biClrImportant;//位图显示过程中重要的颜色数,一般不用关心,设为0 } BITMAPINFOHEADER;该结构占据40个字节。 三、BMP的调色板结构,或叫色彩表 这一项在网络上很多文章没有提及,或只说到调色板的概念,主要是因为现在使用颜色表的BMP(24真彩以下的图片很少的缘故),这里介绍一下,颜色表表示BMP文件的DIB(device-independent bitmap)尺寸和颜色信息。结构定义如下: typedef struct _BITMAPCOREINFO { BITMAPCOREHEADER bmciHeader; //见下面的结构定义 RGBTRIPLE bmciColors[1]; //见下面的结构定义 } BITMAPCOREINFO; BITMAPCOREHEADER的定义如下: typedef struct tagBITMAPCOREHEADER { // bmch DWORD bcSize; //表示本结构的占用字节数 WORD bcWidth; //位图的宽度 WORD bcHeight; //位图的高度 WORD bcPlanes; //设备平面数,设为1 WORD bcBitCount; //每像素位数,比如为1、4、8、24,实际上最后的24似乎没用,当然也可以使用程序约定使用。 } BITMAPCOREHEADER RGBTRIPLE的结构定义如下: typedef struct tagRGBTRIPLE { // rgbt BYTE rgbtBlue; //蓝色 BYTE rgbtGreen; //绿色 BYTE rgbtRed; //红色 } RGBTRIPLE 四、BMP的位图数据区 提到位图数据区,肯定要涉及到颜色表的概念,颜色表用于说明位图中的颜色,按照位图的像素划分,每一个像素用一个RGBQUAD结构表示一种颜色。RGBQUAD结构的定义如下: typedef struct tagRGBQUAD { BYTE rgbBlue;//蓝色 BYTE rgbGreen; // 绿色 BYTE rgbRed; // 红色 BYTE rgbReserved;// 保留 } RGBQUAD; 根据天缘的认识,该结构只是在程序处理时候用得着,随意你怎么解释都可以,只要不把RGB颜色倒反即可。位图信息头和颜色表组成位图信息区,BITMAPINFO结构定义如下: typedef struct tagBITMAPINFO { BITMAPINFOHEADER bmiHeader; // 位图信息头 RGBQUAD bmiColors[1]; // 颜色表 } BITMAPINFO; 结构体里头的RGBQUAD项就是真实的颜色表,大小根据实际情况确定。 颜色表的结构来也很简单,就是使用RGB三色调和最终的位图颜色信息。至于最终实际使用多少字节的RGBQUAD数据还需要由biBitCount决定,所以,并不是上述结构中使用BYTE来定义就表示一定占用四字节。天缘说明如下: 1、当biBitCount=1时,8个像素占1个字节,每个像素智能用一BIT来表示,颜色只能有两种1或0,也就是双色,具体颜色需查色彩表。 2、当biBitCount=4时,2个像素占1个字节,每个像素占半个字节(4位),可能颜色有2^4=16种,也就是16色,具体颜色需查色彩表。 3、当biBitCount=8时,1个像素占1个字节,可能颜色有2^8=256种,也就是256色,具体颜色需查色彩表。 4、当biBitCount=16时,1个像素占2个字节,可能颜色有2^16=65536种,也就是64K,具体颜色需查色彩表。 5、当biBitCount=24时,1个像素占3个字节,可能颜色有2^24=16777216,这么多颜色如果是写色彩表就需要占用至少16M,全宇宙肯定不同意的,所以干脆就拿每个字节表示一种颜色,正好三个字节RGB,“非常6+1”。 6、当biBitCount=32时,1个像素占4个字节,这在网上很多文章中都没有提到,只说到24位,32位真彩就是原来的rgbReserved使用上,作为透明度标示。理解方法同24位,加上Reserved保留的透明度,具体颜色天缘暂时还算不出来。 编程建议(面向数据处理): 1、BMP文件的读取提取到二维数组,对于使用C/C++、VC++的朋友,有现成DIB派生类可以参考,GOOGLE一下即可。 2、对于BMP文件的普通读取、绘图有很多现成的系统函数可供调用,天缘不再细说,比如CreateDIBitmap、CreateCompatibleDC、BitBlt、StretchBlt等等。 2、BMP文件的写操作只需要按照上述的BMP文件格式,把BMP文件头、信息表及位图数据区按照顺序写成BMP文件即可。
http://www.metsky.com/archives/198.html
JPG格式与bmp格式的具体区别是什么? 数据存储格式不一样,具体看看他们的资料吧! JPG也好,bmp也好,都是一种保存成文件的格式,而不是真正电脑处理的格式。 电脑处理的就是DIB,设备无关位图,不管是什么格式,打开文件的时候就应该转换为DIB来处理了。其实,bmp格式就是直接保存的DIB格式 灰度化,二值化,滤波处理都是针对dib格式,是在内存中处理,不是在磁盘上直接对文件处理。bmp,jpg只是保存的格式不同,当然jpg有压缩,bmp没压缩,最后保存的时候肯定不会一模一样.
将24位位图转换8位位图
标签:
原文地址:http://www.cnblogs.com/leijiangtao/p/4806683.html