在 Qml 中从字节数组加载到图像

Posted

技术标签:

【中文标题】在 Qml 中从字节数组加载到图像【英文标题】:Loading From Byte Array To Image In Qml 【发布时间】:2019-04-28 06:37:12 【问题描述】:

我在 Qt 中创建了一个 c++ 类来读取文件,并将它们转换为字节数组,以便我可以将它们存储在数据库中, 如何处理字节数组数据,例如在 qml 中设置图像源,在 qml 中将此字节数组转换为相关类型的正确方法是什么

这是我的课:

#ifndef UFILE_H
#define UFILE_H

#include <QObject>
#include <QQuickItem>
class UFile : public QObject

    Q_OBJECT
    Q_PROPERTY(QByteArray data READ data NOTIFY dataChanged)
    Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged)
    Q_PROPERTY(int length READ length)
public:
    explicit UFile(QObject *parent = nullptr);
    QByteArray data() const;
    QString path() const;
    int length() const;
    void setPath(QString &path);
    void readFile(QString &filePath);
signals:
    void dataChanged(QByteArray data);
    void pathChanged(QString path);
public slots:
private :
    QByteArray _data;
    QString _path;
;

#endif // UFILE_H

cpp:

#include "ufile.h"
#include <QDir>

UFile::UFile(QObject *parent) : QObject(parent)



QByteArray UFile::data() const
    return _data;

QString UFile::path() const
    return _path;

int UFile::length() const
    int i =_data.count();
    return i;

void UFile::setPath(QString &path)
    if(_path== path)
        return;
    
    _path = path;
    readFile(_path);
    Q_EMIT pathChanged(_path);


void UFile::readFile(QString &filePath)
    if(filePath!= "")
        QString _fp = filePath;
        if(_fp.startsWith("file:///"))
            _fp = QUrl(filePath).toLocalFile();
        if(_fp!= "")
            _fp = QDir::toNativeSeparators(_fp);
            QFile file(_fp);
            if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
                return ;
            QByteArray bytes;
            bytes = file.readAll();
            _data = bytes;
        
    

在 qml 中:

UFile
    id:testfile
    path: "C:/icon.ico"
    onPathChanged: 
        console.log(path)
    
    Component.onCompleted: 
        console.log(length)
    

我试图用这条线加载 QImage 并在 qml 中设置图像源,但它卡住了

QImage img; 
img.loadFromData(bytes);

在 qml 中:

image.source = result of img.loadFromData

【问题讨论】:

您只能将图片 URL 提供给 Image 项目,所以我想您必须实现自定义 QQuickImageProvider @folibis 我将加载大量图像,以便提供商按图像名称加载图像,这不是一个好主意,如果它是动态加载的图像怎么办 好吧,也许......尝试实现自定义 QQuickItem 项目,这样你就可以在里面绘制任何你想要的东西。 【参考方案1】:

一种可能的解决方案是转换为 base64,为此您不应使用标志 QIODevice::Text,我还添加了一些改进,以便您的代码更具可读性。

*.h

#ifndef UFILE_H
#define UFILE_H

#include <QObject>
class UFile : public QObject

    Q_OBJECT
    Q_PROPERTY(QByteArray data READ data NOTIFY dataChanged)
    Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged)
    Q_PROPERTY(QString base64 READ base64 NOTIFY base64Changed)
    Q_PROPERTY(int length READ length)
public:
    explicit UFile(QObject *parent = nullptr);
    QByteArray data() const;
    QString path() const;
    int length() const;
    QString base64() const;

public Q_SLOTS:
    void setPath(const QString &path);
    void readFile(const QString &filePath);

Q_SIGNALS:
    void dataChanged();
    void pathChanged(const QString & path);
    void base64Changed();

private :
    QByteArray _data;
    QString _path;
    QByteArray m_base64;
;

#endif // UFILE_H

*.cpp

#include "ufile.h"
#include <QDir>
#include <QUrl>

UFile::UFile(QObject *parent) : QObject(parent)



QByteArray UFile::data() const
    return _data;

QString UFile::path() const
    return _path;

int UFile::length() const
    int i =_data.count();
    return i;

void UFile::setPath(const QString &path)
    if(_path== path)
        return;
    
    _path = path;
    readFile(_path);
    Q_EMIT pathChanged(_path);
    Q_EMIT dataChanged();
    Q_EMIT base64Changed();


QString UFile::base64() const

    return _data.toBase64();


void UFile::readFile(const QString &filePath)
    if(!filePath.isEmpty())
        QString _fp = filePath;
        if(_fp.startsWith("file:///"))
            _fp = QUrl(filePath).toLocalFile();
        if(!_fp.isEmpty())
            _fp = QDir::toNativeSeparators(_fp);
            QFile file(_fp);
            if (!file.open(QIODevice::ReadOnly))
                return ;
            _data = file.readAll();
        
    

*.qml


UFile
    id: uifile
    path : "C:/icon.ico"

Image 
    source: uifile.base64.length > 0 ? "data:image/png;base64," + uifile.base64: ""

【讨论】:

我会试试的,我认为这会起作用我在网络上做了类似的事情 你能解释一下你是怎么想出"data:image/png;base64,"的吗? Image.source 是一个 QUrl,因此它支持标准 URI,根据:rfc-editor.org/rfc/rfc2397

以上是关于在 Qml 中从字节数组加载到图像的主要内容,如果未能解决你的问题,请参考以下文章

从 YUV 字节数组中获取像素矩阵

使用 JavaFX 将 BMP 加载到字节数组中

在 Flutter/Dart 中从字节加载图像的问题

图像到字节数组失败“GDI+ 中发生一般错误。”

jpeg 标头的字节数组

以编程方式将资源加载为字节数组