/**
* @date 2024/05/14
* CopyRight (c) 2023-2024 ni456xinmie@163.com 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;
}