summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/imageformats/gif/qgifhandler.cpp38
-rw-r--r--tests/auto/qimagereader/images/qt-gif-anim.gifbin0 -> 1661 bytes
-rw-r--r--tests/auto/qimagereader/images/qt-gif-noanim.gifbin0 -> 1642 bytes
-rw-r--r--tests/auto/qimagereader/qimagereader.qrc4
-rw-r--r--tests/auto/qimagereader/tst_qimagereader.cpp14
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
new file mode 100644
index 0000000..8bca4a8
--- /dev/null
+++ b/tests/auto/qimagereader/images/qt-gif-anim.gif
Binary files differ
diff --git a/tests/auto/qimagereader/images/qt-gif-noanim.gif b/tests/auto/qimagereader/images/qt-gif-noanim.gif
new file mode 100644
index 0000000..b6a8540
--- /dev/null
+++ b/tests/auto/qimagereader/images/qt-gif-noanim.gif
Binary files differ
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