使用libjpeg-turbo压缩jpeg图片
libjpeg-turbo 是一个专门为 x86 和 x86-64 处理器优化的高速 libjpeg 的改进版本。上一篇文章讲了如何编译libjpeg-turbo 库,这篇文章主要演示如何使用 libjpeg-turbo 无损转换和压缩jpeg图片。
这篇文章使用的 libjpeg-turbo 版本是1.4,不同版本可能代码略有差异,请注意!
Losslessly transform a JPEG image
无损转换一个 JPEG 图像到另一个 JPEG 图像。无损转换通过移动 raw DCT 系数从一个 JPEG 图像结构到另一个图像,而不改变系数的值。
使用 libjpeg-turbo 无损转换图片的代码如下:
#include "turbojpeg.h"
// Create a new TurboJPEG transformer instance
tjhandle h = tjInitCompress();
if (h != nullptr)
{
// 读取jpeg图像
unsigned char *jpegBuf = nullptr;
unsigned long jpegSize = 0;
__readfile(&jpegBuf, jpegSize);
// 分配目的buffer
unsigned long dstSizes = 0;
unsigned char* dstBufs = nullptr; // dstBufs 为 nullptr, tjTransform()会自动内存
// tjtransform struct
tjtransform transform;
transform.op = TJXOP_NONE; // TJXOP_NONE TJXOP_ROT270;
transform.options = TJXOPT_TRIM;
transform.data = 0;
transform.customFilter = 0;
// 无损转换
int rel = tjTransform(h, jpegBuf, jpegSize, 1, &dstBufs, &dstSizes, &transform, TJFLAG_ACCURATEDCT);
if (rel != 0)
{
char* err = tjGetErrorStr();
}
// 保存图片
__writeFile(...)
// 释放dstBufs
if (dstSizes != 0)
tjFree(dstBufs);
// 释放jpegBuf
free(jpegBuf);
// Destroy a TurboJPEG transformer instance
tjDestroy(h);
}
压缩jpeg图片
相对于无损转换,压缩图片就要麻烦一些。开始本想要获取源文件图像尺寸和 RGB buffer,再使用 tjCompress2()
压缩,结果找了好久都没找到将 jpeg 图片转换为 RGB buffer 的接口和方法。最后只能通过tjDecompressToYUV2()
将 jpeg 图片转换为 YUV buffer,再通过 tjCompressFromYUV()
压缩图片。
使用 libjpeg-turbo 压缩 jpeg 图片的代码如下,其中 quality 参数是压缩比,对于 “jpeg” 格式 quality 的取值范围是0(low visual quality, high compression)到100((high visual quality, low compression)。
#include "turbojpeg.h"
// Create a TurboJPEG compressor instance
tjhandle h = tjInitCompress();
if (h != nullptr)
{
// 读取jpeg图像
unsigned char *jpegBuf = nullptr;
unsigned long jpegSize = 0;
__readfile(&jpegBuf, jpegSize);
int _width = 0;
int _height = 0;
int jpegSubsamp;
int jpegColorspace;
int pad = 2;
unsigned char* rgbbuf = nullptr;
// 获取jpeg文件信息
tjhandle dh = tjInitDecompress();
int rel = tjDecompressHeader3(dh, jpegBuf, jpegSize, &_width, &_height, &jpegSubsamp, &jpegColorspace);
// 计算YUV buffer大小
unsigned long yuvBufSize = tjBufSizeYUV2(_width, pad, _height, jpegSubsamp);
rgbbuf = tjAlloc(yuvBufSize);
// 获取YUV buffer
rel = tjDecompressToYUV2(dh, jpegBuf, jpegSize, rgbbuf, _width, pad, _height, 0);
if (rel != 0)
{
char* err = tjGetErrorStr();
}
rel = tjDestroy(dh);
// 分配目的buffer
unsigned long dstSizes = 0;
unsigned char* dstBufs = 0;
const int quality = 75;
// 压缩
rel = tjCompressFromYUV(h, rgbbuf, _width, pad, _height, jpegSubsamp, &dstBufs, &dstSizes, quality, 0);
// 保存图片
__writeFile(...)
// 释放buffer
if (dstSizes != 0)
tjFree(dstBufs);
tjFree(rgbbuf);
free(jpegBuf);
// Destroy a TurboJPEG compressor instance
tjDestroy(h);
}
压缩bmp格式的图像
对于 bmp 格式的图像,可以在 libjpeg-turbo 源码中找到 “bmp.h” 和 “bmp.c” 并在项目中包含它们,使用loadbmp()
函数读取 RGB buffer 即可。
使用QImageWriter压缩图片
对于 Qt 程序,可以使用 QImageWriter
压缩图片。QImageWriter
支持“BMP”、“JPG”、“PNG”等主流图像格式的压缩,使用起来非常简单。
QImage image("C:/Users/Administrator/Desktop/s.jpg"); // 源文件
QImageWriter imageWriter(QString("C:/Users/Administrator/Desktop/s1.jpg")); // 目的文件
// 设置压缩质量
imageWriter.setQuality(75);
qDebug() << imageWriter.write(image);
参考链接:
http://sourceforge.net/p/libjpeg-turbo/feature-requests/21/
http://stackoverflow.com/questions/9094691/examples-or-tutorials-of-using-libjpeg-turbos-turbojpeg
http://stackoverflow.com/questions/5616216/need-help-in-reading-jpeg-file-using-libjpeg