c语言 clr的定义文件,BMP文件解析

BMP文件简介

BMP(全称Bitmap)是Window操作系统中的标准图像文件格式,可以分成两类:设备相关位图(DDB)和设备无关位图(DIB),使用非常广。它采用位映射存储格式,除了图像深度可选以外,不采用其他任何压缩,因此,BMP文件所占用的空间很大。BMP文件的图像深度可选lbit、4bit、8bit、16bit、24bit或者32bit。BMP文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。 由于BMP文件格式是Windows环境中交换与图有关的数据的一种标准,因此在Windows环境中运行的图形图像软件都支持BMP图像格式。

BMP文件结构

BMP文件一般由四部分组成:

1、文件头

2、文件信息头

3、调色板(不一定有)

4、位图数据

调色板不是必须的,只有在单色位图、16色位图、256色位图中才有,也是位图深度为1bit、4bit、8bit的位图才有调色板。关于BMP文件的定义,在windows.h这个头文件中都有描述,一般来说,一个BMP文件用C语言代码可以这样表示:

struct BMP

{

BITMAPFILEHEADER fileHeader; //文件头

BITMAPINFOHEADER infoHeader; //文件信息头

PALETTEENTRY palette[n]; //调色板信息,n为颜色数目

byte *pixels; //像素数据指针

};

下面将对BMP文件给出详细的解析

1、BMP文件头

BMP文件头在Windows.h中被声明为:BITMAPFILEHEADER。该结构完整的声明如下:

typedef struct tagBITMAPFILEHEADER {

WORD bfType;

DWORD bfSize;

WORD bfReserved1;

WORD bfReserved2;

DWORD bfOffBits;

} BITMAPFILEHEADER, FAR *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;

bfType:两个字节,表示文件的类型,该值一般是0x4D42,也就是‘BM’。

bfSize : 四个字节,说明文件的大小,以字节为单位。文件总的大小=文件头字节数+信息头的字节数+调色板字节数+像素数据字节数。

bfReserved1:保留数据,一般为0。

bfReserved2:保留数据,一般为0。

bfOffBits:文件头到像素数据之间的字节偏移量,用来定位像素数据。这个参数非常有用,因为位图信息头和调色板的长度会根据不同的情况而有所变化,利用这个偏移量可以迅速读取到像素数据。其大小一般是:偏移量=文件头字节数+文件信息头字节数+调色板字节数。

2、位图信息头

BMP信息头在windows.h中被声明为: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, FAR *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;

biSize:4字节,说明BITMAPINFOHEADER结构所需的字节数,数值为sizeof(BITMAPINFOHEADER),一般是40字节,但也可能不是,具体要看系统。

biWidth:4个字节,说明图像的宽度,以像素为单位。

biHeight:4个字节,说明图像的高度,以像素为单位。该值除了指示位图的高度之外,还可指示图像的方向:当该值为正数时,位图是倒向的,当该值为负数时,位图是正向的。一般位图都是倒向的,也就是该值一般是正数。

biPlanes:2个字节,说明图像的位面数,一般就是1;

biBitCount:2个字节,说明每个像素所具有的比特数。该值可以是1、4、8、16、24、32,一般来说,使用24色的位图,该值就是24。

biCompression:4个字节,说明图像数据的压缩类型,其中:BI_RGB表示无压缩;BI_RLE8表示每个像素8比特的RLE压缩编码,压缩格式由2字节组成(重复像素计数和颜色索引);BI_RLE4表示每个像素4比特的RLE压缩编码,压缩格式由2字节组成;BI_BITFIELDS:每个像素的比特由指定的掩码决定;BI_JPEG:JPEG格式。

biSizeImage:4个字节,说明图像的大小,以字节为单位,必须是4的倍数,当使用BI_RGB格式时,该值可以为0。

biXPelsPerMeter:4个字节,水平分辨率,用像素/米表示,不知道就设为0。

biYPelsPerMeter:4个字节,垂直分辨率,用像素/米表示,不知道就设为0。

biClrUsed:4字节,说明位图实际使用的彩色表中颜色索引数,采用索引色时会用到,如果采用无压缩的RGB格式,这个值可以是0。

biClrImportant:4个字节,说明对图像显示有重要影响的颜色索引数目,为0则表示都很重要。

3、调色板

调色板的目的是建立一个颜色索引,从而节省存储空间。在调色板中,保存着位图用到的所有颜色,而位图数据部分储存的是颜色的索引,读取bmp文件的像素数据时,通过索引找到相对应的颜色。调色板不一定会有,像16位色、24位色和32位色的位图就没有调色板。调色板是一个RGBQUAD类型的的数组,数组的大小跟颜色数目有关。RGBQUAD结构体在windows.h中的定义如下:

typedef struct tagRGBQUAD {

BYTE rgbBlue;

BYTE rgbGreen;

BYTE rgbRed;

BYTE rgbReserved;

} RGBQUAD

该结构体占用四个字节,前三个表示颜色的三个分量,取值范围是0到255,分别是蓝、绿、红(不是红、绿、蓝),第四个是保留项,一般都是0。调色板一般可这样定义:

RGBQUAD palette[n];

其中n表示颜色的数目,对于单色位图,颜色数目只有两个,n=2;对于4bit的位图,颜色数是16,n=16;对于8bit的位图,颜色数是256,n=256;而对于16bit、24bit和32bit的位图,由于颜色过多,不适宜使用调色板,因此没有调色板,n=0。由于色彩的需要,现在大多数位图都是24位的真彩色,甚至有32位的。

4、位图数据

位图数据一般可以保存在一个二维的数组里,值得注意的是:

(1)window系统扫描BMP图像时是逐行按每四个字节进行扫描的,也就是说,位图每行的字节长度应该是4的倍数,如果不是4的倍数,要补全,没有像素的地方,用0填充。例如一个16*16的单色位图,它的宽度为16像素,每像素用1bit表示,则每行的字节长度为2字节,但是2字节不是4的倍数,所以要将行的字节数扩充为4字节,这样的话,相当于位图变为32*16大小了。多出的部分只是占个位置,方便系统扫描罢了,不会影响原来的位图显示。

(2)window系统显示位图时,扫描像素数据时时按照B、G、R的顺序来的,而不是R、G、B,因此在填充位图数据时,要注意颜色分量的存储顺序。

C语言代码生成BMP文件

下面用C语言创建BMP文件,该文件可以是单色位图、16色位图、256色位图、16bit位图、24bit位图或者是32bit位图。的位图数据没有经过压缩,调色板的有无根据颜色深度而定。

/*********************************************************************************************************************/

//函数名:SaveBmp

//功能: 将像素数据保存文BMP文件

//参数: 分别为文件名、图片宽度、图片高度、每像素比特数、调色板指针、像素数据指针

//返回值:如果保存成功,返回true,否则为false

//说明: bCount参数可以是1、4、8、16、24、32,crPalette参数是一个指向调色板数组的指针,如果没有调色板,该项可以写NULL。

// bPixels是指向像素数据的指针,该项应该与bCount项相匹配。

/**********************************************************************************************************************/

#include#includebool SaveBmp(const char *fileName, int bWidth, int bHeight, int bCount, RGBQUAD *crPalette, byte *bPixels)

{

//调色板字节数

int paletteSize;

switch (bCount)

{

case 1:

paletteSize = 8;

break;

case 4:

paletteSize = 64;

break;

case 8:

paletteSize = 1024;

break;

default:

paletteSize = 0;

break;

}

//需要写进文件的像素字节数

int pixelsSize;

pixelsSize = 4 * ((bCount*bWidth+31) / 32 )*bHeight;

//文件头

BITMAPFILEHEADER bmpFileHeader;

bmpFileHeader.bfType = 'MB';

bmpFileHeader.bfSize = 54+paletteSize+pixelsSize;

bmpFileHeader.bfReserved1 = 0;

bmpFileHeader.bfReserved2 = 0;

bmpFileHeader.bfOffBits =54+paletteSize ;

//信息头

BITMAPINFOHEADER bmpInfoHeader;

bmpInfoHeader.biBitCount = bCount;

bmpInfoHeader.biClrImportant = 0;

bmpInfoHeader.biClrUsed = 0;

bmpInfoHeader.biCompression = BI_RGB;

bmpInfoHeader.biHeight = bHeight;

bmpInfoHeader.biPlanes = 1;

bmpInfoHeader.biSize =40;

bmpInfoHeader.biSizeImage =pixelsSize;

bmpInfoHeader.biWidth = bWidth;

bmpInfoHeader.biXPelsPerMeter = 0;

bmpInfoHeader.biYPelsPerMeter = 0;

//分配新的像素缓冲

byte *pPixels;

if ( (bCount*bWidth)%32==0)

{

//如果行的字节数刚好是4的倍数,则直接利用原来的像素缓冲

pPixels = bPixels;

}

else

{

//否则,新创建一个缓冲区,使得每行的字节数刚好是4的倍数

pPixels = (byte*)malloc(pixelsSize);

//像素缓冲初始化为0

memset(pPixels, 0, pixelsSize);

int oldRow, newRow;

//原来的像素缓冲每行所占的字节数

oldRow = (bCount*bWidth+7)/ 8;

//新的像素缓冲每行所占的字节数

newRow = pixelsSize / bHeight;

//将旧的像素缓冲的数据复制到新的像素缓冲

for (int i = 0;i "wb");

if (!fp)

{

return false;

}

//写入文件头

fwrite(&bmpFileHeader, 14, 1, fp);

//写入信息头

fwrite(&bmpInfoHeader, 40, 1, fp);

//写入调色板

fwrite(crPalette,paletteSize, 1, fp);

//写入像素数据

fwrite(pPixels,pixelsSize, 1, fp);

fclose(fp);

//如果像素缓冲区是动态创建的,则释放缓冲

if(pPixels!=bPixels)free(pPixels);

return true;

}

C语言代码读取BMP文件

以下代码是读取BMP文件,返回的是位图信息、调色板和像素数据。

/***************************************************************************************************************/

//函数名:LoadBmp

//功能: 载入bmp文件

//参数: 分别为文件名、位图信息头结构、调色板二重指针、像素数据二重指针

//返回值:如果读取文件成功,则返回true,否则返回false

//说明: 文件的相关信息都会被填充到bmpInfoHeader指向的结构中,crPalette、bPixels参数分别传回调色板和像素数据的指针

/***************************************************************************************************************/

#include#includebool LoadBmp(const char *fileName, BITMAPINFOHEADER *bmpInfoHeader, RGBQUAD **crPalette, byte **bPixels)

{

BITMAPFILEHEADER fileHeader;

FILE *fp;

fp = fopen(fileName, "rb");

if (!fp)

{

return false;

}

//读取文件头

fread(&fileHeader, 14, 1, fp);

//读取信息头

fread(bmpInfoHeader, 40, 1, fp);

//调色板字节数

int paletteSize;

switch ((*bmpInfoHeader).biBitCount)

{

case 1:

paletteSize = 8;

break;

case 4:

paletteSize = 64;

break;

case 8:

paletteSize = 1024;

break;

default:

paletteSize = 0;

break;

}

//动态创建调色板缓冲区

*crPalette = (RGBQUAD*)malloc(paletteSize);

//读入调色板数据

fread(*crPalette, paletteSize, 1, fp);

int pixelsSize;

pixelsSize = fileHeader.bfSize - fileHeader.bfOffBits;

//动态创建像素缓冲区

*bPixels = (byte*)malloc(pixelsSize);

//读入像素数据

fread(*bPixels,pixelsSize, 1, fp);

fclose(fp);

return false;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个简单的 C 语言示例程序,用于从 BMP 文件中读取图像数据: ```c #include <stdio.h> #include <stdlib.h> #include <stdint.h> #pragma pack(push, 1) typedef struct { uint16_t type; uint32_t size; uint16_t reserved1; uint16_t reserved2; uint32_t offset; } bmp_file_header_t; typedef struct { uint32_t size; int32_t width; int32_t height; uint16_t planes; uint16_t bit_count; uint32_t compression; uint32_t size_image; int32_t x_pels_per_meter; int32_t y_pels_per_meter; uint32_t clr_used; uint32_t clr_important; } bmp_info_header_t; #pragma pack(pop) int main(int argc, char *argv[]) { if (argc != 2) { printf("Usage: %s input.bmp\n", argv[0]); return 0; } FILE *input_file = fopen(argv[1], "rb"); if (!input_file) { printf("Failed to open input file: %s\n", argv[1]); return 0; } bmp_file_header_t file_header; bmp_info_header_t info_header; fread(&file_header, sizeof(bmp_file_header_t), 1, input_file); fread(&info_header, sizeof(bmp_info_header_t), 1, input_file); if (file_header.type != 0x4d42 || info_header.bit_count != 24 || info_header.compression != 0) { printf("Invalid input file format.\n"); fclose(input_file); return 0; } uint32_t width = abs(info_header.width); uint32_t height = abs(info_header.height); uint32_t line_size = (width * 3 + 3) & ~3; uint8_t *image_data = (uint8_t *)malloc(line_size * height); fseek(input_file, file_header.offset, SEEK_SET); fread(image_data, line_size, height, input_file); fclose(input_file); // 现在 image_data 中存储了 BMP 文件中的像素数据,可以进行进一步处理 free(image_data); printf("Done.\n"); return 0; } ``` 在这个示例代码中,我们使用了两个结构体来解析 BMP 文件和信息的数据。首先,我们打开 BMP 文件并读取文件和信息。然后,我们检查文件和信息是否符合要求(即文件类型必须是 "BM",颜色位数必须是 24 位,不支持压缩)。接下来,我们计算每一行像素数据的字节数,使用 malloc 函数分配足够的内存来存储像素数据,并使用 fread 函数从文件中读取像素数据。最后,我们关闭文件,并使用 free 函数释放内存。 请注意,这个示例代码只适用于 24 位彩色 BMP 图片。如果你想处理其他格式的 BMP 图片,需要根据实际情况进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值