百问FB显示开发图像处理 - JPEG图像处理

2.2 JPEG图像处理

2.2.1 JPEG文件格式和libjpeg编译

​ JPEG的后缀名为.jpg的图像文件。对于图像内容和信息相同的JPEG文件和BMP文件,JPEG格式的文件要比BMP格式的文件小得多,这是因为JPEG文件是经过JPEG压缩算法后得到的一种文件格式。

​ 相对于BMP格式的文件,JPEG由于压缩算法的关系,其文件解析较为复杂,我们可以利用Linux系统开源的优点,使用开源工具对jpeg文件进行格式的解析和转换。

​ 我们可以使用libjpeg库来对jpeg文件进行格式的解析和转换。libjpeg支持X86,ARM等架构。libjpeg是开源工具,所以可以在网上免费下载。

​ 在使用libjpeg之前,我们先要交叉编译libjpeg的库文件和头文件并存到开发板的文件系统中。以下是libjpeg的编译过程:

  1. 解压并进入文件目录
c 复制代码
tar xzf libjpeg-turbo-1.2.1.tar.gz
cd libjpeg-turbo-1.2.1/
  1. 交叉编译
c 复制代码
tar xzf libjpeg-turbo-1.2.1.tar.gz
./configure --prefix=/work/projects/libjpeg-turbo-1.2.1/tmp/ --host=arm-linux
make
make install
  1. 将编译出来的头文件和库文件拷贝到交叉编译器的相应目录下
c 复制代码
cd /work/projects/libjpeg-turbo-1.2.1/tmp/include
cp * /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include
cd /work/projects/libjpeg-turbo-1.2.1/tmp/lib
cp *so* -d /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib
  1. 将编译出来的头文件和库文件拷贝到开发板文件系统的相应目录下
c 复制代码
cd /work/projects/libjpeg-turbo-1.2.1/tmp/lib
cp *.so* /work/nfs_root/fs_mini_mdev_new/lib/ -d

2.2.2 libjpeg接口函数的解析和使用

libjpeg的使用方法可以参考解压包中的使用说明libjpeg.txt和例程example.c。libjpeg的使用步骤简单总结如下:

1. 分配和初始化一个jpeg_compress_struct结构体

c 复制代码
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);

2. 指定源文件

c 复制代码
jpeg_stdio_src(&cinfo, infile);

参数1是步骤1中分配的jpeg_compress_struct类型的结构体

参数2是要解析的JPEG文件的文件句柄。

3. 获得jpg信息头并设置解压参数

c 复制代码
jpeg_read_header(&cinfo, TRUE);

当调用完这个参数之后,我们就可以通过cinfo中的image_width,image_height等成员来获得图像的信息了。此外我们还可以设置cinfo中的scale_num和scale_denom等成员变量来设置解压参数。

4. 启动解压

c 复制代码
jpeg_start_decompress(&cinfo);

调用这个函数后,就可以对cinfo所指定的源文件进行解压,并将解压后的数据存到cinfo结构体的成员变量中。

5. 读取解压后数据

c 复制代码
jpeg_read_scanlines(&cinfo, buffer, 1);

调用这个函数后,可以读取RGB数据到buffer中,参数3能指定读取多少行

6. 完成读取

c 复制代码
jpeg_finish_decompress(&cinfo);

7. 释放jpeg_compress_struct结构体

c 复制代码
jpeg_destroy_decompress(&cinfo);

完成读取后释放结构体

2.2.3 使用libjpeg把JPEG文件解析为RGB格式,在LCD上显示

根据上节的解析,利用上述的库函数将JPEG文件解析为RGB格式了。

c 复制代码
代码清单2.2
1.	/********************************************************************** 
2.	 * 函数名称: IsJpg 
3.	 * 功能描述:判断是否为Jpg文件 
4.	 * 输入参数: ptData - 内含图像信息 
5.	                    strFileName - 文件名 
6.	 * 返 回 值:0 - 不是JPG格式 其他-是JPG格式 
7.	 ***********************************************************************/  
8.	static int IsJpg(PT_PictureData ptData, const char *strFileName)   
9.	{  
10.	    int iRet;  
11.	  
12.	    jpeg_stdio_src(&ptData->tInfo, ptData->ptFp);  
13.	  
14.	    /* 用jpeg_read_header获得jpeg信息*/  
15.	    iRet = jpeg_read_header(&ptData->tInfo, TRUE);  
16.	      
17.	        return (iRet == JPEG_HEADER_OK);  
18.	}  
19.	  
20.	/********************************************************************** 
21.	 * 函数名称: DecodeJpg2Rgb 
22.	 * 功能描述:把JPG文件解析为RGB888格式 
23.	 * 输入参数: ptData - 内含文件信息 
24.	 *                             strFileName - 文件名 
25.	 * 输出参数:PT_PictureData->pucRgbData - 内含rgb数据 
26.	 * 返 回 值:0 - 成功 其他-失败 
27.	 ***********************************************************************/  
28.	static int DecodeJpg2Rgb(const char *strFileName, PT_PictureData ptData){  
29.	    int iRowSize;  
30.	    unsigned char *pucbuffer;  
31.	    unsigned char *pucHelp;//辅助拷贝变量  
32.	      
33.	    /* 1.分配和初始化一个jpeg_compress_struct结构体 */  
34.	    ptData->tInfo.err = jpeg_std_error(&ptData->tJerr);  
35.	    jpeg_create_decompress(&ptData->tInfo);  
36.	  
37.	  
38.	    /* 2.指定源文件*/  
39.	    if ((ptData->ptFp= fopen(strFileName, "rb")) == NULL) {  
40.	        fprintf(stderr, "can't open %s\n", strFileName);  
41.	        return -1;  
42.	    }  
43.	  
44.	    /* 3.获得jpg信息头并设置解压参数并判断是否为JPEG格式文件 */  
45.	    if (!IsJpg(ptData, strFileName)) {  
46.	    printf("file is not jpg ...\n");  
47.	    return -1;  
48.	    }   
49.	  
50.	      
51.	  
52.	    /* 默认尺寸为原尺寸 */  
53.	    ptData->tInfo.scale_num = 1;  
54.	    ptData->tInfo.scale_denom = 1;  
55.	    /* 4. 启动解压:jpeg_start_decompress */   
56.	    jpeg_start_decompress(&ptData->tInfo);  
57.	  
58.	  
59.	    /* 解压完成后可以通过tInfo中的成员获得图像的某些信息 */  
60.	    ptData->iWidth= ptData->tInfo.output_width;  
61.	    ptData->iHeight = ptData->tInfo.output_height;  
62.	    ptData->iBpp = ptData->tInfo.output_components*8;  
63.	    /* 计算一行的数据长度 */   
64.	    iRowSize = ptData->iWidth * ptData->tInfo.output_components;  
65.	    pucbuffer = malloc(iRowSize);  
66.	    ptData->iRgbSize= iRowSize * ptData->iHeight;  
67.	    ptData->pucRgbData = malloc(ptData->iRgbSize);  
68.	  
69.	    /* pucHelp指向ptData->pucRgbData首地址 */  
70.	    pucHelp = ptData->pucRgbData;  
71.	    /*  5.循环调用jpeg_read_scanlines来一行一行地获得解压的数据 */  
72.	    while (ptData->tInfo.output_scanline < ptData->tInfo.output_height)   
73.	    {  
74.	        /* 调用jpeg_read_scanlines得到的时候会存到pucbuffer中 */  
75.	        jpeg_read_scanlines(&ptData->tInfo, &pucbuffer, 1);  
76.	        /* 将数据一行行读到缓冲区中 */  
77.	        memcpy(pucHelp,pucbuffer,iRowSize);  
78.	        pucHelp  += iRowSize;  
79.	    }  
80.	    free(pucbuffer);  
81.	    /* 6.完成读取 */  
82.	    jpeg_finish_decompress(&ptData->tInfo);  
83.	    /* 7.释放jpeg_compress_struct结构体 */  
84.	    jpeg_destroy_decompress(&ptData->tInfo);  
85.	    return 0;  
86.	}  
相关推荐
文心快码BaiduComate44 分钟前
百度云与光本位签署战略合作:用AI Agent 重构芯片研发流程
前端·人工智能·架构
风象南1 小时前
Claude Code这个隐藏技能,让我告别PPT焦虑
人工智能·后端
Mintopia2 小时前
OpenClaw 对软件行业产生的影响
人工智能
陈广亮3 小时前
构建具有长期记忆的 AI Agent:从设计模式到生产实践
人工智能
会写代码的柯基犬3 小时前
DeepSeek vs Kimi vs Qwen —— AI 生成俄罗斯方块代码效果横评
人工智能·llm
Mintopia3 小时前
OpenClaw 是什么?为什么节后热度如此之高?
人工智能
爱可生开源社区4 小时前
DBA 的未来?八位行业先锋的年度圆桌讨论
人工智能·dba
叁两6 小时前
用opencode打造全自动公众号写作流水线,AI 代笔太香了!
前端·人工智能·agent
前端付豪6 小时前
LangChain记忆:通过Memory记住上次的对话细节
人工智能·python·langchain