首页
社区
课程
招聘
[原创]纯手写bmp图片
发表于: 2009-5-13 13:54 15962

[原创]纯手写bmp图片

2009-5-13 13:54
15962

纯手写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以及数据区域。

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

大小                字段                        值和意义
WORD             bfType                    文件类型,标识,必须为”BM”,即0x4d42
DWORD           bfSize                     整个bmp文件的大小,包括2个头以及数据区域,
                                                  计算方法如下:
                                                  sizeof(BITMAPFILEHEADER)+
                                                  sizeof(BITMAPINFOHEADER)+
                                                  16*16*3
                                                  因为我们要设计一个16×16的24色位图,所以整个
                                                  数据区域的大小为:宽度×高度×每个像素的大小,
                                                  因为每个像素是用RGB三原色表示的,所以,每个像
                                                  素所占大小为3个字节,即这个字段的大小为:
                                                  sizeof(BITMAPFILEHEADER) = 14 +
                                                  sizeof(BITMAPINFOHEADER) = 40 +
                                                  16*16*3 = 768
                                                  即14+40+768=822个字节,即0x0336字节

WORD            bfReserved1              保留值,必须为0
WORD            bfReserved2              保留值,必须为0
DWORD          bfOffBits                   数据到文件开始位置的偏移,即
                                                  sizeof(BITMAPFILEHEADER) = 14 +
                                                  sizeof(BITMAPINFOHEADER) = 40
                                                  即14+40=54

DWORD          biSize                      本结构的大小,即sizeof(BITMAPINFOHEADER)
                                                  = 40,即0x28

LONG             biWidth                    位图的宽度,我们设为16,即0x10
LONG             biHeight                   位图的高度,我们设为16,即0x10
WORD            biPlanes                   固定值1,即0x01
WORD            biBitCount                多少位色的图片,这里为24,0x18
DWORD          biCompression           压缩方式,这里为BI_RGB= 0x00
DWORD          biSizeImage              这里无需关心,设置为0,详细意义查MSDN
LONG             biXPelsPerMeter        这里无需关心,设置为0,详细意义查MSDN
LONG             biYPelsPerMeter        这里无需关心,设置为0,详细意义查MSDN
DWORD          biClrUsed                 这里无需关心,设置为0,详细意义查MSDN
DWORD          biClrImportant           这里无需关心,设置为0,详细意义查MSDN

了解了每个字段的含义以及计算好了它们的值之后,下面的任务就是要在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, 结果图片总是无法正确显示,后来检查了多遍,才发现这个问题。对于文件头的数据,每个字节都必须填写正确,只要有一个字节出错,图片就可能无法正确显示。


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (36)
雪    币: 65
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
嗯 好东西 谢谢LZ

不过恕我直言 这是原创么...没见到“上面的红色字”...
2009-5-13 13:59
0
雪    币: 387
活跃值: (25)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
3
看附件, 这个是从word上拷贝下来的
我直接粘贴的

这是绝对是原创, 本人不善于抄袭
2009-5-13 14:02
0
雪    币: 387
活跃值: (25)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
4
如果你看到哪篇博客上有此文, 那么很可能就是我的个人博客
2009-5-13 14:03
0
雪    币: 387
活跃值: (25)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
5
因为上面有表格, 这里似乎不支持表格, 编辑起来太麻烦, 所以, 就简单编辑了一下, 让人能看清楚
至于颜色,我就没有加了
想看比较整齐一点的, 请下载后面的附件
2009-5-13 14:06
0
雪    币: 164
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
我看见老大下载了,我就下载了。
2009-5-13 14:16
0
雪    币: 387
活跃值: (25)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
7
哇, 回来看看, 这篇拙文居然被加精了, 太感谢斑竹的鼓励了
2009-5-13 14:21
0
雪    币: 9
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
期待LZ再次出手, PE出JPG,PNG,GIF......格式图片来。
2009-5-13 18:04
0
雪    币: 115
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
很不错的。。。顶一个。。。
2009-5-13 18:40
0
雪    币: 125
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
这样都能那精华,早知道我也来个手写Bmp
2009-5-13 21:02
0
雪    币: 264
活跃值: (41)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
好帖,高手.谢谢楼主
2009-5-14 10:48
0
雪    币: 164
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
下完回帖
2009-8-21 10:08
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
好贴 学习一下
2009-8-27 15:23
0
雪    币: 222
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
14
mark下,一直对图片的东西不解
2009-8-29 10:54
0
雪    币: 237
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
还有机会的,不如写写jpg?
2009-9-9 15:46
0
雪    币: 4560
活跃值: (1002)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
16
偶对图片格式解析最头疼了,谢谢楼主的文章
2009-9-9 16:07
0
雪    币: 217
活跃值: (97)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
以前对bmp不了解现在了解一点了 谢谢楼主的文章
2009-9-9 16:34
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
看我ID...07年注册的...比15楼次点.
哎...依然还是新手...
2009-9-13 03:36
0
雪    币: 15612
活跃值: (3817)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
19
虽然不是太懂,不过还是下载看看,支持楼主继续原创出好的东西
2009-9-13 13:16
0
雪    币: 100
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
郁闷

看到 高阁逆风  
的头像..以为偶电脑上有虫子..用嘴巴去吹!!
2009-9-13 23:31
0
雪    币: 14
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
呵呵,学习下,
2009-9-17 12:37
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
想熟悉下jpg格式
2009-9-17 14:09
0
雪    币: 92
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
很不错啊,
楼主可以讲解下怎么无损压缩bmp图片不?
2009-9-21 11:41
0
雪    币: 92
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
我06年注册的,还是新手。。
2009-9-21 11:42
0
雪    币: 249
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
学习了,
  谢.
2009-9-23 05:36
0
游客
登录 | 注册 方可回帖
返回
//