纯手写bmp图片

bmp图片就是位图,是在几乎任何的操作平台上都支持的图片格式,今天我们就用bmp图片来做一个有趣的试验,不用任何的画图工具, 我们只用16进制编辑器,在里面输入16进制数,然后保存后缀为.bmp的文件,由此而构成一副bmp图片。虽然最后生成的bmp图片在现实生活中没有任何的用处, 但是在纯手工构建这个图片的过程中,你能深刻的体会到bmp图片是怎么构成的,这样对于我们做有关bmp图片的编程时也是大有裨益的,同时我们还能从中体会到计算机表示数据的思想。OK, let's begin:


为了减少我们输入和计算的麻烦,我将会构建一个比较简单的图片,16*16的图片,即宽16个像素,高16个像素的bmp图片,同时为了不涉及到调色板这种比较麻烦的问题,我们将构建24位色的图片,即用R,G,B三原色表示一个像素点的图片。

首先我们需要了解一下bmp图片的文件头的组成:
bmp图片的文件头由下面2个结构构成:
typedef struct tagBITMAPFILEHEADER {
        WORD    bfType;   // 文件类型
        DWORD   bfSize;   // 文件大小
        WORD    bfReserved1; // 保留值,为0
        WORD    bfReserved2; // 保留值,为0
        DWORD   bfOffBits;   // 文件中数据的偏移
} BITMAPFILEHEADER;

typedef struct tagBITMAPINFO {
    BITMAPINFOHEADER    bmiHeader;  // bmp文件信息头
    RGBQUAD             bmiColors[1];  // 调色板数组
} BITMAPINFO;

在BITMAPINFO结构中,根据bmp图片位数的不同(1bit, 2bit, 8bit, 16bit, 24bit, 32bit)RGQUARD这个数组的大小也不一样,而对于24位色以上的图片,这个结构大小为0,即没有调色板,它的后面的数值就代表了像素的颜色。所以,对于24位色的bmp图片,实际构成将会是下面这个样子:

BITMAPFILEHEADER
BITMAPINFOHEADER
DATA (R, G, B)

所以,对于我们的任务就是填充文件头BITMAPFILEHEADER和信息头BITMAPINFOHEADER以及数据区域。


接着,我们要做的事情就是,根据文件头每个字段的意义以及大小分别填充它们。为了让大家看的更加清楚,我将会以表格的形式来填充每个字段。



了解了每个字段的含义以及计算好了它们的值之后,下面的任务就是要在16进制编辑器里面把它写出来,这里,我将使用比较流行的WinHex。


打开WinHex,新建立一个文件,大小为822个字节,然后将文件保存为test.bmp,接着我们开始填充这个文件的每个字节。因为平时我们表示一个16进制数字的时候,高字节在前,低字节在后,而文件中正好相反,即低字节在前,而高字节在后,所以,当一个数字是0x4d42的时候,我们在编辑器里面填入42 4D ,所有的数字都以此类推,不再说明。

 我们先来填充BITMAPFILEHEADER结构的每个字段的值,如下:
                0   1   2   3    4   5    6   7    8   9    A   B   C   D   E   F
00000000  42  4D 36  03  00  00  00  00  00  00  36

接着,我们来填充BITMAPINFOHEADER结构的每个字段的值,要接着上面的开始填:
                0   1    2   3   4     5   6    7    8   9    A    B   C    D   E   F
00000000  42  4D  36  03  00  00  00  00  00  00  36  00  00  00  28  00
00000010  00  00  10  00  00  00  10  00  00  00  01  00  18  00  00  00
00000020  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00  00
00000030  00  00  00  00  00  00  FF  00  00  FF  00  00  FF  00  00  FF

00000040

.......

00000330  00  FF  FF  00  FF  FF 

 
上面的红色部分表示BITMAPFILEHEADER结构填充的内容,蓝色部分表示BITMAPINFOHEADER结构填充的内容,从0x0036开始,到0x0335结束,都是数据区域的内容,这里面可以随便填,填入内容的不同,显示的bmp图片也不一样,全部内容填充完毕,重新保存一下文件,然后用windows自带的图片浏览器就可以查看自己纯手写出来的bmp图片了。


需要说明的是,我们在计算图片数据大小的时候,一定是宽度×高度×3, 我刚开始做的时候,因为忘了×3, 结果图片总是无法正确显示,后来检查了多遍,才发现这个问题。对于文件头的数据,每个字节都必须填写正确,只要有一个字节出错,图片就可能无法正确显示。