【Linux下6818开发板(ARM)】在液晶屏上显示RGB颜色和BMP图片

  • (꒪ꇴ꒪ ),hello我是祐言
  • 博客主页:C语言基础,Linux基础,软件配置领域博主🌍
  • 快上🚘,一起学习!
  • 送给读者的一句鸡汤🤔:
  • 集中起来的意志可以击穿顽石!
  • 作者水平很有限,如果发现错误,可在评论区指正,感谢🙏

在嵌入式系统的开发中,我们经常需要在液晶屏上显示一些信息,如文本、图片等。在本篇文章中,我将解析两个C语言的例程,这些例程分别用于在液晶屏上显示不同的RGB颜色和显示BMP图片。

一、在液晶屏上显示RGB颜色

RGB颜色想必大家都懂吧,简单介绍一下:

RGB是一种用于表示颜色的色彩模型,它是英文单词"Red(红色)"、"Green(绿色)"和"Blue(蓝色)"的缩写。在RGB色彩模型中,每种颜色由红色、绿色和蓝色三个分量的不同强度组成,通过调整这三个分量的数值,可以得到各种不同的颜色。

在RGB色彩模型中,每个颜色分量的取值范围通常是0到255。数值为0表示没有该颜色分量,而数值为255表示该颜色分量的最大强度。因此,RGB颜色可以用一个三元组(R, G, B)来表示,其中R表示红色分量的强度,G表示绿色分量的强度,B表示蓝色分量的强度。

例如,纯红色的RGB颜色表示为(255, 0, 0) ,即红色分量为最大强度,而绿色和蓝色分量均为0。类似地,纯绿色的RGB颜色表示为(0, 255, 0)纯蓝色的RGB颜色表示为(0, 0, 255) ,我们通常在编程中用0x00ff0000的十六进制表示红色。

通过调整RGB颜色的三个分量的数值,可以得到各种不同的颜色,包括所有可见的颜色。由于RGB色彩模型在计算机图形和显示技术中得到广泛应用,所以它是最常用的色彩模型之一。

下面来看一下综合例程:

复制代码
//在屏幕上交替的显示红绿蓝三色
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <errno.h>		
#include <time.h>		
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <linux/fb.h>		//帧缓冲设备的结构体定义在这个里面

#define LCDDEV		"/dev/fb0"			
#define LCDSIZE  800*480*4

struct color {
    unsigned int red;
    unsigned int green;
    unsigned int blue;
};
	
void input_color(int *lcd_buf, int color)
{
	int x, y;
	for ( y=0; y<480; y++)
	{
		for(x=0; x<800; x++)
		{
			lcd_buf[y*800 + x] = color;	
		}
	}
}

void output_color(int color)
{
	// 1. 打开液晶屏设备
	int lcd_fd = open(LCDDEV, O_RDWR);
	if(lcd_fd == -1)
	{
		perror("open lcd fail");
		exit(errno);
	}
	
	// 给液晶屏文件映射一块内存
	// void *mmap(void *addr, size_t len, int prot, int flags,int fildes, off_t off); 
	int *fb = mmap(NULL, LCDSIZE, PROT_READ|PROT_WRITE, MAP_SHARED, lcd_fd, 0);
	if(fb == MAP_FAILED)
	{
		perror("mmap fail");
		exit(errno);
	}
	
	int lcd_buf[800*480] ={0}; 
	
	input_color(lcd_buf,color);
	
	memcpy(fb,lcd_buf,LCDSIZE);
	
	
	// 3. 关闭液晶屏
	munmap(fb, LCDSIZE);
	close(lcd_fd);

}				
int main(int argc, char *argv[])
{

    // 2. 初始化颜色值
    struct color rgb = { .red = 0x00ff0000, .green = 0x0000ff00, .blue = 0x000000ff };
	
	
	while(1)
	{
		output_color(rgb.red);
		sleep(1);
		output_color(rgb.green);
		sleep(1);
		output_color(rgb.blue);
		sleep(1);
		
	}
	
	return 0;
}

这个代码的主要思路是,首先定义一个颜色结构体,然后创建一个颜色缓冲区,将颜色数据填充到缓冲区中,最后将缓冲区的内容写入到液晶屏设备中。

在代码中,我们首先定义了一个颜色结构体struct color ,它包含了3个成员:红色、绿色和蓝色。然后,我们定义了一个**input_color函数** ,该函数的主要作用是将颜色数据填充到颜色缓冲区中。output_color函数则负责将颜色缓冲区的内容写入到液晶屏设备中。

在**main函数**中,我们首先初始化了颜色的值,然后在一个无限循环中,不断的将红色、绿色和蓝色的颜色信息写入到液晶屏设备中,每次写入后暂停1秒。

二、在液晶屏上显示BMP图片

这个操作就像把大象放进冰箱需要几步这个问题一样,第一步打开液晶屏,第二步导入bmp格式的图片,第三步关闭液晶屏,顺着这个思路我们很快就能写出如下程序,当然细节处怎么做到还需自己研究一下哦,其实很简单,主要用到了像素转换的思想

像素转换代码:color = bmp_buf[k] | bmp_buf[k+1]<<8 | bmp_buf[k+2]<<16;

  • 在这个循环中,我们使用ij变量遍历每个像素点的行和列,同时使用k变量来遍历bmp_buf缓冲区,处理每个像素的BGR颜色数据。
  • 由于BMP图像是BGR顺序存储的,我们通过位运算将3个字节的颜色数据合成为一个32位的像素颜色值。
  • 位运算操作的目的是将BGR颜色数据拼接成一个32位整数的颜色值,其中高8位为0(alpha通道,不透明度),接下来8位为红色值,再接下来8位为绿色值,最低8位为蓝色值。

另外还需搞清楚,BMP图片的像素数据是从左到右,从下到上存储的,而液晶屏的读取是从左往右,从上往下,刚好是上下颠倒。

复制代码
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <errno.h>		
#include <time.h>		
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <linux/fb.h>		//帧缓冲设备的结构体定义在这个里面

#define LCDDEV		"/dev/fb0"			
	
void show_bmp(char *name)
{
	// 1. 打开液晶屏设备
	int lcd_fd = open(LCDDEV, O_RDWR);
	if(lcd_fd == -1)
	{
		perror("open lcd fail");
		exit(errno);
	}

	int bmp_fd = open(name, O_RDONLY);
	if(bmp_fd == -1)
	{
		perror("open bmp fail");
		exit(errno);
	}
	
	// 给液晶屏文件映射一块内存
	// void *mmap(void *addr, size_t len, int prot, int flags,int fildes, off_t off);
           // 
	int *fb = mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE, MAP_SHARED, lcd_fd, 0);
	if(fb == MAP_FAILED)
	{
		perror("mmap fail");
		exit(errno);
	}

	// 先跳过54字节的文件头和信息头
	lseek(bmp_fd, 54, SEEK_SET);
	
	// 读取位图数据(图像的BGR颜色数据))
	char bmp_buf[800*480*3] = {0};
	read(bmp_fd, bmp_buf, 800*480*3);
	
	int i, j, k = 0;
	int color = 0;
	
	//液晶屏的扫描方式是:从上到下,从左到右
	//而bmp图像数据的存储方式是:从左到右,从下到上
	//所以要反着写入,就能解决翻转问题
	for (i = 479; i >= 0; i--) {
		for (j = 0; j < 800; j++) {
			color = bmp_buf[k] | bmp_buf[k + 1] << 8 | bmp_buf[k + 2] << 16;// 像素转换
			k += 3;
			fb[i * 800 + j] = color;// 写入液晶屏
		}
	}

	
	munmap(fb, 800*480*4);
	close(bmp_fd);
	// 3. 关闭液晶屏
	close(lcd_fd);
	
}

	
		
int main(int argc, char *argv[])
{
		
	if (argc != 2) {
        printf("Usage: %s <picture> \n", argv[0]);
        return 1;
    }

	show_bmp(argv[1]);
	return 0;
}

例程的主要思路是,首先打开BMP图片文件和液晶屏设备,然后读取BMP图片的像素数据,将这些像素数据写入到液晶屏的缓冲区中,最后将缓冲区的内容写入到液晶屏设备中。

在代码中,我们首先打开了液晶屏设备和BMP图片文件,然后创建了一个映射,这个映射将液晶屏设备的内存映射到了进程的地址空间。接着,我们从BMP图片文件中读取像素数据,将这些数据写入到液晶屏的缓冲区中。最后,我们将缓冲区的内容写入到液晶屏设备中。

三、运行

有了代码那怎么运行呢,其实之前的博客里也教过,但是还是凑点字数,多说说,只要需要用rz -y命令把可执行文件传给开发板就行。

什么?又不会编译了,看这里:

传统就是arm-linux-gcc ,那么快捷方法就是用alias命令把它变成一个快捷指令ag。

四、总结

通过这两个例程,我们可以看到在C语言中如何操作液晶屏设备,如何将颜色和图片显示到液晶屏上。这些例程提供了一个很好的起点,让我们能够理解如何在嵌入式系统中进行液晶屏的编程。希望这个文章能对你有所帮助,如果你有任何问题,欢迎在评论区留言。

更多C语言和Linux系统相关文章,关注专栏:

手撕C语言

玩转linux

📢写在最后

  • 今天的分享就到这啦~
  • 觉得博主写的还不错的烦劳 一键三连喔~
  • 🎉感谢关注🎉
相关推荐
AOwhisky10 小时前
MySQL 学习笔记(第一期):数据库基础与 MySQL 初探
运维·数据库·笔记·学习·mysql·云计算
Peace10 小时前
【Prometheus】
linux·运维·prometheus
LZZ and MYY11 小时前
RTS 在windows和Linux之间ShareMem
linux·运维·服务器
aningx11 小时前
openSUSE Leap 16.0 运行 sunshine 报错的解决方法
linux
爱学习的徐徐11 小时前
Linux 基础IO
linux·服务器
蛋蛋的学习记录11 小时前
C#窗体应用中使用EasyModbusCore通讯
服务器·c#·tcp
zt1985q11 小时前
本地部署源代码管理解决方案 Bitbucket Data Center 并实现外部访问
运维·服务器·数据库·网络协议·postgresql·源代码管理
xiaobobo333011 小时前
面向对象:linux内核中函数转数据的用法
linux·面向对象·隔离·函数指针绑定
极客先躯11 小时前
高级java每日一道面试题-2026年01月18日-实战篇[Docker]-如何清理仓库中的旧镜像?
java·运维·docker·容器
姓刘的哦11 小时前
C++软件架构设计思路
linux