Qt Webp qml 动图在线加载失败解决办法

目前 webp 图片格式大行其道,Qt 已经支持了,只是在线 webp 动图在 QML (AnimatedImage), 不能加载,向Qt提bug(https://bugreports.qt.io/browse/QTBUG-75044),也不理采,只能自己动手丰衣足食了。

import QtQuick 2.9
import QtQuick.Window 2.2

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

    Column {
        anchors.centerIn: parent
        // error
        AnimatedImage {
            source: "https://p.upyun.com/demo/webp/webp/animated-gif-0.webp"
            Text {
                text: qsTr("AnimatedImage online webp animation image")
                color: "red"
            }
        }

        // ok
        Image {
            source: "https://p.upyun.com/demo/webp/webp/animated-gif-0.webp"
            Text {
                text: qsTr("Image webp online animation image")
                color: "red"
            }
        }

        // ok
        AnimatedImage {
            source: "qrc:/image/animated-gif-0.webp"
            Text {
                text: qsTr("AnimatedImage webp local animation image")
                color: "red"
            }
        }
    }
}

在线动图会加载失败,报错如下:

QNetworkReplyHttpImplPrivate::_q_startOperation was called more than once QUrl("https://p.upyun.com/demo/webp/webp/animated-gif-0.webp") Sequential devices are not supported qrc:/main.qml:13:9: QML AnimatedImage: Error Reading Animated Image File https://p.upyun.com/demo/webp/webp/animated-gif-0.webp

查看源码发现在线webp 从网络下载 图片缓存在 QNetworkReply, 然而webp 从 QNetworkRreply 解码因为 QNetworkRreply isSequential 失败导致。

解决办法,修改源码(Src\qtdeclarative\src\quick\items\qquickanimatedimage.cpp)

找到函数:movieRequestFinished

把QNetworkRreply人webp动图的内容存到QBuffer里面,然后再用于解码加载

// 修改前
#if QT_CONFIG(qml_network)
    if (d->reply) {
        d->redirectCount++;
        if (d->redirectCount < ANIMATEDIMAGE_MAXIMUM_REDIRECT_RECURSION) {
            QVariant redirect = d->reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
            if (redirect.isValid()) {
                QUrl url = d->reply->url().resolved(redirect.toUrl());
                d->reply->deleteLater();
                setSource(url);
                return;
            }
        }

        d->redirectCount=0;
        d->setMovie(new QMovie(d->reply));
    }
#endif

// 修改后
#if QT_CONFIG(qml_network)
    if (d->reply) {
        d->redirectCount++;
        if (d->redirectCount < ANIMATEDIMAGE_MAXIMUM_REDIRECT_RECURSION) {
            QVariant redirect = d->reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
            if (redirect.isValid()) {
                QUrl url = d->reply->url().resolved(redirect.toUrl());
                d->reply->deleteLater();
                setSource(url);
                return;
            }
        }

        d->redirectCount=0;
        // for webp animation
        static const int riffHeaderSize = 12; // RIFF_HEADER_SIZE from webp/format_constants.h
        QByteArray header = d->reply->peek(riffHeaderSize);
        if(header.startsWith("RIFF") && header.endsWith("WEBP")) {
            //qmlWarning(this) << "=============================== QFile replace d->reply";
            QBuffer *imgBuf = new QBuffer(this);
            imgBuf->setData(d->reply->readAll());
            d->setMovie(new QMovie(imgBuf));
        } else {
            d->setMovie(new QMovie(d->reply));
        }
    }
#endif

 然后编译,直接替换Qt5Quick库

注意: windows android 可以有直接编译 qtdeclarative 模块, ios 要编译全部源码。如有其它问题,欢迎各位大佬指导

猜你喜欢

转载自blog.csdn.net/cbdg3757/article/details/89840973
今日推荐