目前 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 要编译全部源码。如有其它问题,欢迎各位大佬指导