BMP格式

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

    -      位图文件头:它包含BMP图像文件的类型、显示内容等信息;
    -      位图信息段:它包含有BMP图像的宽、高、压缩方法,以及定义颜色等信息;
    -      调色板:这个部分是可选的,有些位图需要调色板,有些位图,比如真彩色图(24位的BMP)就不需要调色板;b
    -      位图数据:这部分的内容根据BMP位图使用的位数不同而不同,在24位图中直接使用RGB,而其他的小于24位的使用调色板中颜色索引值。

一个BMP文件,可以用代码表示如下:
typedef struct tagBITMAP_FILE{
        BITMAPFILEHEADER  bitmapheader;
        BITMAPINFOHEADER  bitmapinfoheader;
        PALETTEENTRY  palette[256];
        UCHAR  *buffer;        //UCHAR  大小1字节(同BYTE),在VC6下
}  BITMAP_FILE;

①BMP文件头 (14字节):BITMAPFILEHEADER
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字节,低位在前)
        //文件头的偏移量表示,以字节为单位
}BITMAPFILEHEADER;

bfType
说明文件的类型,该值必须是0x4D42,也就是字符'BM',否则表示根本不是BMP
bfSize
说明该位图文件的大小,用字节为单位
bfReserved1
保留,必须设置为0
bfReserved2
保留,必须设置为0
bfOffBits
说明从文件头开始到实际的图像数据之间的字节偏移量。这个参数是非常有用的,因为位图信息和调色板的长度会根据不同的情况而变化,所以你可以用这个偏移值迅速的从文件中读取到位数据。

下面用Notepad++打开一个BMP文件

如图所示:
bfType:0X4D42。表示字符'BM'
bfSize:0X0004a436 == 304182字节 == 297K字节,说明这个位图文件的大小为297K字节,和我们看到的正好符合。
跳过四个字节的保留字节,
bfOffBits:0X00000036 == 54字节。表示从头文件开始到实际的图像数据之间的字节偏移量为54字节。BMP文件头14字节、位图信息头40字节,省略了颜色表,共54字节。

②位图信息段 (40字节):BITMAPINFOHEADER
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字节)
}  BITMAPINFOHEADER;

biSize
说明BITMAPINFOHEADER结构所需要的字节数
biWidth
说明图像的宽度,以像素为单位
biHeight
说明图像的高度,以像素位单位。注:这个值除了用于描述图像的高度之外,它还有另外一个用处,就是指明该图像是倒向的位图,还是正向的位图。如果该值是一个正数,说明图像是倒向的,即数据的第一行其实是图像的最后一行,如果该值是一个负数,则说明图像是正向的。大多数的BMP文件都是倒向的位图,也就是高度值是一个正数。
biPlanes
表示bmp图片的平面属性,显然显示器只有一个平面,所以恒等于1
biBitCount
说明比特数/像素,其值为1、4、8、16、24或32.
biCompression
说明图像数据压缩的类型,其中:
BI_RGB:没有压缩
BI_RLE8:每个像素8比特的RLE压缩编码,压缩格式由2字节组成(重复像素计数和颜色索引)
BI_RLE4:每个像素4比特的RLE压缩编码,压缩格式由2字节组成
BI_BITFIELDS:每个像素的比特由指定的掩码决定
BI_JPEG:JPEG格式
biSizeImage
说明图像的大小,以字节为单位。当用BI_RGB格式时,可设置为0
biXPelsPerMeter
说明水平分辨率,用像素/米表示
biYPelsPerMeter
说明垂直分辨率,用像素/米表示
biClrUsed
说明位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有的调色板项)
biClrImportant
说明对图像显示有重要影响的颜色索引的数目,如果是0,表示都重要


biSize:位图信息段结构BITMAPINFOHEADER所需的字节数  0X00000028 == 40字节
biWidth:图像的宽度。0X00000160 == 352 像素
biHeight:图像的高度。0X00000120 == 288 像素

和图片信息相符
biPlanes:bmp图片的平面属性,显示器只有一个平面,恒等于1。0X0001 == 1
biBitCount:比特数/像素。0X0018 == 24 位
biCompression:0X00000000 == 0 。没有压缩
biSizeImage:图像压缩的类型。0X0004a400 == 304128 字节。位图的大小
        bigSizeImage = biWidth * biHeight * 每个像素的字节数
        那么这里应该是:352 * 288 * 24/8 = 304128 。
        这里的biBitCount是24位,所以每个像素的字节数是24/8 = 3
        注意:这里的biWidth必须是4的倍数,如果不是4的倍数,则需要取4的倍数。eg。241,则取244.
        因为这里涉及到了一个行对齐的问题。由于windows在进行行行扫描的时候,最小的单位是4个字节,所以当图片的宽度不是4的倍数的时候,需要在每行的后面补上缺少的字节,以0填充。
biXPelsPerMeter:0x00000000
biYPelsPerMeter:0x00000000
biClrUsed:0x00000000  表示使用所有调色板项
biClrImportant:0X00000000 。 表示所有颜色对图像显示都有重要影响。在早期的计算机中,显卡相对来说比较落后,不一定能保证显示所有的颜色,所以在调色板中的颜色数据应尽可能的将图像中主要的颜色按顺序排列在前面,biClrImportant指出了有多少种颜色是重要的。


③调色板
typedef struct tagRGBQUAD { 
        BYTE    rgbBlue; 
        BYTE    rgbGreen; 
        BYTE    rgbRed; 
        BYTE    rgbReserved;
 } RGBQUAD;

字段名称
大小(单位:字节)
描述
rgbBlue
1
蓝色值
rgbGreen
1
绿色值
rgbRed
1
红色值
rgbReserved
1
保留,总为0

调色板是单色、16色和256色图像文件所特有的,相对应的调色板大小是2、16和256,调色板以4字节为单位,每4个字节存放一个颜色值,图像的数据是指向调色板的索引。
如果图像是单色、16色和256色,则紧跟着调色板的是位图数据,位图数据是指向调色板的索引号。
如果位图是16位、24位和32位色,则图像文件中不保留调色板,即不存在调色板,图像的颜色直接在位图数据中绘出。
如果图像带有调色板,则位图数据可以根据需要选择压缩与不压缩,如果选择压缩,则根据BMP图像是16色或256色,采用RLE4或RLE8压缩算法。
灰度图的调色板共有256项RGBQUAD结构,存放0到255的灰度值,每一项rgbRed、rgbGreen、rgbBlue分量值相等。灰度图调色板空间的申请的具体设置如下:
RGBQUAD *ipRGB2 = (RGBQUAD *)malloc(256*sizeof(RGBQUAD));//调色板的大小为1024字节

for (int   i = 0; i < 256; i++ )

ipRGB2[i].rgbRed = ipRGB2[i].rgbGreen = ipRGB2[i].rgbBlue = i;


上面例子的这幅图片并没有调色板

也验证了bfOffBits == sizeof(BITMAPFILEHEADER )+sizeof(BITMAPINFOHEADER);正好是54字节。

三原色RGB: 自然界中的所有颜色都可以由红、绿、蓝(R,G,B)组合而成。每种颜色都可以量化为0到255共256个等级。不同的组合会显示出不同的颜色。

当一幅图中每个像素被赋予不同的额RGB值时,就能呈现出五彩缤纷的颜色了,这样就形成了彩色图。
让我们距离说明什么是调色板?为什么需要调色板?

有一个长宽各为200个象素,颜色数为16色的彩色图,每一个象素都用R、G、B三个分量表示。因为每个分量有256个级别,要用8位(bit),即一个字节(byte)来表示,所以每个象素需要用3个字节。整个图象要用200×200×3,约120k字节,可不是一个小数目呀!如果我们用下面的方法,就能省的多。

因为是一个16色图,也就是说这幅图中最多只有16种颜色,我们可以用一个表:表中的每一行记录一种颜色的R、G、B值。这样当我们表示一个象素的颜色时,只需要指出该颜色是在第几行,即该颜色在表中的索引值。举个例子,如果表的第0行为255,0,0(红色),那么当某个象素为红色时,只需要标明0即可。

让我们再来计算一下:16种状态可以用4位(bit)表示,所以一个象素要用半个字节。整个图象要用200×200×0.5,约20k字节,再加上表占用的字节为3×16=48字节.整个占用的字节数约为前面的1/6,省很多吧?

这张R、G、B的表,就是我们常说的调色板(Palette),另一种叫法是颜色查找表LUT(Look Up Table),似乎更确切一些。

那么为什么我们这张BMP不带调色板呢?

       是因为我们这张BMP是24位真彩色的BMP,所谓真彩色图(true color),就是它的颜色数高达256×256×256种,也就是说包含我们上述提到的R、G、B颜色表示方法中所有的颜色。真彩色图并不是说一幅图包含了所有的颜色,而是说它具有显示所有颜色的能力,即最多可以包含所有的颜色。表示真彩色图时,每个象素直接用R、G、B三个分量字节表示,而不采用调色板技术。原因很明显:如果用调色板,表示一个象素也要用24位,这是因为每种颜色的索引要用24位(因为总共有256×256×256种颜色,即调色板有256×256×256行),和直接用R,G,B三个分量表示用的字节数一样,不但没有任何便宜,还要加上一个256×256×256×3个字节的大调色板。所以真彩色图直接用R、G、B三个分量表示,它又叫做24位色图。

这么看来BMP文件不能一概而论了,其是否用调色板或者是RGB掩码,位图数据中的数据的真正含义直接与biBitCount 有关,不同类型的位图,其中的设计原理也不同,下面对此作一个对比:




④位图数据
24位BMP图,每三个字节表示一个像素,三个字节分别代表R、G、B的分量值


这里每3个字节表示一个像素的颜色,注意:由于位图信息头中的图像高度是正数,所以位图数据在文件中的排列顺序是从左下角到右上角,以行为主序排列的。

http://blog.csdn.net/u013162930/article/details/47296455







  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值