使用jpeg图片库,显示图片并简单实现LCD的触屏功能
2024-05-14 23:43 由
Rice_rice 发表于
#操作系统
/**
* @date 2024/05/14
* CopyRight (c) 2023-2024 [email protected] All Right Reseverd
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> //open 函数三部曲
#include <unistd.h> //close read 等函数
#include <sys/mman.h> //映射功能
#include "jpeglib.h"
#include <linux/input.h>
int *lcd_mp;
int cnt = 0;
int x, y;
int read_JPEG_file(char *filename, int start_x, int start_y)
{
struct jpeg_decompress_struct cinfo; // 解压缩实例的主记录
struct jpeg_error_mgr jerr; // 错误处理程序对象
FILE *infile; // 建立源文件流
unsigned char *buffer; // 行缓存
int row_stride; // 缓冲区中的物理行宽
if ((infile = fopen(filename, "rb")) == NULL)
{
fprintf(stderr, "can't open %s\n", filename); // 如果不能打开文件,就输出错误信息并退出
return 0;
}
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo); // 初始化解码对象
jpeg_stdio_src(&cinfo, infile); // 指定源文件数据
jpeg_read_header(&cinfo, TRUE); // 读取头文件信息
jpeg_start_decompress(&cinfo); // 开始解码
row_stride = cinfo.output_width * cinfo.output_components; // 计算物理地址一行宽的大小
buffer = calloc(1, row_stride); // 申请一行的堆空间,用于循环解码
int data = 0;
while (cinfo.output_scanline < cinfo.output_height)
{
jpeg_read_scanlines(&cinfo, &buffer, 1); // 按每1行进行扫描,丛buffer进行读取
for (int i = 0; i < cinfo.output_width; ++i) // 012 345
{
data |= buffer[3 * i] << 16; // R
data |= buffer[3 * i + 1] << 8; // G
data |= buffer[3 * i + 2]; // B
lcd_mp[800 * start_y + start_x + 800 * (cinfo.output_scanline - 1) + i] = data; // 考虑了初始坐标后的数据处理
data = 0;
}
}
(void)jpeg_finish_decompress(&cinfo); // 完成解码
jpeg_destroy_decompress(&cinfo); // 释放内存
fclose(infile); // 关闭文件
return 1;
}
int main(int argc, char const *argv[])
{
// 1.打开LCD open
int lcd_fd = open("/dev/fb0", O_RDWR);
// 2.对LCD进行内存映射 mmap
lcd_mp = (int *)mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, lcd_fd, 0);
// 3.显示开机动画
char gif_path[128] = {0};
for (int i = 0; i < 112; ++i)
{
sprintf(gif_path, "./gif/Init%d.jpg", i); // 构造jpg图片的路径
read_JPEG_file(gif_path, 0, 0); // 在LCD设备上上显示
usleep(1000 * 5); // 设置每帧画面的间隔
}
// 4.打开触摸屏
int ts_fd = open("/dev/input/event0", O_RDWR);
// 5.读取输入设备的信息
struct input_event ts_event;
int logo = 1; // 设定 logo=1 初始界面;2 退出界面;3 登陆界面
read_JPEG_file("./pic/init.jpg", 0, 0);
while (1)
{
read(ts_fd, &ts_event, sizeof(ts_event));
// 6.分析读取的设备信息 (type + code + value)
if (ts_event.type == EV_ABS) // 说明是触摸屏
{
if (ts_event.code == ABS_X) // 说明是X轴
{
cnt++;
x = ts_event.value * 800 / 1024;
}
if (ts_event.code == ABS_Y) // 说明是Y轴
{
cnt++;
y = ts_event.value * 480 / 600;
}
if (logo = 1 && cnt >= 2 && x > 100 && x < 300 && y > 190 && y < 290) // 初始界面的登陆按钮
{
logo = 1;
cnt = 0;
}
else if (logo = 1 && cnt >= 2 && x > 500 && x < 700 && y > 190 && y < 290) // 初始界面的退出按钮
{
printf("Think you for supporting.\n");
sleep(2);
return 0;
}
else if (logo = 2 && cnt >= 2 && x > 650 && x < 750 && y > 30 && y < 80) // 登陆界面的返回按钮
{
logo = 2;
cnt = 0;
}
switch (logo)
{
case 1:
read_JPEG_file("./pic/login.jpg", 0, 0); // 登陆界面
break;
case 2:
read_JPEG_file("./pic/init.jpg", 0, 0); // 初始界面
break;
}
}
}
// 7.关闭设备
close(ts_fd);
close(lcd_fd);
return 0;
}
热门相关:江南 女人的呼吸 禁止性爱 外遇:善良的儿媳3 性感区