Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loading From Byte Array To Image In Qml

Tags:

c++

qt

qml

i created a c++ class in Qt to read files,and convert them to byte array so i can store them in database ,
how can i deal with byte array data for example setting image source in qml ,what is the correct way of converting this byte array to related types in qml

here is my class:

#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;
        }
    }
}

and in qml :

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

i tried to load QImage and set Image source in qml with this lines but it stuck

QImage img; 
img.loadFromData(bytes);

and in qml:

image.source = result of img.loadFromData
like image 757
MoreMag Avatar asked Apr 28 '19 06:04

MoreMag


1 Answers

A possible solution is to convert to base64, and for this you should not use the flag QIODevice::Text, also I have added improvements so that your code is more readable.

*.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: ""
}
like image 97
eyllanesc Avatar answered Nov 04 '22 18:11

eyllanesc