Category 赛事速报

位图的格式如下:

1.文件头信息块

0000-0001 :文件标识,为字母ASCII码“BM”。

0002-0005 :文件大小。

0006-0009 :保留,每字节以“00”填写。

000A-000D :记录图像数据区的起始位置。各字节的信息含义依次为:文件头信息块大小,图像描述信息块的大小,图像颜色表的大小,保留(为01)。

2.图像描述信息块

000E-0011:图像描述信息块的大小,常为28H。

0012-0015:图像宽度。

0016-0019:图像高度。

001A-001B:图像的plane总数(恒为1)。

001C-001D:记录像素的位数,很重要的数值,图像的颜色数由该值决定。

001E-0021:数据压缩方式(数值位0:不压缩;1:8位压缩;2:4位压缩)。

0022-0025:图像区数据的大小。

0026-0029:水平每米有多少像素,在设备无关位图(.DIB)中,每字节以00H填写。

002A-002D:垂直每米有多少像素,在设备无关位图(.DIB)中,每字节以00H填写。

002E-0031:此图像所用的颜色数,如值为0,表示所有颜色一样重要。

3.颜色表

颜色表的大小根据所使用的颜色模式而定:2色图像为8字节;16色图像位64字节;256色图像为1024字节。其中,每4字节表示一种颜色,并以B(蓝色)、G(绿色)、R(红色)、alpha(32位位图的透明度值,一般不需要)。即首先4字节表示颜色号0的颜色,接下来表示颜色号1的颜色,依此类推。

4.图像数据区

颜色表接下来位是位图文件的图像数据区,在此部分记录着每点像素对应的颜色号,其记录方式也随颜色模式而定,既2色图像每点占1位;16色图像每点占4位;256色图像每点占8位;真彩色图像每点占24位。所以,整个数据区的大小也会随之变化。究其规律而言,可的出如下计算公式:图像数据信息大小=(图像宽度*图像高度*记录像素的位数)/8。 然而,未压缩的图像信息区的大小。除了真彩色模式外,其余的均大于或等于数据信息的大小。这是为什么呢?原因有两个:

1.BMP文件记录一行图像是以字节为单位的。因此,就不存在一个字节中的数据位信息表示的点在不同的两行中。也就是说,设显示模式位16色,在每个字节分配两个点信息时,如果图像的宽度位奇数,那么最后一个像素点的信息将独占一个字节,这个字节的后4位将没有意义。接下来的一个字节将开始记录下一行的信息。

2.为了显示的方便,除了真彩色外,其他的每中颜色模式的行字节数要用数据“00”补齐为4的整数倍。如果显示模式为16色,当图像宽为19时,存储时每行则要补充4-(19/2+1)%4=2个字节(加1是因为里面有一个像素点要独占了一字节)。如果显示模式为256色,当图像宽为19时,每行也要补充4-19%4=1个字节。

一下代码实现的是位图宽,高是4的整数倍,颜色位深是24位。

头文件定义:

#pragma pack(1)

typedef unsigned char BYTE ;

typedef unsigned short WORD ;

typedef unsigned int DWORD ;

typedef long LONG ;

typedef struct BW_BITMAPFILEHEADER

{

WORD fileType ;

DWORD fileSize ;

WORD fileReserved1 ;

WORD fileReserved2 ;

DWORD offSet ;

} BITMAPFILEHEADER ;

typedef struct BW_BITMAPFINFOHEADER

{

DWORD headSize ;

LONG width ;

LONG height ;

WORD plant ;

WORD bitCount ;

DWORD compression ;

DWORD sizeImage ;

LONG XPelPerMeter ;

LONG YPelPerMeter ;

DWORD clrUsed ;

DWORD clrImportant ;

}BITMAPINFOHEAD;

typedef struct BW_RGBQUAD

{

BYTE rgbBlue ;

BYTE rgbGreen ;

BYTE rgbRed ;

BYTE rgbReserved ;

}RGBQUAD;

typedef struct BW_PIXEL

{

BYTE blue ;

BYTE green ;

BYTE red ;

} PIXEL ;

class BW_BITMAP

{

public:

bool ReadBMP(char*) ;

BITMAPFILEHEADER bitMapFileHeader ;

BITMAPINFOHEAD bitMapInfoHead ;

RGBQUAD *rgbquad ;

PIXEL* pixelData ;

};

具体cpp文件:

bool BW_BITMAP::ReadBMP(char *fileName)

{

FILE *fileR ,fileW ;

fileR = fopen(fileName , "rb") ;

if (fileR != NULL)

{

//BW_BITMAP* bitMap = new BW_BITMAP ;

fread(&bitMapFileHeader , 1 , sizeof(BITMAPFILEHEADER) , fileR) ;

if (0x4d42 != bitMapFileHeader.fileType)

{

fclose(fileR) ;

return NULL ;

}

fread(&bitMapInfoHead, 1, sizeof(BITMAPINFOHEAD) , fileR) ;

rgbquad = new RGBQUAD[bitMapInfoHead.clrUsed] ;

for (int icount = 0 ; icount < bitMapInfoHead.clrUsed ; ++icount)

{

fread((char *)&(rgbquad[icount].rgbBlue),1,sizeof(BYTE),fileR);

fread((char *)&(rgbquad[icount].rgbGreen),1,sizeof(BYTE),fileR);

fread((char *)&(rgbquad[icount].rgbRed),1,sizeof(BYTE),fileR);

//fread((char *)&(bitMap->rgbquad[icount].rgbReserved),1,sizeof(BYTE),fileR);

}

int width = bitMapInfoHead.width ;

int height = bitMapInfoHead.height ;

pixelData = new PIXEL[width * height * sizeof(PIXEL)];

//初始化原始图片的像素数组

//fseek(fpi,54,SEEK_SET);

//读出图片的像素数据

fread(pixelData,sizeof(PIXEL) * width,height,fileR);

fclose(fileR);

return true ;

}

else

{

//cout<<"file open error!"<

return false ;

}

}

}

在写该段代码时要注意在头文件的文件头使用#pragma pack(1),这是告诉编译器使用边界1对齐(也就是不对齐)。

如果不是用#pragma pack(1),经过测试有如下结果:sizeof(BITMAPFILEHEADER)的值为16,而不是14。说明编译器对其使用了4为边界对齐。

如果实在linux环境下,要使用__attribute__((packed))来实现相同的效果。

但是,在xcode 5.0下用#pragma pack(1) 居然可以~!

总结可知:在实现对数据格式有严格要求的功能时,要注意到编译器的优化带来的麻烦。而且要注意PIXEL的定义,一定不能写成red ,green ,blue 。

Copyright © 2088 竞技暴风-网游赛事活动中心 All Rights Reserved.
友情链接