一、概述
需求:
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,压缩,JPEG,OpenCV,vLayout,addWidget,new,setText,图片 From: https://www.cnblogs.com/tony-yang-flutter/p/18195306