summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEirik Aavitsland <eirik.aavitsland@qt.io>2022-09-08 14:52:19 +0200
committerEirik Aavitsland <eirik.aavitsland@qt.io>2022-09-13 07:25:47 +0200
commit369be99d82a7c1182e3693756ab545cea86bb90d (patch)
treec754df4db7f64cd272ad48fe6e7953528b7dbafb /src
parentc5f837d59e1ebc628aa8393c49587795746dab7e (diff)
downloadqtimageformats-369be99d82a7c1182e3693756ab545cea86bb90d.tar.gz
webp: support sequential input device if full file is available
Since we do no random access during decoding, just a readAll() of the whole image file. So if it is all available already, we can handle a sequential device. That is useful for Quick AnimationImage, which will pass a finished QNetworkReply as the input device. This commit removes some seek() calls in the header checking, that supposedly should reset the device position. These were in practice either no-ops or bugs, since the device is only being peeked, so the position never changes in the first place, and a QImageIOHandler is supposed to read from the device at the position it is at when passed. Fixes: QTBUG-70245 Change-Id: I5a4ff5fa4bbd19b0545ad41645969d714b4dc7d5 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io> Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/imageformats/webp/qwebphandler.cpp29
1 files changed, 14 insertions, 15 deletions
diff --git a/src/plugins/imageformats/webp/qwebphandler.cpp b/src/plugins/imageformats/webp/qwebphandler.cpp
index 59513f6..922868c 100644
--- a/src/plugins/imageformats/webp/qwebphandler.cpp
+++ b/src/plugins/imageformats/webp/qwebphandler.cpp
@@ -9,6 +9,7 @@
#include <qdebug.h>
#include <qpainter.h>
#include <qvariant.h>
+#include <QtEndian>
static const int riffHeaderSize = 12; // RIFF_HEADER_SIZE from webp/format_constants.h
@@ -66,21 +67,23 @@ bool QWebpHandler::ensureScanned() const
m_scanState = ScanError;
- if (device()->isSequential()) {
- qWarning() << "Sequential devices are not supported";
+ QWebpHandler *that = const_cast<QWebpHandler *>(this);
+ const int headerBytesNeeded = sizeof(WebPBitstreamFeatures);
+ QByteArray header = device()->peek(headerBytesNeeded);
+ if (header.size() < headerBytesNeeded)
return false;
- }
- qint64 oldPos = device()->pos();
- device()->seek(0);
-
- QWebpHandler *that = const_cast<QWebpHandler *>(this);
- QByteArray header = device()->peek(sizeof(WebPBitstreamFeatures));
+ // We do no random access during decoding, just a readAll() of the whole image file. So if
+ // if it is all available already, we can accept a sequential device. The riff header contains
+ // the file size minus 8 bytes header
+ qint64 byteSize = qFromLittleEndian<quint32>(header.constData() + 4);
+ if (device()->isSequential() && device()->bytesAvailable() < byteSize + 8) {
+ qWarning() << "QWebpHandler: Insufficient data available in sequential device";
+ return false;
+ }
if (WebPGetFeatures((const uint8_t*)header.constData(), header.size(), &(that->m_features)) == VP8_STATUS_OK) {
if (m_features.has_animation) {
// For animation, we have to read and scan whole file to determine loop count and images count
- device()->seek(oldPos);
-
if (that->ensureDemuxer()) {
that->m_loop = WebPDemuxGetI(m_demuxer, WEBP_FF_LOOP_COUNT);
that->m_frameCount = WebPDemuxGetI(m_demuxer, WEBP_FF_FRAME_COUNT);
@@ -93,17 +96,13 @@ bool QWebpHandler::ensureScanned() const
if (that->m_features.has_alpha)
that->m_composited->fill(Qt::transparent);
- // We do not reset device position since we have read in all data
m_scanState = ScanSuccess;
- return true;
}
} else {
m_scanState = ScanSuccess;
}
}
- device()->seek(oldPos);
-
return m_scanState == ScanSuccess;
}
@@ -126,7 +125,7 @@ bool QWebpHandler::ensureDemuxer()
bool QWebpHandler::read(QImage *image)
{
- if (!ensureScanned() || device()->isSequential() || !ensureDemuxer())
+ if (!ensureScanned() || !ensureDemuxer())
return false;
QRect prevFrameRect;