libjpeg解码 jpeg文件

举报
糖果罐子 发表于 2023/07/21 19:58:51 2023/07/21
【摘要】 Libjpeg 是一个广泛使用的 C 库,用于读取和写入 JPEG 图像文件。这篇文章主要讲解在 LCD 上,使用 Libjpeg 库显示图片,以及图片的缩放。@TOC 一、解压 libjpeg-turbo-1.2.1.tar.gz 库libjpeg-turbo-1.2.1.tar.gz库是以 .tar.gz 结尾的文件。解压到当前文件:tar -zxvf 压缩文件名.tar.g...

Libjpeg 是一个广泛使用的 C 库,用于读取和写入 JPEG 图像文件。
这篇文章主要讲解在 LCD 上,使用 Libjpeg 库显示图片,以及图片的缩放。

@TOC


一、解压 libjpeg-turbo-1.2.1.tar.gz 库

libjpeg-turbo-1.2.1.tar.gz库是以 .tar.gz 结尾的文件。

解压到当前文件:
tar -zxvf 压缩文件名.tar.gz

二、Libjpeg 的使用介绍

1. struct jpeg_decompress_struct 结构体:

用于定义一个结构体变量 cinfo 。该变量保存着 jpeg 数据的详细信息也保存着输出数据的详细信息。

/* 解压缩对象 */
struct jpeg_decompress_struct cinfo; 

2. struct jpeg_error_mgr 结构体:

该结构体定义的变量,用于处理 libjpeg 库解码 jpeg 数据时的错误处理。

/* 用于错误处理的结构体对象 */
struct jpeg_error_mgr jerr;

3.设置错误处理函数:

libjpeg 库解码 jpeg 数据时,可能出现内存不足导致错误,可以 ==调用默认错误处理函数继而会调用***exit*** 函数结束整个进程==。

当然,我们也可以==使用 libjpeg 提供的接口注册自定义错误处理函数==。


	/* 将错误处理结构对象绑定在JPEG对象上 */
    cinfo.err = jpeg_std_error(&jerr);
    
	//设置自定义错误处理函数 
	jerr.error_exit = my_error_exit;
	void my_error_exit(struct jpeg_decompress_struct *cinfo)
	{
	    /* ... */
	}
	

4.初始化解码对象(cinfo结构):

jpeg_create_decompress(&cinfo);

5.指定解压源文件:

	FILE * infile;
	
	/* 打开jpg 图像文件,argv[1] 是jpeg图片名 */
	if ((infile = fopen(argv[1], "rb")) == NULL) 
	 {
		return -1;
	}
	
	/* 指定源文件 */
	jpeg_stdio_src(&cinfo, infile);

6. 获取文件信息:

	/* 获得jpg信息 */
	jpeg_read_header(&cinfo, TRUE);

7.设置解压参数:

在开始解压缩之前可以进行解压缩参数的设定,也就是为cinfo结构的成员赋值。我们需要使用 cinfo.scale_numcinfo.scale_denom 这两个参数,来确定缩小比例。
可以设置 解压出来的图像的大小 与 原图 的比例,

例如:
cinfo. scale_num= 1;
cinfo. scale_denom = 2;
则解压出来的图片是原图的 1/2.

PEG 当前仅支持 1/1、 1/2、 1/4、 和 1/8 这几种缩小比例。 默认是 1/1,就是保持原图大小。

8.开始解压:

jpeg_start_decompress(&cinfo);

9.读取数据:

解码后的数据是 按行 取出的。数据像素按照scanline来存储,scanline 是从左到右,从上到下的顺序,每个像素对应的各颜色或灰度通道数据是依次存储。一个 scanline 中的数据存储模式是R,G,B,R,G,B,R,G,B**,…。

因为是 按行 读取数据,所以要 ==计算 每行数据 的空间大小==。我们定义一个缓冲区发 buffer 来存放数据。

(1) 计算 每行数据 的空间大小:

cinfo. output_components 为每个像素字节大小
cinfo. output_width 输出图像的宽度。
.

	unsigned char *buffer;
	int row_stride;
	
	// 一行的数据的空间大小
	row_stride = cinfo.output_width * cinfo.output_components;
	buffer = malloc(row_stride);

(2) 调用 jpeg_read_scanlines()来读取数据
jpeg_read_scanlines()可以指定一次读多少行,但是目前该函数还只能支持一次只读 1 行.

	// 循环调用jpeg_read_scanlines来一行一行地获得解压的数据
	while (cinfo.output_scanline < cinfo.output_height) 
	{
		(void) jpeg_read_scanlines(&cinfo, &buffer, 1);
	}

10.解压缩完毕

free(buffer); //释放 malloc 申请的空间
jpeg_finish_decompress(&cinfo);

11.释放解码对象:

jpeg_destroy_decompress(&cinfo);
fclose(infile); //关闭 jpg 图像文件

总结

libjpeg解码 jpeg文件 主要就是依靠上面几步。大家可以自己试试。

效果展示:

实验效果录制在 B站 :(有兴趣的可以看看实验效果)
https://www.bilibili.com/video/BV1zG4y1A7bT/?vd_source=986c364d205fa1124b337bc665f57c4f

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。