利用QQuickImageProvider发送cv::Mat及QImage图片至qml上显示

第一步,继承QQuickImageProvider

新建一个类继承QQuickImageProvider,并重写函数 requestImage 及 requestPixmap。

class ImageProvider : public QQuickImageProvider
{
public:
    ImageProvider();
    QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize);
    QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize);

    QImage img;
};
ImageProvider::ImageProvider() : QQuickImageProvider(QQuickImageProvider::Image)
{
}

QImage ImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
{
    return this->img;
}

QPixmap ImageProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
{
    return QPixmap::fromImage(this->img);
}

第二步,新建一个类用来调用QQuickImageProvider继承类

这里主要是调用第一步创建的继承类ImageProvider ,创建三个函数用来处理Mat、QImage、QString图片路径。

class ShowImage : public QObject
{
    Q_OBJECT
public:
    ShowImage();
    ~ShowImage();
    ImageProvider *m_pImgProvider;
    QImage cvMat2QImage(cv::Mat mat);

public slots:
    void sendimage(QImage);
    void sendimage(cv::Mat);
    void sendimage(QString);

private:

signals:
    void callQmlRefreshImg();
};

第三步,写一个Demo用来测试

创建一个线程,循环显示三张图片,分别用三种格式向qml发送图片。

void Demo::run()
{
    // 拿三张图片用来测试
    QStringList imageList;
    imageList << "E:/work/Image/Dog/1.jpg"
    << "E:/work/Image/Dog/2.jpeg"
    << "E:/work/Image/Dog/3.jpeg";

    int currentIndex = 0;
    while(demoRunning){
        if(currentIndex == 0){
            currentIndex = 1;
            showImage->sendimage(imageList[0]);
        } else if(currentIndex == 1){
            currentIndex = 2;
            cv::Mat mat = cv::imread(imageList[1].toStdString().data());
            showImage->sendimage(mat);
        } else {
            currentIndex = 0;
            QImage image(imageList[2]);
            showImage->sendimage(image);
        }
        sleep(4);
    }
}

源码

ImageToQml.h

#ifndef IMAGETOQML_H
#define IMAGETOQML_H


#include <QObject>
#include <QDebug>
#include <QPixmap>
#include <QImage>
#include <QQuickImageProvider>
#include <opencv.hpp>


class ImageProvider : public QQuickImageProvider
{
public:
    ImageProvider();
    QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize);
    QPixmap requestPixmap(const QString &id, QSize *size, const QSize &requestedSize);

    QImage img;
};

class ShowImage : public QObject
{
    Q_OBJECT
public:
    ShowImage();
    ~ShowImage();
    ImageProvider *m_pImgProvider;
    QImage cvMat2QImage(cv::Mat mat);

public slots:
    void sendimage(QImage);
    void sendimage(cv::Mat);
    void sendimage(QString);

private:

signals:
    void callQmlRefreshImg();
};

#endif // IMAGETOQML_H

ImageToQml.cpp

#include "ImageToQml.h"


ImageProvider::ImageProvider() : QQuickImageProvider(QQuickImageProvider::Image)
{
}

QImage ImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
{
    return this->img;
}

QPixmap ImageProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
{
    return QPixmap::fromImage(this->img);
}

ShowImage::ShowImage()
{
    m_pImgProvider = new ImageProvider();
}

ShowImage::~ShowImage()
{
    if(m_pImgProvider != nullptr){
        delete m_pImgProvider;
        m_pImgProvider = nullptr;
    }
}

void ShowImage::sendimage(QImage img)
{
    m_pImgProvider->img = img;
    emit callQmlRefreshImg();//告诉qml刷新一下。
}

void ShowImage::sendimage(cv::Mat mat)
{
    QImage img = cvMat2QImage(mat);
    sendimage(img);
}

void ShowImage::sendimage(QString imgFile)
{
    QImage img(imgFile);
    sendimage(img);
}

QImage ShowImage::cvMat2QImage(cv::Mat mat)
{
    switch(mat.type()){
    case CV_8UC1:{
        QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);
        image.setColorCount(256);
        for(int i = 0; i < 256; i++){
            image.setColor(i,qRgb(i,i,i));
        }
        uchar *pSrc = mat.data;
        for(int row = 0; row < mat.rows; row++){
            uchar *pDest = image.scanLine(row);
            memcpy(pDest, pSrc,mat.cols);
            pSrc += mat.step;
        }
        return image;
    }
    case CV_8UC3:{
        const uchar *pSrc = (const uchar*)mat.data;
        QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
        return image.rgbSwapped();
    }
    case CV_8UC4:{
        const uchar *pSrc = (const uchar*)mat.data;
        QImage image(pSrc,mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
        return image.copy();
        break;
    }
    default:
        return QImage();
    }
}

Demo.h

#ifndef DEMO_H
#define DEMO_H

#include <QObject>
#include <QThread>
#include <opencv.hpp>
#include "ImageToQml.h"

class Demo : public QThread
{
    Q_OBJECT
public:
    explicit Demo(QObject *parent = nullptr);
    ~Demo();
    void startDemo();

    ShowImage *getShowImage() { return showImage; }

protected:
    void run();

private:
    ShowImage *showImage = NULL;
    bool demoRunning = false;

signals:
    void sigRefreshImage();

};

#endif // DEMO_H

Demo.cpp

#include "Demo.h"

Demo::Demo(QObject *parent) : QThread(parent)
{
    showImage = new ShowImage();
    connect(showImage, SIGNAL(callQmlRefreshImg()), this, SIGNAL(sigRefreshImage()));
}

Demo::~Demo()
{
    showImage->deleteLater();
    showImage = NULL;
    demoRunning = false;
    this->quit();
    this->wait();
}

void Demo::startDemo()
{
    demoRunning = true;
    this->start();
}

void Demo::run()
{
    // 拿三张图片用来测试
    QStringList imageList;
    imageList << "E:/work/Image/Dog/1.jpg"
    << "E:/work/Image/Dog/2.jpeg"
    << "E:/work/Image/Dog/3.jpeg";

    int currentIndex = 0;
    while(demoRunning){
        if(currentIndex == 0){
            currentIndex = 1;
            showImage->sendimage(imageList[0]);
        } else if(currentIndex == 1){
            currentIndex = 2;
            cv::Mat mat = cv::imread(imageList[1].toStdString().data());
            showImage->sendimage(mat);
        } else {
            currentIndex = 0;
            QImage image(imageList[2]);
            showImage->sendimage(image);
        }
        sleep(4);
    }
}

main.cpp

#include <QQmlContext>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <Demo.h>

int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif

    QGuiApplication app(argc, argv);

    QQmlApplicationEngine engine;

    Demo demo;
    demo.startDemo();
    engine.rootContext()->setContextProperty("Demo", &demo);
    engine.addImageProvider(QLatin1String("MyImg"), demo.getShowImage()->m_pImgProvider);

    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);

    return app.exec();
}

main.qml

import QtQuick 2.12
import QtQuick.Window 2.12

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    Image {
        id: image
        anchors.fill: parent
        anchors.centerIn: parent
        fillMode: Image.PreserveAspectFit
        cache: false
    }

    Connections {
        target: Demo
        function onSigRefreshImage() {
            image.source = ""
            image.source = "image://MyImg"
        }
    }
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值