上一篇文章分析了jpeg编解码的原理,发展了这么多年,也有了很完善的开源库,这里来记录一下libjpeg turbo库的使用
1.Introduction
libjpeg-turbo图像编解码器,使用了SIMD指令(MMX,SSE2,NEON,AltiVec)来加速x86,x86-64,ARM和PowerPC系统上的JPEG压缩和解压缩。在这样的系统上,libjpeg-turbo的速度通常是libjpeg的2-6倍,其他条件相同。在其他类型的系统上,凭借其高度优化的霍夫曼编码,libjpeg-turbo仍然可以大大超过libjpeg。在许多情况下,libjpeg-turbo的性能可与专有的高速JPEG编解码器相媲美。
2.Install
github下载代码,参考building进行编译
(1) sudo yum -y install nasm
安装nasm,NASM全称The Netwide Assembler,是一款基于80x86和x86-64平台的汇编语言编译程序,其设计初衷是为了实现编译器程序跨平台和模块化的特性
(2)安装libjpeg turbo
cd {build_directory}
cmake -G"Unix Makefiles" [additional CMake flags] {source_directory}
make
3.Test
sudo make test
4.Demo测试
编译生成的动态链接库在/opt/libjpeg-turbo/lib64目录,因此,使用下列命令设置共享库路径
export LD_LIBRARY_PATH=/opt/libjpeg-turbo/lib64:$LD_LIBRARY_PATH
tjexample.c是测试编解码的demo,这里面会先将jpg文件解码到YUV或者BGR,再将其编码成jpg文件,编译该生成可执行文件
gcc -L /opt/libjpeg-turbo/lib64 -lturbojpeg tjexample_test.c -o tjexample
5.测试2
上面的demo代码写的比较重,一般解码为BGRX或者YUV平面格式,我们提取这里面的关键代码,这里只做了解码:
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <math.h>
#include "turbojpeg.h"
const char *subsampName[TJ_NUMSAMP] = {
"4:4:4", "4:2:2", "4:2:0", "Grayscale", "4:4:0", "4:1:1"
};
const char *colorspaceName[TJ_NUMCS] = {
"RGB", "YCbCr", "GRAY", "CMYK", "YCCK"
};
int main(int argc, char **argv)
{
FILE *jpegFile = NULL;
unsigned long jpegSize;
int flags = 0;
int width, height;
unsigned char *imgBuf = NULL;
unsigned char *jpegBuf = NULL;
long size;
if ((jpegFile = fopen(argv[1], "rb")) == NULL)
{
printf("open input file failure\n");
}
if (fseek(jpegFile, 0, SEEK_END) < 0 || (size = ftell(jpegFile)) < 0 ||
fseek(jpegFile, 0, SEEK_SET) < 0)
{
printf("determining input file size failure\n");
}
if (size == 0)
{
printf("determining input file size, Input file contains no data\n");
}
jpegSize = (unsigned long)size;
if ((jpegBuf = (unsigned char *)malloc(jpegSize * sizeof(unsigned char))) == NULL)
{
printf("allocating JPEG buffer\n");
}
if (fread(jpegBuf, jpegSize, 1, jpegFile) < 1)
{
printf("reading input file");
}
fclose(jpegFile);
jpegFile = NULL;
tjhandle handle = NULL;
int subsample, colorspace;
int padding = 1;
int ret = 0;
handle = tjInitDecompress();
ret = tjDecompressHeader3(handle, jpegBuf, size, &width, &height, &subsample, &colorspace);
if(ret < 0)
{
printf("header file error, errorStr:%s, errorCode:%d\n", tjGetErrorStr(), tjGetErrorCode(handle));
return -1;
}
printf("input image: %d x %d, %s subsampling, %s colorspace\n", width, height, subsampName[subsample], colorspaceName[colorspace]);
int sw_out_size = width * height * 3; // We alloc the largest buf to support YUV444.
unsigned char *sw_out_buf = (unsigned char*)malloc(sw_out_size * sizeof(unsigned char));
if (sw_out_buf == NULL) {
printf("sw_out_buf is NULL\n");
}
flags |= 0;
//ret<-1表示解码异常,此时通过tjGetErrorCode查看错误码,错误码为0时,表示警告,错误码为-1时表示错误
int pixelFormat = TJPF_BGRX;
ret = tjDecompress2(handle, jpegBuf, size, sw_out_buf, width, 0, height, pixelFormat, flags);
//ret = tjDecompressToYUV2(handle, jpeg_buf, size, dst_buf, *width, padding, *height, flags);
if ((0 != tjGetErrorCode(handle)) && (ret < 0))
{
printf("error : decompress to yuv failed, errorStr:%s, errorCode:%d\n", tjGetErrorStr(), tjGetErrorCode(handle));
return -1;
}
if ((0 == tjGetErrorCode(handle)) && (ret < 0))
printf("warning : errorStr:%s, errorCode:%d\n", tjGetErrorStr(), tjGetErrorCode(handle));
tjDestroy(handle);
if (sw_out_buf)
{
free(sw_out_buf);
}
if (jpegBuf)
{
free(jpegBuf);
}
return 0;
}
gcc -L /opt/libjpeg-turbo/lib64 -lturbojpeg libjpeg_test.c -o libjpeg_test
./libjpeg_test …/jpegdecoder/4.jpg
出现上述warning的原因是jpeg文件头有些信息不正确,errorcode=0表示只是warning,解码器会继续解码,但显示的图像可能会有问题。
下面文章来讲讲icc信息和质量参数。