0

I am trying to load an image from QML using its source. In main.qml I have:

Image {
    id: photoFiltering
    fillMode: Image.PreserveAspectFit
    width: parent.width
    height: parent.height/2
    anchors.leftMargin: 20
    anchors.rightMargin: 20
    anchors.bottomMargin: 20
}

and

Button{
            id: filtersButtons
            text: "Filter"
            anchors.top: photoFiltering.bottom
            anchors.horizontalCenter: photoFiltering.horizontalCenter
            onClicked: ()=>{
                filterController.setFilterType(filterController.Original);
                var filteredImage = filterController.filterImage(photoFiltering.source);
            }
        }

Thus in my C++ code I ma trying to do the following:

QImage FilterController::filterImage(QString imageSource)
{
    QImage image;
    bool loaded = image.load(imageSource);
    cout << "image laoded " << loaded << endl;
     ...
    return image;
}

The problem is I can't simply load the image like that to get the Object QImage. What Should I do to get that image?

Ahmad Wehbe
  • 53
  • 1
  • 7
  • 1
    Have you looked at [QQuickImageProvider](https://doc.qt.io/qt-6/qquickimageprovider.html)? – JarMan Nov 04 '22 at 17:12

1 Answers1

1

This is one way to retrieve a QImage from a QUrl:

  • Instantiates a QNetworkAccessManager
  • Turns your QUrl into a QNetworkRequest
  • Invokes QNetworkAccessManager::get()
  • Asynchronously wait for the QNetworkAccessManager::finished() signal
  • Use QNetworkReply::readAll() to get the QByteArray
  • Use QImage::loadFromData to populate a QImage

Below is an ImageUtil helper class for doing the above:

//ImageUtil.h
#ifndef __ImageUtil__
#define __ImageUtil__

#include <QObject>
#include <QImage>
#include <QNetworkAccessManager>
#include <QNetworkReply>

class ImageUtil : public QObject
{
    Q_OBJECT
public:
    ImageUtil(QObject* parent = nullptr) :
        QObject(parent),
        m_Manager(new QNetworkAccessManager(this))
    {
        connect(m_Manager, &QNetworkAccessManager::finished, this, &ImageUtil::onFinished);
    }

    const QImage& image() const { return m_Image; }
    Q_INVOKABLE void loadFromUrl(const QUrl& url)
    {
        QNetworkRequest request(url);
        m_Manager->get(request);
    }

signals:
    void loaded();

protected slots:
    void onFinished(QNetworkReply* reply)
    {
        QByteArray data = reply->readAll();
        m_Image.loadFromData(data);
        emit loaded();
    }

protected:
    QImage m_Image;
    QNetworkAccessManager* m_Manager;

};

#endif

This is a test of the class:

void test()
{
    ImageUtil* imageUtil = new ImageUtil();
    imageUtil->loadFromUrl(QUrl("https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"));
    imageUtil->connect(imageUtil, &ImageUtil::loaded,
                       [=]() {
        QImage image = imageUtil->image();
        qDebug() << image.width() << image.height(); // 272 92
    });
}

Please treat the above code as a guide only and do not expect it to stand up in a production environment. For you to do a proper job, you really need to understand:

  • Qt signal/slot mechanism
  • asynchronous programming
  • proper patterns for instantiating and cleaning classes (the test code, in particular, is leaky, so some effort is required to make a proper test)
  • there is no HTTP error handling (invalid HTTP/HTTPS request, poor or no internet connectivity, 404 errors (i.e. no image), HTTPS/SSL certificate errors, other HTTP status errors
  • there is no image handling (the downloaded content may not be a valid image)
Stephen Quan
  • 21,481
  • 4
  • 88
  • 75