Linux C语言解析.bmp格式图片并显示汉字
bmp.h 文件
1 #ifndef __BMP_H__
2 #define __BMP_H__
3
4
5 #include <unistd.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <fcntl.h>
9 #include <string.h>
10 #include <linux/fb.h>
11 #include <sys/mman.h>
12 #include <sys/ioctl.h>
13 #include <arpa/inet.h>
14
15
16 //文件头
17 typedef struct
18 {
19 unsigned char bfType[2]; //文件类型
20 unsigned long bfSize; //位图大小
21 unsigned short bfReserved1; //位0
22 unsigned short bfReserved2; //位0
23 unsigned long bfOffBits; //到数据偏移量
24 } __attribute__((packed)) BitMapFileHeader;
25
26
27 //信息头
28 typedef struct
29 {
30 unsigned long biSize; // BitMapFileHeader 字节数
31 long biWidth; //位图宽度
32 long biHeight; //位图高度,正位正向,反之为倒图
33 unsigned short biPlanes; //为目标设备说明位面数,其值将总是被设为1
34 unsigned short biBitCount; //说明比特数/象素,为1、4、8、16、24、或32。
35 unsigned long biCompression; //图象数据压缩的类型没有压缩的类型:BI_RGB
36 unsigned long biSizeImage; //说明图象的大小,以字节为单位
37 long biXPelsPerMeter; //说明水平分辨率
38 long biYPelsPerMeter; //说明垂直分辨率
39 unsigned long biClrUsed; //说明位图实际使用的彩色表中的颜色索引数
40 unsigned long biClrImportant; //对图象显示有重要影响的索引数,0都重要。
41 } __attribute__((packed)) BitMapInfoHeader;
42
43
44 //位图颜色分量
45 typedef struct
46 {
47 unsigned char Blue; //该颜色的蓝色分量
48 unsigned char Green; //该颜色的绿色分量
49 unsigned char Red; //该颜色的红色分量
50 unsigned char Reserved; //保留值
51 } __attribute__((packed)) RgbQuad;
52
53
54
55 typedef struct DealInfo
56 {
57 unsigned char tmp;
58 unsigned char hum;
59 unsigned char light;
60 unsigned char fan;
61 unsigned char buzz;
62 }DealInfo;
63
64 typedef struct QNode
65 {
66 DealInfo buf;
67 struct QNode *pNext;
68 }QNode;
69
70
71
72 void plan();
73 int show_photo(const char *fbp, struct fb_var_screeninfo *scrinfo); //显示图片
74
75
76
77 #endif //__BMP_H__
bmp.c 文件
1 #include "bmp.h"
2 #include "word.h"
3
4
5 extern char photo_name[20];
6 extern QNode heard;
7
8
9 //汉字字模
10 unsigned char word[WORD_DATA_HEIGTH][WORD_DATA_WIDTH] = {
11
12 0x08,0x40,0x08,0x40,0x0B,0xFC,0x10,0x40,0x10,0x40,0x30,0x40,0x3F,0xFE,0x50,0x00,
13 0x90,0x40,0x10,0x40,0x13,0xFC,0x10,0x40,0x10,0x40,0x10,0x40,0x1F,0xFE,0x10,0x00,
14
15 0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x02,0x80,0x02,0x80,
16 0x04,0x40,0x04,0x40,0x08,0x20,0x08,0x20,0x10,0x10,0x20,0x08,0x40,0x04,0x80,0x02,
17
18 0x08,0x20,0x04,0x40,0x7F,0xFC,0x01,0x00,0x01,0x00,0x3F,0xF8,0x01,0x00,0x01,0x00,
19 0xFF,0xFE,0x01,0x00,0x01,0x00,0x7F,0xFC,0x02,0x80,0x04,0x40,0x18,0x30,0xE0,0x0E,
20
21 0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x7C,0xFE,0x44,0x22,0x44,0x22,0x44,0x22,0x44,
22 0x42,0x44,0x24,0x44,0x14,0x44,0x08,0x44,0x14,0x44,0x22,0x7C,0x42,0x44,0x80,0x00,
23
24 0x00,0x00,0xFF,0xFE,0x00,0x00,0x00,0x00,0x4F,0xE4,0x49,0x24,0x49,0x24,0x4F,0xE4,
25 0x49,0x24,0x49,0x24,0x49,0x24,0x4F,0xE4,0x40,0x04,0x40,0x04,0x7F,0xFC,0x00,0x04,
26
27 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
28 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
29
30 0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,
31 0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x3F,0xF8,0x00,0x08,0x00,0x00,
32
33 0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x08,0x01,0x08,0x7D,0x90,0x05,0xA0,0x09,0x40,
34 0x09,0x40,0x11,0x20,0x11,0x10,0x21,0x08,0x41,0x06,0x81,0x00,0x05,0x00,0x02,0x00,
35
36 0x00,0x00,0xFF,0xFE,0x00,0x00,0x00,0x00,0x4F,0xE4,0x49,0x24,0x49,0x24,0x4F,0xE4,
37 0x49,0x24,0x49,0x24,0x49,0x24,0x4F,0xE4,0x40,0x04,0x40,0x04,0x7F,0xFC,0x00,0x04,
38
39 0x10,0x40,0x10,0x40,0x10,0x40,0x10,0x40,0x3E,0x40,0x22,0x60,0x42,0x50,0x42,0x48,
40 0xA4,0x44,0x14,0x44,0x08,0x40,0x08,0x40,0x10,0x40,0x20,0x40,0x40,0x40,0x80,0x40,
41
42 0x00,0x00,0x20,0x80,0x13,0x3C,0x12,0x24,0x02,0x24,0x02,0x24,0xF2,0x24,0x12,0x24,
43 0x12,0x24,0x12,0xB4,0x13,0x28,0x12,0x20,0x10,0x20,0x28,0x20,0x47,0xFE,0x00,0x00
44
45 };
46
47
48
49
50 void plan(void)
51 {
52 //映射内存地址,屏幕信息
53 char *fbp = NULL;
54 struct fb_var_screeninfo scrinfo;
55
56
57 //设备文件的操作
58 int devfb = open("/dev/fb0", O_RDWR);
59 if(!devfb)
60 {
61 printf("devfb open error!\r\n");
62 exit(1);
63 }
64
65 //屏幕信息
66 if(ioctl(devfb, FBIOGET_VSCREENINFO, &scrinfo))
67 {
68 printf("get screen infomation error!\r\n");
69 exit(2);
70 }
71 //设置参数(图片大小为1280*168)
72 scrinfo.xres = 1280;
73 scrinfo.yres = 768;
74
75 if(ioctl(devfb, FBIOPUT_VSCREENINFO, &scrinfo))
76 {
77 printf("set screen infomation error!\r\n");
78 exit(2);
79 }
80
81
82
83 //内存映射
84 unsigned long screensize = scrinfo.xres_virtual * scrinfo.yres_virtual * scrinfo.bits_per_pixel / 8;
85 fbp = (char *)mmap(NULL, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, devfb, 0);
86 if(-1 == (int)fbp)
87 {
88 printf("mmap error!\r\n");
89 exit(3);
90 }
91
92 //字形处理和视频显示
93 //update_word(&heard);
94 show_photo(fbp, &scrinfo);
95
96 //结束
97 munmap(fbp, screensize);
98 close(devfb);
99
100 return ;
101 }
102
103
104
105
106 int show_photo(const char *fbp, struct fb_var_screeninfo *scrinfo)
107 {
108 if(NULL == fbp || NULL == scrinfo)
109 return -1;
110
111
112 int xres = scrinfo->xres_virtual;
113 int bits_per_pixel = scrinfo->bits_per_pixel;
114 BitMapFileHeader FileHead;
115 BitMapInfoHeader InfoHead;
116 RgbQuad rgb;
117 unsigned long location = 0;
118
119 //打开.bmp文件
120 FILE *fb = fopen(photo_name, "rb");
121 if (fb == NULL)
122 {
123 printf("fopen bmp error\r\n");
124 return -1;
125 }
126
127 //读文件头,并判断是否为.bmp文件
128 if (1 != fread( &FileHead, sizeof(BitMapFileHeader),1, fb))
129 {
130 printf("read BitMapFileHeader error!\n");
131 fclose(fb);
132 return -1;
133 }
134 if (memcmp(FileHead.bfType, "BM", 2) != 0)
135 {
136 printf("it's not a BMP file\n");
137 fclose(fb);
138 return -1;
139 }
140
141 //获取.bmp文件信息
142 if (1 != fread( (char *)&InfoHead, sizeof(BitMapInfoHeader),1, fb))
143 {
144 printf("read BitMapInfoHeader error!\n");
145 fclose(fb);
146 return -1;
147 }
148
149 //移动至数据段,准备读数据
150 fseek(fb, FileHead.bfOffBits, SEEK_SET);
151
152
153 //图片行,列,像素信息
154 int line_x = 0, line_y = 0;
155 unsigned long tmp = 0;
156
157
158 int len = InfoHead.biBitCount / 8; //原图像素点所占字节数,24/8=3
159 int bits_len = bits_per_pixel / 8; //屏幕像素点所占字节数,32/8=4
160
161
162 //右上角文字显示区相关信息
163 int word_line_y = WORD_DATA_HEIGTH - 1; //三行文字最底端的行
164 int word_line_x; //三行文字最左端的列
165 int k; //字模移动位数
166 unsigned char data = 0, one = 0;
167
168 while(!feof(fb))
169 {
170 tmp = 0;
171 rgb.Reserved = 0xFF;
172
173 //对应的内存相对映射首地址的偏移量
174 location = line_x * bits_len + (InfoHead.biHeight - 1 - line_y ) * xres * bits_len;
175
176 tmp = rgb.Reserved << 24 | rgb.Red << 16 | rgb.Green << 8 | rgb.Blue;
177
178
179 //文字显示区
180 if(line_x > WORD_WIDTH && line_x < InfoHead.biWidth - 10 &&
181 line_y > WORD_HEIGTH && line_y < InfoHead.biHeight - 10 && word_line_y >= 0)
182 {
183 tmp = 0;
184
185
186 for(word_line_x = 0; word_line_x < WORD_DATA_WIDTH; word_line_x++)
187 {
188
189 //读字模
190 data = word[word_line_y][word_line_x];
191
192 one = 0x80;
193
194 for(k = 0; k < BIT_WIDTH; k++)
195 {
196
197 fread((char *)&rgb, 1, len, fb);
198
199 //确定有效位
200 if(data & one)
201 tmp = 0; //黑色字体
202
203 else
204 tmp = rgb.Reserved << 24 | rgb.Red << 16 | rgb.Green << 8 | rgb.Blue;
205
206
207 location = line_x * bits_len + (InfoHead.biHeight - 1 - line_y ) * xres * bits_len;
208 *((unsigned long *)(fbp + location)) = tmp;
209
210 one >>= 1;
211
212 //自增列
213 line_x++;
214 if (line_x == InfoHead.biWidth )
215 {
216 line_x = 0;
217
218 //自增行
219 line_y++;
220 if(line_y == InfoHead.biHeight)
221 break;
222 }
223 }
224 }
225
226 //字模从下往上读和显示
227 word_line_y--;
228 continue;
229
230 }
231
232 //读.bmp文件
233 if (len != fread((char *)&rgb, 1, len, fb))
234 break;
235
236
237 //显示非文字区的图片
238 *((unsigned long *)(fbp + location)) = tmp;
239
240 //自增列
241 line_x++;
242 if (line_x == InfoHead.biWidth )
243 {
244 line_x = 0;
245
246 //自增行
247 line_y++;
248 if(line_y == InfoHead.biHeight)
249 break;
250 }
251 }
252
253
254 fclose(fb);
255
256 return 0;
257 }
main函数
1 int main()
2 {
3
4 plan();
5
6 return 0;
7 }
效果图(我不是给这游戏打广告)
说明:1.图片是24位或32位bmp图
2.屏幕是32位屏幕
3.不同的设备,可能设备文件不同
4.需要在root用户下执行