BITMAP文件大体上分成四个部分,如下表所示。
文件部分 | 长度(字节) |
---|---|
位图文件头 Bitmap File Header | 14 |
位图信息数据头 Bitmap Info Header | 40 |
调色板 Palette | 4*n (n≥0) |
位图数据 Image Data | 不定长 |
BITMAP文件格式
1、位图文件头 Bitmap File Header
1
2
3
4
5
6
7typedef 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、位图信息数据头 Bitmap Info Header
1
2
3
4
5
6
7
8
9
10
11
12
13typedef 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 | 该结构体长度。 |
biWidth | 说明图象的宽度,单位为象素。 |
biHeight | 说明图象的高度,单位为象素。 |
biPlanes | 位平面数,必须为1。 |
biBitCount | 指定颜色位数,1为二值,4为16色,8为256色,16、24、32为真彩色。 |
biCompression | 指定是否压缩,有效的值为BI_RGB,BI_RLE8,BI_RLE4、BI_BITFIELDS。 |
biSizeImage | 实际的位图数据占用的字节数。 |
biXPelsPerMeter | 目标设备水平分辨率,单位是每米的像素数。 |
biYPelsPerMeter | 目标设备垂直分辨率,单位是每米的像素数。 |
biClrUsed | 实际使用的颜色数。 |
biClrImportant | 图像中重要的颜色数,若该值为0,则所有的颜色都是重要的。 |
3、调色板 Palette
第三部分为调色板(Palette),当然,这里是对那些需要调色板的位图文件而言的。有些位图,如真彩色图,前面已经讲过,是不需要调色板的,BITMAPINFOHEADER后直接是位图数据。
调色板实际上是一个数组,共有biClrUsed个元素(如果该值为零,则有2的biBitCount次方个元素)。数组中每个元素的类型是一个RGBQUAD结构,占4个字节,其定义如下:
1
2
3
4
5
6typedef struct tagRGBQUAD { BYTE rgbBlue; //该颜色蓝色分量 BYTE rgbGreen; //该绿色蓝色分量 BYTE rgbRed; //该红色蓝色分量 BYTE rgbReserved; //保留 } RGBQUAD;
4、位图数据 ImageData
第四部分就是实际的图象数据了。对于用到调色板的位图,图象数据就是该像素颜在调色板中的索引值,对于真彩色图,图象数据就是实际的R,G,B值。下面就2色,16色,256色位图和真彩色位图分别介绍。
- 2色位图:用1位就可以表示该像素的颜色(一般0表示黑,1表示白),所以一个字节可以表示8个像素。
- 16色位图:用4位可以表示一个像素的颜色,所以一个字节可以表示2个像素。
- 256色位图:一个字节刚好可以表示1个像素。
- 真彩色图:三个字节才能表示1个像素。
例子
以一幅24位真彩色图像为例,读取并顺时针旋转并保存。该BITMAP图片尺寸为450 * 227。
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
142
143
144
145
146
147
148
149
150
151#include <stdio.h> #include <stdlib.h> #include <windows.h> #pragma pack(push) #pragma pack(1) //24位真彩色 struct RGB { BYTE b; BYTE g; BYTE r; }; #pragma pack(pop) void imgOpr(RGB &a, RGB &b) { b.b = a.b; b.g = a.g; b.r = a.r; } //二维数组申请img[m][n] RGB ** RGB_new(int m, int n) { int i; RGB **img; img = new RGB * [m]; for (i = 0; i < m; i ++) { img[i] = new RGB [n]; } return img; } //释放img[m][n] void RGB_delete(RGB **img, int m, int n) { int i; for (i = 0; i < m; i ++) { delete [] img[i]; } delete [] img; } int main() { BITMAPFILEHEADER bfh; BITMAPINFOHEADER bih; RGB **img1; RGB **img2; BYTE *tmp; int i, j; int height, width; int m, n; FILE *fp, *fq; errno_t err; err = fopen_s(&fp, "D:\Work\Debug\7.bmp", "rb"); if (err == 0) { printf("The input file was opened!n"); } else { printf("The input file was not opened!n"); return 1; } err = fopen_s(&fq, "D:\Work\Debug\2.bmp", "wb"); if (err == 0) { printf("The output file was opened!n"); } else { printf("The output file was not opened!n"); return 1; } fread(&bfh, sizeof(BITMAPFILEHEADER), 1, fp); fread(&bih, sizeof(BITMAPINFOHEADER), 1, fp); height = bih.biHeight; width = bih.biWidth; img1 = RGB_new(height, width); img2 = RGB_new(width, height); //计算每行图像字节数,必须是4的整倍数,不够需要填充 m = (bih.biWidth * bih.biBitCount + 31) / 32 * 4; n = (bih.biHeight * bih.biBitCount + 31) / 32 * 4; tmp = new BYTE [n]; memset(tmp, 0x0, n); //对图片进行操作 for (i = 0; i < height; i ++) { //跳过调色板数据段,并寻址 fseek(fp, bfh.bfOffBits + i * m, SEEK_SET); fread(img1[i], sizeof(RGB), width, fp); for (j = 0; j < width; j ++) { //将数组 img 赋值给 img2 imgOpr(img1[i][j], img2[j][i]); } } //更新BITMAPINFOHEADER结构体 bih.biHeight = width; bih.biWidth = height; bih.biSizeImage = n * width; //将修改后的图片保存到文件 fwrite(&bfh, sizeof(BITMAPFILEHEADER), 1, fq); fwrite(&bih, sizeof(BITMAPINFOHEADER), 1, fq); for (i = 0; i < width; i ++) { memcpy(tmp, img2[i], sizeof(RGB) * height); fwrite(tmp, 1, n, fq); } fclose(fp); fclose(fq); //释放 RGB_delete(img1, height, width); RGB_delete(img2, width, height); delete [] tmp; system("pause"); return 0; }
原图
顺时针旋转90度
下载地址:https://download.csdn.net/download/sunriver2000/12152422
最后
以上就是碧蓝雨最近收集整理的关于【C/C++】BITMAP格式分析的全部内容,更多相关【C/C++】BITMAP格式分析内容请搜索靠谱客的其他文章。
发表评论 取消回复