参考
- 说明:图片数据转换工具,可以批量将图片转换成数据,将数据转换为图片。
- 亮点:延时处理,图片数据解码,16进制格式和base64格式,进度条同步显示,文件保存等。
- 新增: 自动推算路径无需再选择(不存在则自动创建)
实现
main.cpp
#include "imagetodatatools.h"
#include <QApplication>
#include <QFont>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// 设置全局字体大小
QFont font;
font.setPointSize(15); // 设置字体大小
qApp->setFont(font);
ImageToDataTools w;
w.show();
return a.exec();
}
imagetodatatools.h
#ifndef IMAGETODATATOOLS_H
#define IMAGETODATATOOLS_H
#pragma execution_character_set("utf-8")
#include <QWidget>
#include <QDesktopWidget>
#include <QTimer>
#include <QDateTime>
#include <QFileDialog>
#include <QDebug>
#include <QMessageBox>
#include <QListWidgetItem>
#include <QDragEnterEvent>
#include <QMimeData>
#include <QBuffer>
#include <QImage>
QT_BEGIN_NAMESPACE
namespace Ui {
class ImageToDataTools; }
QT_END_NAMESPACE
class ImageToDataTools : public QWidget
{
Q_OBJECT
public:
ImageToDataTools(QWidget *parent = nullptr);
~ImageToDataTools();
private:
Ui::ImageToDataTools *ui;
public:
void initUI();
void ShowTime();
void DelayTime(int s);
void PicToData(QString fromPic,QString toData,QString myformat);//图片转数据
void DataToPic(QString fromData,QString toPic,QString myformat);//数据转图片
private slots:
void on_btnBrowseToPic_clicked();
void on_btnBrowseToTxt_clicked();
void on_btnPicToData_clicked();
void on_btnDataToPic_clicked();
void on_btnSelectFile_clicked();
void on_btnSelectTxt_clicked();
void on_btnChangeToJpg_clicked();
void on_btnChangeToTxt_clicked();
void on_listWidget_doubleClicked(const QModelIndex &index);
protected:
void dragEnterEvent(QDragEnterEvent *event) override; // 处理拖动操作进入窗口事件
void dropEvent(QDropEvent *event) override; //处理拖放操作完成的事件。当拖动的数据在窗口上释放时,会触发该事件
};
#endif // IMAGETODATATOOLS_H
imagetodatatools.cpp
#include "imagetodatatools.h"
#include "ui_imagetodatatools.h"
ImageToDataTools::ImageToDataTools(QWidget *parent)
: QWidget(parent)
, ui(new Ui::ImageToDataTools)
{
ui->setupUi(this);
initUI();
}
ImageToDataTools::~ImageToDataTools()
{
delete ui;
}
void ImageToDataTools::initUI()
{
//窗体居中显示
QDesktopWidget *desktop=QApplication::desktop();
int width=desktop->width();
int height=desktop->height();
//设置窗口将始终显示在其他窗口之上
setWindowFlags(Qt::WindowStaysOnTopHint);
this->move((width-this->width())/2,(height-this->height())/2);
setWindowIcon(QIcon(":/1.ico"));
setWindowTitle(tr("图片数据转换工具"));
this->setAcceptDrops(true); //设置允许向窗口拖入
// 定时器更新
QTimer *updateTimer = new QTimer(this);
updateTimer->callOnTimeout(this,&ImageToDataTools::ShowTime);
updateTimer->start(1000);
}
void ImageToDataTools::ShowTime()
{
QDateTime time=QDateTime::currentDateTime();
QString s=time.toString("yyyy年MM月dd日 hh时mm分ss秒 dddd");
ui->labTime->setText(tr("现在是:%1").arg(s));
}
void ImageToDataTools::DelayTime(int s)
{
QTime t=QTime::currentTime().addMSecs(s); // addMSecs(s) 将当前时间增加指定的毫秒数s,得到一个目标时间点t
while(QTime::currentTime()<t){
/*处理当前线程的事件队列,并等待最多100毫秒来接收新的事件。
这是为了确保程序的其他部分仍然能够响应用户操作,避免程序卡死。*/
QCoreApplication::processEvents(QEventLoop::AllEvents,100);
}
}
//图片转数据
void ImageToDataTools::PicToData(QString fromPic, QString toData, QString myformat)
{
QImage img(fromPic);
// 保存图像数据到 QByteArray
QByteArray ba;
QBuffer buf(&ba);
buf.open(QIODevice::WriteOnly);
img.save(&buf,"JPG"); //按照JPG解码保存数据
buf.close();
QByteArray cc=qCompress(ba,1); // 对图像数据进行压缩
QByteArray hh;
if (myformat=="Hex")
{
hh=cc.toHex(); //获取十六进制数据
}
else
{
hh=cc.toBase64(); //获取Base64数据
}
/*
* 将hh直接写入文件可能会导致文件保存的是二进制数据,而不是文本数据。
* 由于文件通常存储文本数据,而不是二进制数据,将QByteArray以文本格式写入文件是常见的做法
*/
QString str(hh);
QFile file(toData);
if (file.open(QFile::WriteOnly|QFile::Truncate))
{
file.write(str.toLatin1()); // 字符编码是Latin1可以表示大多数ASCII字符
file.close();
}
}
//数据转图片
void ImageToDataTools::DataToPic(QString fromData, QString toPic, QString myformat)
{
QFile file(fromData);
if (file.open(QFile::ReadOnly))
{
QByteArray read = file.readAll();
file.close();
QByteArray rc;
if (myformat == "Hex")
{
//QString hexString = QString::fromLatin1(read); // Latin1编码方式写入文件,读取转换为字符串
//rc = QByteArray::fromHex(hexString.toLatin1()); // 解析十六进制字符串
rc = QByteArray::fromHex(read);
}
else
{
rc = QByteArray::fromBase64(read);
}
QByteArray rdc = qUncompress(rc); // 解压缩,得到解压后的二进制数据
QImage img;
img.loadFromData(rdc);
img.save(toPic);
}
}
void ImageToDataTools::on_btnBrowseToPic_clicked()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("选择图片文件"), "", tr("图片文件(*.jpg;*.gif;*.bmp;*.png;*.jpeg)"));
if (fileName.isEmpty()) // 用户取消选择或者没有选择有效的文件
fileName= "未选择图片";
ui->pic->setText(fileName);
// 自动推算txt路径
QFileInfo fileInfo(fileName);
QString txtPath(fileName.remove(fileInfo.suffix())+"txt");// 文件的后缀名
ui->txt->setText(txtPath);
}
void ImageToDataTools::on_btnBrowseToTxt_clicked()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("选择文本文件"), "", tr("文本文件(*.txt)"));
if (fileName.isEmpty()) // 用户取消选择或者没有选择有效的文件
fileName= "未选择文本";
ui->txt->setText(fileName);
// 自动推算pic路径
QFileInfo fileInfo(fileName);
QString picPath(fileName.remove(fileInfo.suffix())+"jpg");// 文件的后缀名
ui->pic->setText(picPath);
}
// 图片转数据
void ImageToDataTools::on_btnPicToData_clicked()
{
if (ui->pic->text()==""||ui->pic->text()=="未选择图片")
{
QMessageBox::information(this,tr("提示"),tr("请选择图片文件"));
return;
}
if (ui->txt->text()==""||ui->txt->text()=="未选择文本")
{
QMessageBox::information(this,tr("提示"),tr("请选择文本文件"));
return;
}
if (ui->rbtn16->isChecked())
{
PicToData(ui->pic->text(),ui->txt->text(),"Hex");
}
else
{
PicToData(ui->pic->text(),ui->txt->text(),"Base64");
}
QMessageBox::information(this,tr("提示"),tr("恭喜你!转换完成!"));
}
// 数据转图片
void ImageToDataTools::on_btnDataToPic_clicked()
{
if (ui->pic->text()==""||ui->pic->text()=="未选择图片")
{
QMessageBox::information(this,tr("提示"),tr("请选择图片文件"));
return;
}
if (ui->txt->text()==""||ui->txt->text()=="未选择文本")
{
QMessageBox::information(this,tr("提示"),tr("请选择文本文件"));
return;
}
if (ui->rbtn16->isChecked())
{
DataToPic(ui->txt->text(),ui->pic->text(),"Hex");
}
else
{
DataToPic(ui->txt->text(),ui->pic->text(),"Base64");
}
QMessageBox::information(this,tr("提示"),tr("恭喜你!转换完成!"));
}
// 选择JPG
void ImageToDataTools::on_btnSelectFile_clicked()
{
QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("选择图片文件"), "", tr("图片文件(*.jpg;*.gif;*.bmp;*.png;*.jpeg)"));
if (!fileNames.isEmpty()) // 用户选择有效的文件
ui->listWidget->addItems(fileNames);
else
qDebug() << "未选择文件";
}
// 选择TXT
void ImageToDataTools::on_btnSelectTxt_clicked()
{
QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("选择文本文件"), "", tr("文本文件(*.txt)"));
if (!fileNames.isEmpty())// 用户选择有效的文件
ui->listWidget->addItems(fileNames);
else
qDebug() << "未选择文件";
}
// 批量转图片
void ImageToDataTools::on_btnChangeToJpg_clicked()
{
QListWidgetItem *myitem;
int count=ui->listWidget->count();
if (count==0)
{
QMessageBox::information(this,tr("提示"),tr("请选择图片文件"));
return;
}
ui->pbar->setValue(0);
ui->pbar->setMaximum(count);
for (int i=0;i<count;i++)
{
QString timeNow=QDateTime::currentDateTime().toString("yyyyMMddHHmmss");
QString saveFileName=QCoreApplication::applicationDirPath()+QString("/%1.jpg").arg(timeNow);
myitem=ui->listWidget->item(i);
if (ui->rbtn16->isChecked())
{
DataToPic(myitem->text(),saveFileName,"Hex");
}
else
{
DataToPic(myitem->text(),saveFileName,"Base64");
}
ui->pbar->setValue(ui->pbar->value()+1);
this->DelayTime(1000); //为了确保命名不冲突和转换完成,延时1秒
}
QMessageBox::information(this,tr("提示"),tr("恭喜你!转换完成!"));
}
// 批量转TXT
void ImageToDataTools::on_btnChangeToTxt_clicked()
{
QListWidgetItem *myitem;
int count=ui->listWidget->count();
if (count==0)
{
QMessageBox::information(this,tr("提示"),tr("请选择文本文件"));
return;
}
ui->pbar->setValue(0);
ui->pbar->setMaximum(count);
for (int i=0;i<count;i++)
{
QString timeNow=QDateTime::currentDateTime().toString("yyyyMMddHHmmss");
QString saveFileName=QCoreApplication::applicationDirPath()+QString("/%1.txt").arg(timeNow);
qDebug()<<"saveFileName ="<<saveFileName;
myitem=ui->listWidget->item(i);
if (ui->rbtn16->isChecked())
{
PicToData(myitem->text(),saveFileName,"Hex");
}
else
{
PicToData(myitem->text(),saveFileName,"Base64");
}
ui->pbar->setValue(ui->pbar->value()+1);
this->DelayTime(1000); //为了确保命名不冲突和转换完成,延时1秒
}
QMessageBox::information(this,tr("提示"),tr("恭喜你!转换完成!"));
}
// 双击项
void ImageToDataTools::on_listWidget_doubleClicked(const QModelIndex &index)
{
// 示例:获取双击的项的文本
QString text = ui->listWidget->item(index.row())->text();
qDebug() << "双击了:" << text;
ui->listWidget->clear();
}
// 处理拖动操作进入窗口事件
void ImageToDataTools::dragEnterEvent(QDragEnterEvent *event)
{
// 处理拖动操作进入的逻辑
if (event->mimeData()->hasUrls()) //检查拖放事件的数据是否包含 URL
{
QList<QUrl> urls = event->mimeData()->urls();
foreach (const QUrl &url, urls)
{
QString fileName = url.toLocalFile(); // 获取文件的本地路径
QFileInfo fileInfo(fileName);
// 将文件的后缀名转换为小写
if (fileInfo.suffix().toLower() == "jpg" ||
fileInfo.suffix().toLower() == "gif" ||
fileInfo.suffix().toLower() == "bmp" ||
fileInfo.suffix().toLower() == "png" ||
fileInfo.suffix().toLower() == "jpeg")
{
event->acceptProposedAction(); // 接受拖放操作
return;
}
}
}
event->ignore(); //没有找到匹配的图片文件,忽略拖放操作
}
//处理拖放操作完成的事件。当拖动的数据在窗口上释放时,会触发该事件
void ImageToDataTools::dropEvent(QDropEvent *event)
{
// 处理文件或文件路径的拖放
QList<QUrl> urls = event->mimeData()->urls();
foreach (const QUrl& url, urls) {
QString filePath = url.toLocalFile();
qDebug() << "拖放文件:" << filePath;
}
if (urls.isEmpty())
return;
QString filePath=urls.first().toLocalFile();
ui->pic->setText(filePath);
}
imagetodatatools.ui
效果
模糊知识点
处理当前线程的事件队列,并等待100毫秒来接收新的事件。
// addMSecs(s) 将当前时间增加指定的毫秒数s,得到一个目标时间点t QTime t=QTime::currentTime().addMSecs(s); while(QTime::currentTime()<t){ QCoreApplication::processEvents(QEventLoop::AllEvents,100); }
为了确保程序的其他部分仍然能够响应用户操作,避免程序卡死。
文件
通常存储文本数据
,而不是二进制数据
,将QByteArray以文本格式Latin1字符编码 写入文件是常见的做法
//图片转数据
void ImageToDataTools::PicToData(QString fromPic, QString toData, QString myformat)
{
QImage img(fromPic);
// 保存图像数据到 QByteArray
QByteArray ba;
QBuffer buf(&ba);
buf.open(QIODevice::WriteOnly);
img.save(&buf,"JPG"); //按照JPG解码保存数据
buf.close();
QByteArray cc=qCompress(ba,1); // 对图像数据进行压缩
QByteArray hh;
if (myformat=="Hex")
{
hh=cc.toHex(); //获取十六进制数据
}
else
{
hh=cc.toBase64(); //获取Base64数据
}
/*
* 将hh直接写入文件可能会导致文件保存的是二进制数据,而不是文本数据。
* 由于文件通常存储文本数据,而不是二进制数据,将QByteArray以文本格式写入文件是常见的做法
*/
QString str(hh);
QFile file(toData);
if (file.open(QFile::WriteOnly|QFile::Truncate))
{
file.write(str.toLatin1()); // 字符编码是Latin1可以表示大多数ASCII字符
file.close();
}
}
QFile::Truncate
只能创建QCoreApplication::applicationDirPath()路径下的文件,不能创建再带有路径的,如QCoreApplication::applicationDirPath()/imagexx/xxx.txt,如果路径中的imagexx文件夹不存在,使用 QFile 直接创建文件时将无法成功创建文件 /imagexx/xxx.txt可以通过
QString filePath = QCoreApplication::applicationDirPath() + "/imagexx/xxx.txt";
QDir folder(QCoreApplication::applicationDirPath());
if (!folder.exists("imagexx")) // 检查文件夹是否存在
{
if (!folder.mkpath("imagexx")) // 创建文件夹并检查是否成功
{
// 创建文件夹失败,进行适当的错误处理
return;
}
}
QFile file(filePath);
if (file.open(QIODevice::WriteOnly | QIODevice::Truncate))
{
// 进行文件写入操作...
file.close();
}