| for (int y = 0; y < height; y++) {
fread(row, sizeof(uint8_t), row_size, bmp_file); for (int x = 0; x < width; x++) { int pixel_index = x * 3; // 每个像素 3 字节 uint8_t blue = row[pixel_index]; uint8_t green = row[pixel_index + 1]; uint8_t red = row[pixel_index + 2]; // 计算帧缓冲区位置 long location = (vinfo->yres_virtual - 1 - y) * vinfo->xres_virtual * (vinfo->bits_per_pixel / 8) + x * (vinfo->bits_per_pixel / 8); fb_ptr[location] = blue; // 蓝色分量 fb_ptr[location + 1] = green; // 绿色分量 fb_ptr[location + 2] = red; // 红色分量 } } |
完整main.c:
| #include <stdio.h>
#include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <linux/fb.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <stdint.h> #pragma pack(push, 1) typedef struct { uint16_t bfType; // BMP 文件类型 uint32_t bfSize; // 文件大小 uint16_t bfReserved1; // 保留字段 uint16_t bfReserved2; // 保留字段 uint32_t bfOffBits; // 图像数据的偏移量 } BMPFileHeader; typedef struct { uint32_t biSize; // 信息头的大小 int32_t biWidth; // 图像宽度 int32_t biHeight; // 图像高度 uint16_t biPlanes; // 颜色平面数 uint16_t biBitCount; // 每个像素的位数 uint32_t biCompression; // 压缩类型 uint32_t biSizeImage; // 图像大小 int32_t biXPelsPerMeter; // 水平分辨率 int32_t biYPelsPerMeter; // 垂直分辨率 uint32_t biClrUsed; // 使用的颜色数 uint32_t biClrImportant; // 重要的颜色数 } BMPInfoHeader; #pragma pack(pop) void draw_bmp(const char *filename, int fb_fd, struct fb_var_screeninfo *vinfo) { FILE *bmp_file = fopen(filename, "rb"); if (!bmp_file) { perror("Failed to open BMP file"); exit(1); } BMPFileHeader file_header; BMPInfoHeader info_header; fread(&file_header, sizeof(BMPFileHeader), 1, bmp_file); fread(&info_header, sizeof(BMPInfoHeader), 1, bmp_file); // 检查 BMP 文件格式 if (file_header.bfType != 0x4D42) { fprintf(stderr, "Not a valid BMP file\n"); fclose(bmp_file); return; } // BMP 文件宽度和高度 int width = info_header.biWidth; int height = info_header.biHeight; // 每行字节对齐到 4 字节 int row_size = (width * 3 + 3) & ~3; // 分配内存并读取像素数据 uint8_t *row = malloc(row_size); if (!row) { perror("Failed to allocate memory"); fclose(bmp_file); return; } // 映射帧缓冲区 size_t screensize = vinfo->yres_virtual * vinfo->xres_virtual * (vinfo->bits_per_pixel / 8); uint8_t *fb_ptr = (uint8_t *)mmap(NULL, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0); if (fb_ptr == MAP_FAILED) { perror("Failed to map framebuffer device to memory"); free(row); fclose(bmp_file); return; } // 清空帧缓冲 memset(fb_ptr, 0, screensize); // 绘制 BMP 图像到帧缓冲区 for (int y = 0; y < height; y++) { fread(row, sizeof(uint8_t), row_size, bmp_file); for (int x = 0; x < width; x++) { int pixel_index = x * 3; // 每个像素 3 字节 uint8_t blue = row[pixel_index]; uint8_t green = row[pixel_index + 1]; uint8_t red = row[pixel_index + 2]; // 计算帧缓冲区位置 long location = (vinfo->yres_virtual - 1 - y) * vinfo->xres_virtual * (vinfo->bits_per_pixel / 8) + x * (vinfo->bits_per_pixel / 8); fb_ptr[location] = blue; // 蓝色分量 fb_ptr[location + 1] = green; // 绿色分量 fb_ptr[location + 2] = red; // 红色分量 } } // 清理 munmap(fb_ptr, screensize); free(row); fclose(bmp_file); } int main(int argc, char *argv[]) { if (argc != 3) { fprintf(stderr, "Usage: %s <framebuffer_device> <image_file>\n", argv[0]); return 1; } const char *fb_device = argv[1]; const char *image_file = argv[2]; // 打开帧缓冲设备 int fb_fd = open(fb_device, O_RDWR); if (fb_fd == -1) { perror("Error opening framebuffer device"); return 1; } // 获取屏幕信息 struct fb_var_screeninfo vinfo; if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo)) { perror("Error reading variable information"); close(fb_fd); return 1; } printf(".xres=%d, .yres=%d, .bit=%d\r\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel); printf(".xres_virtual=%d, .yres_virtual=%d\r\n", vinfo.xres_virtual, vinfo.yres_virtual); // 显示 BMP 图片 draw_bmp(image_file, fb_fd, &vinfo); close(fb_fd); return 0; } |
进程名:elf2_cmd_lcd_bmp
使用方法:./elf2_cmd_lcd_bmp 设备名 [参数选项]… …
| 参数 | 含义 | 描述 |
| device | 设备名 | 例如fb0 |
| bmpname | 图片名称 | 包含路径的图片名称 |
191