JPEG图片解码能力——STM32F769I 图像处理能力评测之三

硬件平台:STM32F769IDISCOVERY

软件开发平台:Keil 5.1

测试方法:

1.采用SD卡,并把测试的图片存放到根目录中。SD卡的容量为8G,Class 4。选用3种色彩丰富程度差别较大的图片,并把每种图片裁剪成800X480、480X320、320X240大小,作为基准测试图片。

2.配置系统时钟为200MHZ,SD卡时钟为25MHZ,SDRAM的时钟为100MHZ,使用FATFS文件系统。关闭LCD层0的显示,开启LCD层1的显示,使用RGB888显示。

3.选用STM32自带的JPEG硬件编解码器、TjpgDEC解码库和LIBJPEG解码库,分别对图片进行测试,比较三者的解码能力。

LIBJPEG解码库简介:

ibjpeg是一个完全用C语言编写的库,包含了被广泛使用的JPEG解码、JPEG编码和其他的JPEG功能的实现。目前最新的版本为9b。官网地址: http://www.ijg.org/。libjpeg具有稳定、兼容性强和解码速度较快等优点,但是使用这个库文件进行JPEG解码,消耗内存较大,对于内存不足的处理器来说,是一个很大的负担。在我们下载的STM32CUBEF7资源包里就有LIBJPEG库文件,因此不用去下载。库文件的存放路径如下图所示:

直接将整个文件夹复制到工程文件夹,然后添加文件,修改相应的配置参数即可使用。

TjpgDEC解码库简介:

TJpgDec是一个通用的JPEG图像解压缩器模块,针对小型嵌入式系统进行了高度优化。它使用非常低的内存消耗,使其可以被并入微小的微控制器,如AVR,8051,PIC,Z80,Cortex-M0等。支持输出RGB888or RGB565,支持图片缩放。官网地址:http://elm-chan.org/fsw/tjpgd/00index.html。目前版本为R0.01B,作者基本上没有进行更新。

JPEG硬件编解码器简介:

这个是STM32自带的硬件解码器,目前只存在于STM32F7X7、 STM32F7X8和STM32F7X9这几个系列产品中。它提供了一个快速和简单的硬件压缩器和解压缩器。JPEG编解码器可以解码ISO / IEC 10918-1规范中定义的JPEG流,它可以选择性地解析JPEG头,并相应地更新JPEG编解码器寄存器的量化表和霍夫曼表。

JPEG编解码块主要特性:

1.支持8位通道像素采样

2.对每个像素数据进行编解码只需一个时钟周期

3.支持JPEG图片头信息生成和解析,可以使能/禁止对JPEG图片头信息处理。

4.拥有四个可编程量化表和完全可编程的霍夫曼表。

5. 完全可编程的最小编码单元。

6.支持编码/解码。

7.数据传送支持DMA、中断和轮询。

JPEG编解码器框图如下所示:

从图中可以看出,JPEG编解码器拥有两个FIFO,一个为输入一个为输出,并且支持FIFO阈值中断。可以通过检测FIFO阈值中断是否产生,及时将数据送进FIFO或者从FIFO读出数据,从而使JPEG编解码操作维持连续性,使JPEG编解码器的性能得到最大的发挥。其中有一点需要注意,解码器输出的数据不是RGB数据,不能直接往LCD里送数据,需要进行数据转换算法,换算成RGB数据(就是这个问题,整整折腾了我一天的时间)。

下面是我选用的测试图片,按照图片色彩丰富程度从高到低进行排列:

好了,现在我们开始进行测试。为了保证测试的一致性,我们选用同一块开发板,并使系统运行时的工作参数保持相同。解码时间的计算以毫秒为单位,配置系统滴答定时器每隔1ms产生中断,提供时间计数。当图片文件打开后,开始时间计数,到LCD显示图片完成后,停止时间计数。计算二者的时间差,就是图片的解码时间。

JPEG硬件解码器分别使用DMA、IT和轮询的方式对图片进行解码。同时对TjpgdDEC和LIBJPEG进行优化处理,使解码时间尽量最短,因为我们比较的是三种解码方式工作在最优模式下的解码速度(个人能力有限,已经尽最大努力优化TjpgDEC和LIBJPEG,以下的时间数据仅供参考。)。经过三天的移植和测试,最后的测试数据如下图所示:

图片像素800X480

图片质量

硬件JPEG 中断方式

硬件JPEG DMA方式

硬件JPEG轮询方式

TjpgDEC解码

LIBJPEG解码

89ms

62ms

87ms

238ms

148ms

151ms

121ms

148ms

316ms

213ms

189ms

158ms

185ms

413ms

271ms

图片像素480X320

图片质量

硬件JPEG 中断方式

硬件JPEG DMA方式

硬件JPEG轮询方式

TjpgDEC解码

LIBJPEG解码

39ms

28ms

37ms

102ms

64ms

80ms

69ms

78ms

151ms

107ms

97ms

85ms

95ms

196ms

133ms

图片像素320X240

图片质量

硬件JPEG 中断方式

硬件JPEG DMA方式

硬件JPEG轮询方式

TjpgDEC解码

LIBJPEG解码

21ms

15ms

20ms

55ms

34ms

54ms

48ms

54ms

93ms

70ms

63ms

57ms

62ms

116ms

82ms

从上述三张数据表中可以看出,使用DMA方式的JPEG硬件解码速度是最快的,而采用TjpgDEC库解码是速度最慢的。其中中断方式的JPEG硬件解码要和使用轮询方式的JPEG硬件解码二者的速度差不多,都比TjpgDEC解码和LIBJPEG解码来的快。但是使用轮询方式的JPEG硬件解码会占用整个CPU,不如中断来的灵活。当解码的图片越来越小时,LIBJPEG解码和JPEG硬件解码在速度上不会差太多.因此,当解码较大的图片时,JPEG硬件解码的优势就发挥出来了。

最后奉上几张800X600的图片在开发板上的显示:

关于JPEG硬件编解码器使用的一些注意:

1.添加固件库文件stm32f7xx_hal_jpeg.c和stm32f7xx_hal_jpeg.h到项目工程。同时添加jpeg_utils.c、jpeg_utils.h和jpeg_utils_conf_template.h到项目工程,这三个是编解码数据格式转换相关的文件。

2.打开jpeg_utils_conf_template.h文件,修改第51行和52行的内容如下图所示:

修改第72行和73行的内容,如果使用解码器,将73行的内容修改为:#define USE_JPEG_ENCODER    0;如果使用编码器,将72行的内容修改为:#defineUSE_JPEG_DECODER     0。然后修改第75行的内容,这个是配置像素数据转换完成后的格式,根据屏幕像素的格式修改相应的值,比如我这里是RGB888,因此修改为:#define JPEG_RGB_FORMAT      JPEG_RGB888。最后修改第76行的内容,这个是配置是否需要交换RB,如果使能,那么经过转换后,像素的格式为BGR888。我这里不需要这个功能,设置为:#defineJPEG_SWAP_RB         0。

保存并关闭文件,将文件名修改为jpeg_utils_conf.h。

3. 打开stm32f7xx_hal_conf.h文件,修改第96行如下图所示:

4.进行初始化,包括使能JPEG模组时钟,使能DMA2模组时钟,调用初始化函数对JPEG进行初始化,配置JPEG中断和DMA2中断。最后不要忘了,如果是进行解码操作,一定要调用JPEG_InitColorTables函数,初始化JPEG查找表。这个函数只能在初始化的时候调用,并且只能调用一次,后面不允许掉用,无论你有多少张JPEG图片要解码,都只在初始化的时候调用一次就够了。

5.使用轮询方式解码图片时,会完全占用CPU,直到解码完成后者解码出错才会退出。采用DMA和中断,不会一直占用CPU。解码过程中会回调以下个函数:

HAL_JPEG_InfoReadyCallback:指示JPEG头解析完成,可以查看图片的宽度和高度,以及像素数据的组成方式。在这一步中通常调用JPEG_GetDecodeColorConvertFunc函数来设定转换完成后,数据格式转换的函数。

HAL_JPEG_GetDataCallback:这个是请求数据输入的函数。参数NbDecodedData是指示解码器需要采集数据的字节数。

HAL_JPEG_DataReadyCallback:解码器数据转换好的通知函数。注意如果是一次性将JPEG图片数据传送到解码器,那么这里出来的是全部的解码数据,否则为部分解码数据。参数pDataOut为数据存放区,参数OutDataLength为输出数据的字节数量。通常在里调用函数进行数据转换操作。

HAL_JPEG_DecodeCpltCallback:编解码完成的指示函数。

HAL_JPEG_ErrorCallback:编解码错误的指示函数。

关于我编写程序的使用注意事项:

1.我已经将TjpgDEC和LIBJPEG都移植到工程项目中,编译完成后只会选用一种方式解码图片。要用其他的方式解码图片,需修改JpegDecode.h文件,如下图所示:

2.硬件JPEG、TjpgDEC和LIBJPEG的解码函数都存放在JpegDecode.c中。并且测试图片要存在放在SD卡的根目录中。

(0)

相关推荐