From b9b1d0c5ae9ff9a8799616acd7165565afbd2337 Mon Sep 17 00:00:00 2001
From: aavit <qt-info@nokia.com>
Date: Thu, 17 Mar 2011 11:16:16 +0100
Subject: Fixes: some text fields in PNG image files were not read

Text chunks placed after the real image data (IDAT chunks) were ignored.

Reviewed-by: Kim
---
 src/gui/image/qpnghandler.cpp                |  65 ++++++++++++++++-----------
 tests/auto/qimagereader/images/txts.png      | Bin 0 -> 5413 bytes
 tests/auto/qimagereader/qimagereader.qrc     |   1 +
 tests/auto/qimagereader/tst_qimagereader.cpp |  28 ++++++++++++
 4 files changed, 68 insertions(+), 26 deletions(-)
 create mode 100755 tests/auto/qimagereader/images/txts.png

diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index a9aad51..450e8c6 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -109,6 +109,7 @@ public:
 
     bool readPngHeader();
     bool readPngImage(QImage *image);
+    void readPngTexts(png_info *info);
 
     QImage::Format readImageFormat();
 
@@ -359,6 +360,39 @@ static void CALLBACK_CALL_TYPE qt_png_warning(png_structp /*png_ptr*/, png_const
 }
 #endif
 
+
+/*!
+    \internal
+*/
+void Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngTexts(png_info *info)
+{
+#ifndef QT_NO_IMAGE_TEXT
+    png_textp text_ptr;
+    int num_text=0;
+    png_get_text(png_ptr, info, &text_ptr, &num_text);
+
+    while (num_text--) {
+        QString key, value;
+        key = QString::fromLatin1(text_ptr->key);
+#if defined(PNG_iTXt_SUPPORTED)
+        if (text_ptr->itxt_length) {
+            value = QString::fromUtf8(text_ptr->text, int(text_ptr->itxt_length));
+        } else
+#endif
+        {
+            value = QString::fromLatin1(text_ptr->text, int(text_ptr->text_length));
+        }
+        if (!description.isEmpty())
+            description += QLatin1String("\n\n");
+        description += key + QLatin1String(": ") + value.simplified();
+        readTexts.append(key);
+        readTexts.append(value);
+        text_ptr++;
+    }
+#endif
+}
+
+
 /*!
     \internal
 */
@@ -394,30 +428,7 @@ bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngHeader()
     png_set_read_fn(png_ptr, this, iod_read_fn);
     png_read_info(png_ptr, info_ptr);
 
-#ifndef QT_NO_IMAGE_TEXT
-    png_textp text_ptr;
-    int num_text=0;
-    png_get_text(png_ptr,info_ptr,&text_ptr,&num_text);
-
-    while (num_text--) {
-        QString key, value;
-        key = QString::fromLatin1(text_ptr->key);
-#if defined(PNG_iTXt_SUPPORTED)
-        if (text_ptr->itxt_length) {
-            value = QString::fromUtf8(text_ptr->text, int(text_ptr->itxt_length));
-        } else
-#endif
-        {
-            value = QString::fromLatin1(QByteArray(text_ptr->text, int(text_ptr->text_length)));
-        }
-        if (!description.isEmpty())
-            description += QLatin1String("\n\n");
-        description += key + QLatin1String(": ") + value.simplified();
-        readTexts.append(key);
-        readTexts.append(value);
-        text_ptr++;
-    }
-#endif
+    readPngTexts(info_ptr);
 
     state = ReadHeader;
     return true;
@@ -492,11 +503,13 @@ bool Q_INTERNAL_WIN_NO_THROW QPngHandlerPrivate::readPngImage(QImage *outImage)
     outImage->setDotsPerMeterX(png_get_x_pixels_per_meter(png_ptr,info_ptr));
     outImage->setDotsPerMeterY(png_get_y_pixels_per_meter(png_ptr,info_ptr));
 
+    state = ReadingEnd;
+    png_read_end(png_ptr, end_info);
+
+    readPngTexts(end_info);
     for (int i = 0; i < readTexts.size()-1; i+=2)
         outImage->setText(readTexts.at(i), readTexts.at(i+1));
 
-    state = ReadingEnd;
-    png_read_end(png_ptr, end_info);
     png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
     delete [] row_pointers;
     png_ptr = 0;
diff --git a/tests/auto/qimagereader/images/txts.png b/tests/auto/qimagereader/images/txts.png
new file mode 100755
index 0000000..99be1eb
Binary files /dev/null and b/tests/auto/qimagereader/images/txts.png differ
diff --git a/tests/auto/qimagereader/qimagereader.qrc b/tests/auto/qimagereader/qimagereader.qrc
index 5536b38..632b73a 100644
--- a/tests/auto/qimagereader/qimagereader.qrc
+++ b/tests/auto/qimagereader/qimagereader.qrc
@@ -64,5 +64,6 @@
         <file>images/corrupt.svg</file>
         <file>images/corrupt.svgz</file>
         <file>images/qtbug13653-no_eoi.jpg</file>
+        <file>images/txts.png</file>
     </qresource>
 </RCC>
diff --git a/tests/auto/qimagereader/tst_qimagereader.cpp b/tests/auto/qimagereader/tst_qimagereader.cpp
index f02fd6a..5db5f56 100644
--- a/tests/auto/qimagereader/tst_qimagereader.cpp
+++ b/tests/auto/qimagereader/tst_qimagereader.cpp
@@ -183,6 +183,9 @@ private slots:
     void saveFormat_data();
     void saveFormat();
 
+    void readText_data();
+    void readText();
+
     void preserveTexts_data();
     void preserveTexts();
 };
@@ -1968,6 +1971,31 @@ void tst_QImageReader::saveFormat()
 }
 
 
+void tst_QImageReader::readText_data()
+{
+    QTest::addColumn<QString>("fileName");
+    QTest::addColumn<QString>("key");
+    QTest::addColumn<QString>("text");
+
+    QTest::newRow("png, tEXt before img") << "txts.png" << "Title" << "PNG";
+    QTest::newRow("png, zTXt before img") << "txts.png" << "Comment" << "Some compressed text.";
+    QTest::newRow("png, tEXt after img") << "txts.png" << "Disclaimer" << "For testing only.";
+    QTest::newRow("png, zTXt after img") << "txts.png" << "Description" << "Rendered by Persistence of Vision (tm) Ray Tracer";
+}
+
+
+void tst_QImageReader::readText()
+{
+    QFETCH(QString, fileName);
+    QFETCH(QString, key);
+    QFETCH(QString, text);
+
+    QImage img(prefix + fileName);
+    QVERIFY(img.textKeys().contains(key));
+    QCOMPARE(img.text(key), text);
+}
+
+
 void tst_QImageReader::preserveTexts_data()
 {
     QTest::addColumn<QString>("text");
-- 
cgit v0.12