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用户下执行

  

posted @ 2016-12-19 16:01  皓首匹夫  阅读(2462)  评论(2)    收藏  举报