当前位置: 首页 > news >正文

Linux下的lcd屏幕显示操作

1.lcd屏幕显示的基本原理

  • 像素:
    屏幕上显示颜色的最小单位,英文叫 pixel。注意,位图(如jpg、bmp等格式的常见图片)也是由一个个的像素点构成的,跟屏幕的像素点的概念一样。原理上讲,将一张位图显示到屏幕上,就是将图片上的像素点一个个复制到屏幕像素点上。

  • 分辨率:
    • 宽、高两个维度上的像素点数目。
    • 分辨率越高,所需要的显存越大。

  • 色深:
    • 每个像素所对应的内存字节数,一般有8位、16位、24位或32位
    • GEC6818开发板的屏幕的色深是32位的
    • 32位色深的屏幕一般被称为真彩屏,或1600万色屏。

色深决定了一个像素点所能表达的颜色的丰富程度,色深越大,色彩表现力越强。

 2. mmap映射

虽然LCD设备本质上也可以看作是一个文件,在文件系统中有其对应的设备节点,可以像普通文件一样对其进行读写操作(read/write),但由于对字符设备的读写操作是以字节流的方式进行的,因此除非操作的图像尺寸刚好与屏幕尺寸完全一致,如下图所示,图片的宽高与LCD的宽高完全一致,否则将会画面会乱。并且效率相对较低

图像的尺寸大小是随机的,因此更方便的做法是为LCD做内存映射,将屏幕的每一个像素点跟映射内存一一对应,而映射内存可以是二维数组,因此就可以非常方便地通过操作二维数组中的任意元素,来操作屏幕中的任意像素点了。这里的映射内存,有时被称为显存。

  1. LCD上面显示的图像色彩,由其对应的内存的数据决定
  2. 映射内存的大小至少得等于LCD的真实尺寸大小
  3. 映射内存的大小可以大于LCD的真实尺寸,有利于优化动态画面(视频)体验

bmp格式

文件组成

        特征是都没有任何的压缩,因此文件尺寸都比较大,不适合在互联网上传播,优点是数据读取出来即可使用,无需任何解码器支持。

数据段名称对应大小
bmp头文件14
信息头

40

调色板从54开始,有像素点的大小决定

注意 

a. 4字节倍数行距
BMP图片文件的一个重要规则是,每行数据字节数必须是4的倍数,假设某BMP图片的分辨率是 65 × 200,也就是说宽是 65 像素,假设每个字节色深是24bits(即3字节),那么这张图片一行的实际数据量是 65×3=195个字节,但195不是4的倍数,因此在每一行的末尾都会添加一个无效字节,将行距尺寸补到196个字节。

int pad = ((4-( width * bpp/8 ) % 4)) % 4;//计算增加的无效字节

其次,在处理图像数据的时候,直接跳过这些无效字节就好了。

 b. 上下颠倒
BMP图片中的RGB数据是上下颠倒的,因此文件数据中的最后一行是图像的最上面第一行。需要注意的是,上下是颠倒的,但是左右是正常的,因此在处理数据的时候不能从最后一个字节开始,而是从最末一行的首字节开始。

3.jpg格式

在bmp格式下可以直接读文件中RGB值进行显示,但是在jpg格式下的文件必须先进行解码

 jpg第三方开源解码器下载与配置使用

在嵌入式来发中,运用第三方库套路基本一致,所以在这详细介绍一下

(1)下载

直接官方进行下载Independent JPEG Group

不要在Windows下进行解压,会导致问价损坏,将压缩包放在Linux下进行解压

可以阅读README了解开发原理

如何安装

如何使用和例程

在install.txt中

移植三件套./config make makefile

当运行config的时候会检查各种配置,配置检查完成会生成makefile
在开发板中使用的编译工具为gcc

在install,txt中说明需要使用CC=命令进行改变便以及

 将所有的编译命令的前缀改为arrch64-linux

 生成makefile

指定其他路径 

 开启4条线程

 

 提取

提取完成后需要将。文件夹中的lib 与include 中的文件导入到所要使用的文件对应目录中使用一下命令进行编译

 -L:指定库路径    -l指定库名称 -I(i)指定头文件路径 

需要将lib的函数库文件拷贝到开发板的/lib/里面  解决掉找不到库文件的问题

用于指明编译工具

--host=编译工具 

用于指明存放路径

--prifix=存放路径                                         

 ​​​​​

(2)通过官方例程example进行修改 

以下为例程

METHODDEF(void)
my_error_exit (j_common_ptr cinfo)
{/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */my_error_ptr myerr = (my_error_ptr) cinfo->err;/* Always display the message. *//* We could postpone this until after returning, if we chose. */(*cinfo->err->output_message) (cinfo);/* Return control to the setjmp point */longjmp(myerr->setjmp_buffer, 1);
}struct RGB
{char rad;cahr green;char blue;
};int read_JPEG_file(char *filename, int *screen_buf)
{struct jpeg_decompress_struct cinfo;struct my_error_mgr jerr;FILE *infile;       /* source file */struct RGB *buffer; /* Output row buffer */int row_stride;     /* physical row width in output buffer */if ((infile = fopen(filename, "rb")) == NULL){fprintf(stderr, "can't open %s\n", filename);return 0;}/* Step 1: allocate and initialize JPEG decompression object *//* We set up the normal JPEG error routines, then override error_exit. */cinfo.err = jpeg_std_error(&jerr.pub);jerr.pub.error_exit = my_error_exit;/* Establish the setjmp return context for my_error_exit to use. */if (setjmp(jerr.setjmp_buffer)){/* If we get here, the JPEG code has signaled an error.* We need to clean up the JPEG object, close the input file, and return.*/jpeg_destroy_decompress(&cinfo);fclose(infile);return 0;}if ((infile = fopen(filename, "r")) == NULL) // 打开源文件{fprintf(stderr, "can't open %s\n", filename);return 0;}/* Step 1: allocate and initialize JPEG decompression object */jpeg_create_decompress(&cinfo);/* Step 2: specify data source (eg, a file) */jpeg_stdio_src(&cinfo, infile);/* Step 3: read file parameters with jpeg_read_header() */(void)jpeg_read_header(&cinfo, TRUE);/*开始解码*/(void)jpeg_start_decompress(&cinfo);row_stride = cinfo.output_width * cinfo.output_components;/* Make a one-row-high sample array that will go away when done with image */buffer = malloc(row_stride);int x, y;int calor;/*逐行进行数据读取 */for (y = 0; cinfo.output_scanline < cinfo.output_height; y++){/*将数据的一行读取出来方入buffer中 */(void)jpeg_read_scanlines(&cinfo, (JSAMPARRAY)&buffer, 1);for (x = 0; x < cinfo.output_width; x++){calor = (buffer[x].rad << 16) | (buffer[x].green << 8) | (buffer[x].blue);screen_disp(x, y, screen_buf, calor);}/* Assume put_scanline_someplace wants a pointer and sample count. */// put_scanline_someplace(buffer[0], row_stride);}(void)jpeg_finish_decompress(&cinfo);jpeg_destroy_decompress(&cinfo);fclose(infile);return 1;
}

 

 

http://www.dtcms.com/a/293880.html

相关文章:

  • 【前端】【Vue DevTools】Vue DevTools 进阶:用 Trae / Cursor 替换 VSCode 打开文件(跳转行列无误)
  • 直播一体机技术方案解析:基于RK3588S的硬件架构特性​
  • 7.23 减肥感悟
  • 为什么IMU是无人机稳定控制的的核心?
  • 深入解析Hive SQL转MapReduce的编译原理:从AST抽象语法树到Operator执行树
  • 无人机光伏巡检误检率↓78%!陌讯多模态融合算法实战解析
  • 【趣味解读】淘宝登录的前后端交互机制:Cookie-Session 如何保障你的账户安全?
  • 【网络编程】二、socket编程
  • 趣玩-Ollama-Llm-Chatrbot
  • 前端开发 React 状态优化
  • readelf -d a.out | vim - 和 readelf -d a.out | vim 有什么区别?
  • PyTorch武侠演义 第一卷:初入江湖 第5章:玉如意的秘密
  • gig-gitignore工具实战开发(一):项目愿景与蓝图规划
  • C Primer Plus 第6版 编程练习——第10章(上)
  • 漫画机器学习播客对话图文版
  • TGD第二篇:破局——去除导数计算中的无穷小极限
  • CodeBuddy IDE实战:用AI全栈能力快速搭建课程表网页
  • 【机器学习深度学习】比较 LLaMA-Factory、vLLM 和 LMDeploy 的量化导出:为何 LLaMA-Factory 不是首选?
  • 2025暑期—06神经网络-常见网络3
  • UWA DAY 2025 游戏开发者大会|全议程
  • Java UDP 通信详解:从基础到实战,彻底掌握无连接网络编程
  • Python进阶知识之pandas库(一)基础数据类型
  • 论文略读:REMEDY: RECIPE MERGING DYNAMICS IN LARGE VISION-LANGUAGE MODELS
  • 深入解析预训练语言模型在文本生成中的革命性应用:技术全景与未来挑战
  • 【Elasticsearch】跨集群检索(Cross-Cluster Search)
  • 18.设备虚拟化
  • Java 堆(优先级队列)
  • Linux基本指令:掌握系统操作的钥匙
  • Unity3D性能优化全攻略
  • 原创-基于 PHP 和 MySQL 的证书管理系统 第三版