Qt实现图片的简单压缩

2023-11-15

在编程过程中,涉及到网络传输或资源加载时,过大的图片往往是编程人员的噩梦,加载时间过长,体验效果差,特别在即时通讯的发送图片时,大图往往半天加载不出来,于是,先对图片进行压缩,暂时显示模糊图片,然后下载大图最后更新下载的大图,这一过程成为解决大图片加载过慢体验效果差的关键。
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相关技术,请扫码关注【三个程序员】接收实时消息^_^.


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt实现图片的简单压缩 的相关文章

  • Qt 信号槽,新符号中的转换类型[重复]

    这个问题在这里已经有答案了 鉴于以下两个 connect ui gt comboBox SIGNAL activated QString ps SLOT requestPlotsAvailable QString connect ui gt
  • 如何在 QTableWidget 的行和列中自动换行文本?

    I tried QTableWidget j new QTableWidget 10000 5 centralWidget j gt setColumnWidth 0 500 j gt setColumnWidth 1 30 j gt se
  • Qt、PushButton、id 属性?有什么方法可以知道点击了哪个按钮

    void MainWindow addRadioToUI int button cunter 4 while database isEmpty button cunter QPushButton one new QPushButton Pl
  • 如何在Qt中设置编译器?

    我对 Qt 完全陌生 我下载了离线版本 Qt 5 3 2 for Windows 64 bit VS 2013 OpenGL 573 MB 我无法编译我的项目 I have Qt Creator 3 2 1 开源 基于Qt 5 3 2 MS
  • Qt + win32 + mingw 上的原生 Windows API 链接问题

    我正在尝试使用 mingw 工具集将本机 Windows API 与 Qt 结合使用 部分功能存在链接问题 会发生什么 这是 mingw 名称修改的错误吗 ifdef Q WS WIN HWND hwnd QWidget winId HDC
  • QToolBar 的菜单延迟

    我通过制作 QAction 并向其添加 QMenu 在 QToolBar 上有一个菜单 如何消除单击图标时出现菜单之前的延迟 QToolBar myToolBar new QToolBar this QAction myAction new
  • 调整 QML 图像显示尺寸

    我有一个带有嵌套的 QML 窗口RowLayout 在内排我有两个图像 来源 png这些图像的文件 故意 相当大 当我尝试设置height这些图像上的属性使它们变小 但它们仍然被画得很大 Desired Appearance Actual
  • 从 QML 实例化 C++ 对象会产生巨大的内存使用开销

    实例化一个QObjectC 堆中的派生类为每个对象提供了大约 160 个字节 通过注册相同的对象qmlRegisterType 用于从 QML 创建并通过以下方式动态创建对象createObject 每个对象给我 2000 多个字节 这是完
  • QGraphicsView 和 eventFilter

    这个问题已经困扰我两天多了 所以我想我应该问一下 我在Win7上使用Qt 4 5 3 用VC2008编译 我有 MyGraphicsView 继承 QGraphicsView 和 MyFilter 继承 QObject 类 当我将 MyFi
  • 如何在 C++ 和 QML 应用程序中使用 qrc?

    我在 Windows7 上用 c qnd Qt Creator QML 编写了 Qt Quick Desktop 应用程序 现在 我必须部署它 并且我需要隐藏 qml 文件和图像 意味着 将它们放入资源等中 我读到有一个很好的方法可以使用
  • 当我尝试构建 Qt 4.7.1 静态库时,“找不到 -ljscore”

    我尝试从最新的源构建静态 Qt 库 但出现以下错误 usr bin ld cannot find ljscore collect2 ld returned 1 exit status 如何解决这个问题呢 这是 Qt 构建系统中自 4 7 0
  • Qt WinRT 应用程序无法访问文件权限被拒绝

    我需要使用 Qt 和 FFMPEG 开发 WinRT 应用程序 我根据指令构建了 WinRT 的 ffmpeghere https github com Microsoft FFmpegInterop我可以将库与我的项目链接起来 现在我需要
  • QTcpSocket 有时不发送数据

    我有两个 QT 应用程序 一个应用程序可以被认为保存了大数据 它每秒向第二个应用程序发送大约 10 KB 的数据块 之前我尝试使用QUdpSocket来传输数据 但由于MTU限制在2 5K左右 并且需要自己分割和重新组合数据 所以我改用QT
  • Qt - 如何粘合两个窗口并将它们移动在一起?

    就像qmmp Qt 音乐播放器ui设计一样 这两个或三个窗口实际上在同一个窗口中 因为只有一个dock图标 并且这些窗口可以一起移动并相互附着 我看了源码 好像有用QDockWidget 但我真的不知道如何获得它的细节 当您手动移动辅助窗口
  • 如何在模型更改时停止ListView“跳跃”

    我需要做什么 我需要创建一个聊天窗口用一个ListView在 QML 中存储聊天消息 我设置listView positionViewAtEnd 以便跟踪最后的消息 我禁用positionViewAtEnd当我向上滚动时 我可以阅读过去的消
  • 如何在带有预编译头的项目中使用google protobuf

    我有一个包含多个项目的解决方案 我的项目 但不是全部 使用预编译头 我决定使用 protobuf 但遇到了一个问题 在 protoc exe 从 proto 生成 pb h 后 我尝试包含标头并收到错误 预编译标头未包含在 pb h 中 我
  • 加权 Voronoi 的 CGAL 2D APOLLONIUS 图 - 如何生成和获取面和顶点?

    我正在尝试根据阿波罗尼乌斯图生成加权沃罗诺伊 我正在使用 CGAL 库 我找不到如何从 apollonius 获取面和顶点的好例子 我有以下类型定义 typedef double NT typedef CGAL Cartesian lt N
  • 从布局中按名称获取小部件

    如果我想从 python Qt 的布局中获取特定的小部件 我应该如何进行 到目前为止我所做的 for i in range self ui horizontalLayout 14 count here it does fail name s
  • 为 Windows 98 编译 Qt

    我需要支持 Windows 98 Qt 文档声称这是可能的 但没有说明 Qt 4 6 的分布式二进制文件不能在 Win98 上运行 而且我采样的大多数 Qt 应用程序也不能在 Win98 上运行 对于几个确实在 98 上运行的应用程序 我询
  • 如何获取 QTableView 的标题列表?

    我有一个QTableView我的对话框中的对象 我需要访问该表的水平标题并将它们放入QStringList object 尽管进行了大量搜索 但我在 Qt 文档中找不到如何获取此标头列表 编辑 我发现的最接近的地方是this https w

随机推荐