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相关技术,请扫码关注【三个程序员】接收实时消息^_^.