bmp文件结构的探索 (1)

合集下载

BMP图片文件详解

BMP图片文件详解

有一个长宽各为 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*2 00*0.5,约 20k 字节,再加上表占用的字节为 3*16=48 字节.整个占用的字节数约为前面的 1/6,省很多吧。 这 张 RGB 的 表 , 即 是 我 们 常 说 的 调 色 板 (Palette) , 另 一 种 叫 法 是 颜 色 查 找 表 LUT(LookUpTable),似乎更确切一些。Windows 位图中便用
biXPelsPerMeter 指定目标设备的水平分辨率,单位是每米的象素个数,关于分辨率的概念,我们将在打印部 分详细介绍。
biYPelsPerMeter 指定目标设备的垂直分辨率,单位同上。
biClrUsed 指定本图象实际用到的颜色数,如果该值为零,则用到的颜色数为 2 的 biBitCount 次方。
biSizeImage 指定实际的位图数据占用的字节数,其实也可以从以下的公式中计算出来:

bmp读取详解

bmp读取详解

bmp读取详解BMP图像文件由三部分组成:位图文件头数据结构,它包含BMP图像文件的类型、显示内容等信息;位图信息数据结构,它包含有BMP图像的宽、高、压缩方法,以及定义颜色等信息。

<?xml:namespace prefix = o ns ="urn:schemas-microsoft-com:office:office" />位图文件主要分为如下3个部分:块名称对应Windows结构体定义大小(Byte)文件信息头BITMAPFILEHEADER 14位图信息头BITMAPINFOHEADER 40RGB颜色阵列BYTE* 由图像长宽尺寸决定1、文件信息头BITMAPFILEHEADER结构体定义如下:typedef struct tagBITMAPFILEHEADER {WORD bfType;DWORD bfSize;WORD bfReserved1;WORD bfReserved2;DWORD bfOffBits;} BITMAPFILEHEADER;其中:bfType 说明文件的类型,该值必需是0x4D42,也就是字符'BM'。

bfSize 说明该位图文件的大小,用字节为单位,即整个图像文件的存储需要多少存储空间。

bfReserved1 保留,必须设置为0 bfReserved2 保留,必须设置为0bfOffBits 说明从文件头开始到实际的图象数据之间的字节的偏移量。

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

2、位图信息头BITMAPINFOHEADER结构体定义如下:typedef struct tagBITMAPINFOHEADER {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结构所需要的字数。

BMP图像信息隐藏及检测

BMP图像信息隐藏及检测

《信息隐藏与数字水印》实验报告实验二 BMP图像信息隐藏及检测1.实验目的(1)了解BMP图像文件格式(2)了解利用BMP图像文件隐藏信息的原理(3)掌握基于24位真彩色BMP图像的文件信息隐藏方法2.实验内容(1)在图像数据后隐藏信息(2)文件头与图像数据之间隐藏信息(3)BMP图像文件隐藏信息的检测(4)在图像文件头和信息头的保留字段中的隐藏信息(5)灰度、二值图像的其他信息隐藏及检测(扩展)3.实验原理针对文件结构的信息隐藏方法需详细掌握文件的格式,利用文件结构块之间的关系或根据块数据和块大小之间的关系来隐藏信息。

BMP ( Bitmap-File)图形文件是Windows采用的常见图形文件格式,要利用BMP位图进行信息隐藏首先需要详细了解BMP文件的格式,BMP图像文件结构比较单一而且固定,BMP 图像由文件头、信息头、调色板区和数据区四个部分组成,而24位真彩色图像中没有调色板信息。

24位真彩色BMP位图文件包括3部分。

第一部分是BMP文件头。

前2个字节是“BM”,是用于识别BMP文件的标志;第3,4,5,6字节存放的是位图文件的大小,以字节为单位;第7,8,9,10字节是保留的,必须为0;第11,12,13,14字节给出位图阵列相对于文件头的偏移,在24位真彩色图像中,这个值固定为54;第19,20,21,22字节表示的是图像文件的宽度,以像素为单位;第23,24, 25, 26表示的是图像文件的高度,以像素为单位。

第二部分是位图信息头。

从第29个字节开始,第29,30字节描述的是像素的位数,24位真彩色位图。

该位的值为0x18; 第三部分是数据区。

从第55个字节开始,每3个字节表示一个像素,这3个字节依次表示该像素的红、绿、蓝亮度分量值。

在不影响图像正常显示情况下,可使用以下四种方法在24位真彩色BMP图像中隐藏信息。

●在图像文件尾部添加任意长度的数据,秘密信息存放在文件尾部可以减少修改文件头的数据量,仅需修改文件头中文件长度的值即可。

BMP文件构造

BMP文件构造

附录1:BMP文件一.简介BMP(Bitmap-File)图形文件是Windows采用的图形文件格式,在Windows环境下运行的所有图象处理软件都支持BMP图象文件格式。

Windows系统内部各图像绘制操作都是以BMP为基础的。

实际上由于微软公司的在业界地位,BMP文件已成为跨操作系统和硬件系统的图像文件的实用工业标准.Windows 3.0以前的BMP图文件格式与显示设备有关,因此把这种BMP图象文件格式称为设备相关位图DDB(device-dependent bitmap)文件格式。

Windows 3.0以后的BMP图象文件与显示设备无关,因此把这种BMP图象文件格式称为设备无关位图DIB(device-independent bitmap)格式。

BMP位图文件默认的文件扩展名是BMP或者bmp(有时它也会以.DIB或.RLE作扩展名)。

1.文件结构位图文件可看成由4个部分组成:位图文件头(bitmap-file header)、位图信息头(bitmap-information header)、彩色表(color table)和定义位图的字节阵列,它具有如下所示的形式。

位图文件的组成结构名称位图文件头(bitmap-file header)BITMAPFILEHEADER位图信息头(bitmap-informationheader)BITMAPINFOHEADER彩色表(color table)RGBQUAD图象数据阵列字节BYTE2.位图文件详细结构可综合在下表。

 域的名称大小内容图象文件头 文件标识 2 bytes两字节的内容用来识别位图的类型:‘BM’ : Windows 3.1x, 95, NT, …‘BA’ :OS/2 Bitmap Array‘CI’ :OS/2 Color Icon‘CP’ :OS/2 Color Pointer‘IC’ : OS/2 Icon‘PT’ :OS/2 Pointer注:因为OS/2系统并没有被普及开,所以在编程时,你只需判断第一个标识“BM”就行。

02_bmp格式分析

02_bmp格式分析

查看BMP文件结构1. 利用Photoshop创建一个宽度为4像素,高度为5像素,颜色模式为RGB,每个颜色通道由8位表示的空白图像。

2. 按快捷键Ctrl+=放大显示该空白图像以便于操作。

点选工具栏中的颜色组合按钮的左上角按钮设置前景色,依次设置5种颜色(R、G、B通道值:红(255,0,0),黑(0,0,0),绿(0,255,0),白(255,255,255),蓝(0,0,255)),并利用工具栏中的铅笔工具填涂该空白图片,每种颜色涂一行。

最后存储该图像为BMP文件格式。

4*5像素的图像的放大示意图3. 利用UltraEdit32应用程序打开该BMP文件,可以见到文件以16进制形式显示。

根据BMP文件结构,可知前14个字节为BITMAPFILEHEADER(位图文件头),接下来40个字节为BITMAPINFOHEADER(位图信息头)。

由于该图像是24位真彩色图像,所以没有调色板,那么在位图信息头之后紧随的就是位图数据了,其大小为60个字节(宽度4像素*高度5像素*每个像素3个字节),最后由两个0字节作为文件结束标志。

4.请对照BMP文件结构,认真分析每个字节的含义。

需要注意的是:(1)数据的存储是高位数据存在高地址字节中,反之亦反。

如DWORD类型的十六进制数据00000036,实际存储为36 00 00 00。

(2)BMP是以图像左下角为起点开始逐行存储的。

(3)BMP中每个像素的三基色存储顺序为B、G、R,而不是常说的RGB。

如00 00 FF代表的是红色。

思考题:用同样的方法创建一个5*5像素的bmp文件,用UltraEdit32查看文件结构与4*4的bmp文件有何不同。

(bmp格式的图像每一行的字节数必须是4的整数倍,如果不是,则需要补齐)。

BMP24位位图格式总结

BMP24位位图格式总结

图像BMP24位位图格式总结1、创建图片创建一张只有六个像素的图片(两行三列),每个像素的颜色RGB组合值如图1(示意图)所示:图12、windows系统下存储格式(使用WinHex打开)3、文件结构3.1 文件头(bmp file header),提供文件的格式、大小等信息,共14个字节,如图2所示。

图23.1.1 0-1字节(2个字节)0x42 0x4d = "BM",表示这是Windows支持的位图格式,如图3所示。

图33.1.2 2-5字节(4个字节),表示该bmp文件的大小,存储形式为图4所示,因为小端对齐形式存储,实际存储的16进制数为0x4e,转换为十进制为78,与我们直接查看此图片的属性所看到的文件大小一致。

注:对于arm,intel这种x86架构的复杂指令CPU,整数在内存中是倒着存放的,低地址放低位,高地址放高位,小端对齐,但对于unix服务器的CPU,更多是采用大端对齐的情况图43.1.3 6-9字节这是两个保留段,为0如图5所示。

图53.1.4 A-D字节如图6所示,存储数据为0x36,十进制为54,表示的意义为从文件头到位图数据需偏移54字节。

图63.2 位图信息头(bitmap information):提供图像数据的尺寸、位平面数、压缩方式、颜色索引等信息,40个字节,如图7所示。

图73.2.1 0E-11字节,如图8所示,存储数据为0x28,十进制为40,表示意义为:位图信息头的大小为40个字节。

图83.2.2 12-15字节,如图9所示,存储数据为0x03,十进制为3,表示意义为:图像宽为3个像素,与我们创建的图像一致。

图93.2.3 16-19字节,如图10所示,存储数据为0x02,十进制为2,表示意义为:图像高为2个像素,与我们创建的图像一致。

图103.2.4 1A-1B字节,如图11所示,存储数据为0x01,该值总为1,表示意义为位元面数。

bmp文件结构

bmp文件结构

BMP文件结构1. BMP文件组成BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。

文件头主要包含文件的大小、文件类型、图像数据偏离文件头的长度等信息;位图信息头包含图象的尺寸信息、图像用几个比特数值来表示一个像素、图像是否压缩、图像所用的颜色数等信息。

颜色信息包含图像所用到的颜色表,显示图像时需用到这个颜色表来生成调色板,但如果图像为真彩色,既图像的每个像素用24个比特来表示,文件中就没有这一块信息,也就不需要操作调色板。

文件中的数据块表示图像的相应的像素值,需要注意的是:图像的像素值在文件中的存放顺序为从左到右,从下到上,也就是说,在BMP文件中首先存放的是图像的最后一行像素,最后才存储图像的第一行像素,但对与同一行的像素,则是按照先左边后右边的的顺序存储的;另外一个需要关注的细节是:文件存储图像的每一行像素值时,如果存储该行像素值所占的字节数为4的倍数,则正常存储,否则,需要在后端补0,凑足4的倍数。

2. BMP文件头BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息。

其结构定义如下:3. 位图信息头BMP位图信息头数据用于说明位图的尺寸等信息。

其结构如下:注意:对于BMP文件格式,在处理单色图像和真彩色图像的时候,无论图象数据多么庞大,都不对图象数据进行任何压缩处理,一般情况下,如果位图采用压缩格式,那么16色图像采用RLE4压缩算法,256色图像采用RLE8压缩算法。

4. 颜色表颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。

RGBQUAD结构的定义如下:颜色表中RGBQUAD结构数据的个数由BITMAPINFOHEADER 中的biBitCount项来确定,当biBitCount=1,4,8时,分别有2,16,256个颜色表项,当biBitCount=24时,图像为真彩色,图像中每个像素的颜色用三个字节表示,分别对应R、G、B值,图像文件没有颜色表项。

BMP位图浅析

BMP位图浅析

什么是位图计算机能以位图和矢量图格式显示图像。

位图(Bitmap)图像又称点阵图或光栅图,它使用我们称为像素(象素,Pixel)的一格一格的小点来描述图像。

计算机屏幕其实就是一张包含大量像素点的网格。

当我们把位图放大时,每一个像素小点看上去就像是一个个马赛克色块。

矢量图(Vector)使用直线和曲线来描述图形,这些图形的元素是一些点、线、矩形、多边形、圆和弧线等等,它们都是通过数学公式计算获得的。

位图和矢量图最简单的区别就是:矢量图可以无限放大,而且不会失真;而位图则不能。

像Photoshop(PS)这样主要用于处理位图的软件,我们称之为图像处理软件;专门处理矢量图的软件,我们称之为图形设计软件,例如Adobe Illustrator,CorelDRAW,Flash MX等。

BMP位图文件常见的图像文件格式有:BMP、JPG(JPE,JPEG)、GIF等。

BMP图像文件(Bitmap-File)格式是Windows采用的图像文件存储格式,在Windows环境下运行的所有图像处理软件都支持这种格式。

Windows 3.0以后的BMP文件都是指设备无关位图(DIB,device-independent bitmap)。

BMP位图文件默认的文件扩展名是.BMP,有时它也会以.DIB或.RLE作扩展名。

创建BMP文件打开Photoshop,新建一个尺寸为2*3像素的文件。

放大图片到最大(1600%),然后用铅笔工具对每个像素都点一个不同颜色的点,如下图所示。

储存这个文件为BMP格式,文件名为“MyBmp.bmp”,在BMP选项中选择Windows,24位。

BMP文件结构BMP文件由4部分组成:1. 位图文件头(bitmap-file header)2. 位图信息头(bitmap-information header)3. 颜色表(color table)4. 颜色点阵数据(bits data)24位真彩色位图没有颜色表,所以只有1、2、4这三部分。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

BMP文件结构的探索BMP文件结构的探索WhatIf 2004-9-10一、文件格式Bmp文件是非常常用的位图文件,无论是游戏还是其他都被广泛使用。

针对bmp文件的处理也有一堆现成的api进行调用,然而文件内部究竟怎样,如何自己来解析这样的文件呢?为了消除无聊,我用了几天时间来研究了一下,同时作为学习笔记,进行记录。

首先,整个bmp文件的内容可以分为3到4块。

之所以分为3到4块而不是固定的值,是因为,对于bmp来说可能存在调色板或者一些掩码。

具体稍候讨论。

第一块是bmp的文件头用于描述整个bmp文件的情况。

结构如下:typedef struct BITMAPFILEHEADER {WORD bfType; //两个字节DWORD bfSize; //四个字节WORD bfReserved1;WORD bfReserved2;DWORD bfOffBits;} BITMAPFILEHEADER, *PBITMAPFILEHEADER;这些信息相当有用,如果你想直接来解析bmp文件。

第一个bfType用于表示文件类型,如果它是bmp文件,那么它这个位置的值一定是”BM”也就是0x4D42。

第二个bfSize表示整个文件的字节数。

第三第四个则保留,目前无意义,最后一个相当重要,表示,位图的数据信息离文件头的偏移量,以字节为单位。

第二块是位图信息头,即BITMAPINFOHEADER,用于描述整个位图文件的情况。

以下挑重要的数据进行解释typedef struct BITMAPINFOHEADER{DWORD biSize; //表示本结构的大小LONG biWidth; //位图的宽度LONG biHeight; //位图的高度WORD biPlanes; //永远为1 ,由于没有用过所以没做研究附msdn解释//Specifies the number of planes for the target device. This value must be set to 1.WORD biBitCount;//位图的位数分为1 4 8 16 24 32 本文没对1 4 进行研究DWORD biCompression; //本以为压缩类型,但是却另外有作用,稍候解释DWORD biSizeImage; //表示位图数据区域的大小以字节为单位LONG biXPelsPerMeter;LONG biYPelsPerMeter;DWORD biClrUsed;DWORD biClrImportant;} BITMAPINFOHEADER, *PBITMAPINFOHEADER;第三块就是调色板信息或者掩码部分,如果是8位位图则存放调色板;16 与32位位图则存放RGB颜色的掩码,这些掩码以DWORD 大小来存放。

最后一块就是位图的数据实体。

以上文件信息可以在任意一篇bmp文件结构的文章中找到描述,所以本文只是稍微带过。

二、4字节对其问题关于数据读取。

Bmp文件有个重要特性,那就是对于数据区域而言,每行的数据它必须凑满4字节,如果没有满,则用冗余的数据来补齐。

这个特性直接影响到我们读取位图数据的方法,因为在我们看来(x,y)的数据应该在 y*width+x这样的位置上但是因为会有冗余信息那么必须将width用width+该行的冗余量来处理,而由于位图文件有不同的位数,所以这样的计算也不尽相同。

下面列出计算偏移量的一般公式。

首先将位图信息读入一个UCHAR 的buffer中:8位:int pitch;if(width%4==0){pitch=width;}else{pitch=width+4-width%4;}index=buffer[y*pitch+x]; 因为8位位图的数据区域存放的是调色板索引值,所以只需读取这个index16位int pitch=width+width%2;buffer[(y*pitch+x)*2]buffer[(i*pitch+j)*2+1]两个UCHAR内,存放的是(x,y)处的颜色信息24位int pitch=width%4;buffer[(y*width+x)*3+y*pitch];buffer[(y*width+x)*3+y*pitch+1];buffer[(y*width+x)*3+y*pitch+2];32位由于一个象素就是4字节所以无需补齐虽然计算比较繁琐,但是这些计算是必须的,否则当你的位图每行的象素数不是4的倍数,那么y*width+x带给你的是一个扭曲的图片,当然如果你想做这样的旋转,也不错啊,至少我因为一开始没有考虑(不知道这个特性)让一个每行象素少1字节的16位图片变成了扭曲的菱形。

三、有了数据分离RGB分量。

由于我的测试代码用了GDI,所以我必须讲得到的某一个点的值分离成 24位模式下的RGB分离,这不是一件容易的工作。

位图麻烦的地方之一就是他的格式太多,所以我们还是要分格式再讨论。

8位通过第二部分提到的操作我们得到了一个index,这个值的范围是0~255 一共256个正好是调色板的颜色数量。

在8位bmp图片中数据信息前256个RGBQUAD的大小开始就是调色板的信息。

不过如果要组织成调色板还要一定的转换因为里面是RGBQUAD信息 r b 两个与调色板中的顺序是颠倒的。

因为我不需要调色板设置所以我字节读取到RGBQUAD数组中,并且通过下面的表达式获取RGB值:UCHAR r=quad[index].rgbRed;UCHAR g=quad[index].rgbGreen;UCHAR b=quad[index].rgbBlue;16位这是最麻烦的一个。

因为在处理时有555 565 两种格式的区别,而且还有所谓压缩类型的区别。

之前的bitmapinfoheader里面提到一个biCompression现在我们分两种情况讨论:BI_RGB和BI_BITFIELDS当他等于BI_RGB时只有555 这种格式,所以可以放心大胆的进行如下的数据分离:UCHAR b=buffer[(i*pitch+j)*2]&0x1F;UCHARg=(((buffer[(i*pitch+j)*2+1]<<6)&0xFF)>>3)+(buffer[(i*pitch +j)*2]>>5);UCHAR r=(buffer[(i*pitch+j)*2+1]<<1)>>3;希望不要被这个表达式折磨的眼花缭乱,我想既然你在看这篇文章,你就有能力阅读这样的代码,否则只能说你还没有到阅读这方面的地步,需要去学习基础的语法了。

有一点值得提醒的是由于有较多的位操作,所以在处理的时候在前一次操作的上面加上一对括号,我就曾经因为没有加而导致出现误差,另外虽然buffer中一个元素代表的是一个UCHAR 但是右移操作会自动增长为两字节所以需要在进行一次与操作截取低位的1字节数据。

现在讨论BI_BITFIELDS。

这个模式下既可以有555 也可以有565 。

555 格式 x rrrrr ggggg bbbbb565 格式rrrrr gggggg bbbbb显然不同的格式处理不同,所以我们要首先判断处到底属于那种格式。

Bitmapinfoheader的biCompression为BI_BITFIELDS时,在位图数据区域前存在一个RGB掩码的描述是3个DWORD值,我们只需要读取其中的R或者G的掩码,来判断是那种格式。

以红色掩码为例 0111110000000000的时候就是555格式1111100000000000就是565格式。

以下是565格式时的数据分离:UCHAR b=buffer[(i*pitch+j)*2]&0x1F;UCHARg=(((buffer[(i*pitch+j)*2+1]<<5)&0xFF)>>2)+(buffer[(i*pitch+j)*2]>>5);UCHAR r=buffer[(i*pitch+j)*2+1]>>3;现在我们得到了RGB各自的分量,但是还有一个新的问题,那就是由于两字节表示了3个颜色 555下每个颜色最多到0x1F 565格式下最大的绿色分量也就0x3F。

所以我们需要一个转换color=color*255/最大颜色数即可如565下RGB(r*0xFF/0x1F,g*0xFF/0x3F,b*0xFF/0x1F)24位UCHAR b=buffer[(i*width+j)*3+realPitch];UCHAR g=buffer[(i*width+j)*3+1+realPitch];UCHAR r=buffer[(i*width+j)*3+2+realPitch];32位UCHAR b=buffer[(i*width+j)*4];UCHAR g=buffer[(i*width+j)*4+1];UCHAR r=buffer[(i*width+j)*4+2];四、剩余的问题当数据取到了,颜色也分离出来了,但是可能你绘出的位图是倒转的,这是因为有些位图的确是翻转的。

通过bitmapinfoheader的biHeight可以判断是正常还是翻转,当biHeight>0的时候颠倒,它小于0的时候正常,不过测试写到现在看到的文件都是颠倒过来的。

五、相关测试代码:(9798.0*r+19235*g+3735*b)/32768.0+0.5采用MFC 目的只是实现自行解析位图文件void CBmpTestView::OnDraw(CDC* pDC){CBmpTestDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);// TODO: 在此处为本机数据添加绘制代码if(filename==""){return;}FILE *fp=fopen(filename,"r");if(fp==NULL){pDC->TextOut(100,200,"no file found");return;}BITMAPFILEHEADER fileheader;BITMAPINFO info;fread(&fileheader,sizeof(fileheader),1,fp);if(fileheader.bfType!=0x4D42){pDC->TextOut(100,200,"无位图文件请选择位图文件");fclose(fp);return ;}fread(&info.bmiHeader,sizeof(BITMAPINFOHEADER),1,fp); long width=info.bmiHeader.biWidth;long height=info.bmiHeader.biHeight;UCHAR *buffer=new UCHAR[info.bmiHeader.biSizeImage]; fseek(fp,fileheader.bfOffBits,0);fread(buffer,info.bmiHeader.biSizeImage,1,fp);if(info.bmiHeader.biBitCount==8){int pitch;if(width%4==0){pitch=width;}else{pitch=width+4-width%4;}RGBQUAD quad[256];fseek(fp,fileheader.bfOffBits-sizeof(RGBQUAD)*256,0);fread(quad,sizeof(RGBQUAD)*256,1,fp);if(height>0){//height>0 表示图片颠倒for(int i=0;i<height;i++){for(int j=0;j<width;j++){int index=buffer[i*pitch+j];UCHAR r=quad[index].rgbRed;UCHAR g=quad[index].rgbGreen;UCHAR b=quad[index].rgbBlue;pDC->SetPixel(j,height-i,RGB(r,g,b));}}}else{for(int i=0;i<0-height;i++){for(int j=0;j<width;j++){int index=buffer[i*pitch+j];UCHAR r=quad[index].rgbRed;UCHAR g=quad[index].rgbGreen;UCHAR b=quad[index].rgbBlue;pDC->SetPixel(j,i,RGB(r,g,b));}}}}else if(info.bmiHeader.biBitCount==16){int pitch=width+width%2;if(height>0){//height>0 表示图片颠倒if(info.bmiHeader.biCompression==BI_RGB){//该模式只有555for(int i=0;i<height;i++){for(int j=0;j<width;j++){//5 5 5 格式UCHAR b=buffer[(i*pitch+j)*2]&0x1F;UCHARg=(((buffer[(i*pitch+j)*2+1]<<6)&0xFF)>>3)+(buffer[(i*pitch +j)*2]>>5);UCHAR r=(buffer[(i*pitch+j)*2+1]<<1)>>3;pDC->SetPixel(j,height-i,RGB((r*0xFF)/0x1F,(g*0xFF)/0x1F ,(b*0xFF)/0x1F));}}}elseif(info.bmiHeader.biCompression==BI_BITFIELDS){//该模式在bitmapinfoheader之后存在RGB掩码每个掩码1 DWORDfseek(fp,fileheader.bfOffBits-sizeof(DWORD )*3,0);DWORD rMask;fread(&rMask,sizeof(DWORD ),1,fp);if(rMask==0x7C00){// 5 5 5 格式MessageBeep(0);for(int i=0;i<height;i++){for(int j=0;j<width;j++){UCHAR b=buffer[(i*pitch+j)*2]&0x1F;UCHARg=(((buffer[(i*pitch+j)*2+1]<<6)&0xFF)>>3)+(buffer[(i*pitch +j)*2]>>5);UCHARr=(buffer[(i*pitch+j)*2+1]<<1)>>3;pDC->SetPixel(j,height-i,RGB((r*0xFF)/0x1F,(g*0xFF)/0x1F ,(b*0xFF)/0x1F));}}}else if(rMask==0xF800){//5 6 5 格式for(int i=0;i<height;i++){for(int j=0;j<width;j++){UCHAR b=buffer[(i*pitch+j)*2]&0x1F;UCHARg=(((buffer[(i*pitch+j)*2+1]<<5)&0xFF)>>2)+(buffer[(i*pitch +j)*2]>>5);UCHAR r=buffer[(i*pitch+j)*2+1]>>3;pDC->SetPixel(j,height-i,RGB(r*0xFF/0x1F,g*0xFF/0x3F,b*0 xFF/0x1F));}}}}}else{if(info.bmiHeader.biCompression==BI_RGB){//该模式只有555for(int i=0;i<0-height;i++){for(int j=0;j<width;j++){//5 5 5 格式UCHAR b=buffer[(i*pitch+j)*2]&0x1F;UCHARg=(((buffer[(i*pitch+j)*2+1]<<6)&0xFF)>>3)+(buffer[(i*pitch +j)*2]>>5);UCHAR r=(buffer[(i*pitch+j)*2+1]<<1)>>3;pDC->SetPixel(j,i,RGB((r*0xFF)/0x1F,(g*0xFF)/0x1F,(b*0xF F)/0x1F));}}}elseif(info.bmiHeader.biCompression==BI_BITFIELDS){//该模式在bitmapinfoheader之后存在RGB掩码每个掩码1 DWORDfseek(fp,fileheader.bfOffBits-sizeof(DWORD )*3,0);DWORD rMask;fread(&rMask,sizeof(DWORD ),1,fp);if(rMask==0x7C00){// 5 5 5 格式MessageBeep(0);for(int i=0;i<0-height;i++){for(int j=0;j<width;j++){UCHAR b=buffer[(i*pitch+j)*2]&0x1F;UCHARg=(((buffer[(i*pitch+j)*2+1]<<6)&0xFF)>>3)+(buffer[(i*pitch +j)*2]>>5);UCHARr=(buffer[(i*pitch+j)*2+1]<<1)>>3;pDC->SetPixel(j,i,RGB((r*0xFF)/0x1F,(g*0xFF)/0x1F,(b*0xF F)/0x1F));}}}else if(rMask==0xF800){//5 6 5 格式for(int i=0;i<0-height;i++){for(int j=0;j<width;j++){UCHAR b=buffer[(i*pitch+j)*2]&0x1F;UCHARg=(((buffer[(i*pitch+j)*2+1]<<5)&0xFF)>>2)+(buffer[(i*pitch +j)*2]>>5);UCHAR r=buffer[(i*pitch+j)*2+1]>>3;pDC->SetPixel(j,i,RGB(r*0xFF/0x1F,g*0xFF/0x3F,b*0xFF/0x1 F));}}}}}//pDC->TextOut(100,200,"16位图");}else if(info.bmiHeader.biBitCount==24){int pitch=width%4;//b g rif(height>0){//height>0 表示图片颠倒for(int i=0;i<height;i++){int realPitch=i*pitch;for(int j=0;j<width;j++){UCHAR b=buffer[(i*width+j)*3+realPitch];UCHAR g=buffer[(i*width+j)*3+1+realPitch];UCHAR r=buffer[(i*width+j)*3+2+realPitch];pDC->SetPixel(j,height-i,RGB(r,g,b));}}}else{for(int i=0;i<0-height;i++){int realPitch=i*pitch;for(int j=0;j<width;j++){UCHAR b=buffer[(i*width+j)*3+realPitch];UCHAR g=buffer[(i*width+j)*3+1+realPitch];UCHAR r=buffer[(i*width+j)*3+2+realPitch];pDC->SetPixel(j,i,RGB(r,g,b));}}}//pDC->TextOut(100,200,"24位图");}else if(info.bmiHeader.biBitCount==32){// b g r aif(height>0){//height>0 表示图片颠倒for(int i=0;i<0-height;i++){for(int j=0;j<width;j++){UCHAR b=buffer[(i*width+j)*4];UCHAR g=buffer[(i*width+j)*4+1];UCHAR r=buffer[(i*width+j)*4+2];pDC->SetPixel(j,height-i,RGB(r,g,b));}}}else{for(int i=0;i<height;i++){for(int j=0;j<width;j++){UCHAR b=buffer[(i*width+j)*4];UCHAR g=buffer[(i*width+j)*4+1];UCHAR r=buffer[(i*width+j)*4+2];pDC->SetPixel(j,i,RGB(r,g,b));}}}//pDC->TextOut(100,200,"32位图");}delete buffer;fclose(fp);}。

相关文档
最新文档