使用libjpeg解码库对JPEG文件进行解码,得到解码之后的RGB颜色分量,然后把解码之后的RGB颜色分量写入到LCD屏。
实际操作:
(1)下载需要移植的库的源码包,libjpeg库源码包在官网可以下载 www.ijg.org,如图所示
下载近5年左右版本

(2)解压
把下载好的源码包v9f.tar.gz发送到linux系统的家目录下进行解压,注意不可以在共享文件夹进行解压
tar -xzvf 文件名.tar.gz
(3)配置
./configure --host=arm-linux --prefix=/home/gec/workspace/libjpeg

(4)
配置成功之后,会得到一个makefile脚本文件,此时可以完成移植的第二步:编译,在命令行输入指令:make ,该指令会自动执行makefile
(5)编译通过之后,则可以完成libjpeg库的安装,此时在命令行输入指令: make install
(6)安装完成后,可以在指定的安装路径中找到生成的libjpeg库的头文件和库文件,此时就可以选择拷贝出来,就可以设计程序时使用

(7)库的使用
libjpeg.txt中包含了解码和编码流程,我们只讨论解码

example
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdlib.h>
#include "jpeglib.h"
#define LCD_PATH "/dev/fb0" // LCD设备路径
#define LCD_MEM 800*480*4 // LCD显存大小(800x480,每像素4字节)
/**
* 解码JPEG文件并直接绘制到LCD显存
* @param filename JPEG文件路径
* @param lcd_mp LCD显存映射地址
* @return 0成功, -1失败
*/
int read_JPEG_file(char *filename, unsigned int *lcd_mp)
{
struct jpeg_decompress_struct cinfo; // JPEG解压参数结构体
struct jpeg_error_mgr jerr; // JPEG错误处理结构体
FILE *infile; // 源文件指针
unsigned char *buffer; // 行缓冲区
int row_stride; // 行缓冲区字节宽度
// 以二进制只读方式打开JPEG文件
if ((infile = fopen(filename, "rb")) == NULL) {
fprintf(stderr, "无法打开 %s\n", filename);
return -1;
}
// 步骤1: 分配并初始化JPEG解压对象
cinfo.err = jpeg_std_error(&jerr); // 设置错误处理
jpeg_create_decompress(&cinfo); // 初始化解压对象
// 步骤2: 指定数据源(文件输入)
jpeg_stdio_src(&cinfo, infile);
// 步骤3: 读取JPEG文件头参数
jpeg_read_header(&cinfo, TRUE);
// 步骤4: 设置解压参数(此处使用默认参数)
// 步骤5: 启动解压,获取图像尺寸和颜色信息
jpeg_start_decompress(&cinfo);
// 根据图像实际参数分配行缓冲区
row_stride = cinfo.output_width * cinfo.output_components;
buffer = calloc(row_stride, 1);
// 步骤6: 逐行读取并解码扫描线
while (cinfo.output_scanline < cinfo.output_height) {
// 读取一行解码后的RGB数据
jpeg_read_scanlines(&cinfo, &buffer, 1);
// 将RGB888像素转换为32位颜色值,写入LCD显存
for (size_t x = 0; x < cinfo.output_width; x++) {
unsigned int data = (buffer[x*3+0] << 16) | // R
(buffer[x*3+1] << 8) | // G
buffer[x*3+2]; // B
*(lcd_mp + (cinfo.output_scanline - 1) * 800 + x) = data;
}
}
// 步骤7: 完成解压
jpeg_finish_decompress(&cinfo);
// 步骤8: 释放JPEG解压对象及所有资源
jpeg_destroy_decompress(&cinfo);
fclose(infile);
free(buffer);
return 0;
}
int main()
{
// 1. 打开LCD设备驱动
int lcd_fd = open(LCD_PATH, O_RDWR);
if (-1 == lcd_fd) {
perror("打开LCD设备失败\r\n");
return -1;
}
// 2. 内存映射LCD显存,提高刷新效率
unsigned int *lcd_mp = mmap(NULL, LCD_MEM, PROT_READ | PROT_WRITE,
MAP_SHARED, lcd_fd, 0);
// 3. 循环播放JPEG序列帧(模拟GIF动画)
for (size_t i = 0; i < 122; i++) {
char gifname[128] = {0};
sprintf(gifname, "./GIF/gif%d.jpg", i); // 构造帧文件路径
read_JPEG_file(gifname, lcd_mp); // 解码并显示当前帧
usleep(12 * 1000); // 延时30ms(约33FPS)
}
// 4. 关闭设备并解除映射
close(lcd_fd);
munmap(lcd_mp, LCD_MEM);
return 0;
}
浙公网安备 33010602011771号