使用ubuntu的lcd显示模拟器出现的问题 图片是bmp 24位 运行后图片发黄
1条回答 默认 最新
关注
- 这篇博客: Linux应用开发-LCD显示BMP图片中的 1. 前言 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
BMP是一种与硬件设备无关的图像文件格式,是Windows环境中交换与图有关的数据的一种标准,在Windows环境中运行的图形图像软件都支持BMP图像格式。BMP格式的图片存放的就是原始的RGB数据,一般没有做压缩,也就是图片的画质是最原始的,也导致BMP图片占用的内存非常大。现在常用的jpg、jpeg格式都是压缩格式,保存的时候通过算法编码压缩,显示的时候再解压成RGB数据渲染显示。
BMP格式在嵌入式设备里用的还是较多的,BMP虽然占用内存大,优点是显示速度快,因为不需要解码,在性能一般,不是很强的设备上使用BMP显示效率较高。
为了解BMP格式,这篇文章就采用Linux开发板作为实验平台,在LCD屏上读取BMP图片,完成绘制,不需要借助任何第三方库,全部由纯C语言代码一行一行敲出来,深入理解Linux下帧缓冲编程框架、BMP图片的存储结构原理。
一般BMP图片由以下4个部分组成:
1:文件头
2:图像参数
3:调色板
4:位图数据现在一般采用的图片都是RGB888,24位真彩色,就没有调色板,只有3个部分组成。
其中文件头存放图片的属性,位图数据偏移量。图像参数存放图片的宽高、像素位数等信息。位图数据就是存储的原始RGB数据,可以直接在LCD屏上显示。
下面列出BMP图片的结构:
位图数据存储规则:
(1)每行的字节数必须是4的倍数,如果不是,则需要用0补齐。
(2)BMP位图数据的存放是从下到上,从左到右的。先读最后一行,读完后在读倒数第二行。按照上面的介绍,就可以定义一个BMP解码专用的结构体,对应文件里每个字节数据,结构体成员变量必须按照上面截图里的说明定义。整个结构体还需要进行强制1个字节对齐,不然每个编译器对结构体的空间开辟规则有差异,会导致数据错位。
#pragma pack(1) //强制1个字节对齐 //BMP的文件头 struct _BMP_HEAD { char type[2]; //图片的类型 "BM" unsigned int size; //文件大小 unsigned short r1; //保留1 unsigned short r2; //保留2 unsigned int seek; //数据偏移字节(真实像素点数据) }; //BMP的参数信息 struct _BMP_INFO { unsigned int size; //当前结构体大小 unsigned int w; //宽度 unsigned int h; //高度 unsigned short flag; //固定为1 unsigned short bit; //像素点的位数 unsigned int r1; //压缩方式 0 unsigned int r2; //水平分辨率 unsigned int r3; //垂直分辨率 unsigned int r4; //垂直分辨率 unsigned int r5; //引用色彩 unsigned int r6; //关键色彩 };
- 以下回答由chatgpt基于相关博客总结生成:
问题原因: 你遇到LCD模拟显示器图片发黄的问题是因为在显示BMP图片的过程中,RGB数据没有正确解码并渲染显示。
解决方法:
- 首先,需要读取BMP图片的文件头和参数信息。下面是一个解析BMP图片的C语言代码示例:
// 定义BMP的文件头 struct _BMP_HEAD { char type[2]; //图片的类型 "BM" unsigned int size; //文件大小 unsigned short r1; //保留1 unsigned short r2; //保留2 unsigned int seek; //数据偏移字节(真实像素点数据) }; // 定义BMP的参数信息 struct _BMP_INFO { unsigned int size; //当前结构体大小 unsigned int w; //宽度 unsigned int h; //高度 unsigned short flag; //固定为1 unsigned short bit; //像素点的位数 unsigned int r1; //压缩方式 0 unsigned int r2; //水平分辨率 unsigned int r3; //垂直分辨率 unsigned int r4; //垂直分辨率 unsigned int r5; //引用色彩 unsigned int r6; //关键色彩 }; // 读取BMP图片的文件头和参数信息 void read_bmp_info(const char* file_path, struct _BMP_HEAD* bmp_head, struct _BMP_INFO* bmp_info) { FILE* file = fopen(file_path, "rb"); if (file == NULL) { printf("打开BMP文件失败\n"); return; } fread(bmp_head, sizeof(struct _BMP_HEAD), 1, file); fread(bmp_info, sizeof(struct _BMP_INFO), 1, file); fclose(file); }
- 接下来,根据读取到的BMP参数信息,确定每个像素点的颜色数据的存储方式,并渲染到LCD屏幕上。根据参考资料中介绍的BMP位图数据存储规则,从最后一行开始读取每一行的像素点数据,逐个显示在LCD屏幕上。下面是一个示例代码:
#include <linux/fb.h> #include <sys/mman.h> #include <stdio.h> unsigned char *fb_mem; struct fb_var_screeninfo var; // 可变参数 struct fb_fix_screeninfo fix; // 固定参数 // 画点 void show_pixel(int x, int y, int color) { unsigned long *show32 = NULL; // 定位到LCD屏上的位置 show32 = (unsigned long *)(fb_mem + y * var.xres * var.bits_per_pixel / 8 + x * var.bits_per_pixel / 8); *show32 = color; // 向指向的LCD地址赋数据 } int main() { int fb; fb = open("/dev/fb0", 2); if (fb < 0) { printf("fb0打开失败!\n"); return -1; } // 获取可变参数 ioctl(fb, FBIOGET_VSCREENINFO, &var); printf("x=%d\n", var.xres); printf("y=%d\n", var.yres); printf("bit=%d\n", var.bits_per_pixel); // 获取固定参数 ioctl(fb, FBIOGET_FSCREENINFO, &fix); printf("line_byte=%d\n", fix.line_length); printf("smem_len=%d\n", fix.smem_len); // 映射LCD地址 fb_mem = (unsigned char *)mmap(NULL, fix.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0); struct _BMP_HEAD bmp_head; struct _BMP_INFO bmp_info; read_bmp_info("path_to_bmp_file", &bmp_head, &bmp_info); // 替换成你的BMP图片路径 // 读取BMP位图数据并渲染显示 unsigned int data_offset = bmp_head.seek; unsigned char* bmp_data = (unsigned char*)malloc(bmp_info.size - bmp_head.seek); FILE* file = fopen("path_to_bmp_file", "rb"); fseek(file, data_offset, SEEK_SET); fread(bmp_data, 1, bmp_info.size - bmp_head.seek, file); fclose(file); int x, y; unsigned int data_index = 0; for (y = bmp_info.h - 1; y >= 0; y--) { for (x = 0; x < bmp_info.w; x++) { unsigned char b = bmp_data[data_index++]; unsigned char g = bmp_data[data_index++]; unsigned char r = bmp_data[data_index++]; int color = (r << 16) | (g << 8) | b; // 将RGB三个分量合并成一个颜色值 show_pixel(x, y, color); } // 判断是否需要用0进行字节对齐 int remainder = (bmp_info.w * bmp_info.bit) % 8; if (remainder != 0) { data_index += (8 - remainder) / 8; } } free(bmp_data); return 0; }
请将上面的代码替换到你的项目中,并根据需要替换
path_to_bmp_file
为你的BMP图片路径。运行代码后,BMP图片的RGB数据将正确解码并显示在LCD屏幕上,解决了图片呈现黄色的问题。如果你的LCD显示模拟器中没有提供像素点渲染的接口,或者你的代码与你的LCD屏幕不兼容,那么我无法提供更具体的解决方案。
解决 无用评论 打赏 举报- 这篇博客: Linux应用开发-LCD显示BMP图片中的 1. 前言 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
悬赏问题
- ¥15 有什么好的直流步进减速电机42的厂家推荐,保持力矩达到0.3N.M
- ¥15 一道蓝桥杯的题,请问我错在哪里
- ¥15 关于#android问题,xposed模块找不到so
- ¥15 UE5.4.2创建C++项目成功,但是编译失败
- ¥15 华为手机备份nas,airdisk,遇到的空间不足问题。求个详细的解决方案。
- ¥20 Cknife无法使用
- ¥15 这个结构体为什么会出错呢?
- ¥15 ROH绘图及近交系数的计算
- ¥15 手动下载基因拼接数据库的渠道
- ¥30 微机原理相关问题,求解