当前位置首页 > 百科> 正文

BMP(图像档案格式(Bitmap))

2019-09-27 05:00:05 百科
BMP(图像档案格式(Bitmap))

BMP(图像档案格式(Bitmap))

BMP(全称Bitmap)是Windows作业系统中的标準图像档案格式,可以分成两类:设备有向量相关点阵图(DDB)和设备无向量相关点阵图(DIB),使用非常广。它採用位映射存储格式,除了图像深度可选以外,不採用其他任何压缩,因此,BMP档案所占用的空间很大。BMP档案的图像深度可选lbit、4bit、8bit及24bit。BMP档案存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。由于BMP档案格式是Windows环境中交换与图有关的数据的一种标準,因此在Windows环境中运行的图形图像软体都支持BMP图像格式。

基本介绍

  • 中文名:图像档案格式
  • 外文名:Bitmap
  • 简称:BMP
  • 系统:Windows作业系统
  • 套用:设备相关点阵图设备无关点阵图

格式组成

典型的BMP图像档案由四部分组成:
1:点阵图头档案数据结构,它包含BMP图像档案的类型、显示内容等信息;
2:点阵图信息数据结构,它包含有BMP图像的宽、高、压缩方法,以及定义颜色等信息;
3:调色板,这个部分是可选的,有些点阵图需要调色板,有些点阵图,比如真彩色图(24位的BMP)就不需要调色板;
4:点阵图数据,这部分的内容根据BMP点阵图使用的位数不同而不同,在24点阵图中直接使用RGB,而其他的小于24位的使用调色板中颜色索引值。

格式类型

点阵图一共有两种类型,即:设备相关点阵图(DDB)和设备无关点阵图(DIB)。DDB点阵图在早期的Windows系统(Windows 3.0以前)中是很普遍的,事实上它也是唯一的。然而,随着显示器製造技术的进步,以及显示设备的多样化,DDB点阵图的一些固有的问题开始浮现出来了。比如,它不能够存储(或者说获取)创建这张图片的原始设备的解析度,这样,应用程式就不能快速的判断客户机的显示设备是否适合显示这张图片。为了解决这一难题,微软创建了DIB点阵图格式。
设备无关点阵图 (Device-Independent Bitmap)
DIB点阵图包含下列的颜色和尺寸信息:
* 原始设备(即创建图片的设备)的颜色格式。
* 原始设备的解析度。
* 原始设备的调色板
* 一个位数组,由红、绿、蓝(RGB)三个值代表一个像素。
* 一个数组压缩标誌,用于表明数据的压缩方案(如果需要的话)。
以上这些信息保存在BITMAPINFO结构中,该结构由BITMAPINFOHEADER结构和两个或更多个RGBQUAD结构所组成。BITMAPINFOHEADER结构所包含的成员表明了图像的尺寸、原始设备的颜色格式、以及数据压缩方案等信息。RGBQUAD结构标识了像素所用到的颜色数据。
DIB点阵图也有两种形式,即:底到上型DIB(bottom-up),和顶到下型DIB(top-down)。底到上型DIB的原点(origin)在图像的左下角,而顶到下型DIB的原点在图像的左上角。如果DIB的高度值(由BITMAPINFOHEADER结构中的biHeight成员标识)是一个正值,那幺就表明这个DIB是一个底到上型DIB,如果高度值是一个负值,那幺它就是一个顶到下型DIB。注意:顶到下型的DIB点阵图是不能被压缩的。
点阵图的颜色格式是通过颜色面板值(planes)和颜色位值(bitcount)计算得来的,颜色面板值永远是1,而颜色位值则可以是1、4、8、16、24、32其中的一个。如果它是1,则表示点阵图是一张单色点阵图(译者注:通常是黑白点阵图,只有黑和白两种颜色,当然它也可以是任意两种指定的颜色),如果它是4,则表示这是一张VGA点阵图,如果它是8、16、24、或是32,则表示该点阵图是其他设备所产生的点阵图。如果应用程式想获取当前显示设备(或印表机)的颜色位值(或称位深度),可调用API函式GetDeviceCaps(),并将第二个参数设为BITSPIXEL即可。
显示设备的解析度是以每米多少个像素来表明的,应用程式可以通过以下三个步骤来获取显示设备或印表机的水平解析度:
1. 调用GetDeviceCaps()函式,指定第二个参数为HORZRES。
2. 再次调用GetDeviceCaps()函式,指定第二个参数为HORZSIZE。
3. 用第一个返回值除以第二个返回值。即:GetDeviceCaps(hDC,HORZRES)/GetDeviceCaps(hDC,HORZSIZE);
应用程式也可以使用相同的三个步骤来获取设备的垂直解析度,不同之处只是要将HORZRES替换为VERTRES,把HORZSIZE替换为VERTSIZE,即可。
调色板是被保存在一个RGBQUAD结构的数组中,该结构指出了每一种颜色的红、绿、蓝的分量值。位数组中的每一个索引都对应于一个调色板项(即一个RGBQUAD结构),应用程式将根据这种对应关係,将像素索引值转换为像素RGB值(真实的像素颜色)。应用程式也可以通过调用GetDeviceCaps()函式来获取当前显示设备的调色板尺寸(将该函式的第二个参数设为NUMCOLORS即可)。
Win32 API支持位数据的压缩(只对8位和4位的底到上型DIB点阵图)。压缩方法是採用运行长度编码方案(RLE),RLE使用两个位元组来描述一个句法,第一个位元组表示重複像素的个数,第二个位元组表示重複像素的索引值。有关压缩点阵图的详细信息请参见对BITMAPINFOHEADER结构的解释。
应用程式可以从一个DDB点阵图创建出一个DIB点阵图,步骤是,先初始化一些必要的结构,然后再调用GetDIBits()函式。不过,有些显示设备有可能不支持这个函式,你可以通过调用GetDeviceCaps()函式来确定一下(GetDeviceCaps()函式在调用时指定RC_DI_BITMAP作为RASTERCAPS的标誌)。
应用程式可以用DIB去设定显示设备上的像素(译者注:也就是显示DIB),方法是调用SetDIBitsToDevice()函式或调用StretchDIBits()函式。同样,有些显示设备也有可能不支持以上这两个函式,这时你可以指定RC_DIBTODEV作为RASTERCAPS标誌,然后调用GetDeviceCaps()函式来判断该设备是否支持SetDIBitsToDevice()函式。也可以指定RC_STRETCHDIB作为RASTERCAPS标誌来调用GetDeviceCaps()函式,来判断该设备是否支持StretchDIBits()函式。
如果应用程式只是要简单的显示一个已经存在的DIB点阵图,那幺它只要调用SetDIBitsToDevice()函式就可以。比如一个电子表格软体,它可以打开一个图表档案,在视窗中简单的调用SetDIBitsToDevice()函式,将图形显示在视窗中。但如果应用程式要重複的绘製点阵图的话,则应该使用BitBlt()函式,因为BitBlt()函式的执行速度要比SetDIBitsToDevice()函式快很多。
设备相关点阵图 (Device-Dependent Bitmaps)
设备相关点阵图(DDB)之所以现在还被系统支持,只是为了兼容旧的Windows 3.0软体,如果程式设计师现在要开发一个与点阵图有关的程式,则应该儘量使用或生成DIB格式的点阵图。
DDB点阵图是被一个单个结构BITMAP所描述,这个结构的成员标明了该点阵图的宽度、高度、设备的颜色格式等信息。
DDB点阵图也有两种类型,即:可废弃的(discardable)DDB和不可废弃的(nondiscardable)DDB。可废弃的DDB点阵图就是一种当系统记忆体缺乏,并且该点阵图也没有被选入设备描述表(DC)的时候,系统就会把该DDB点阵图从记忆体中清除(即废弃)。不可废弃的DDB则是无论系统记忆体多少都不会被系统清除的DDB。API函式CreateDiscardableBitmap()函式可用于创建可废弃点阵图。而函式CreateBitmap()、CreateCompatibleBitmap()、和CreateBitmapIndirect()可用于创建不可废弃的点阵图。
应用程式可以通过一个DIB点阵图而创建一个DDB点阵图,只要先初始化一些必要的结构,然后再调用CreateDIBitmap()函式就可以。如果在调用该函式时指定了CBM_INIT标誌,那幺这一次调用就等价于先调用CreateCompatibleBitmap()创建当前设备格式的DDB点阵图,然后又调用SetDIBits()函式转换DIB格式到DDB格式。(可能有些设备并不支持SetDIBits()函式,你可以指定RC_DI_BITMAP作为RASTERCAPS的标誌,然后调用GetDeviceCaps()函式来判断一下)。

对应数据结构

1:BMP档案组成
BMP档案由档案头、点阵图信息头、颜色信息和图形数据四部分组成。
2:BMP档案头(14位元组)
BMP档案头数据结构含有BMP档案的类型、档案大小和点阵图起始位置等信息。
其结构定义如下:
typedef struct tagBITMAPFILEHEADER{    WORD bfType;//点阵图档案的类型,必须为BM(1-2位元组)    DWORD bfSize;//点阵图档案的大小,以位元组为单位(3-6位元组,低位在前)    WORD bfReserved1;//点阵图档案保留字,必须为0(7-8位元组)    WORD bfReserved2;//点阵图档案保留字,必须为0(9-10位元组)    DWORD bfOffBits;//点阵图数据的起始位置,以相对于点阵图(11-14位元组,低位在前)    //档案头的偏移量表示,以位元组为单位}__attribute__((packed)) BITMAPFILEHEADER;
3:点阵图信息头(40位元组)
BMP点阵图信息头数据用于说明点阵图的尺寸等信息。
typedef struct tagBITMAPINFOHEADER{DWORD biSize;//本结构所占用位元组数(15-18位元组)LONG biWidth;//点阵图的宽度,以像素为单位(19-22位元组)LONG biHeight;//点阵图的高度,以像素为单位(23-26位元组)WORD biPlanes;//目标设备的级别,必须为1(27-28位元组)WORD biBitCount;//每个像素所需的位数,必须是1(双色),(29-30位元组)//4(16色),8(256色)16(高彩色)或24(真彩色)之一DWORD biCompression;//点阵图压缩类型,必须是0(不压缩),(31-34位元组)//1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一DWORD biSizeImage;//点阵图的大小(其中包含了为了补齐行数是4的倍数而添加的空位元组),以位元组为单位(35-38位元组)LONG biXPelsPerMeter;//点阵图水平解析度,每米像素数(39-42位元组)LONG biYPelsPerMeter;//点阵图垂直解析度,每米像素数(43-46位元组)DWORD biClrUsed;//点阵图实际使用的颜色表中的颜色数(47-50位元组)DWORD biClrImportant;//点阵图显示过程中重要的颜色数(51-54位元组)}__attribute__((packed)) BITMAPINFOHEADER;
4:颜色表
颜色表用于说明点阵图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下:
typedef struct tagRGBQUAD{BYTE rgbBlue;//蓝色的亮度(值範围为0-255)BYTE rgbGreen;//绿色的亮度(值範围为0-255)BYTE rgbRed;//红色的亮度(值範围为0-255)BYTE rgbReserved;//保留,必须为0}__attribute__((packed)) RGBQUAD;
颜色表中RGBQUAD结构数据的个数有biBitCount来确定:
当biBitCount=1,4,8时,分别有2,16,256个表项;
当biBitCount=24时,没有颜色表项。
点阵图信息头和颜色表组成点阵图信息,BITMAPINFO结构定义如下:
typedef struct tagBITMAPINFO{BITMAPINFOHEADER bmiHeader;//点阵图信息头RGBQUAD bmiColors[1];//颜色表}__attribute__((packed)) BITMAPINFO;
5:点阵图数据
点阵图数据记录了点阵图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。点阵图的一个像素值所占的位元组数:
当biBitCount=1时,8个像素占1个位元组;
当biBitCount=4时,2个像素占1个位元组;
当biBitCount=8时,1个像素占1个位元组;
当biBitCount=24时,1个像素占3个位元组,按顺序分别为B,G,R;
Windows规定一个扫描行所占的位元组数必须是
4的倍数(即以long为单位),不足的以0填充,
biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8) * bi.biHeight;
具体数据举例:
如某BMP档案开头:
4D42 46900000 0000 0000 4600 0000 2800 0000 8000 0000 9000 0000 0100*1000 0300 0000 0090 0000 A00F 0000 A00F0000 0000 00000000 0000*00F8 E007 1F00 0000*02F1 84F1 04F1 84F1 84F1 06F2 84F1 06F2 04F2 86F2 06F2 86F2 86F2 .... ....

读取方法

/*
功能:在图片的第50行画一条黑线
为简化代码,只支持24位色的图片
codeblocks下正确运行。VC下需要将二维数组img改为malloc动态分配。需要添加#include "stdlib.h"。
*/
#include<stdio.h>#include<windows.h>typedef struct{BYTE b;BYTE g;BYTE r;}RGB;int main(void){BITMAPFILEHEADER fileHeader;BITMAPINFOHEADER infoHeader;FILE*pfin=fopen("原始图像.bmp","rb");FILE*pfout=fopen("修改后的图像.bmp","wb");//ReadtheBitmapfileheader;fread(&fileHeader,sizeof(BITMAPFILEHEADER),1,pfin);//ReadtheBitmapinfoheader;fread(&infoHeader,sizeof(BITMAPINFOHEADER),1,pfin);//为简化代码,只处理24位彩色if(infoHeader.biBitCount==24){int size=infoHeader.biWidth*infoHeader.biHeight;RGB img[infoHeader.biHeight][infoHeader.biWidth];  //这里有错误,尺度改为常量fread(img,sizeof(RGB),size,pfin);//把第50行染成黑色int i=0;for(;i<infoHeader.biWidth;i++){img[50][i].b=img[50][i].g=img[50][i].r=0;}//将修改后的图片保存到档案fwrite(&fileHeader,sizeof(fileHeader),1,pfout);fwrite(&infoHeader,sizeof(infoHeader),1,pfout);fwrite(img,sizeof(RGB),size,pfout);}fclose(pfin);fclose(pfout);}

档案部分

图像档案头
1)1-2:(这里的数字代表的是位元组,下同)图像档案头。0x4d42=’BM’,表示是Windows支持的BMP格式。(注意:查ascii表B 0x42,M0x4d,bfType 为两个位元组,B为low位元组,M为high位元组所以bfType=0x4D42,而不是0x424D,请注意)
2)3-6:整个档案大小。4690 0000,为00009046h=36934。
3)7-8:保留,必须设定为0。
4)9-10:保留,必须设定为0。
5)11-14:从档案开始到点阵图数据之间的偏移量(14+40+4*(2^biBitCount))(在有颜色板的情况下)。4600 0000,为00000046h=70,上面的档案头就是35字=70位元组。
点阵图信息头
6)15-18:点阵图图信息头长度。
7) 19-22:点阵图宽度,以像素为单位。8000 0000,为00000080h=128。
8)23-26:点阵图高度,以像素为单位。9000 0000,为00000090h=144。
9)27-28:点阵图的位面数,该值总是1。0100,为0001h=1。
10)29-30:每个像素的位数。有1(单色),4(16色),8(256色),16(64K色,高彩色),24(16M色,真彩色),32(4096M色,增强型真彩色)。1000为0010h=16。
11)31-34:压缩说明:有0(不压缩),1(RLE 8,8位RLE压缩),2(RLE 4,4位RLE压缩,3(Bitfields,位域存放)。RLE简单地说是採用像素数+像素值的方式进行压缩。T408採用的是位域存放方式,用两个位元组表示一个像素,位域分配为r5b6g5。图中0300 0000为00000003h=3(这张图片不存在颜色板)。
12)35-38:用位元组数表示的点阵图数据的大小,该数必须是4的倍数,数值上等于:一行所占的位元组数×点阵图高度。0090 0000为00009000h=80×90×2h=36864。假设点阵图是24位,宽为41,高为30,则数值= (biWidth*biBitCount+31)/32*4*biHeight,即=(41*24+31)/32*4*30=3720
13)39-42:用象素/米表示的水平解析度。A00F 0000为0000 0FA0h=4000。
14)43-46:用象素/米表示的垂直解析度。A00F 0000为0000 0FA0h=4000。
15)47-50:点阵图使用的颜色索引数。设为0的话,则说明使用所有调色板项。
16)51-54:对图象显示有重要影响的颜色索引的数目。如果是0,表示都重要。
彩色板
17)(55+0)到(50-1+2^biBitCount):彩色板规范。对于调色板中的每个表项,用下述方法来描述RGB的值:
1位元组用于蓝色分量
1位元组用于绿色分量
1位元组用于红色分量
1位元组用于填充符(设定为0)
对于24-位真彩色图像就不使用彩色板,因为点阵图中的RGB值就代表了每个象素的颜色。
如,彩色板为00F8 0000 E007 0000 1F00 0000 0000 0000,其中:
00F8为F800h = 1111 1000 0000 0000(二进制),是蓝色分量的掩码。
E007 为 07E0h = 0000 0111 1110 0000(二进制),是绿色分量的掩码。
1F00为001Fh = 0000 0000 0001 1111(二进制),是红色分量的掩码。
0000 总设定为0。
将掩码跟像素值进行“与”运算再进行移位操作就可以得到各色分量值。看看掩码,就可以明白事实上在每个像素值的两个位元组16位中,按从高到低取5、6、5位分别就是r、g、b分量值。取出分量值后把r、g、b值分别乘以8、4、8就可以补齐第个分量为一个位元组,再把这三个位元组按rgb组合,放入存储器(同样要反序),就可以转换为24位标準BMP格式了。
图像数据阵列
18)55(无调色板)-bfSize:每两个位元组表示一个像素。阵列中的第一个位元组表示点阵图左下角的象素,而最后一个位元组表示点阵图右上角的象素。
//----图像处理-----BMP为DIB类型,从底向上显示---------
//阵列中的第一个位元组表示点阵图左下角的象素,而最后一个位元组表示点阵图右上角的象素。
//下面的代码可以完成第一个位元组表示点阵图左上角的象素,而最后一个位元组表示点阵图右下角的象素,即正常的显示状态,便于操作。
int m,n;
unsigned char k;
m = BMPPIC.BMPInfoHead.biWidth/8; //24
n = BMPPIC.BMPInfoHead.biHeight; //96, 24*96 = 2304 bytes
for(int i=0; i < n/2; i++ )
{
for(int a=0; a < m; a++ )
{
k = pbufout1[m*(n-i-1) + a];
pbufout1[m*(n-i-1) + a] = pbufout1[i*m + a];
pbufout1[i*m + a] = k;
}
}
存储算法
BMP档案通常是不压缩的,所以它们通常比同一幅图像的压缩图像档案格式要大很多。例如,一个800×600的24位几乎占据1.4MB空间。因此它们通常不适合在网际网路或者其它低速或者有容量限制的媒介上进行传输。根据颜色深度的不同,图像上的一个像素可以用一个或者多个位元组表示,它由n/8所确定(n是位深度,1位元组包含8个数据位)。图片浏览器等基于位元组的ASCII值计算像素的颜色,然后从调色板中读出相应的值。更为详细的信息请参阅下面关于点阵图档案的部分。n位2n种颜色的点阵图近似位元组数可以用下面的公式计算:BMP档案大小约等于 54+4*2的n次方+(w*h*n)/8,其中高度和宽度都是像素数。需要注意的是上面公式中的54是点阵图档案的档案头,是彩色调色板的大小。另外需要注意的是这是一个近似值,对于n位的点阵图图像来说,儘管可能有最多2n中颜色,一个特定的图像可能并不会使用这些所有的颜色。由于彩色调色板仅仅定义了图像所用的颜色,所以实际的彩色调色板将小于。如果想知道这些值是如何得到的,请参考下面档案格式的部分。由于存储算法本身决定的因素,根据几个图像参数的不同计算出的大小与实际的档案大小将会有一些细小的差别。
数据类型
Oracle产品 EPC Bitmap 中数据类型 EPC bitmap的缩写。
Oracle提出了一种EPC bitmap的数据类型对基于RFID产品项级别跟蹤套用产生的大量的数据进行有效处理,。
EPC bitmap数据类型定义一个EPC集合,集合共享EPC的一些特徵(例如header,manager number,and object class)。支持这个数据类型的关键是使用RFID标识的物品项,在一个群组里可以基于共同属性(例如位置,截止日期,或製造商),在通常情况下可以被追蹤。而EPC集合可以表示为一个EPC bitmap,bitmap可以被访问并可通过epc2bmp或bmp2epc进行数据类型的转换操作。
引入EPC bitmap(epc bmp)类型的好处:
(1)可以简单的标识一个RFID EPC集合,而不会丢失任何信息;
(2)对于同类的EPC操作可以简单的在bitmap上操作,简化了操作方式
br/
声明:此文信息来源于网络,登载此文只为提供信息参考,并不用于任何商业目的。如有侵权,请及时联系我们:baisebaisebaise@yeah.net