<2>[QTCN]图片数据转换工具

简介: 说明:图片数据转换工具,可以批量将图片转换成数据,将数据转换为图片。亮点:延时处理,图片数据解码,16进制格式和base64格式,进度条同步显示,文件保存等。新增: 自动推算路径无需再选择(不存在则自动创建)

参考

<2>[QTCN]图片数据转换工具

  • 说明:图片数据转换工具,可以批量将图片转换成数据,将数据转换为图片。
  • 亮点:延时处理,图片数据解码,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

image.png

效果

image.png

模糊知识点

  1. 处理当前线程的事件队列,并等待100毫秒来接收新的事件。

    // addMSecs(s) 将当前时间增加指定的毫秒数s,得到一个目标时间点t
    QTime t=QTime::currentTime().addMSecs(s);       
    while(QTime::currentTime()<t){
                          
    QCoreApplication::processEvents(QEventLoop::AllEvents,100);
    }
    

    为了确保程序的其他部分仍然能够响应用户操作,避免程序卡死。

  2. 文件 通常存储 文本数据,而不是 二进制数据,将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();
    }
}
  1. 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();
}
相关文章
|
存储 传感器 自动驾驶
几种常见的点云格式数据解析与在线预览
3D模型在线转换网站支持pcd、pts、xyz、las、laz、asc、ply等点云格式文件在线预览,同时支持将点云格式在线转换为ply、xyz等模型格式。
2957 1
|
2月前
|
监控 测试技术
【问题实战】Jmeter中jtl格式转换图片后如何分开展示各个性能指标?
在使用JMeter进行性能测试时,若希望将不同性能指标(如CPU、DiskIO、Mem)分别显示在不同图片中,需在测试计划中为每个指标添加独立的`jp@gc - PerfMon Metrics Collector`监控器,并设置各自的数据保存路径。通过命令行模式执行压测并使用`JMeterPluginsCMD`工具针对每个生成的`.jtl`文件转换为单独的图片,从而实现分指标展示的效果。这解决了默认情况下所有监控指标显示在同一张图片上的问题。
75 0
【问题实战】Jmeter中jtl格式转换图片后如何分开展示各个性能指标?
|
7月前
|
存储 传感器 监控
工业相机如何实现实时和本地Raw格式图像和Bitmap格式图像的保存和相互转换(C#代码,UI界面版)
工业相机如何实现实时和本地Raw格式图像和Bitmap格式图像的保存和相互转换(C#代码,UI界面版)
259 0
|
7月前
|
JSON 数据格式
将json格式的数据快速转换为excel,使用在线工具轻松搞定
将json格式的数据快速转换为excel,使用在线工具轻松搞定
433 0
|
人工智能 前端开发 Linux
Python编程:利用ImageMagick转换PDF为图片并识别提取图表
Python编程:利用ImageMagick转换PDF为图片并识别提取图表
324 0
|
数据采集 API Android开发
简单易用的图像解码库介绍-stb_image
说到图像解码库,最容易想起的就是libpng和libjpeg这两个老牌图像解码库了。
1028 0
简单易用的图像解码库介绍-stb_image
|
数据采集 监控 应用服务中间件
一日一技:更友好的格式化数据提取方案
一日一技:更友好的格式化数据提取方案
90 0
|
算法 数据挖掘 开发者
数据转换| 学习笔记
快速学习数据转换。
数据转换| 学习笔记
|
存储 Python
提取出 Word 文档里的图片 并利用 python 批量转换格式
日常工作中,你是否遇到过这样的场景,领导发来一份 Word 文档,要求你将文档中的图片存储到一个文件夹内,并且还要将图片都改成 .jpg 或者 .png,你会怎么办?你是不是一边内心崩溃,一边开始一张张的 另存为。今天,庭云教你两招省时省力的方法,不管文档中有几张甚到几百张图片,你都可以快速保存下来。
240 0
提取出 Word 文档里的图片 并利用 python 批量转换格式