我是靠谱客的博主 感性书本,这篇文章主要介绍Bitmap 格式,现在分享给大家,希望可以做个参考。

Bitmap是Windows操作系统中的标准图像文件格式,可以分成两类:设备相关位图(DDB)和设备无关位图(DIB),DDB已经基本停用。

Bitmap格式有4部分组成: 文件头、图像描述、颜色表(在真彩色(24或32位)模式无颜色表)和图像数据区

1. 文件头  14B

2B    0000-0001:文件标识,为字母ASCII码“BM”,即0x4d42
4B    0002-0005:文件大小,字节数,最大为4G
4B    0006-0009:保留,每字节以“00”填写。
4B    000A-000D:记录图像数据区的起始位置。各字节的信息依次含义为:文件头信息块大小,图像描述信息块的大小,图像颜色表的大小,保留(为01)。


数据类型定义:(32位系统下的定义;64位系统下在编译时需要加入-m32)

复制代码
1
2
3
4
5
6
7
8
typedef unsigned char BYTE; // 1B typedef unsigned short WORD; // 2B typedef unsigned long DWORD; // 4B typedef long LONG; // 4B

文件头结构定义
复制代码
1

typedef struct tagBITMAPFILEHEADER {

复制代码
1
2
3
4
5
6
7
WORD magic; // "BM",即0x4d42 DWORD bfSize; //文件大小 WORD bfReserved1; //保留字,不考虑 WORD bfReserved2; //保留字,同上 DWORD bfOffBits; //实际位图数据的偏移字节数,即前三个部分长度之和 } BITMAPFILEHEADER;

2. 图像描述      40B

4B    000E-0011:图像描述信息块的大小,常为40。 

4B    0012-0015:图像宽度。

4B    0016-0019:图像高度。

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

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

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

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

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

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

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

4B    0032-0035:重要的颜色数

图像信息描述结构

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
typedef struct tagBITMAPINFOHEADER{ DWORD biSize; //指定此结构体的长度,为40 LONG biWidth; //位图宽 LONG biHeight; //位图高 WORD biPlanes; //平面数,为1 WORD biBitCount; //采用颜色位数,可以是1,2,4,8,16,24,新的可以是32 DWORD biCompression; //压缩方式,可以是0,1,2,其中0表示不压缩 DWORD biSizeImage; //实际位图数据占用的字节数 LONG biXPelsPerMeter; //X方向分辨率 LONG biYPelsPerMeter; //Y方向分辨率 DWORD biClrUsed; //使用的颜色数,如果为0,则表示默认值(2^颜色位数) DWORD biClrImportant; //重要颜色数,如果为0,则表示所有颜色都是重要的 } BITMAPINFOHEADER;


不包含颜色表的数据头大小为54B


3. 颜色表

    在真彩色(24或32位)模式无颜色表

    其他色彩图像的颜色表的大小根据所使用的颜色模式而定:

              2色图像的颜色表大小是8字节;16色图像的颜色表大小是64字节;256色图像颜色表大小是1024字节。

             其中,每4字节表示一种颜色,并以B(蓝色)、G(绿色)、R(红色)、alpha(像素的透明度值,一般不需要)。即首先4字节表示颜色号0的颜色,接下来表示颜色号1的颜色,依此类推。

             以16色图像为例:每一种颜色是4B,所以颜色表大小就是16*4=64B。

4 图像数据区

    注意情况: 每种颜色模式的行字节数要用数据“00”补齐为4的整数倍

    16色图像,图像宽为19,存储时每行则要补充4-(19/2+1)%4=2个字节(加1是因为里面有一个像素点要独占了一字节)。

    256色图像,图像宽为19,每行也要补充4-19%4=1个字节。

    24位色彩图,图像宽为19,每行也要补充4-(19*3)%4=3个字节。

    32位色彩图,图像宽为19,每行也要补充4-(19*4)%4=0个字节,即无需补字节,本身已经是4B对齐了


参考程序

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include <stdio.h> #include <stdlib.h> #define WIDTHBYTES(bits) (((bits)+31)/32*4) typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned long DWORD; typedef long LONG; //位图文件头信息结构定义 //其中不包含文件类型信息(由于结构体的内存结构决定,要是加了的话将不能正确读取文件信息) typedef struct tagBITMAPFILEHEADER { DWORD bfSize; //文件大小 WORD bfReserved1; //保留字,不考虑 WORD bfReserved2; //保留字,同上 DWORD bfOffBits; //实际位图数据的偏移字节数,即前三个部分长度之和 } BITMAPFILEHEADER; //信息头BITMAPINFOHEADER,也是一个结构,其定义如下: typedef struct tagBITMAPINFOHEADER{ //public: DWORD biSize; //指定此结构体的长度,为40 LONG biWidth; //位图宽 LONG biHeight; //位图高 WORD biPlanes; //平面数,为1 WORD biBitCount; //采用颜色位数,可以是1,2,4,8,16,24,新的可以是32 DWORD biCompression; //压缩方式,可以是0,1,2,其中0表示不压缩 DWORD biSizeImage; //实际位图数据占用的字节数 LONG biXPelsPerMeter; //X方向分辨率 LONG biYPelsPerMeter; //Y方向分辨率 DWORD biClrUsed; //使用的颜色数,如果为0,则表示默认值(2^颜色位数) DWORD biClrImportant; //重要颜色数,如果为0,则表示所有颜色都是重要的 } BITMAPINFOHEADER; //调色板Palette,当然,这里是对那些需要调色板的位图文件而言的。24位和32位是不需要调色板的。 //(似乎是调色板结构体个数等于使用的颜色数。) typedef struct tagRGBQUAD { //public: BYTE rgbBlue; //该颜色的蓝色分量 BYTE rgbGreen; //该颜色的绿色分量 BYTE rgbRed; //该颜色的红色分量 BYTE rgbReserved; //保留值 } RGBQUAD; void showBmpHead(BITMAPFILEHEADER* pBmpHead) { printf("位图文件头:n"); printf("文件大小:%dn",pBmpHead->bfSize); printf("保留字:%dn",pBmpHead->bfReserved1); printf("保留字:%dn",pBmpHead->bfReserved2); printf("实际位图数据的偏移字节数:%dn",pBmpHead->bfOffBits); } void showBmpInforHead(BITMAPINFOHEADER* pBmpInforHead) { printf("位图信息头:n"); printf("结构体的长度:%dn",pBmpInforHead->biSize); printf("位图宽:%dn",pBmpInforHead->biWidth); printf("位图高:%dn",pBmpInforHead->biHeight); printf("biPlanes平面数:%dn",pBmpInforHead->biPlanes); printf("biBitCount采用颜色位数:%dn",pBmpInforHead->biBitCount); printf("压缩方式:%dn",pBmpInforHead->biCompression); printf("biSizeImage实际位图数据占用的字节数:%dn",pBmpInforHead->biSizeImage); printf("X方向分辨率:%dn",pBmpInforHead->biXPelsPerMeter); printf("Y方向分辨率:%dn",pBmpInforHead->biYPelsPerMeter); printf("使用的颜色数:%dn",pBmpInforHead->biClrUsed); printf("重要颜色数:%dn",pBmpInforHead->biClrImportant); } void showRgbQuan(RGBQUAD* pRGB) { printf("(%-3d,%-3d,%-3d) ",pRGB->rgbRed,pRGB->rgbGreen,pRGB->rgbBlue); } void main() { #ifdef __x86_64__ printf("__x86_64__n"); #elif __i386__ printf("__i386__n"); #endif BITMAPFILEHEADER bitHead; BITMAPINFOHEADER bitInfoHead; FILE* pfile; char strFile[50]; printf("please input the .bmp file name:n"); scanf("%s",strFile); pfile = fopen(strFile,"rb");//打开文件 if(pfile!=NULL) { printf("file bkwood.bmp open success.n"); //读取位图文件头信息 WORD fileType; fread(&fileType,1,sizeof(WORD),pfile); if(fileType != 0x4d42) {<span style="color:#ff0000;"> // 将magic单独出来,没有放到头信息里处理,来判断该文件是否时bitmap文件</span> printf("file is not .bmp file!"); return; } fread(&bitHead,1,sizeof(BITMAPFILEHEADER),pfile); showBmpHead(&bitHead); printf("nn"); //读取位图信息头信息 fread(&bitInfoHead,1,sizeof(BITMAPINFOHEADER),pfile); showBmpInforHead(&bitInfoHead); printf("n"); } else { printf("file open fail!n"); return; } RGBQUAD *pRgb ; int width = bitInfoHead.biWidth; int height = bitInfoHead.biHeight; //分配内存空间把源图存入内存 int l_width = WIDTHBYTES(width* bitInfoHead.biBitCount);//计算位图的实际宽度并确保它为32的倍数 BYTE *pColorData=(BYTE *)malloc(height*l_width); memset(pColorData,0,height*l_width); long nData = height*l_width; //把位图数据信息读到数组里 fread(pColorData,1,nData,pfile); //将位图数据转化为RGB数据 RGBQUAD* dataOfBmp; dataOfBmp = (RGBQUAD *)malloc(width*height*sizeof(RGBQUAD));//用于保存各像素对应的RGB数据 memset(dataOfBmp,0,width*height*sizeof(RGBQUAD)); int k = 0; int i = 0, j = 0, index = 0; for(;i<height;i++) { for(j=0;j<width;j++) { k = i*l_width + j*3; dataOfBmp[index].rgbRed = pColorData[k+2]; dataOfBmp[index].rgbGreen = pColorData[k+1]; dataOfBmp[index].rgbBlue = pColorData[k]; index++; } } printf("像素数据信息:n"); for (i=0; i<width*height; i++) { if (i%5==0) { printf("n"); } showRgbQuan(&dataOfBmp[i]); } fclose(pfile); if (bitInfoHead.biBitCount<24) { free(pRgb); } free(dataOfBmp); free(pColorData); printf("n"); }

编译时需要注意:

         如果是64位,需要使用-m32参数。例如gcc main.c -m32

         这是因为某些数据类型如long,在32和64是不同的



参考文章: http://blog.sina.com.cn/s/blog_523491650100fk1z.html

这里有详细的带有颜色表的bitmap的处理






最后

以上就是感性书本最近收集整理的关于Bitmap 格式的全部内容,更多相关Bitmap内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(94)

评论列表共有 0 条评论

立即
投稿
返回
顶部