我是靠谱客的博主 碧蓝雨,这篇文章主要介绍【C/C++】BITMAP格式分析,现在分享给大家,希望可以做个参考。

BITMAP文件大体上分成四个部分,如下表所示。

文件部分长度(字节)
位图文件头 Bitmap File Header14
位图信息数据头 Bitmap Info Header40
调色板 Palette4*n (n≥0)
位图数据 Image Data不定长

 

BITMAP文件格式

1、位图文件头 Bitmap File Header

复制代码
1
2
3
4
5
6
7
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、位图信息数据头 Bitmap Info Header 

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
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

该结构体长度。

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
6
typedef 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格式分析内容请搜索靠谱客的其他文章。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部