Qt实现图片的简单压缩

在编程过程中,涉及到网络传输或资源加载时,过大的图片往往是编程人员的噩梦,加载时间过长,体验效果差,特别在即时通讯的发送图片时,大图往往半天加载不出来,于是,先对图片进行压缩,暂时显示模糊图片,然后下载大图最后更新下载的大图,这一过程成为解决大图片加载过慢体验效果差的关键。
QImage提供了缩放图片的函数scaled,并且可以用参数指定”快速缩放(FastTransformation)”还是”平滑缩放(SmoothTransformation)”, 使用还是很方便的。 但是如果你用缩放函数去做大图片的缩略图可能会发现”快速缩放”得到的图片质量不佳, 而”平滑缩放”质量很好但速度欠佳, 特别是原图非常大的时候smoothscale简直就是个噩梦阿。 这里就可以使用被称为“Cheat Scaling”的缩小图片的技巧了, 那就是先使用”快速缩放”得到一个中等大小的图片以获得较快的缩放速度, 再使用”平滑缩放”缩小至需要的大小以获得较好的图片质量。
实现代码如下:
#include <QFile>
void compressImg()
{
QImage img;
img.load("./in.jpg");
QImage result = img.scaled(800, 600, Qt::KeepAspectRatio, Qt::FastTransformation).scaled(260, 140, Qt::KeepAspectRatio, Qt::SmoothTransformation);
bool isSuccess = result.save("out.jpg", "JPEG", 100);
if (!isSuccess)
{
qDebug() << "save image fail!";
}
QFile file("out.jpg");
qint64 fsz = file.size();


int quality = 100;
while (fsz > 2048)
{
quality = quality - 5;
isSuccess = result.save("out.jpg", "JPEG", quality);
if (!isSuccess)
{
qDebug() << "save image fail! quality=" << quality;
}
fsz = file.size();
qDebug() << "+++++++++++++++++++++++quality=" << quality;
if (quality <= 0)
break;
}
}
通过压缩,可以将图片压缩至2K(2048字节)以内,此时,图片的质量有明显的下降,但是解决了大图片下载耗时的问题。
以上代码,先通过QImage的scaled()方法将图片缩放到260x140,然后通过save的quality参数将图片的质量下调,直至图片文件大小满足要求(2K以内)。使用技巧是调用scaled()将图片缩放至中等图片img.scaled(800, 600, Qt::KeepAspectRatio, Qt::FastTransformation)时,使用的transformMode为Qt::FastTransformation进行快速压缩,然后在进行二次缩放scaled(260, 140, Qt::KeepAspectRatio, Qt::SmoothTransformation)时,使用transformMode为Qt::SmoothTransformation进行缩放,这样既保障图片的质量,又提高了压缩速度。
实现了压缩以后,要对图片进行读取,通过字节形式进行发送,然后在接收端对数据进行保存并显示模糊的压缩图片,代码如下:
#include <QFile>
void saveImg() {
QFile file("out.jpg");
file.open(QIODevice::ReadOnly);
QByteArray arr = file.readAll();
file.close();
char* p = arr.data();


//file.remove();


QImage aout;
aout.loadFromData(arr);
aout.save("aout.jpg", "JPEG", 100);


QFile file_out("aout.jpg");
fsz = file_out.size();
quality = 100;
while (fsz > 2048)
{
quality = quality - 5;
isSuccess = aout.save("aout.jpg", "JPEG", quality);
fsz = file_out.size();
qDebug() << "+++++++++++++++++++++++quality=" << quality;
if (quality <= 0)
break;
}
}
用QFile的readAll()方法可以将图片以文件形式全部读出,返回一个QByteArray保存读出的数据,即为图片的二进制数据,也可以用QByteArray的data()方法将数据转换为char*指针,且该指针是以'\0'结尾的,因此可以通过网络对较少字节的数据进行传输。

用QImage的loadFromData()方法对读出的QByteArray进行加载并保存为aout.jpg文件,当用aout.save("aout.jpg", "JPEG", 100);对保存的2K数据转换为图片aout.jpg时,设置quality为100,输出图片aout.jpg的大小竟然变大了(7K左右),但是图片的质量依然和原始的2K图片质量一样,因此,最后最图片又进行了循环保存,以减少不必要的空间浪费。

效果图如下:

压缩前:1.4M   4208*3120


压缩后:1.98K   188*140


了解更多关于Qt、QML、Linux、MacOSX相关技术,请扫码关注【三个程序员】接收实时消息^_^.


发布了58 篇原创文章 · 获赞 83 · 访问量 23万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章