weixin_49323105 2023-06-30 16:21 采纳率: 25%
浏览 9

ubuntu lcd模拟显示器 图片发黄问题

使用ubuntu的lcd显示模拟器出现的问题 图片是bmp 24位 运行后图片发黄

img

  • 写回答

1条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2023-06-30 18:30
    关注
    • 这篇博客: 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图片的结构:

      image-20220124001914847

      image-20220124001941914

      位图数据存储规则:

      (1)每行的字节数必须是4的倍数,如果不是,则需要用0补齐。
      (2)BMP位图数据的存放是从下到上,从左到右的。先读最后一行,读完后在读倒数第二行。

      image-20220124002345869

      按照上面的介绍,就可以定义一个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数据没有正确解码并渲染显示。

      解决方法:

      1. 首先,需要读取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);
      }
      
      1. 接下来,根据读取到的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屏幕不兼容,那么我无法提供更具体的解决方案。

    评论

报告相同问题?

问题事件

  • 创建了问题 6月30日

悬赏问题

  • ¥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 微机原理相关问题,求解