bitmap文件格式分析

说到图片,位图(Bitmap)当然是最简单的,它Windows显示图片的基本格式,其文件扩展名为*.BMP。在Windows下,任何各式的图片文件(包括视频播放)都要转化为位图个时候才能显示出来,各种格式的图片文件也都是在位图格式的基础上采用不同的压缩算法生成的(Flash中使用了适量图,是按相同颜色区域存储的)。

一、下面我们来看看位图文件(*.BMP)的格式。

位图文件主要分为如下3个部分:


块名称

对应Windows结构体定义

大小(Byte)

文件信息头

BITMAPFILEHEADER

14

位图信息头

BITMAPINFOHEADER

40

RGB颜色阵列

BYTE*

由图像长宽尺寸决定

1、   文件信息头BITMAPFILEHEADER

结构体定义如下:

typedef struct tagBITMAPFILEHEADER { /* bmfh */

UINT bfType;  
DWORD bfSize; 
UINT bfReserved1; 
UINT bfReserved2; 
DWORD bfOffBits;

} BITMAPFILEHEADER;

其中:


bfType

说明文件的类型,该值必需是0x4D42,也就是字符‘BM‘。

bfSize

说明该位图文件的大小,用字节为单位

bfReserved1

保留,必须设置为0

bfReserved2

保留,必须设置为0

bfOffBits

说明从文件头开始到实际的图象数据之间的字节的偏移量。这个参数是非常有用的,因为位图信息头和调色板的长度会根据不同情况而变化,所以你可以用这个偏移值迅速的从文件中读取到位数据。

2、位图信息头BITMAPINFOHEADER

结构体定义如下:

typedef struct tagBITMAPINFOHEADER { /* bmih */

DWORD biSize; 
LONG biWidth; 
LONG biHeight; 
WORD biPlanes; 
WORD biBitCount; 
DWORD biCompression; 
DWORD biSizeImage; 
LONG biXPelsPerMeter; 
LONG biYPelsPerMeter; 
DWORD biClrUsed; 
DWORD biClrImportant;

} 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,表示都重要。

3、RGB颜色阵列

有关RGB三色空间我想大家都很熟悉,这里我想说的是在Windows下,RGB颜色阵列存储的格式其实BGR。也就是说,对于24位的RGB位图像素数据格式是:


蓝色B值

绿色G值

红色R值

对于32位的RGB位图像素数据格式是:


蓝色B值

绿色G值

红色R值

透明通道A值

透明通道也称Alpha通道,该值是该像素点的透明属性,取值在0(全透明)到255(不透明)之间。对于24位的图像来说,因为没有Alpha通道,故整个图像都不透明。

二、搞清了文件格式,下一步我们要实现加载。

加载文件的目的是要得到图片属性,以及RGB数据,然后可以将其绘制在DC上(GDI),或是生成纹理对象(3D:OpenGL/Direct3D)。这两种用途在数据处理上有点区别,我们主要按前一种用法讲,在和3D有不同的地方,我们再提出来。

1、加载文件头

//Load the file header

BITMAPFILEHEADER header;

memset(&header, 0, sizeof(header));

inf.read((char*)&header, sizeof(header));

if(header.bfType != 0x4D42)

return false;

这个很简单,没有什么好说的。

2、加载位图信息头

//Load the image information header

BITMAPINFOHEADER infoheader;

memset(&infoheader, 0, sizeof(infoheader));

inf.read((char*)&infoheader, sizeof(infoheader));

m_iImageWidth = infoheader.biWidth;

m_iImageHeight = infoheader.biHeight;

m_iBitsPerPixel = infoheader.biBitCount;

这里我们得到了3各重要的图形属性:宽,高,以及每个像素颜色所占用的位数。

3、行对齐

由于Windows在进行行扫描的时候最小的单位为4个字节,所以当

图片宽 X 每个像素的字节数 != 4的整数倍

时要在每行的后面补上缺少的字节,以0填充(一般来说当图像宽度为2的幂时不需要对齐)。位图文件里的数据在写入的时候已经进行了行对齐,也就是说加载的时候不需要再做行对齐。但是这样一来图片数据的长度就不是:宽 X 高 X 每个像素的字节数  了,我们需要通过下面的方法计算正确的数据长度:

//Calculate the image data size

int iLineByteCnt = (((m_iImageWidth*m_iBitsPerPixel) + 31) >> 5) << 2;

m_iImageDataSize = iLineByteCnt * m_iImageHeight;

4、加载图片数据

对于24位和32位的位图文件,位图数据的偏移量为sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER),也就是说现在我们可以直接读取图像数据了。

if(m_pImageData) delete []m_pImageData;

m_pImageData = new unsigned char[m_iImageDataSize];

inf.read((char*)m_pImageData, m_iImageDataSize);

如果你足够细心,就会发现内存m_pImageData里的数据的确是BGR格式,可以用个纯蓝色或者是纯红色的图片测试一下。

5、绘制

好了,数据和属性我们都有了,现在就可以拿来随便用了,就和吃馒头一样,爱粘白糖粘白糖,爱粘红糖粘红糖。下面是我的GDI绘制代码,仅作参考。

void CImage::DrawImage(HDC hdc, int iLeft, int iTop, int iWidth, int iHeight)

{

if(!hdc || m_pImageData == NULL)

return;

BITMAPINFO bmi;

memset(&bmi, 0, sizeof(bmi));

bmi.bmiHeader.biSize = sizeof(BITMAPINFO);

bmi.bmiHeader.biWidth = m_iImageWidth;

bmi.bmiHeader.biHeight = m_iImageHeight;

bmi.bmiHeader.biPlanes = 1;

bmi.bmiHeader.biBitCount = m_iBitsPerPixel;

bmi.bmiHeader.biCompression = BI_RGB;

bmi.bmiHeader.biSizeImage = m_iImageDataSize;

StretchDIBits(hdc, iLeft, iTop, iWidth, iHeight,

0, 0, m_iImageWidth, m_iImageHeight,

m_pImageData, &bmi, DIB_RGB_COLORS, SRCCOPY);

}

6、3D(OpenGL)的不同之处

如果你是想用刚才我们得到的数据生成纹理对象,那么你还要请出下面的问题。

首先,用来生成纹理的数据不需要对齐,也就是说不能在每行的后面加上对齐的字节。当然在OpenGL里要求纹理图片的尺寸为2的幂,所以这个问题实际上不存在;

其次,我们得到的图形数据格式是BGR(BGRA),所以在生成纹理的时候,需指定格式为GL_BGR_EXT(GL_BGRA_EXT);否则需要做BGR->RGB(BGRA->RGBA)的转化。

说了这么多,其实bitmap文件在编程中需要注意两点,一:文件行对齐的问题。二:bitmap文件的像素是从左下角开始存储,而开发板的LCD是从左上角开始显示的。

时间: 2024-10-07 15:03:13

bitmap文件格式分析的相关文章

AVI 文件格式分析

************************************************************************ AVI 文件格式分析 --- 2014/8/23 16:40:05 ************************************************************************ avi含三部分:文件头.数据块和索引块. 1.文件头包括文件的通用信息,定义数据格式,所用的压缩算法等参数. 2.数据块包含实际数据流,即图

wav文件格式分析详解

wav文件格式分析详解 文章转载自:http://blog.csdn.net/BlueSoal/article/details/932395 一.综述    WAVE文件作为多媒体中使用的声波文件格式之一,它是以RIFF格式为标准的.RIFF是英文Resource Interchange File Format的缩写,每个WAVE文件的头四个字节便是"RIFF".    WAVE文件是由若干个Chunk组成的.按照在文件中的出现位置包括:RIFF WAVEChunk, Format C

OBJ文件格式分析工具: objdump, nm,ar

首先简要阐述关于gcc.glibc和 binutils模块之间的关系 一.关于gcc.glibc和binutils模块之间的关系 1.gcc(gnu collect compiler)是一组编译工具的总称.它主要完成的工作任务是"预处理"和"编译",以及提供了与编译器紧密相关的运行库的支持,如 libgcc_s.so.libstdc++.so等. 2.binutils提供了一系列用来创建.管理和维护二进制目标文件的工具程序,如汇编(as).连接(ld).静态库归档(

mpeg文件格式分析

MPEG-1流比特层次结构分析总结 1.简要介绍Mpeg 2.Mpeg-1数据流分析 2.1视频序列层(VideoStream) 2.2画面组层(GOP) 2.3画面层(Pictures) 2.4片层(Slice) 2.5宏块层(Macroblock) 2.6块层(Block) 3.加密位置的思考 附录 MPEG-1流比特层次结构分析总结 1.简要介绍Mpeg Mpeg是Motion Picture Expert Group的缩写.活动图像专家组是在1988年由ISO和IEC联合成立的专家组,负

多媒体(2):WAVE文件格式分析

目录 多媒体(1):MCI接口编程 多媒体(2):WAVE文件格式分析 多媒体(3):基于WindowsAPI的视频捕捉卡操作 多媒体(4):JPEG图像压缩编码 多媒体(2):WAVE文件格式分析

Linux及安全实践四——ELF文件格式分析

Linux及安全实践四——ELF文件格式分析 一.ELF文件格式概述 1. ELF:是一种对象文件的格式,用于定义不同类型的对象文件中都放了什么东西.以及都以什么样的格式去放这些东西. 二.分析一个ELF文件 以一个最简单的helloworld程序为例 1. ELF文件头 使用工具查看ELF文件头:readelf -h obj 在/usr/include/elf.h中可以找到文件头结构定义: 大小总共为64字节,换算成十六进制为0x40.在十六进制代码中找到前0x40字节,即为文件头信息部分(阅

201303-lnk文件格式分析以及木马利用-willj[4st TeAm]

前不久在卡饭爆出各种木马利用快捷方式启动绕过杀毒软件的主动防御,随分析下. 0x01. Lnk文件介绍 lnk文件是用于指向其他文件的一种文件. 这些文件通常称为快捷方式文件.通常它以快捷方式放在硬盘上.以方便使用者快速的调用,其扩展名为.lnk. 0x02. Lnk文件格式解析 Lnk文件头 Shell Item Id List段(可选) 文件本地信息段 描述字符串段(可选) 相对路径段(可选) 工作目录段(可选) 命令行段(可选) 图标文件段(可选) 附加信息段(可选) @Lnk文件头结构

《PNG文件格式》(二)PNG文件格式分析

欢迎查看系列博客: <PNG文件格式>(一)PNG文件概述     <PNG文件格式>(二)PNG文件格式分析(本篇) <PNG文件格式>(三)PNG文件实例剖析 摘自: 中文PNG格式说明:dev.gameres.com PNG文件格式白皮书:www.w3.org LZ77算法的JAVA实现:jazzlib.sourceforge.net LZ77算法的JAVA实现,包括J2ME版本:www.jcraft.com ===========================

PE文件格式分析

第一阶段:PE文件格式分析 使用UltraEdit观察PE文件例子程序hello-2.5.exe的16进制数据,在打印稿中画出该PE文件基本结构. 使用Ollydbg对该程序进行初步调试,了解该程序功能结构,在内存中观察该程序的完整结构. 熟悉各类PE文件格式查看和编辑工具(PEView.Stud_PE等). 使用UltraEdit修改该程序,使得该程序仅弹出第二个对话框. 第二阶段:熟悉并分析PE文件的引出表 找到系统System32目录下的user32.dll文件,用UltraEdit打开并