blob: bc35a0740d14fe1ee7783610f95c9b946a4f365c [file] [log] [blame]
liubin281ac462023-07-19 14:22:54 +08001#include <stdio.h>
2#include <string.h>
3#include <stdlib.h>
4#include <unistd.h>
5#include <sys/ioctl.h>
6#include <linux/fb.h>
7#include <sys/types.h>
8#include <sys/stat.h>
9#include <fcntl.h>
10#include <sys/mman.h>
11#include <math.h>
12
b.liu9e8584b2024-11-06 19:21:28 +080013#include "mbtk_utils.h"
14
liubin281ac462023-07-19 14:22:54 +080015/**< \brief 根据实际情况修改,此处为unsigned short是565的屏,根据程序打印出的
16 bits_per_pixel的值可以判断出输出格式是565还是888 */
17// typedef unsigned int color_t;
18typedef unsigned short color_t;
19/**< \brief 定义每个像素点对应的位数,如果是565的屏则为16,如果是888的屏则为32 */
20// #define BITS_PER_PIXEL 32
21#define BITS_PER_PIXEL 16
22
23static struct fb_var_screeninfo __g_vinfo; /* 显示信息 */
24color_t *__gp_frame; /* 虚拟屏幕首地址 */
25
26#pragma pack(2)
27typedef unsigned short WORD;
28typedef unsigned char BYTE;
29typedef unsigned int DWORD;
30typedef int LONG;
31
32typedef struct tagBITMAPFILEHEADER
33{
34 WORD bfType; // 位图文件的类型,必须为BM
35 DWORD bfSize; // 位图文件的大小,以字节为单位
36 WORD bfReserved1; // 位图文件保留字,必须为0
37 WORD bfReserved2; // 位图文件保留字,必须为0
38 DWORD bfOffBits; // 位图数据的起始位置,以相对于位图
39 // 文件头的偏移量表示,以字节为单位
40} BITMAPFILEHEADER;
41
42typedef struct tagBITMAPINFOHEADER
43{
44 DWORD biSize; // 本结构所占用字节数
45 LONG biWidth; // 位图的宽度,以像素为单位
46 LONG biHeight; // 位图的高度,以像素为单位
47 WORD biPlanes; // 目标设备的级别,必须为1
48 WORD biBitCount;// 每个像素所需的位数,必须是1(双色),
49 // 4(16色),8(256色)或24(真彩色)之一
50 DWORD biCompression; // 位图压缩类型,必须是 0(不压缩),
51 // 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
52 DWORD biSizeImage; // 位图的大小,以字节为单位
53 LONG biXPelsPerMeter; // 位图水平分辨率,每米像素数
54 LONG biYPelsPerMeter; // 位图垂直分辨率,每米像素数
55 DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数
56 DWORD biClrImportant;// 位图显示过程中重要的颜色数
57} BITMAPINFOHEADER;
58#pragma pack(0)
59
60typedef WORD (*bmp_xx_to_16)(char *);
61
62//画点
63void draw_point(int x, int y, color_t color)
64{
65 color_t *p = __gp_frame;
66
67 p += __g_vinfo.xres * y + x;
68 *p = color;
69}
70
71WORD bmp_24_to_16(char *input)
72{
73 /* 如果使用的bmp图片的颜色深度是24位,适用于888的屏,但如果一定要在565的屏
74 上显示,则取红色的高5位,绿色的高6位和蓝色的高5位,拼成16位的数据
75 进行显示。这样做并不是最好的办法,更好的方法是将需要丢失的部分数
76 据进行进位或舍去。
77 */
78 WORD c;
79 char b, g, r;
80 r = *input >> 3;
81 input++;
82 g = *input >> 2;
83 input++;
84 b = *input >> 3;
85
86 c = (b << 11) | (g << 5) | r;
87
88 return c;
89}
90
91WORD bmp_16_to_16(char *input)
92{
93 WORD c;
94
95 c = *input;
96 input++;
97 c = (c << 8) | *input;
98 c = ((c >> 8) & 0x00ff) | ((c & 0x00ff) << 8);
99
100 return c;
101}
102
103//功能:在指定坐标显示指定BPM24位图
104//参数:(x , y)坐标
105// pic:24位BMP图像
106void Show_BMP(int x , int y , const char *pic)
107{
108 int fd = 0;
109 color_t c;
110 BITMAPFILEHEADER filehead;
111 BITMAPINFOHEADER infohead;
112 int i,j;
113 unsigned char pixel_byte;
114 unsigned char *p = NULL , *p_data = NULL;
115 int width_error = 0;
116 short* t_data = NULL;
117 bmp_xx_to_16 transform_func = NULL;
118 int index = 0;
119
120 printf("%s: %s\n", __FUNCTION__, pic);
121 fd = open(pic , O_RDONLY);
122 if(fd == -1) {
123 printf("fail to open\n");
124 return;
125 }
126
b.liu9e8584b2024-11-06 19:21:28 +0800127 mbtk_read(fd , &filehead , sizeof(filehead));
128 mbtk_read(fd , &infohead , sizeof(infohead));
liubin281ac462023-07-19 14:22:54 +0800129 printf("bfType: 0x%x, bfSize: %d, bfOffBits: 0x%x\n", filehead.bfType, filehead.bfSize, filehead.bfOffBits);
130
131 printf("biSize: %d, biWidth: %d, biHeight: %d\n", infohead.biSize, infohead.biWidth, infohead.biHeight);
132 printf("biPlanes: %d, biBitCount: %d, biCompression: %d\n", infohead.biPlanes, infohead.biBitCount, infohead.biCompression);
133 printf("biSizeImage: %d, biXPelsPerMeter: %d, biYPelsPerMeter: %d\n", infohead.biSizeImage, infohead.biXPelsPerMeter, infohead.biYPelsPerMeter);
134
135 width_error = (4 - infohead.biWidth * 3 % 4) % 4;
136 pixel_byte = infohead.biBitCount / 8;
137
138 if (16 == infohead.biBitCount) {
139 transform_func = bmp_16_to_16;
140 } else if (24 == infohead.biBitCount) {
141 transform_func = bmp_24_to_16;
142 } else {
143 printf("Not Suppurt %d bmp\n", infohead.biBitCount);
144 close(fd);
145 return;
146 }
147
148 t_data = malloc(__g_vinfo.xres_virtual * __g_vinfo.yres_virtual * __g_vinfo.bits_per_pixel / 8);
149
150 if(t_data == NULL) {
151 perror("fail to malloc");
152 }
153
154 p_data = malloc(infohead.biSizeImage);
155 if(p_data == NULL) {
156 perror("fail to malloc");
157 }
158
159 printf("biSizeImage:%d, width_error: %d\n", infohead.biSizeImage, width_error);
b.liu9e8584b2024-11-06 19:21:28 +0800160 mbtk_read(fd , p_data , infohead.biSizeImage);
liubin281ac462023-07-19 14:22:54 +0800161 p = p_data;
162
163 int ret;
b.liu9e8584b2024-11-06 19:21:28 +0800164 char data[100] = {0};
liubin281ac462023-07-19 14:22:54 +0800165 int debug_fd = open("/data/debug_fb", O_RDWR|O_CREAT|O_TRUNC, 0644);
166 if (debug_fd < 0) {
167 printf("debug_fb open error\n");
168 return;
169 }
170 printf("height:%d, width:%d\n", infohead.biHeight, infohead.biWidth);
171 for(j = infohead.biHeight - 1; j >= 0; j--) {
172 for(i = 0; i < infohead.biWidth; i++) {
b.liu9e8584b2024-11-06 19:21:28 +0800173 c = transform_func((char*)p);
liubin281ac462023-07-19 14:22:54 +0800174 // c = *p;
175 p += pixel_byte;
176 // c = ((c >> 8) & 0x00ff) | ((c & 0x00ff) << 8);
177 t_data[__g_vinfo.xres * (y + j) + (x + i)] = c;
178 // draw_point(x + i, y + j, c);
179 index++;
180
181 sprintf(data, "index:%d, i:%d, j:%d\n", index, i, j);
182 ret = write(debug_fd, data, strlen(data));
183 if (ret < 0) {
184 printf("%s write error\n", __FUNCTION__);
185 }
186 }
187 p += width_error;
188 }
189 close(debug_fd);
190 printf("%s: %d\n", __FUNCTION__, infohead.biHeight * infohead.biWidth * __g_vinfo.bits_per_pixel / 8);
191 memcpy(__gp_frame, t_data,
192 infohead.biHeight * infohead.biWidth * __g_vinfo.bits_per_pixel / 8);
193 printf("%s: %d\n", __FUNCTION__, index);
194 free(p_data);
195 free(t_data);
196 close(fd);
197}
198
199/**
200 * \brief 填充整屏
201 */
202void full_screen (color_t color)
203{
204 int i;
205 color_t *p = __gp_frame;
206
207 for (i = 0; i < __g_vinfo.xres_virtual * __g_vinfo.yres_virtual; i++) {
208 *p++ = color;
209 }
210}
211
212/**
213 * \brief 清屏
214 */
215void clear()
216{
217 full_screen(0);
218}
219
220/* framebuffer初始化 */
221int framebuffer_init (void)
222{
223 int fd = 0;
224
225 fd = open("/dev/fb0", O_RDWR);
226 if (fd == -1) {
227 perror("fail to open /dev/fb0\n");
228 return -1;
229 }
230
231 /* 获取显示信息 */
232 ioctl(fd, FBIOGET_VSCREENINFO, &__g_vinfo); /* 获取显示信息 */
233 printf("bits_per_pixel = %d\n", __g_vinfo.bits_per_pixel); /* 得到一个像素点对应的位数 */
234 printf("xres_virtual = %d\n", __g_vinfo.xres_virtual); /* 打印虚拟屏幕列数 */
235 printf("yres_virtual = %d\n", __g_vinfo.yres_virtual); /* 打印虚拟屏幕行数 */
236 printf("xres = %d\n", __g_vinfo.xres); /* 打印屏幕列数 */
237 printf("yres = %d\n", __g_vinfo.yres); /* 打印屏幕行数 */
238
239 int len = __g_vinfo.xres_virtual * __g_vinfo.yres_virtual * __g_vinfo.bits_per_pixel / 8; /* 映射区大小 */
240
241 printf("fb size = %d\n", len);
242 __gp_frame = mmap(NULL, /* 映射区的开始地址,为NULL表示由系统决定映射区的起始地址 */
243 len,
244 PROT_WRITE | PROT_READ, /* 内存保护标志(可读可写) */
245 MAP_SHARED, /* 映射对象类型(与其他进程共享) */
246 fd, /* 有效的文件描述符 */
247 0); /* 被映射内容的偏移量 */
248 if (__gp_frame == NULL) {
249 perror("fail to mmap\n");
250 return -1;
251 }
252
253 return fd;
254}
255
256
257int main(int argc, const char *argv[])
258{
259 int fd;
260
261 if (argc < 2) {
262 printf("%s \" img \"", argv[0]);
263 exit(1);
264 }
265
266 fd = framebuffer_init();
267 if (fd < 0) {
268 printf("framebuffer_init error\n");
269 return 0;
270 }
271
272 printf("framebuffer_init Success.\n");
273 /* 清屏 */
274 clear();
275
276 printf("clear Success.\n");
277
278 // full_screen(0xF800); // 显示红色
279
280 Show_BMP(0 , 0 , argv[1]);
281
282 close(fd);
283
284 return 0;
285}