Fix GIF image decoding: do not zero transparent pixels
authoraavit <eirik.aavitsland@digia.com>
Wed, 7 Nov 2012 14:19:20 +0000 (15:19 +0100)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Fri, 9 Nov 2012 15:07:51 +0000 (16:07 +0100)
For the special transparent color index, the decoder would skip
writing anything out (thus leaving the pixels at 0 rgba value).
Although correct for later frames, for the initial frame this would
loose the color information for such pixels (which one otherwise
could have made visible e.g. by converting then image to an
alpha-less image format).

Change-Id: I316cefce8f21797feedebfbf98296ad84eaa4b99
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
(cherry picked from qt/c309d424f45dc0e7b62fbbbabf20dbfe355f48a7)
Reviewed-by: aavit <eirik.aavitsland@digia.com>
src/gui/image/qgifhandler.cpp
tests/auto/gui/image/qimagereader/images/trans.gif [new file with mode: 0644]
tests/auto/gui/image/qimagereader/tst_qimagereader.cpp

index cedb27c..b60d1a1 100644 (file)
@@ -488,7 +488,7 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
                 } else {
                     if (needfirst) {
                         firstcode=oldcode=code;
-                        if (!out_of_bounds && image->height() > y && firstcode!=trans_index)
+                        if (!out_of_bounds && image->height() > y && ((frame == 0) || (firstcode != trans_index)))
                             ((QRgb*)FAST_SCAN_LINE(bits, bpl, y))[x] = color(firstcode);
                         x++;
                         if (x>=swidth) out_of_bounds = true;
@@ -540,17 +540,13 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
                         }
                         oldcode=incode;
                         const int h = image->height();
-                        const QRgb *map = lcmap ? localcmap : globalcmap;
                         QRgb *line = 0;
                         if (!out_of_bounds && h > y)
                             line = (QRgb*)FAST_SCAN_LINE(bits, bpl, y);
                         while (sp>stack) {
                             const uchar index = *(--sp);
-                            if (!out_of_bounds && h > y && index!=trans_index) {
-                                if (index > ncols)
-                                    line[x] = Q_TRANSPARENT;
-                                else
-                                    line[x] = map ? map[index] : 0;
+                            if (!out_of_bounds && h > y && ((frame == 0) || (index != trans_index))) {
+                                line[x] = color(index);
                             }
                             x++;
                             if (x>=swidth) out_of_bounds = true;
@@ -1031,11 +1027,12 @@ void QGIFFormat::nextY(unsigned char *bits, int bpl)
 
 inline QRgb QGIFFormat::color(uchar index) const
 {
-    if (index == trans_index || index > ncols)
+    if (index > ncols)
         return Q_TRANSPARENT;
 
     QRgb *map = lcmap ? localcmap : globalcmap;
-    return map ? map[index] : 0;
+    QRgb col = map ? map[index] : 0;
+    return index == trans_index ? col & Q_TRANSPARENT : col;
 }
 
 //-------------------------------------------------------------------------
diff --git a/tests/auto/gui/image/qimagereader/images/trans.gif b/tests/auto/gui/image/qimagereader/images/trans.gif
new file mode 100644 (file)
index 0000000..e26398a
Binary files /dev/null and b/tests/auto/gui/image/qimagereader/images/trans.gif differ
index 8965cbd..57aaeb9 100644 (file)
@@ -756,6 +756,15 @@ void tst_QImageReader::gifHandlerBugs()
         QVERIFY(io.canRead());
         QCOMPARE(io.loopCount(), -1);
     }
+
+    // Check that pixels with the transparent color are transparent but not zeroed
+    {
+        QImageReader io(prefix + "trans.gif");
+        QVERIFY(io.canRead());
+        QImage im = io.read();
+        QCOMPARE(im.pixel(0,0), qRgba(0x3f, 0xff, 0x7f, 0x00));
+        QCOMPARE(im.pixel(10,10), qRgba(0x3f, 0xff, 0x7f, 0x00));
+    }
 }
 
 void tst_QImageReader::animatedGif()