Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1613014
  • 博文数量: 441
  • 博客积分: 20087
  • 博客等级: 上将
  • 技术积分: 3562
  • 用 户 组: 普通用户
  • 注册时间: 2006-06-19 15:35
文章分类

全部博文(441)

文章存档

2014年(1)

2012年(1)

2011年(8)

2010年(16)

2009年(15)

2008年(152)

2007年(178)

2006年(70)

分类: C/C++

2008-12-15 12:17:04

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×1624色位图,所以整个数据区域的大小为:宽度×高度×每个像素的大小,因为每个像素是用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

多少位色的图片,这里为240x18

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, 结果图片总是无法正确显示,后来检查了多遍,才发现这个问题。对于文件头的数据,每个字节都必须填写正确,只要有一个字节出错,图片就可能无法正确显示。


手写的效率比较低,如果想知道用程序如何生成一幅bmp图片,请看下面的文章:

用程序生成bmp图片


Author: thinker

QQ: 94483026

E-Mail:cnhnyugmailcom

 

阅读(3141) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~