一、概述

  需求:

    1.编写一个小工具实现图片压缩

    2.图片仅支持JPEG和PNG格式

    3.目的是压缩图片在磁盘中所占用的大小

    4.使用的开发语言是Qt、C++、OpenCV

    5.压缩的质量可以动态调节

    如下图所示:

  ps:

    1.如果图片是jpeg压缩质量可以设置10~100,值越大质量越好,图片所占用的磁盘空间也就越大。综合测试下来值设置30的时候压缩的最为合理,且图片不失真,如果图片要求质量较高建议设置40以上。

    2.如果图片是png格式,压缩质量是从0~9,值越大压缩率越高,如果没有特殊要求直接设置压缩率为9,直接压缩到最小就行。

二、代码示例

点击查看代码

#include "ImageCompressTool.h" ImageCompressTool::ImageCompressTool(QWidget* parent)
: CommonGraphicsView{ parent }
{
this->setWindowTitle("图片压缩");
this->setFixedSize(QSize(320, 800));
QVBoxLayout* vLayout = new QVBoxLayout(this); QHBoxLayout* hLayout = new QHBoxLayout(this);
EditText* et = new EditText(this);
et->setEnabled(false);
et->setFixedHeight(30);
Button* btnChoiceBtn = new Button(this);
btnChoiceBtn->setText("请选择图片"); hLayout->addWidget(et);
hLayout->addWidget(btnChoiceBtn);
hLayout->setAlignment(Qt::AlignTop); QHBoxLayout* radioTypeHLayout = new QHBoxLayout(this);
QButtonGroup* group = new QButtonGroup(this);
QRadioButton* radioButtonJPEG = new QRadioButton("JPEG", this);
radioButtonJPEG->setFixedSize(60, 30);
QRadioButton* radioButton2PNG = new QRadioButton("PNG", this);
radioButton2PNG->setFixedSize(60, 30);
group->addButton(radioButtonJPEG, 1);
group->addButton(radioButton2PNG, 2);
radioTypeHLayout->addWidget(radioButtonJPEG);
radioTypeHLayout->addWidget(radioButton2PNG);
radioTypeHLayout->setAlignment(Qt::AlignLeft); //图片质量(JPEG)
qualitLabel = new QLabel(this);
qualitLabel->setText("图片质量:" + QString::number(mKsize));
qualitLabel->setFixedHeight(15);
//显示原图大小(KB)
srcImageKb = new QLabel(this);
srcImageKb->setText("原图大小:");
srcImageKb->setFixedHeight(15);
//显示压缩后图片大小(KB)
compressImageKb = new QLabel(this);
compressImageKb->setText("压缩后图片大小:");
compressImageKb->setFixedHeight(15);
//开始压缩按钮
Button* startCompressBtn = new Button(this);
startCompressBtn->resize(60, 30);
startCompressBtn->setText("开始压缩"); QLabel* comBoxLabel = new QLabel(this);
comBoxLabel->setText("请选择图片质量:");
comBoxLabel->setFixedHeight(15);
//ComBox选择图片质量
comBox = new ComboBox(this);
for (int i = 10;i <= 100;i += 10) {
comBox->addItem(QString::number(i));
}
QHBoxLayout* comBoxHLayout2 = new QHBoxLayout(this);
comBoxHLayout2->addWidget(comBoxLabel);
comBoxHLayout2->addWidget(comBox); imageViewResult = new QLabel(this); vLayout->addLayout(hLayout);
vLayout->addLayout(radioTypeHLayout);
//vLayout->addWidget(imageViewSrc);
vLayout->addWidget(imageViewResult);
vLayout->setAlignment(Qt::AlignTop); vLayout->addWidget(qualitLabel);
vLayout->addWidget(srcImageKb);
vLayout->addWidget(compressImageKb);
vLayout->addLayout(comBoxHLayout2);
vLayout->addWidget(startCompressBtn);
this->setLayout(vLayout); connect(btnChoiceBtn, &Button::clicked, this, [=]() {
QFileInfo fileInfo;
filePath = QFileDialog::getOpenFileName(this, tr("请选择图片"), "C:/Users/DBF-DEV-103/Downloads/", tr("Image Files(*.jpg *.png *.jpeg)"));
et->setText(filePath);
fileInfo = QFileInfo(filePath);
//获取文件后缀名
QString fileSuffix = fileInfo.suffix();
qDebug() << "文件的后缀名为:" << fileSuffix;
if (fileSuffix == "jpeg" || fileSuffix == "jpg") {
imageType = 0;
radioButtonJPEG->setChecked(true);
comBox->clear();
for (int i = 10;i <= 100; i += 10) {
comBox->addItem(QString::number(i));
}
}
else if (fileSuffix == "png") {
imageType = 1;
radioButton2PNG->setChecked(true);
comBox->clear();
for (int i = 0;i <= 10; i++) {
comBox->addItem(QString::number(i));
}
}
//compressImage();
}); //选择了JPEG
connect(radioButtonJPEG, &QRadioButton::clicked, this, [=]() {
imageType = 0;
qDebug() << "图片类型" << imageType;
});
//选择了PNG
connect(radioButton2PNG, &QRadioButton::clicked, this, [=]() {
imageType = 1;
qDebug() << "图片类型:" << imageType;
}); //开始压缩按钮信号槽(点击事件)
connect(startCompressBtn, &Button::clicked, this, [=]() {
compressImage(); }); //选择图片质量信号槽
connect(comBox, &ComboBox::currentTextChanged, [=](const QString value) {
qDebug() << "选择的value值:" << value;
mKsize = value.toInt();
qualitLabel->setText("图片质量:" + QString::number(mKsize));
}); }
//压缩图片
void ImageCompressTool::compressImage() {
cv::Mat src = cv::imread(this->filePath.toStdString().c_str());
//imshow("src", src);
double srcKb = matSizeInKB(filePath.toStdString());
srcImageKb->setText("原图大小:" + QString::number(srcKb));
std::cout << "原图大小:" << srcKb << std::endl;
std::vector<int> compression_params;
if (imageType == 0) {
compression_params.push_back(cv::IMWRITE_JPEG_QUALITY);
//压缩级别范围从0~100,值越小压缩率越高,即在磁盘占用的空间越小,相应的图片的质量越差
compression_params.push_back(mKsize);
}
else {
compression_params.push_back(cv::IMWRITE_PNG_COMPRESSION);
if (mKsize > 10) {
mKsize = 3;
}
compression_params.push_back(mKsize); // 压缩级别范围从0到9,9是最高压缩
}
//将图片以jpg的格式存入文件
char* compressImgPath = "E://opencv_compress_img.jpeg";
if (imageType == 1) {
compressImgPath = "E://opencv_compress_img.png";
}
bool result = cv::imwrite(compressImgPath, src, compression_params);
if (!result) {
std::cout << "压缩图片失败" << endl;
return;
}
QFile compressFile = QFile(compressImgPath);
double compressSizeKb = matSizeInKB(compressImgPath);
compressImageKb->setText("压缩后的图片大小:" + QString::number(compressSizeKb));
std::cout << "压缩后的图片大小为:" << compressSizeKb << std::endl;
std::cout << "压缩图片成功,存储路径为:" << compressImgPath << std::endl;
} long ImageCompressTool::matSizeInKB(std::string filePath) {
std::ifstream mFile(filePath, std::ifstream::binary);
if (mFile) {
mFile.seekg(0, mFile.end);
long size = mFile.tellg(); // 获取文件大小(字节)
mFile.close();
return size / 1024; // 转换为KB
}
return -1; // 文件打开失败,返回-1
} ImageCompressTool::~ImageCompressTool()
{
}

Qt+OpenCV实现图片压缩(JPEG、PNG)的更多相关文章

  1. 使用 opencv 将图片压缩到指定文件尺寸

    前言 图片压缩应用很广泛,如生成缩略图等.前期我在进行图片处理的过程中碰到了一个问题,就是如何将图片压缩到指定尺寸,此处尺寸指的是生成图片文件的大小. 我使用 opencv 进行图片处理,于是想着直接 ...

  2. 搭建Android+QT+OpenCV环境,实现“单色图片着色”效果

               OpenCV是我们大家非常熟悉的图像处理开源类库:在其新版本将原本在Contrib分库中的DNN模块融合到了主库中,并且更新了相应文档.这样我们就能够非常方便地利用OpenCV实 ...

  3. Qt OpenCV Support Image Type 支持读写的图像格式

    Qt 支持的图片格式如下: Format Description Qt's support BMP Windows Bitmap Read/write GIF Graphic Interchange ...

  4. Golang 编写的图片压缩程序,质量、尺寸压缩,批量、单张压缩

    目录: 前序 效果图 简介 全部代码 前序: 接触 golang 不久,一直是边学边做,边总结,深深感到这门语言的魅力,等下要跟大家分享是最近项目 服务端 用到的图片压缩程序,我单独分离了出来,做成了 ...

  5. 三款不错的图片压缩上传插件(webuploader+localResizeIMG4+LUploader)

    涉及到网页图片的交互,少不了图片的压缩上传,相关的插件有很多,相信大家都有用过,这里我就推荐三款,至于好处就仁者见仁喽: 1.名气最高的WebUploader,由Baidu FEX 团队开发,以H5为 ...

  6. Java中图片压缩处理

    原文http://cuisuqiang.iteye.com/blog/2045855 整理文档,搜刮出一个Java做图片压缩的代码,稍微整理精简一下做下分享. 首先,要压缩的图片格式不能说动态图片,你 ...

  7. android 图片压缩

    引用:http://104zz.iteye.com/blog/1694762 第一:我们先看下质量压缩方法: private Bitmap compressImage(Bitmap image) { ...

  8. HTML5 CANVAS 实现图片压缩和裁切

    原文地址:http://leonshi.com/2015/10/31/html5-canvas-image-compress-crop/?utm_source=tuicool&utm_medi ...

  9. C# 图片压缩

    /// <summary>        /// 图片压缩方法        /// </summary>        /// <param name="sF ...

  10. Html5+asp.net mvc 图片压缩上传

    在做图片上传时,大图片如果没有压缩直接上传时间会非常长,因为有的图片太大,传到服务器上再压缩太慢了,而且损耗流量. 思路是将图片抽样显示在canvas上,然后用通过canvas.toDataURL方法 ...

随机推荐

  1. Debian 12 (bookworm) 安装方法及其国内软件源

    摘要: Debian 12 (bookworm) 已经于2023年6月份正式发布.以下为原来信息: Debian 12 (bookworm) 预计于2023年中期发布,但是目前(2023年4月)已经处 ...

  2. Windows下如何在当前目录下,打开cmd命令窗口

    方法一: 在当前目录下,按下shift + 鼠标右键,会出现"在此处打开命令窗口"的字样,然后点击即可. 方法二: 在该文件夹上,按下shift + 鼠标右键,会出现"在 ...

  3. 超轻巧modbus调试助手使用说明

    一.使用说明 1.1 数据格式 和其他的modbus采集工具一样,本组件也支持各种数据格式,其实就是高字节低字节的顺序. 一般是2字节表示一个数据,后面又有4字节表示一个数据,目前好像还有8字节表示一 ...

  4. Qt/C++编写的Onvif调试助手调试神器工具/支持云台控制/预置位设置等/有手机版本

    一.功能特点 广播搜索设备,支持IPC和NVR,依次返回. 可选择不同的网卡IP进行对应网段设备的搜索. 依次获取Onvif地址.Media地址.Profile文件.Rtsp地址. 可对指定的Prof ...

  5. Qt/C++推流程序(视频文件/视频流/摄像头/桌面转成流媒体rtmp+hls+webrtc)可在网页和播放器远程观看

    一.前言说明 推流直播就是把采集阶段封包好的内容传输到服务器的过程.其实就是将现场的视频信号从手机端,电脑端,摄影机端打包传到服务器的过程."推流"对网络要求比较高,如果网络不稳定 ...

  6. Qt音视频开发27-ffmpeg视频旋转显示

    一.前言 用手机或者平板拍摄的视频文件,很可能是旋转的,比如分辨率是1280x720,确是垂直的,相当于分辨率变成了720x1280,如果不做旋转处理的话,那脑袋必须歪着看才行,这样看起来太难受,所以 ...

  7. C# .Net FrameWork3.5中异步HTTP请求时,由于安全协议的问题System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)方法抛出“基础连接已经关闭: 发送时发生错误”的解决办法

    现象描述: C# .Net FrameWork3.5中异步HTTP请求时,由于安全协议的问题System.Net.HttpWebRequest.EndGetResponse(IAsyncResult ...

  8. 即时通讯技术文集(第38期):IM代码入门实践(Part2) [共15篇]

    为了更好地分类阅读 52im.net 总计1000多篇精编文章,我将在每周三推送新的一期技术文集,本次是第38 期. [- 1 -] 高仿Android版手机QQ首页侧滑菜单源码 [附件下载] [链接 ...

  9. IM通讯协议专题学习(一):Protobuf从入门到精通,一篇就够!

    本文由IBM开发者社区分享,有较多修订和改动. 1.引言 在当今移动网络时代,手机流量和电量是宝贵的资源,对于移动端最常见的即时通讯IM应用,由于实时通信基于Socket长连接,它对于流量和电量的需求 ...

  10. Pytorch Utils 总结

    Utils 从torch.nn.utils模块 clip_grad_norm_ 裁剪参数迭代的梯度范数. clip_grad_value_ 在指定值处剪辑可迭代参数的梯度. parameters_to ...