libjpeg-turbo使用教程

buildroot下libjpeg-turbo的使用

        libjpeg-turbo是一种JPEG图像编解码器的库,它使用SIMD指令(MMX、SSE2、AVX2、NEON、AltiVec)来加速x86、x86-64、ARM和PowerPC系统上的基线JPEG压缩和解压缩。libjpeg库使用的更广泛,不过它是使用纯c语言编写的,所以编解码速度慢。 libjpeg-turbo的速度通常是libjpeg的2-6倍。
        libjpeg-turbo支持rgba图像数据转jpeg,或者yuv格式的图像数据转jpeg。反之亦然。

主要功能

        libjpeg-turbo包含两种API,一种是libjpeg-turbo,另一种是libjpeg。当两种API都用于执行类似的操作时,这两种API没有显著的性能优势。具体的api使用方法可以参考 doc/index.html 网页的Modules下面的TurboJPEG链接的内容。
        libjpeg-turbo 使用起来更简单。
        libjpeg API 的存在是为了与API/ABI兼容,又与libjpeg v6b在数学上兼容。它还可以可选地配置为与libjpeg v7和v8兼容的API/ABI。

        libjpeg-turbo库提供的功能主要分为4类,包括编码,解码,格式转换,和读写bmp文件

  1. 编码
    将一个rgb图像编码为jpeg文件
    将一个yuv图像编码为jpeg文件
  2. 解码
    获取jpeg文件宽高,采样率,色彩空间等信息
    将一个jpeg文件解码为rgb图像
    将一个jpeg文件解码为yuv图像
  3. 格式转换
    rgb图像转为yuv图像
    yuv图像转rgb图像
  4. bmp
    读取一个bmp文件到内存
    将图像数据保存为bmp文件

编译库

  1. 查看cpu是否支持simd指令。
    通产cpu的数据手册会提示你有没有simd指令,如neon指令。也可以在linux板子上执行cat /proc/cpuinfo查看cpu信息。

  2. 检查buildroot是否已经配置了simd指令,如neon指令。
    检查buildroot的output文件夹下面的某个项目里的.config文件,里面是否有 BR2_ARM_CPU_HAS_NEON=y这个配置,没有的话,编译库的时候要加上。

  3. 可以参考BUILDING.md文件编译这个库。
            使用buildroot方式编译时,不需要参考这个md文件,只要在configs配置文件中添加 BR2_PACKAGE_JPEG=y 即可。这个配置包括两个配置选项,一个是jpeg库,另一个是jpegturbo库,所以,当cpu支持simd指令时,buildroot不会编译jpeg库,而是会编译jpegturbo库。编译完成后,会生成最重要的libturbojpeg.so文件和turbojpeg.h文件。

测试

        编译成功后,会产生一些可执行程序,将它们和生成的.so库文件一起拷到开发板上,便可开始测试。

  • tjexample
    主要用于把一个bmp文件转为jpeg,或者将一个jpeg文件转为bmp文件。
    bmp转jpeg:
    ./tjexample input.bmp output.jpg
    jpeg转bmp
    ./tjexample input.jpg output.bmp
  • tjbench
    测试编码或者解码性能
    测试编码性能:./tjbench cif.bmp 90    // 90为编码质量,范围为[1, 100]
    测试解码性能:./tjbench cif.jpg
            以下是rv1126_1109芯片所测的数据,测试的图片大小为1280x720,使用arm neon指令,4核Cortex-A7 1.5Ghz,测试时cpu大概占用25%。
    jpegturbo性能测试

示例

        以下代码会生成一个红色图片的jpg文件,保存在 /tmp/123.jpg 文件上。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <turbojpeg.h>

#define _throw(action, message) { \
  printf("ERROR in line %d while %s:\n%s\n", __LINE__, action, message); \
  retval = -1;  goto bailout; \
}
#define _throwtj(action)  _throw(action, tjGetErrorStr2(tjInstance))


void encode_jpeg_by_cpu(const void *input, int width, int height, int pixelFormat, void *output, unsigned long *size)
{
	int retval = 0;
	tjhandle tjInstance = NULL;	// 句柄
	unsigned char *jpegBuf = NULL;
	// pixelFormat = { TJPF_RGB, TJPF_BGR, TJPF_BGRX, TJPF_BGRX, TJPF_XRGB, TJPF_GRAY, TJPF_RGBA,
	// 				TJPF_BGRA, TJPF_ABGR, TJPF_ARGB, TJPF_CMYK, TJPF_UNKNOWN};

	*size = 0;
	if ((tjInstance = tjInitCompress()) == NULL)	// 创建一个TurboJPEG编码器实例
		_throwtj("initializing compressor");
	if (tjCompress2(tjInstance, (const unsigned char *)input, width, 0, height, pixelFormat,	// 将图像编码为jpeg文件
		&jpegBuf, size, TJSAMP_444, 90, 0) < 0)     // 编码质量为90,取值范围为[1,100],超过95会导致性能下降严重。
		_throwtj("compressing image");

	tjDestroy(tjInstance);  tjInstance = NULL;		// 销毁一个TurboJPEG编码器实例
	memcpy(output, jpegBuf, *size);
	tjFree(jpegBuf);	jpegBuf = NULL;

bailout:
	if (tjInstance) tjDestroy(tjInstance);
	if (jpegBuf) tjFree(jpegBuf);
}

int main(int argc, char *argv[])
{
	unsigned long size;
	int *red = malloc(640 * 480 * 4);
	int *jpeg = malloc(640 * 480 * 4);

	// 1. 生成红色图像
	for (int i = 0; i < 480; i++)
		for (int j = 0; j < 640; j++)
			red[i * 640 + j] = 0xffff0000;

	// 2.编码
	encode_jpeg_by_cpu(red, 640, 480, TJPF_BGRA, jpeg, &size);

	// 3.写入文件
	FILE *file = fopen("/tmp/123.jpg", "wb+");
	fwrite(jpeg, size, 1, file);
	fclose(file);
	printf("generate red picture to /tmp/123.jpg success!\n");
}

        将源文件保存为red.c,则编译命令为:arm-linux-gnueabihf-gcc red.c -o red -lturbojpeg,输出应用程序red。运行前需把red和libturbojpeg.so一起拷贝到开发板上。文章来源地址https://uudwc.com/A/VR6o

原文地址:https://blog.csdn.net/qq_20862815/article/details/126511384

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

上一篇 2023年06月15日 07:12
VHDL语言基础-数据类型及运算符
下一篇 2023年06月15日 07:12