将 QML 图像保存在 c++ 中

Save QML image inside c++

本文关键字:c++ 存在 保存 QML 图像      更新时间:2023-10-16

我正在尝试使用 qml 显示网络图像,然后使用 c++ 代码保存此图像,

这是 qml 代码,

import QtQuick 2.3
import QtQuick.Window 2.2
import com.login 1.0
Window {
    visible: true
    width : 500
    height: 500
     Login{id: login}
    MouseArea {
        anchors.fill: parent
        onClicked: {
          //  Qt.quit();
            login.save(image);
        }
    }

    Image {
        id: image
        source: "http://www.test.com/webp/gallery/4.jpg"
    }

}

在我的登录类中保存图像,例如,

void Login::save( QQuickItem *item)
{
    qDebug()<<"width: "<<item->width();
    qDebug()<<"height: "<<item->height();
    QQuickWindow *window = item->window();
    QImage image = window->grabWindow();
    QPixmap pix = QPixmap::fromImage(image);
    pix.save("C:/Users/haris/Desktop/output.png");
}

我在 c++ 类中获得了图像的正确宽度和高度,但问题是我找不到从 QQuickItem 保存图像项的方法。

现在我正在通过抓取窗口来保存图像,该窗口实际上没有给出输出文件的实际图像大小,而是提供具有当前 qml 窗口大小的输出文件。

基本上我按照这里的代码保存 QML 图像,但似乎QDeclarativeItem Qt5 中已弃用,所以我选择了QQuickItem,因为 QQuickItem 中没有绘画选项。

幸运的是,QQuickItem有一个方便的grabToImage函数来做到这一点。

void Login::save( QQuickItem *item)
{
    QSharedPointer<const QQuickItemGrabResult> grabResult = item->grabToImage();
    connect(grabResult.data(), &QQuickItemGrabResult::ready, [=]() {
        grabResult->saveToFile("C:/Users/haris/Desktop/output.png");
        //grabResult->image() gives the QImage associated if you want to use it directly in the program
    });
}

不使用 lambda 的替代解决方案:

void Login::save( QQuickItem *item)
{
    QSharedPointer<const QQuickItemGrabResult> grabResult = item->grabToImage();
    
    /* Need to store grabResult somewhere persistent to avoid the SharedPointer mechanism from deleting it */
    ...
    connect(grabResult.data(), SIGNAL(ready()), this, SLOT(onAsynchroneousImageLoaded()));
}
void Login::onAsynchroneousImageLoaded() {
    auto grabResult = qobject_cast<const QQuickItemGrabResult*>(sender());
    if (grabResult) {
        grabResult->saveToFile("C:/Users/haris/Desktop/output.png");
    } else {
        //something went wrong
    }
});

在 QObject 派生类 (ImageSaver) 中,请像往常一样注册它。它需要一个成员:

bool ImageSaver::saveImage(const QUrl &imageProviderUrl, const QString &filename){
    qDebug() << Q_FUNC_INFO <<imageProviderUrl << filename;
    QQmlEngine *engine = QQmlEngine::contextForObject(this)->engine();
    QQmlImageProviderBase *imageProviderBase = engine->imageProvider(imageProviderUrl.host());
    QQuickImageProvider *imageProvider = static_cast<QQuickImageProvider*>(imageProviderBase);
    QSize imageActualSize;
    QSize imageRequestedSize;
QString imageId = imageProviderUrl.path().remove(0,1);
    QImage image = imageProvider->requestImage(imageId, &imageActualSize, imageRequestedSize);
    qDebug() << Q_FUNC_INFO << imageId << imageActualSize;
    return image.save(filename);
}

然后在 QML 中:

ImageSaver { id: imageSaver} 
...
imageSaver.saveImage(image.source, "my.png");
...

虽然 grabToImage 将使用项目的大小抓取项目,但这可以保留图像的实际大小。