Linux系统JPG解码及应用

使用libjpeg解码库对JPEG文件进行解码,得到解码之后的RGB颜色分量,然后把解码之后的RGB颜色分量写入到LCD屏。

实际操作:

(1)下载需要移植的库的源码包,libjpeg库源码包在官网可以下载 www.ijg.org,如图所示a

下载近5年左右版本

(2)解压

把下载好的源码包v9f.tar.gz发送到linux系统的家目录下进行解压,注意不可以在共享文件夹进行解压

tar -xzvf 文件名.tar.gz

(3)配置

./configure --host=arm-linux --prefix=/home/gec/workspace/libjpeg

c

(4)

配置成功之后,会得到一个makefile脚本文件,此时可以完成移植的第二步:编译,在命令行输入指令:make ,该指令会自动执行makefile

(5)编译通过之后,则可以完成libjpeg库的安装,此时在命令行输入指令:  make   install

(6)安装完成后,可以在指定的安装路径中找到生成的libjpeg库的头文件和库文件,此时就可以选择拷贝出来,就可以设计程序时使用

d

(7)库的使用

    libjpeg.txt中包含了解码和编码流程,我们只讨论解码

e

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;
}

 

posted on 2026-07-16 19:02  撒与日  阅读(5)  评论(0)    收藏  举报