diff options
-rw-r--r-- | src/plugins/imageformats/gif/qgifhandler.cpp | 38 | ||||
-rw-r--r-- | tests/auto/qimagereader/images/qt-gif-anim.gif | bin | 0 -> 1661 bytes | |||
-rw-r--r-- | tests/auto/qimagereader/images/qt-gif-noanim.gif | bin | 0 -> 1642 bytes | |||
-rw-r--r-- | tests/auto/qimagereader/qimagereader.qrc | 4 | ||||
-rw-r--r-- | tests/auto/qimagereader/tst_qimagereader.cpp | 14 |
5 files changed, 47 insertions, 9 deletions
diff --git a/src/plugins/imageformats/gif/qgifhandler.cpp b/src/plugins/imageformats/gif/qgifhandler.cpp index 6d473e3..25d3dfa 100644 --- a/src/plugins/imageformats/gif/qgifhandler.cpp +++ b/src/plugins/imageformats/gif/qgifhandler.cpp @@ -72,7 +72,7 @@ public: int decode(QImage *image, const uchar* buffer, int length, int *nextFrameDelay, int *loopCount); - static void scan(QIODevice *device, QVector<QSize> *imageSizes); + static void scan(QIODevice *device, QVector<QSize> *imageSizes, int *loopCount); bool newFrame; bool partialNewFrame; @@ -646,7 +646,7 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length, Scans through the data stream defined by \a device and returns the image sizes found in the stream in the \a imageSizes vector. */ -void QGIFFormat::scan(QIODevice *device, QVector<QSize> *imageSizes) +void QGIFFormat::scan(QIODevice *device, QVector<QSize> *imageSizes, int *loopCount) { if (!device) return; @@ -842,7 +842,10 @@ void QGIFFormat::scan(QIODevice *device, QVector<QSize> *imageSizes) hold[count] = ch; ++count; if (count == hold[0] + 1) { - state = SkipBlockSize; + if (qstrncmp((char*)(hold+1), "NETSCAPE", 8) == 0) + state=NetscapeExtensionBlockSize; + else + state=SkipBlockSize; count = 0; } break; @@ -855,7 +858,23 @@ void QGIFFormat::scan(QIODevice *device, QVector<QSize> *imageSizes) state = SkipBlockSize; } break; - case NetscapeExtensionBlockSize: // fallthrough + case NetscapeExtensionBlockSize: + blockSize = ch; + count = 0; + if (blockSize) + state = NetscapeExtensionBlock; + else + state = Introducer; + break; + case NetscapeExtensionBlock: + if (count < 3) + hold[count] = ch; + count++; + if (count == blockSize) { + *loopCount = LM(hold[1], hold[2]); + state = SkipBlockSize; + } + break; case SkipBlockSize: blockSize = ch; count = 0; @@ -871,7 +890,6 @@ void QGIFFormat::scan(QIODevice *device, QVector<QSize> *imageSizes) state = Introducer; } break; - case NetscapeExtensionBlock: // fallthrough case SkipBlock: ++count; if (count == blockSize) @@ -1009,7 +1027,7 @@ QGifHandler::QGifHandler() { gifFormat = new QGIFFormat; nextDelay = 0; - loopCnt = 0; + loopCnt = 1; frameNumber = -1; scanIsCached = false; } @@ -1109,7 +1127,7 @@ QVariant QGifHandler::option(ImageOption option) const { if (option == Size) { if (!scanIsCached) { - QGIFFormat::scan(device(), &imageSizes); + QGIFFormat::scan(device(), &imageSizes, &loopCnt); scanIsCached = true; } // before the first frame is read, or we have an empty data stream @@ -1140,7 +1158,7 @@ int QGifHandler::nextImageDelay() const int QGifHandler::imageCount() const { if (!scanIsCached) { - QGIFFormat::scan(device(), &imageSizes); + QGIFFormat::scan(device(), &imageSizes, &loopCnt); scanIsCached = true; } return imageSizes.count(); @@ -1148,6 +1166,10 @@ int QGifHandler::imageCount() const int QGifHandler::loopCount() const { + if (!scanIsCached) { + QGIFFormat::scan(device(), &imageSizes, &loopCnt); + scanIsCached = true; + } return loopCnt-1; // In GIF, loop count is iteration count, so subtract one } diff --git a/tests/auto/qimagereader/images/qt-gif-anim.gif b/tests/auto/qimagereader/images/qt-gif-anim.gif Binary files differnew file mode 100644 index 0000000..8bca4a8 --- /dev/null +++ b/tests/auto/qimagereader/images/qt-gif-anim.gif diff --git a/tests/auto/qimagereader/images/qt-gif-noanim.gif b/tests/auto/qimagereader/images/qt-gif-noanim.gif Binary files differnew file mode 100644 index 0000000..b6a8540 --- /dev/null +++ b/tests/auto/qimagereader/images/qt-gif-noanim.gif diff --git a/tests/auto/qimagereader/qimagereader.qrc b/tests/auto/qimagereader/qimagereader.qrc index 58f2f74..bc48244 100644 --- a/tests/auto/qimagereader/qimagereader.qrc +++ b/tests/auto/qimagereader/qimagereader.qrc @@ -1,5 +1,5 @@ <RCC> - <qresource prefix="/" > + <qresource prefix="/"> <file>images/16bpp.bmp</file> <file>images/4bpp-rle.bmp</file> <file>images/YCbCr_cmyk.jpg</file> @@ -59,5 +59,7 @@ <file>images/qt8.gif</file> <file>images/endless-anim.gif</file> <file>images/four-frames.gif</file> + <file>images/qt-gif-anim.gif</file> + <file>images/qt-gif-noanim.gif</file> </qresource> </RCC> diff --git a/tests/auto/qimagereader/tst_qimagereader.cpp b/tests/auto/qimagereader/tst_qimagereader.cpp index 3e40527..121a8fa 100644 --- a/tests/auto/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/qimagereader/tst_qimagereader.cpp @@ -142,6 +142,7 @@ private slots: void gifHandlerBugs(); void animatedGif(); void gifImageCount(); + void gifLoopCount(); #endif void readCorruptImage_data(); @@ -884,6 +885,19 @@ void tst_QImageReader::gifImageCount() QVERIFY(io.size() == QSize(128,64)); } } + +void tst_QImageReader::gifLoopCount() +{ + { + QImageReader io(":images/qt-gif-anim.gif"); + QCOMPARE(io.loopCount(), -1); // infinite loop + } + { + QImageReader io(":images/qt-gif-noanim.gif"); + QCOMPARE(io.loopCount(), 0); // no loop + } +} + #endif class Server : public QObject |