1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29
30#include <QtTest/QtTest>
31
32#include <QBuffer>
33#include <QColorSpace>
34#include <QDebug>
35#include <QImage>
36#include <QImageReader>
37#include <QImageWriter>
38#include <QPixmap>
39#include <QSet>
40#include <QTcpSocket>
41#include <QTcpServer>
42#include <QTimer>
43#include <QTemporaryDir>
44#include <QTemporaryFile>
45
46#include <algorithm>
47
48// #define DEBUG_WRITE_OUTPUT
49
50typedef QMap<QString, QString> QStringMap;
51typedef QList<int> QIntList;
52Q_DECLARE_METATYPE(QImage::Format)
53
54static QByteArray msgFileOpenWriteFailed(const QFile &file)
55{
56 const QString result = QLatin1String("Cannot open \"")
57 + QDir::toNativeSeparators(pathName: file.fileName())
58 + QLatin1String("\" for writing: ") + file.errorString();
59 return result.toLocal8Bit();
60}
61
62static QByteArray msgFileOpenReadFailed(const QFile &file)
63{
64 const QString result = QLatin1String("Cannot open \"")
65 + QDir::toNativeSeparators(pathName: file.fileName())
66 + QLatin1String("\" for reading: ") + file.errorString();
67 return result.toLocal8Bit();
68}
69
70class tst_QImageReader : public QObject
71{
72 Q_OBJECT
73
74public:
75 tst_QImageReader();
76 virtual ~tst_QImageReader();
77
78public slots:
79 void initTestCase();
80 void cleanupTestCase();
81
82private slots:
83 void getSetCheck();
84 void readImage_data();
85 void readImage();
86 void jpegRgbCmyk();
87
88 void setScaledSize_data();
89 void setScaledSize();
90
91 void setClipRect_data();
92 void setClipRect();
93
94 void setScaledClipRect_data();
95 void setScaledClipRect();
96
97 void imageFormat_data();
98 void imageFormat();
99
100 void blackXPM();
101 void transparentXPM();
102 void multiWordNamedColorXPM();
103
104 void supportedFormats();
105 void supportedMimeTypes();
106
107 void readFromDevice_data();
108 void readFromDevice();
109
110 void readFromFileAfterJunk_data();
111 void readFromFileAfterJunk();
112
113 void devicePosition_data();
114 void devicePosition();
115
116 void setBackgroundColor_data();
117 void setBackgroundColor();
118
119 void supportsAnimation_data();
120 void supportsAnimation();
121
122 void readFromResources_data();
123 void readFromResources();
124
125 void sizeBeforeRead_data();
126 void sizeBeforeRead();
127
128 void sizeBeforeFormat_data();
129 void sizeBeforeFormat();
130
131 void imageFormatBeforeRead_data();
132 void imageFormatBeforeRead();
133
134 void gifHandlerBugs();
135 void animatedGif();
136 void gifImageCount();
137 void gifLoopCount();
138
139 void ppmMaxval_data();
140 void ppmMaxval();
141
142 void readCorruptImage_data();
143 void readCorruptImage();
144 void readCorruptBmp();
145
146 void supportsOption_data();
147 void supportsOption();
148
149 void autoDetectImageFormat();
150 void fileNameProbing();
151
152 void pixelCompareWithBaseline_data();
153 void pixelCompareWithBaseline();
154
155 void task255627_setNullScaledSize_data();
156 void task255627_setNullScaledSize();
157
158 void testIgnoresFormatAndExtension_data();
159 void testIgnoresFormatAndExtension();
160
161 void saveFormat_data();
162 void saveFormat();
163
164 void saveColorSpace_data();
165 void saveColorSpace();
166
167 void readText_data();
168 void readText();
169
170 void preserveTexts_data();
171 void preserveTexts();
172
173 void devicePixelRatio_data();
174 void devicePixelRatio();
175
176 void xpmBufferOverflow();
177
178 void xbmBufferHandling();
179
180private:
181 QString prefix;
182 QTemporaryDir m_temporaryDir;
183};
184
185// helper to skip an autotest when the given image format is not supported
186#define SKIP_IF_UNSUPPORTED(format) do { \
187 if (!QByteArray(format).isEmpty() && !QImageReader::supportedImageFormats().contains(format)) \
188 QSKIP('"' + QByteArray(format) + "\" images are not supported"); \
189} while (0)
190
191// Testing get/set functions
192void tst_QImageReader::getSetCheck()
193{
194 QImageReader obj1;
195 // QIODevice * QImageReader::device()
196 // void QImageReader::setDevice(QIODevice *)
197 QFile *var1 = new QFile;
198 obj1.setDevice(var1);
199
200 //A bit strange but that's the only way to compile under windows.
201 QCOMPARE((QIODevice *) var1, obj1.device());
202 obj1.setDevice((QIODevice *)0);
203 QCOMPARE((QIODevice *) 0,
204 obj1.device());
205 delete var1;
206}
207
208tst_QImageReader::tst_QImageReader() :
209 m_temporaryDir(QDir::tempPath() + QStringLiteral("/tst_qimagereaderXXXXXX"))
210{
211 m_temporaryDir.setAutoRemove(true);
212}
213
214tst_QImageReader::~tst_QImageReader()
215{
216
217}
218
219void tst_QImageReader::initTestCase()
220{
221 prefix = QFINDTESTDATA("images/");
222 if (prefix.isEmpty())
223 QFAIL("Can't find images directory!");
224 QVERIFY2(m_temporaryDir.isValid(), qPrintable(m_temporaryDir.errorString()));
225}
226
227void tst_QImageReader::cleanupTestCase()
228{
229}
230
231void tst_QImageReader::readImage_data()
232{
233 QTest::addColumn<QString>(name: "fileName");
234 QTest::addColumn<bool>(name: "success");
235 QTest::addColumn<QByteArray>(name: "format");
236
237 QTest::newRow(dataTag: "empty") << QString() << false << QByteArray();
238 QTest::newRow(dataTag: "BMP: colorful") << QString("colorful.bmp") << true << QByteArray("bmp");
239 QTest::newRow(dataTag: "BMP: test32bfv4") << QString("test32bfv4.bmp") << true << QByteArray("bmp");
240 QTest::newRow(dataTag: "BMP: test32v5") << QString("test32v5.bmp") << true << QByteArray("bmp");
241 QTest::newRow(dataTag: "BMP: font") << QString("font.bmp") << true << QByteArray("bmp");
242 QTest::newRow(dataTag: "BMP: signed char") << QString("crash-signed-char.bmp") << true << QByteArray("bmp");
243 QTest::newRow(dataTag: "BMP: 4bpp RLE") << QString("4bpp-rle.bmp") << true << QByteArray("bmp");
244 QTest::newRow(dataTag: "BMP: 4bpp uncompressed") << QString("tst7.bmp") << true << QByteArray("bmp");
245 QTest::newRow(dataTag: "BMP: 16bpp") << QString("16bpp.bmp") << true << QByteArray("bmp");
246 QTest::newRow(dataTag: "BMP: negative height") << QString("negativeheight.bmp") << true << QByteArray("bmp");
247 QTest::newRow(dataTag: "BMP: high mask bit set") << QString("rgb32bf.bmp") << true << QByteArray("bmp");
248 QTest::newRow(dataTag: "XPM: marble") << QString("marble.xpm") << true << QByteArray("xpm");
249 QTest::newRow(dataTag: "PNG: kollada") << QString("kollada.png") << true << QByteArray("png");
250 QTest::newRow(dataTag: "PNG: kollada 16bpc") << QString("kollada-16bpc.png") << true << QByteArray("png");
251 QTest::newRow(dataTag: "PPM: teapot") << QString("teapot.ppm") << true << QByteArray("ppm");
252 QTest::newRow(dataTag: "PPM: runners") << QString("runners.ppm") << true << QByteArray("ppm");
253 QTest::newRow(dataTag: "PPM: test") << QString("test.ppm") << true << QByteArray("ppm");
254 QTest::newRow(dataTag: "XBM: gnus") << QString("gnus.xbm") << true << QByteArray("xbm");
255 QTest::newRow(dataTag: "PGM: longcomment") << QString("longcomment.pgm") << true << QByteArray("pgm");
256
257 QTest::newRow(dataTag: "JPEG: beavis") << QString("beavis.jpg") << true << QByteArray("jpeg");
258 QTest::newRow(dataTag: "JPEG: qtbug13653") << QString("qtbug13653-no_eoi.jpg") << true << QByteArray("jpeg");
259
260 QTest::newRow(dataTag: "GIF: earth") << QString("earth.gif") << true << QByteArray("gif");
261 QTest::newRow(dataTag: "GIF: trolltech") << QString("trolltech.gif") << true << QByteArray("gif");
262
263 QTest::newRow(dataTag: "SVG: rect") << QString("rect.svg") << true << QByteArray("svg");
264 QTest::newRow(dataTag: "SVGZ: rect") << QString("rect.svgz") << true << QByteArray("svgz");
265}
266
267void tst_QImageReader::readImage()
268{
269 QFETCH(QString, fileName);
270 QFETCH(bool, success);
271 QFETCH(QByteArray, format);
272
273 SKIP_IF_UNSUPPORTED(format);
274
275 for (int i = 0; i < 2; ++i) {
276 QImageReader io(prefix + fileName, i ? QByteArray() : format);
277 if (success) {
278 if (!io.supportsAnimation())
279 QVERIFY(io.imageCount() > 0);
280 } else {
281 QCOMPARE(io.imageCount(), -1);
282 }
283 QImage image = io.read();
284 if (!success) {
285 QVERIFY(image.isNull());
286 return;
287 }
288
289 QVERIFY2(!image.isNull(), io.errorString().toLatin1().constData());
290
291 // No format
292 QImageReader io2(prefix + fileName);
293 QVERIFY2(!io2.read().isNull(), io.errorString().toLatin1().constData());
294
295 // No extension, no format
296 QImageReader io3(prefix + fileName.left(n: fileName.lastIndexOf(c: QLatin1Char('.'))));
297 QVERIFY2(!io3.read().isNull(), io.errorString().toLatin1().constData());
298
299 // Read into \a image2
300 QImage image2;
301 QImageReader image2Reader(prefix + fileName, i ? QByteArray() : format);
302 QCOMPARE(image2Reader.format(), format);
303 QVERIFY(image2Reader.read(&image2));
304 if (image2Reader.canRead()) {
305 if (i)
306 QVERIFY(!image2Reader.format().isEmpty());
307 else
308 QCOMPARE(image2Reader.format(), format);
309 } else {
310 if (i)
311 QVERIFY(image2Reader.format().isEmpty());
312 else
313 QVERIFY(!image2Reader.format().isEmpty());
314 }
315 QCOMPARE(image, image2);
316 do {
317 QVERIFY2(!image.isNull(), io.errorString().toLatin1().constData());
318 } while (!(image = io.read()).isNull());
319 }
320}
321
322void tst_QImageReader::jpegRgbCmyk()
323{
324 QImage image1(prefix + QLatin1String("YCbCr_cmyk.jpg"));
325 QImage image2(prefix + QLatin1String("YCbCr_cmyk.png"));
326
327 if (image1 != image2) {
328 // first, do some obvious tests
329 QCOMPARE(image1.height(), image2.height());
330 QCOMPARE(image1.width(), image2.width());
331 QCOMPARE(image1.format(), image2.format());
332 QCOMPARE(image1.format(), QImage::Format_RGB32);
333
334 // compare all the pixels with a slack of 3. This ignores rounding errors
335 // in libjpeg/libpng, where some versions sacrifice accuracy for speed.
336 for (int h = 0; h < image1.height(); ++h) {
337 const uchar *s1 = image1.constScanLine(h);
338 const uchar *s2 = image2.constScanLine(h);
339 for (int w = 0; w < image1.width() * 4; ++w) {
340 if (*s1 != *s2) {
341 QVERIFY2(qAbs(*s1 - *s2) <= 3, qPrintable(QString("images differ in line %1, col %2 (image1: %3, image2: %4)").arg(h).arg(w).arg(*s1, 0, 16).arg(*s2, 0, 16)));
342 }
343 s1++;
344 s2++;
345 }
346 }
347 }
348}
349
350void tst_QImageReader::setScaledSize_data()
351{
352 QTest::addColumn<QString>(name: "fileName");
353 QTest::addColumn<QSize>(name: "newSize");
354 QTest::addColumn<QByteArray>(name: "format");
355
356 QTest::newRow(dataTag: "BMP: colorful") << "colorful" << QSize(200, 200) << QByteArray("bmp");
357 QTest::newRow(dataTag: "BMP: font") << "font" << QSize(200, 200) << QByteArray("bmp");
358 QTest::newRow(dataTag: "XPM: marble") << "marble" << QSize(200, 200) << QByteArray("xpm");
359 QTest::newRow(dataTag: "PNG: kollada") << "kollada" << QSize(200, 200) << QByteArray("png");
360 QTest::newRow(dataTag: "PPM: teapot") << "teapot" << QSize(200, 200) << QByteArray("ppm");
361 QTest::newRow(dataTag: "PPM: runners") << "runners.ppm" << QSize(400, 400) << QByteArray("ppm");
362 QTest::newRow(dataTag: "PPM: test") << "test.ppm" << QSize(10, 10) << QByteArray("ppm");
363 QTest::newRow(dataTag: "XBM: gnus") << "gnus" << QSize(200, 200) << QByteArray("xbm");
364
365 QTest::newRow(dataTag: "JPEG: beavis A") << "beavis" << QSize(200, 200) << QByteArray("jpeg");
366 QTest::newRow(dataTag: "JPEG: beavis B") << "beavis" << QSize(175, 175) << QByteArray("jpeg");
367 QTest::newRow(dataTag: "JPEG: beavis C") << "beavis" << QSize(100, 100) << QByteArray("jpeg");
368 QTest::newRow(dataTag: "JPEG: beavis D") << "beavis" << QSize(100, 200) << QByteArray("jpeg");
369 QTest::newRow(dataTag: "JPEG: beavis E") << "beavis" << QSize(200, 100) << QByteArray("jpeg");
370 QTest::newRow(dataTag: "JPEG: beavis F") << "beavis" << QSize(87, 87) << QByteArray("jpeg");
371 QTest::newRow(dataTag: "JPEG: beavis G") << "beavis" << QSize(50, 45) << QByteArray("jpeg");
372 QTest::newRow(dataTag: "JPEG: beavis H") << "beavis" << QSize(43, 43) << QByteArray("jpeg");
373 QTest::newRow(dataTag: "JPEG: beavis I") << "beavis" << QSize(25, 25) << QByteArray("jpeg");
374
375 QTest::newRow(dataTag: "GIF: earth") << "earth" << QSize(200, 200) << QByteArray("gif");
376 QTest::newRow(dataTag: "GIF: trolltech") << "trolltech" << QSize(200, 200) << QByteArray("gif");
377
378 QTest::newRow(dataTag: "SVG: rect") << "rect" << QSize(200, 200) << QByteArray("svg");
379 QTest::newRow(dataTag: "SVGZ: rect") << "rect" << QSize(200, 200) << QByteArray("svgz");
380}
381
382void tst_QImageReader::setScaledSize()
383{
384 QFETCH(QString, fileName);
385 QFETCH(QSize, newSize);
386 QFETCH(QByteArray, format);
387
388 SKIP_IF_UNSUPPORTED(format);
389
390 QImageReader reader(prefix + fileName);
391 reader.setScaledSize(newSize);
392 QImage image = reader.read();
393 QVERIFY(!image.isNull());
394
395 QCOMPARE(image.size(), newSize);
396}
397
398void tst_QImageReader::task255627_setNullScaledSize_data()
399{
400 setScaledSize_data();
401}
402
403void tst_QImageReader::task255627_setNullScaledSize()
404{
405 QFETCH(QString, fileName);
406 QFETCH(QByteArray, format);
407
408 SKIP_IF_UNSUPPORTED(format);
409
410 QImageReader reader(prefix + fileName);
411
412 // set a null size
413 reader.setScaledSize(QSize(0, 0));
414 reader.setQuality(0);
415 QImage image = reader.read();
416 QVERIFY(image.isNull());
417 QCOMPARE(image.size(), QSize(0, 0));
418}
419
420void tst_QImageReader::setClipRect_data()
421{
422 QTest::addColumn<QString>(name: "fileName");
423 QTest::addColumn<QRect>(name: "newRect");
424 QTest::addColumn<QByteArray>(name: "format");
425 QTest::newRow(dataTag: "BMP: colorful") << "colorful" << QRect(0, 0, 50, 50) << QByteArray("bmp");
426 QTest::newRow(dataTag: "BMP: test32bfv4") << "test32bfv4" << QRect(0, 0, 50, 50) << QByteArray("bmp");
427 QTest::newRow(dataTag: "BMP: test32v5") << "test32v5" << QRect(0, 0, 50, 50) << QByteArray("bmp");
428 QTest::newRow(dataTag: "BMP: font") << "font" << QRect(0, 0, 50, 50) << QByteArray("bmp");
429 QTest::newRow(dataTag: "BMP: 4bpp uncompressed") << "tst7.bmp" << QRect(0, 0, 31, 31) << QByteArray("bmp");
430 QTest::newRow(dataTag: "XPM: marble") << "marble" << QRect(0, 0, 50, 50) << QByteArray("xpm");
431 QTest::newRow(dataTag: "PNG: kollada") << "kollada" << QRect(0, 0, 50, 50) << QByteArray("png");
432 QTest::newRow(dataTag: "PPM: teapot") << "teapot" << QRect(0, 0, 50, 50) << QByteArray("ppm");
433 QTest::newRow(dataTag: "PPM: runners") << "runners.ppm" << QRect(0, 0, 50, 50) << QByteArray("ppm");
434 QTest::newRow(dataTag: "PPM: test") << "test.ppm" << QRect(0, 0, 50, 50) << QByteArray("ppm");
435 QTest::newRow(dataTag: "XBM: gnus") << "gnus" << QRect(0, 0, 50, 50) << QByteArray("xbm");
436
437 QTest::newRow(dataTag: "JPEG: beavis") << "beavis" << QRect(0, 0, 50, 50) << QByteArray("jpeg");
438
439 QTest::newRow(dataTag: "GIF: earth") << "earth" << QRect(0, 0, 50, 50) << QByteArray("gif");
440 QTest::newRow(dataTag: "GIF: trolltech") << "trolltech" << QRect(0, 0, 50, 50) << QByteArray("gif");
441
442 QTest::newRow(dataTag: "SVG: rect") << "rect" << QRect(0, 0, 50, 50) << QByteArray("svg");
443 QTest::newRow(dataTag: "SVGZ: rect") << "rect" << QRect(0, 0, 50, 50) << QByteArray("svgz");
444}
445
446void tst_QImageReader::setClipRect()
447{
448 QFETCH(QString, fileName);
449 QFETCH(QRect, newRect);
450 QFETCH(QByteArray, format);
451
452 SKIP_IF_UNSUPPORTED(format);
453
454 QImageReader reader(prefix + fileName);
455 reader.setClipRect(newRect);
456 QImage image = reader.read();
457 QVERIFY(!image.isNull());
458 QCOMPARE(image.rect(), newRect);
459
460 QImageReader originalReader(prefix + fileName);
461 QImage originalImage = originalReader.read();
462 QCOMPARE(originalImage.copy(newRect), image);
463}
464
465void tst_QImageReader::setScaledClipRect_data()
466{
467 QTest::addColumn<QString>(name: "fileName");
468 QTest::addColumn<QRect>(name: "newRect");
469 QTest::addColumn<QByteArray>(name: "format");
470
471 QTest::newRow(dataTag: "BMP: colorful") << "colorful" << QRect(50, 20, 50, 50) << QByteArray("bmp");
472 QTest::newRow(dataTag: "BMP: test32bfv4") << "test32bfv4" << QRect(50, 20, 50, 50) << QByteArray("bmp");
473 QTest::newRow(dataTag: "BMP: test32v5") << "test32v5" << QRect(50, 20, 50, 50) << QByteArray("bmp");
474 QTest::newRow(dataTag: "BMP: font") << "font" << QRect(50, 20, 50, 50) << QByteArray("bmp");
475 QTest::newRow(dataTag: "XPM: marble") << "marble" << QRect(50, 20, 50, 50) << QByteArray("xpm");
476 QTest::newRow(dataTag: "PNG: kollada") << "kollada" << QRect(50, 20, 50, 50) << QByteArray("png");
477 QTest::newRow(dataTag: "PPM: teapot") << "teapot" << QRect(50, 20, 50, 50) << QByteArray("ppm");
478 QTest::newRow(dataTag: "PPM: runners") << "runners.ppm" << QRect(50, 20, 50, 50) << QByteArray("ppm");
479 QTest::newRow(dataTag: "PPM: test") << "test.ppm" << QRect(50, 20, 50, 50) << QByteArray("ppm");
480 QTest::newRow(dataTag: "XBM: gnus") << "gnus" << QRect(50, 20, 50, 50) << QByteArray("xbm");
481
482 QTest::newRow(dataTag: "JPEG: beavis") << "beavis" << QRect(50, 20, 50, 50) << QByteArray("jpeg");
483
484 QTest::newRow(dataTag: "GIF: earth") << "earth" << QRect(50, 20, 50, 50) << QByteArray("gif");
485 QTest::newRow(dataTag: "GIF: trolltech") << "trolltech" << QRect(50, 20, 50, 50) << QByteArray("gif");
486
487 QTest::newRow(dataTag: "SVG: rect") << "rect" << QRect(50, 20, 50, 50) << QByteArray("svg");
488 QTest::newRow(dataTag: "SVGZ: rect") << "rect" << QRect(50, 20, 50, 50) << QByteArray("svgz");
489}
490
491void tst_QImageReader::setScaledClipRect()
492{
493 QFETCH(QString, fileName);
494 QFETCH(QRect, newRect);
495 QFETCH(QByteArray, format);
496
497 SKIP_IF_UNSUPPORTED(format);
498
499 QImageReader reader(prefix + fileName);
500 reader.setScaledSize(QSize(300, 300));
501 reader.setScaledClipRect(newRect);
502 QImage image = reader.read();
503 QVERIFY(!image.isNull());
504 QCOMPARE(image.rect().translated(50, 20), newRect);
505#ifdef DEBUG_WRITE_OUTPUT
506 QString tempPath = QDir::temp().filePath(fileName) + QLatin1String(".png");
507 image.save(tempPath);
508#endif
509
510 QImageReader originalReader(prefix + fileName);
511 originalReader.setScaledSize(QSize(300, 300));
512 QImage originalImage = originalReader.read();
513 QCOMPARE(originalImage.copy(newRect), image);
514}
515
516void tst_QImageReader::imageFormat_data()
517{
518 QTest::addColumn<QString>(name: "fileName");
519 QTest::addColumn<QByteArray>(name: "format");
520 QTest::addColumn<QImage::Format>(name: "imageFormat");
521
522 QTest::newRow(dataTag: "pbm") << QString("image.pbm") << QByteArray("pbm") << QImage::Format_Mono;
523 QTest::newRow(dataTag: "pgm") << QString("image.pgm") << QByteArray("pgm") << QImage::Format_Grayscale8;
524 QTest::newRow(dataTag: "ppm-1") << QString("image.ppm") << QByteArray("ppm") << QImage::Format_RGB32;
525 QTest::newRow(dataTag: "ppm-2") << QString("teapot.ppm") << QByteArray("ppm") << QImage::Format_RGB32;
526 QTest::newRow(dataTag: "ppm-3") << QString("runners.ppm") << QByteArray("ppm") << QImage::Format_RGB32;
527 QTest::newRow(dataTag: "ppm-4") << QString("test.ppm") << QByteArray("ppm") << QImage::Format_RGB32;
528
529 QTest::newRow(dataTag: "jpeg-1") << QString("beavis.jpg") << QByteArray("jpeg") << QImage::Format_Grayscale8;
530 QTest::newRow(dataTag: "jpeg-2") << QString("YCbCr_cmyk.jpg") << QByteArray("jpeg") << QImage::Format_RGB32;
531 QTest::newRow(dataTag: "jpeg-3") << QString("YCbCr_rgb.jpg") << QByteArray("jpeg") << QImage::Format_RGB32;
532
533 QTest::newRow(dataTag: "gif-1") << QString("earth.gif") << QByteArray("gif") << QImage::Format_Invalid;
534 QTest::newRow(dataTag: "gif-2") << QString("trolltech.gif") << QByteArray("gif") << QImage::Format_Invalid;
535
536 QTest::newRow(dataTag: "xbm") << QString("gnus.xbm") << QByteArray("xbm") << QImage::Format_MonoLSB;
537 QTest::newRow(dataTag: "xpm") << QString("marble.xpm") << QByteArray("xpm") << QImage::Format_Indexed8;
538 QTest::newRow(dataTag: "bmp-1") << QString("colorful.bmp") << QByteArray("bmp") << QImage::Format_Indexed8;
539 QTest::newRow(dataTag: "bmp-2") << QString("font.bmp") << QByteArray("bmp") << QImage::Format_Indexed8;
540 QTest::newRow(dataTag: "bmp-3") << QString("test32bfv4.bmp") << QByteArray("bmp") << QImage::Format_ARGB32;
541 QTest::newRow(dataTag: "bmp-4") << QString("test32v5.bmp") << QByteArray("bmp") << QImage::Format_RGB32;
542 QTest::newRow(dataTag: "png") << QString("kollada.png") << QByteArray("png") << QImage::Format_ARGB32;
543 QTest::newRow(dataTag: "png-2") << QString("YCbCr_cmyk.png") << QByteArray("png") << QImage::Format_RGB32;
544 QTest::newRow(dataTag: "png-3") << QString("kollada-16bpc.png") << QByteArray("png") << QImage::Format_RGBA64;
545 QTest::newRow(dataTag: "png-4") << QString("basn0g16.png") << QByteArray("png") << QImage::Format_Grayscale16;
546 QTest::newRow(dataTag: "png-5") << QString("basn2c16.png") << QByteArray("png") << QImage::Format_RGBX64;
547 QTest::newRow(dataTag: "png-6") << QString("basn4a16.png") << QByteArray("png") << QImage::Format_RGBA64; // Grayscale16Alpha16
548 QTest::newRow(dataTag: "png-7") << QString("basn6a16.png") << QByteArray("png") << QImage::Format_RGBA64;
549 QTest::newRow(dataTag: "png-8") << QString("tbwn0g16.png") << QByteArray("png") << QImage::Format_RGBA64; // Grayscale16+tRNS
550 QTest::newRow(dataTag: "svg") << QString("rect.svg") << QByteArray("svg") << QImage::Format_ARGB32_Premultiplied;
551 QTest::newRow(dataTag: "svgz") << QString("rect.svgz") << QByteArray("svgz") << QImage::Format_ARGB32_Premultiplied;
552}
553
554void tst_QImageReader::imageFormat()
555{
556 QFETCH(QString, fileName);
557 QFETCH(QByteArray, format);
558 QFETCH(QImage::Format, imageFormat);
559
560 SKIP_IF_UNSUPPORTED(format);
561
562 QCOMPARE(QImageReader::imageFormat(prefix + fileName), format);
563 QImageReader reader(prefix + fileName);
564 QCOMPARE(reader.imageFormat(), imageFormat);
565}
566
567void tst_QImageReader::blackXPM()
568{
569 QImage image(prefix + QLatin1String("black.xpm"));
570 QImage image2(prefix + QLatin1String("black.png"));
571 QCOMPARE(image.pixel(25, 25), qRgb(190, 190, 190));
572 QCOMPARE(image.pixel(25, 25), image2.pixel(25, 25));
573}
574
575void tst_QImageReader::transparentXPM()
576{
577 QImage image(prefix + QLatin1String("nontransparent.xpm"));
578 QImage image2(prefix + QLatin1String("transparent.xpm"));
579 QCOMPARE(image.format(), QImage::Format_RGB32);
580 QCOMPARE(image2.format(), QImage::Format_ARGB32);
581}
582
583void tst_QImageReader::multiWordNamedColorXPM()
584{
585 QImage image(prefix + QLatin1String("namedcolors.xpm"));
586 QCOMPARE(image.pixel(0, 0), qRgb(102, 139, 139)); // pale turquoise 4
587 QCOMPARE(image.pixel(0, 1), qRgb(250, 250, 210)); // light golden rod yellow
588 QCOMPARE(image.pixel(0, 2), qRgb(255, 250, 205)); // lemon chiffon
589}
590
591void tst_QImageReader::supportedFormats()
592{
593 QList<QByteArray> formats = QImageReader::supportedImageFormats();
594 QList<QByteArray> sortedFormats = formats;
595 std::sort(first: sortedFormats.begin(), last: sortedFormats.end());
596
597 // check that the list is sorted
598 QCOMPARE(formats, sortedFormats);
599
600 QSet<QByteArray> formatSet;
601 foreach (QByteArray format, formats)
602 formatSet << format;
603
604 // check that the list does not contain duplicates
605 QCOMPARE(formatSet.size(), formats.size());
606}
607
608void tst_QImageReader::supportedMimeTypes()
609{
610 QList<QByteArray> mimeTypes = QImageReader::supportedMimeTypes();
611 QList<QByteArray> sortedMimeTypes = mimeTypes;
612 std::sort(first: sortedMimeTypes.begin(), last: sortedMimeTypes.end());
613
614 // check that the list is sorted
615 QCOMPARE(mimeTypes, sortedMimeTypes);
616
617 QSet<QByteArray> mimeTypeSet;
618 foreach (QByteArray mimeType, mimeTypes)
619 mimeTypeSet << mimeType;
620
621 // check the list as a minimum contains image/bmp
622 QVERIFY(mimeTypeSet.contains("image/bmp"));
623
624 // check that the list does not contain duplicates
625 QCOMPARE(mimeTypeSet.size(), mimeTypes.size());
626}
627
628void tst_QImageReader::setBackgroundColor_data()
629{
630 QTest::addColumn<QString>(name: "fileName");
631 QTest::addColumn<QColor>(name: "color");
632
633 QTest::newRow(dataTag: "BMP: colorful") << QString("colorful.bmp") << QColor(Qt::white);
634 QTest::newRow(dataTag: "BMP: font") << QString("font.bmp") << QColor(Qt::black);
635 QTest::newRow(dataTag: "BMP: signed char") << QString("crash-signed-char.bmp") << QColor(Qt::red);
636 QTest::newRow(dataTag: "XPM: marble") << QString("marble.xpm") << QColor(Qt::darkRed);
637 QTest::newRow(dataTag: "PNG: kollada") << QString("kollada.png") << QColor(Qt::green);
638 QTest::newRow(dataTag: "PPM: teapot") << QString("teapot.ppm") << QColor(Qt::darkGreen);
639 QTest::newRow(dataTag: "PPM: runners") << QString("runners.ppm") << QColor(Qt::red);
640 QTest::newRow(dataTag: "PPM: test") << QString("test.ppm") << QColor(Qt::white);
641 QTest::newRow(dataTag: "XBM: gnus") << QString("gnus.xbm") << QColor(Qt::blue);
642
643 QTest::newRow(dataTag: "JPEG: beavis") << QString("beavis.jpg") << QColor(Qt::darkBlue);
644
645 QTest::newRow(dataTag: "GIF: earth") << QString("earth.gif") << QColor(Qt::cyan);
646 QTest::newRow(dataTag: "GIF: trolltech") << QString("trolltech.gif") << QColor(Qt::magenta);
647
648 QTest::newRow(dataTag: "SVG: rect") << QString("rect.svg") << QColor(Qt::darkGreen);
649 QTest::newRow(dataTag: "SVGZ: rect") << QString("rect.svgz") << QColor(Qt::darkGreen);
650}
651
652void tst_QImageReader::setBackgroundColor()
653{
654 QFETCH(QString, fileName);
655 QFETCH(QColor, color);
656 QImageReader io("images/" + fileName);
657 io.setBackgroundColor(color);
658 if (io.backgroundColor().isValid())
659 QCOMPARE(io.backgroundColor(), color);
660}
661
662void tst_QImageReader::supportsAnimation_data()
663{
664 QTest::addColumn<QString>(name: "fileName");
665 QTest::addColumn<bool>(name: "success");
666
667 QTest::newRow(dataTag: "BMP: colorful") << QString("colorful.bmp") << false;
668 QTest::newRow(dataTag: "BMP: font") << QString("font.bmp") << false;
669 QTest::newRow(dataTag: "BMP: signed char") << QString("crash-signed-char.bmp") << false;
670 QTest::newRow(dataTag: "BMP: test32bfv4") << QString("test32bfv4.bmp") << false;;
671 QTest::newRow(dataTag: "BMP: test32v5") << QString("test32v5.bmp") << false;
672 QTest::newRow(dataTag: "XPM: marble") << QString("marble.xpm") << false;
673 QTest::newRow(dataTag: "PNG: kollada") << QString("kollada.png") << false;
674 QTest::newRow(dataTag: "PPM: teapot") << QString("teapot.ppm") << false;
675 QTest::newRow(dataTag: "PPM: runners") << QString("runners.ppm") << false;
676 QTest::newRow(dataTag: "XBM: gnus") << QString("gnus.xbm") << false;
677
678 QTest::newRow(dataTag: "JPEG: beavis") << QString("beavis.jpg") << false;
679
680 QTest::newRow(dataTag: "GIF: earth") << QString("earth.gif") << true;
681 QTest::newRow(dataTag: "GIF: trolltech") << QString("trolltech.gif") << true;
682
683 QTest::newRow(dataTag: "SVG: rect") << QString("rect.svg") << false;
684 QTest::newRow(dataTag: "SVGZ: rect") << QString("rect.svgz") << false;
685}
686
687void tst_QImageReader::supportsAnimation()
688{
689 QFETCH(QString, fileName);
690 QFETCH(bool, success);
691 QImageReader io(prefix + fileName);
692 QCOMPARE(io.supportsAnimation(), success);
693}
694
695void tst_QImageReader::sizeBeforeRead_data()
696{
697 imageFormat_data();
698}
699
700void tst_QImageReader::sizeBeforeRead()
701{
702 QFETCH(QString, fileName);
703 QFETCH(QByteArray, format);
704
705 SKIP_IF_UNSUPPORTED(format);
706
707 QImageReader reader(prefix + fileName);
708 QVERIFY(reader.canRead());
709
710 QSize size = reader.size();
711 QVERIFY(reader.canRead());
712 QImage image = reader.read();
713 QVERIFY(!image.isNull());
714 QCOMPARE(size, image.size());
715}
716
717void tst_QImageReader::sizeBeforeFormat_data()
718{
719 imageFormat_data();
720}
721
722void tst_QImageReader::sizeBeforeFormat()
723{
724 QFETCH(QString, fileName);
725
726 QByteArray formatA, formatB;
727
728 {
729 QImageReader reader(prefix + fileName);
730 formatA = reader.format();
731 }
732
733 {
734 QImageReader reader(prefix + fileName);
735 reader.size();
736 formatB = reader.format();
737 }
738
739 QCOMPARE(formatA, formatB);
740}
741
742void tst_QImageReader::imageFormatBeforeRead_data()
743{
744 imageFormat_data();
745}
746
747void tst_QImageReader::imageFormatBeforeRead()
748{
749 QFETCH(QString, fileName);
750 QFETCH(QByteArray, format);
751 QFETCH(QImage::Format, imageFormat);
752
753 SKIP_IF_UNSUPPORTED(format);
754
755 QImageReader reader(prefix + fileName);
756 QVERIFY(reader.canRead());
757 if (reader.supportsOption(option: QImageIOHandler::ImageFormat)) {
758 QImage::Format fileFormat = reader.imageFormat();
759 QCOMPARE(fileFormat, imageFormat);
760 QSize size = reader.size();
761 QImage image(size, fileFormat);
762 QVERIFY(reader.read(&image));
763 QCOMPARE(image.format(), fileFormat);
764 }
765}
766
767void tst_QImageReader::gifHandlerBugs()
768{
769 SKIP_IF_UNSUPPORTED("gif");
770
771 {
772 QImageReader io(prefix + "trolltech.gif");
773 QVERIFY(io.loopCount() != 1);
774 int count=0;
775 for (; io.canRead(); io.read(), ++count) ;
776 QCOMPARE(count, 34);
777 }
778
779 // Task 95166
780 {
781 QImageReader io1(prefix + "bat1.gif");
782 QImageReader io2(prefix + "bat2.gif");
783 QVERIFY(io1.canRead());
784 QVERIFY(io2.canRead());
785 QImage im1 = io1.read();
786 QImage im2 = io2.read();
787 QVERIFY(!im1.isNull());
788 QVERIFY(!im2.isNull());
789 QCOMPARE(im1, im2);
790 }
791
792 // Task 9994
793 {
794 QImageReader io1(prefix + "noclearcode.gif");
795 QImageReader io2(prefix + "noclearcode.bmp");
796 QVERIFY(io1.canRead()); QVERIFY(io2.canRead());
797 QImage im1 = io1.read(); QImage im2 = io2.read();
798 QVERIFY(!im1.isNull()); QVERIFY(!im2.isNull());
799 QCOMPARE(im1.convertToFormat(QImage::Format_ARGB32), im2.convertToFormat(QImage::Format_ARGB32));
800 }
801
802 // Check the undocumented feature.
803 {
804 QImageReader io(prefix + "endless-anim.gif");
805 QVERIFY(io.canRead());
806 QCOMPARE(io.loopCount(), -1);
807 }
808
809 // Check that pixels with the transparent color are transparent but not zeroed
810 {
811 QImageReader io(prefix + "trans.gif");
812 QVERIFY(io.canRead());
813 QImage im = io.read();
814 QCOMPARE(im.pixel(0,0), qRgba(0x3f, 0xff, 0x7f, 0x00));
815 QCOMPARE(im.pixel(10,10), qRgba(0x3f, 0xff, 0x7f, 0x00));
816 }
817}
818
819void tst_QImageReader::animatedGif()
820{
821 SKIP_IF_UNSUPPORTED("gif");
822
823 QImageReader io(":images/qt.gif");
824 QImage image = io.read();
825 QVERIFY(!image.isNull());
826 int i = 0;
827 while(!image.isNull()){
828 QString frameName = QLatin1String(":images/qt") + QString::number(++i) + QLatin1String(".gif");
829 QCOMPARE(image, QImage(frameName));
830 image = io.read();
831 }
832}
833
834// QTBUG-6696
835// Check the count of images in various call orders...
836void tst_QImageReader::gifImageCount()
837{
838 SKIP_IF_UNSUPPORTED("gif");
839
840 // just read every frame... and see how much we got..
841 {
842 QImageReader io(":images/four-frames.gif");
843
844 QVERIFY(io.canRead());
845 QImage blackFrame = io.read();
846
847 QVERIFY(io.canRead());
848 QImage whiteFrame = io.read();
849
850 QVERIFY(io.canRead());
851 QImage greenFrame = io.read();
852
853 QCOMPARE(io.imageCount(), 4);
854
855 QVERIFY(io.canRead());
856 QImage blueFrame = io.read();
857
858 QVERIFY(!io.canRead());
859 QImage emptyFrame = io.read();
860
861 QVERIFY(!io.canRead());
862 QCOMPARE(blackFrame.pixel(0,0), qRgb(0, 0, 0));
863 QCOMPARE(blackFrame.size(), QSize(64,64));
864
865 QCOMPARE(whiteFrame.pixel(0,0), qRgb(0xff, 0xff, 0xff));
866 QCOMPARE(whiteFrame.size(), QSize(64,64));
867
868 QCOMPARE(greenFrame.pixel(0,0), qRgb(0x0, 0xff, 0x0));
869 QCOMPARE(greenFrame.size(), QSize(64,64));
870
871 QCOMPARE(blueFrame.pixel(0,0), qRgb(0x0, 0x0, 0xff));
872 QCOMPARE(blueFrame.size(), QSize(64,64));
873 QVERIFY(emptyFrame.isNull());
874 }
875
876 // Read and get the size
877 {
878 QImageReader io(":images/four-frames.gif");
879
880 QVERIFY(io.canRead());
881 QCOMPARE(io.size(), QSize(64,64));
882
883 QVERIFY(io.canRead());
884 QCOMPARE(io.size(), QSize(64,64));
885 QCOMPARE(io.size(), QSize(64,64));
886 QVERIFY(io.canRead());
887 QImage blackFrame = io.read();
888
889 QVERIFY(io.canRead());
890 QCOMPARE(io.size(), QSize(64,64));
891 QCOMPARE(io.size(), QSize(64,64));
892 QVERIFY(io.canRead());
893 QImage whiteFrame = io.read();
894
895 QVERIFY(io.canRead());
896 QCOMPARE(io.size(), QSize(64,64));
897 QCOMPARE(io.size(), QSize(64,64));
898 QVERIFY(io.canRead());
899 QImage greenFrame = io.read();
900
901 QVERIFY(io.canRead());
902 QCOMPARE(io.size(), QSize(64,64));
903 QCOMPARE(io.size(), QSize(64,64));
904 QVERIFY(io.canRead());
905 QImage blueFrame = io.read();
906
907 QVERIFY(!io.canRead());
908 QCOMPARE(io.size(), QSize());
909 QCOMPARE(io.size(), QSize());
910 QVERIFY(!io.canRead());
911 QImage emptyFrame = io.read();
912
913 QVERIFY(!io.canRead());
914 QCOMPARE(blackFrame.pixel(0,0), qRgb(0, 0, 0));
915 QCOMPARE(blackFrame.size(), QSize(64,64));
916
917 QCOMPARE(whiteFrame.pixel(0,0), qRgb(0xff, 0xff, 0xff));
918 QCOMPARE(whiteFrame.size(), QSize(64,64));
919
920 QCOMPARE(greenFrame.pixel(0,0), qRgb(0x0, 0xff, 0x0));
921 QCOMPARE(greenFrame.size(), QSize(64,64));
922
923 QCOMPARE(blueFrame.pixel(0,0), qRgb(0x0, 0x0, 0xff));
924 QCOMPARE(blueFrame.size(), QSize(64,64));
925 QVERIFY(emptyFrame.isNull());
926 }
927
928 // Do a Size query as substitute for canRead
929 {
930 QImageReader io(":images/four-frames.gif");
931
932 QCOMPARE(io.size(), QSize(64,64));
933 QCOMPARE(io.size(), QSize(64,64));
934 QImage blackFrame = io.read();
935
936 QCOMPARE(io.size(), QSize(64,64));
937 QCOMPARE(io.size(), QSize(64,64));
938 QImage whiteFrame = io.read();
939
940 QCOMPARE(io.size(), QSize(64,64));
941 QCOMPARE(io.size(), QSize(64,64));
942 QImage greenFrame = io.read();
943
944 QCOMPARE(io.size(), QSize(64,64));
945 QCOMPARE(io.size(), QSize(64,64));
946 QImage blueFrame = io.read();
947
948 QCOMPARE(io.size(), QSize());
949 QVERIFY(!io.canRead());
950 QImage emptyFrame = io.read();
951
952 QVERIFY(!io.canRead());
953 QCOMPARE(blackFrame.pixel(0,0), qRgb(0, 0, 0));
954 QCOMPARE(blackFrame.size(), QSize(64,64));
955
956 QCOMPARE(whiteFrame.pixel(0,0), qRgb(0xff, 0xff, 0xff));
957 QCOMPARE(whiteFrame.size(), QSize(64,64));
958
959 QCOMPARE(greenFrame.pixel(0,0), qRgb(0x0, 0xff, 0x0));
960 QCOMPARE(greenFrame.size(), QSize(64,64));
961
962 QCOMPARE(blueFrame.pixel(0,0), qRgb(0x0, 0x0, 0xff));
963 QCOMPARE(blueFrame.size(), QSize(64,64));
964 QVERIFY(emptyFrame.isNull());
965 }
966 {
967 QImageReader io(":images/trolltech.gif");
968 QCOMPARE(io.imageCount(), 34);
969 QCOMPARE(io.size(), QSize(128,64));
970 }
971}
972
973void tst_QImageReader::gifLoopCount()
974{
975 SKIP_IF_UNSUPPORTED("gif");
976
977 {
978 QImageReader io(":images/qt-gif-anim.gif");
979 QCOMPARE(io.loopCount(), -1); // infinite loop
980 }
981 {
982 QImageReader io(":images/qt-gif-noanim.gif");
983 QCOMPARE(io.loopCount(), 0); // no loop
984 }
985}
986
987void tst_QImageReader::ppmMaxval_data()
988{
989 QTest::addColumn<bool>(name: "hasColor");
990 QTest::addColumn<QByteArray>(name: "bytes");
991
992 QTest::newRow(dataTag: "PGM plain 8bit full") << false << QByteArray("P2 3 1 255 255 0 127\n");
993 QTest::newRow(dataTag: "PGM plain 8bit lim.") << false << QByteArray("P2 3 1 50 50 0 25\n");
994 QTest::newRow(dataTag: "PGM plain 16bit full") << false << QByteArray("P2 3 1 65535 65535 0 32767\n");
995 QTest::newRow(dataTag: "PGM plain 16bit lim.") << false << QByteArray("P2 3 1 5000 5000 0 2500\n");
996 QTest::newRow(dataTag: "PGM raw 8bit full") << false << QByteArray("P5 3 1 255 \xff\x00\x7f", 13 + 3);
997 QTest::newRow(dataTag: "PGM raw 8bit lim.") << false << QByteArray("P5 3 1 50 \x32\x00\x19", 13 + 3);
998 QTest::newRow(dataTag: "PGM raw 16bit full") << false << QByteArray("P5 3 1 65535 \xff\xff\x00\x00\x7f\xff", 13 + 3 * 2);
999 QTest::newRow(dataTag: "PGM raw 16bit lim.") << false << QByteArray("P5 3 1 5000 \x13\x88\x00\x00\x09\xc4", 13 + 3 * 2);
1000
1001 QTest::newRow(dataTag: "PPM plain 8bit full") << true << QByteArray("P3 3 2 255 "
1002 "255 255 255 0 0 0 127 127 127 "
1003 "255 0 0 0 255 0 0 0 255\n");
1004
1005 QTest::newRow(dataTag: "PPM plain 8bit lim.") << true << QByteArray("P3 3 2 50 "
1006 " 50 50 50 0 0 0 25 25 25 "
1007 " 50 0 0 0 50 0 0 0 50\n");
1008
1009 QTest::newRow(dataTag: "PPM plain 16bit full") << true << QByteArray("P3 3 2 65535 "
1010 "65535 65535 65535 0 0 0 32767 32767 32767 "
1011 "65535 0 0 0 65535 0 0 0 65535\n");
1012
1013 QTest::newRow(dataTag: "PPM plain 16bit lim.") << true << QByteArray("P3 3 2 5000 "
1014 " 5000 5000 5000 0 0 0 2500 2500 2500 "
1015 " 5000 0 0 0 5000 0 0 0 5000\n");
1016
1017 QTest::newRow(dataTag: "PPM raw 8bit full") << true << QByteArray("P6 3 2 255 "
1018 "\xff\xff\xff\x00\x00\x00\x7f\x7f\x7f"
1019 "\xff\x00\x00\x00\xff\x00\x00\x00\xff", 13 + 6 * 3);
1020
1021 QTest::newRow(dataTag: "PPM raw 8bit lim.") << true << QByteArray("P6 3 2 50 "
1022 "\x32\x32\x32\x00\x00\x00\x19\x19\x19"
1023 "\x32\x00\x00\x00\x32\x00\x00\x00\x32", 13 + 6 * 3);
1024
1025 QTest::newRow(dataTag: "PPM raw 16bit full") << true << QByteArray("P6 3 2 65535 "
1026 "\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x7f\xff\x7f\xff\x7f\xff"
1027 "\xff\xff\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\xff\xff", 13 + 6 * 3 * 2);
1028
1029 QTest::newRow(dataTag: "PPM raw 16bit lim.") << true << QByteArray("P6 3 2 5000 "
1030 "\x13\x88\x13\x88\x13\x88\x00\x00\x00\x00\x00\x00\x09\xc4\x09\xc4\x09\xc4"
1031 "\x13\x88\x00\x00\x00\x00\x00\x00\x13\x88\x00\x00\x00\x00\x00\x00\x13\x88", 13 + 6 * 3 * 2);
1032}
1033
1034void tst_QImageReader::ppmMaxval()
1035{
1036 SKIP_IF_UNSUPPORTED("ppm");
1037
1038 QFETCH(bool, hasColor);
1039 QFETCH(QByteArray, bytes);
1040
1041 QImage img;
1042 img.loadFromData(data: bytes);
1043 QVERIFY(!img.isNull());
1044 QCOMPARE(img.width(), 3);
1045 QCOMPARE(img.height(), hasColor ? 2 : 1);
1046
1047 QCOMPARE(img.pixel(0,0), qRgb(0xff, 0xff, 0xff));
1048 QCOMPARE(img.pixel(1,0), qRgb(0, 0, 0));
1049 QRgb gray = img.pixel(x: 2,y: 0);
1050 QVERIFY(qIsGray(gray));
1051 QVERIFY(qRed(gray) > 0x70 && qRed(gray) < 0x90 );
1052
1053 if (hasColor) {
1054 QCOMPARE(img.pixel(0,1), qRgb(0xff, 0, 0));
1055 QCOMPARE(img.pixel(1,1), qRgb(0, 0xff, 0));
1056 QCOMPARE(img.pixel(2,1), qRgb(0, 0, 0xff));
1057 }
1058}
1059
1060class Server : public QObject
1061{
1062 Q_OBJECT
1063public:
1064 Server(const QByteArray &data) :serverSocket(0)
1065 {
1066 connect(sender: &server, SIGNAL(newConnection()), receiver: this, SLOT(acceptNewConnection()));
1067 server.listen();
1068 this->data = data;
1069 }
1070
1071public slots:
1072 void runTest()
1073 {
1074 connect(sender: &clientSocket, SIGNAL(connected()), receiver: this, SLOT(connected()));
1075 clientSocket.connectToHost(address: QHostAddress::LocalHost, port: server.serverPort());
1076 }
1077
1078public:
1079 inline QTcpSocket *socket() const { return serverSocket; }
1080
1081signals:
1082 void ready();
1083
1084private slots:
1085 void acceptNewConnection()
1086 {
1087 serverSocket = server.nextPendingConnection();
1088 connect(sender: serverSocket, SIGNAL(errorOccurred(QAbstractSocket::SocketError)),
1089 receiver: this, SLOT(remoteHostClosed()));
1090 }
1091
1092 void connected()
1093 {
1094 clientSocket.write(data);
1095 clientSocket.disconnectFromHost();
1096 }
1097
1098 void remoteHostClosed()
1099 {
1100 emit ready();
1101 }
1102
1103private:
1104 QTcpServer server;
1105 QTcpSocket clientSocket;
1106 QTcpSocket *serverSocket;
1107 QByteArray data;
1108};
1109
1110void tst_QImageReader::readFromDevice_data()
1111{
1112 QTest::addColumn<QString>(name: "fileName");
1113 QTest::addColumn<QByteArray>(name: "format");
1114
1115 QTest::newRow(dataTag: "pbm") << QString("image.pbm") << QByteArray("pbm");
1116 QTest::newRow(dataTag: "pgm") << QString("image.pgm") << QByteArray("pgm");
1117 QTest::newRow(dataTag: "ppm-1") << QString("image.ppm") << QByteArray("ppm");
1118 QTest::newRow(dataTag: "ppm-2") << QString("teapot.ppm") << QByteArray("ppm");
1119 QTest::newRow(dataTag: "ppm-3") << QString("teapot.ppm") << QByteArray("ppm");
1120 QTest::newRow(dataTag: "ppm-4") << QString("runners.ppm") << QByteArray("ppm");
1121
1122 QTest::newRow(dataTag: "jpeg-1") << QString("beavis.jpg") << QByteArray("jpeg");
1123 QTest::newRow(dataTag: "jpeg-2") << QString("YCbCr_cmyk.jpg") << QByteArray("jpeg");
1124 QTest::newRow(dataTag: "jpeg-3") << QString("YCbCr_rgb.jpg") << QByteArray("jpeg");
1125 QTest::newRow(dataTag: "jpeg-4") << QString("qtbug13653-no_eoi.jpg") << QByteArray("jpeg");
1126
1127 QTest::newRow(dataTag: "gif-1") << QString("earth.gif") << QByteArray("gif");
1128 QTest::newRow(dataTag: "gif-2") << QString("trolltech.gif") << QByteArray("gif");
1129
1130 QTest::newRow(dataTag: "xbm") << QString("gnus.xbm") << QByteArray("xbm");
1131 QTest::newRow(dataTag: "xpm") << QString("marble.xpm") << QByteArray("xpm");
1132 QTest::newRow(dataTag: "bmp-1") << QString("colorful.bmp") << QByteArray("bmp");
1133 QTest::newRow(dataTag: "bmp-2") << QString("font.bmp") << QByteArray("bmp");
1134 QTest::newRow(dataTag: "bmp-3") << QString("test32bfv4.bmp") << QByteArray("bmp");
1135 QTest::newRow(dataTag: "bmp-4") << QString("test32v5.bmp") << QByteArray("bmp");
1136 QTest::newRow(dataTag: "png") << QString("kollada.png") << QByteArray("png");
1137
1138 QTest::newRow(dataTag: "svg") << QString("rect.svg") << QByteArray("svg");
1139 QTest::newRow(dataTag: "svgz") << QString("rect.svgz") << QByteArray("svgz");
1140#if defined QTEST_HAVE_TGA
1141 QTest::newRow("tga") << QString("test-flag.tga") << QByteArray("tga");
1142#endif
1143}
1144
1145static QByteArray msgReadFromDeviceFail(const QString &sourceFileName,
1146 const QByteArray &detectedFormat)
1147{
1148 QByteArray result = "Failure for '";
1149 result += sourceFileName.toLocal8Bit();
1150 result += "', detected as: '";
1151 result += detectedFormat;
1152 result += '\'';
1153 return result;
1154}
1155
1156void tst_QImageReader::readFromDevice()
1157{
1158 QFETCH(QString, fileName);
1159 QFETCH(QByteArray, format);
1160
1161 SKIP_IF_UNSUPPORTED(format);
1162
1163 const QString imageFileName = prefix + fileName;
1164 QImage expectedImage(imageFileName, format);
1165 QFile file(imageFileName);
1166 QVERIFY2(file.open(QFile::ReadOnly), msgFileOpenReadFailed(file).constData());
1167 QByteArray imageData = file.readAll();
1168 QVERIFY(!imageData.isEmpty());
1169 {
1170 QBuffer buffer;
1171 buffer.setData(imageData);
1172 QVERIFY(buffer.open(QBuffer::ReadOnly));
1173
1174 QImageReader reader(&buffer);
1175 QVERIFY(reader.canRead());
1176 QImage imageReaderImage = reader.read();
1177
1178 QVERIFY2(!imageReaderImage.isNull(), msgReadFromDeviceFail(imageFileName, reader.format()).constData());
1179 QCOMPARE(imageReaderImage, expectedImage);
1180
1181 buffer.seek(off: 0);
1182
1183 QImage image1;
1184 QVERIFY(image1.loadFromData((const uchar *)buffer.data().data(),
1185 buffer.data().size(), format.data()));
1186 QCOMPARE(image1, expectedImage);
1187
1188 QByteArray throughBase64 = QByteArray::fromBase64(base64: imageData.toBase64());
1189 QVERIFY(image1.loadFromData((const uchar *)throughBase64.data(),
1190 throughBase64.size(), format.data()));
1191 QCOMPARE(image1, expectedImage);
1192 }
1193
1194 Server server(imageData);
1195 QEventLoop loop;
1196 connect(sender: &server, SIGNAL(ready()), receiver: &loop, SLOT(quit()));
1197 QTimer::singleShot(msec: 0, receiver: &server, SLOT(runTest()));
1198 QTimer::singleShot(msec: 5000, receiver: &loop, SLOT(quit()));
1199 loop.exec();
1200
1201 QImageReader reader(server.socket(), format == "xbm" ? "xbm" : "");
1202 if (format == "xbm")
1203 QVERIFY(!reader.canRead());
1204 else
1205 QVERIFY(reader.canRead());
1206 QImage imageReaderImage = reader.read();
1207 QCOMPARE(imageReaderImage, expectedImage);
1208}
1209
1210void tst_QImageReader::readFromFileAfterJunk_data()
1211{
1212 QTest::addColumn<QString>(name: "fileName");
1213 QTest::addColumn<QByteArray>(name: "format");
1214
1215 QTest::newRow(dataTag: "pbm") << QString("image.pbm") << QByteArray("pbm");
1216 QTest::newRow(dataTag: "pgm") << QString("image.pgm") << QByteArray("pgm");
1217 QTest::newRow(dataTag: "ppm-1") << QString("image.ppm") << QByteArray("ppm");
1218 QTest::newRow(dataTag: "ppm-2") << QString("teapot.ppm") << QByteArray("ppm");
1219 QTest::newRow(dataTag: "ppm-3") << QString("teapot.ppm") << QByteArray("ppm");
1220 QTest::newRow(dataTag: "ppm-4") << QString("runners.ppm") << QByteArray("ppm");
1221
1222 QTest::newRow(dataTag: "jpeg-1") << QString("beavis.jpg") << QByteArray("jpeg");
1223 QTest::newRow(dataTag: "jpeg-2") << QString("YCbCr_cmyk.jpg") << QByteArray("jpeg");
1224 QTest::newRow(dataTag: "jpeg-3") << QString("YCbCr_rgb.jpg") << QByteArray("jpeg");
1225
1226 QTest::newRow(dataTag: "xbm") << QString("gnus.xbm") << QByteArray("xbm");
1227 QTest::newRow(dataTag: "xpm") << QString("marble.xpm") << QByteArray("xpm");
1228 QTest::newRow(dataTag: "bmp-1") << QString("colorful.bmp") << QByteArray("bmp");
1229 QTest::newRow(dataTag: "bmp-2") << QString("font.bmp") << QByteArray("bmp");
1230 QTest::newRow(dataTag: "bmp-3") << QString("test32bfv4.bmp") << QByteArray("bmp");
1231 QTest::newRow(dataTag: "bmp-4") << QString("test32v5.bmp") << QByteArray("bmp");
1232 QTest::newRow(dataTag: "png") << QString("kollada.png") << QByteArray("png");
1233 QTest::newRow(dataTag: "svg") << QString("rect.svg") << QByteArray("svg");
1234 QTest::newRow(dataTag: "svgz") << QString("rect.svgz") << QByteArray("svgz");
1235}
1236
1237void tst_QImageReader::readFromFileAfterJunk()
1238{
1239 QFETCH(QString, fileName);
1240 QFETCH(QByteArray, format);
1241
1242 SKIP_IF_UNSUPPORTED(format);
1243
1244 QTemporaryFile junkFile(m_temporaryDir.path() + QLatin1String("/junkXXXXXX"));
1245 QVERIFY2(junkFile.open(), msgFileOpenWriteFailed(junkFile).constData());
1246
1247 QFile imageFile(prefix + fileName);
1248 QVERIFY2(imageFile.open(QFile::ReadOnly), msgFileOpenReadFailed(imageFile).constData());
1249 QByteArray imageData = imageFile.readAll();
1250 QVERIFY(!imageData.isNull());
1251
1252 int iterations = 3;
1253 if (format == "ppm" || format == "pbm" || format == "pgm" || format == "svg" || format == "svgz")
1254 iterations = 1;
1255
1256 if (!QImageWriter::supportedImageFormats().contains(t: format)) {
1257 for (int i = 0; i < iterations; ++i) {
1258 junkFile.write(data: "deadbeef", len: 9);
1259 QCOMPARE(junkFile.write(imageData), qint64(imageData.size()));
1260 }
1261 } else {
1262 for (int i = 0; i < iterations; ++i) {
1263 QImageWriter writer(&junkFile, format);
1264 junkFile.write(data: "deadbeef", len: 9);
1265 QVERIFY(writer.write(QImage(prefix + fileName)));
1266 }
1267 }
1268 junkFile.close();
1269 QVERIFY2(junkFile.open(), msgFileOpenReadFailed(junkFile).constData());
1270
1271 for (int i = 0; i < iterations; ++i) {
1272 QByteArray ole = junkFile.read(maxlen: 9);
1273 junkFile.ungetChar(c: ole[ole.size() - 1]);
1274 char c;
1275 junkFile.getChar(c: &c);
1276 QImageReader reader(&junkFile);
1277 QVERIFY(reader.canRead());
1278 QVERIFY(!reader.read().isNull());
1279 }
1280}
1281
1282void tst_QImageReader::devicePosition_data()
1283{
1284 QTest::addColumn<QString>(name: "fileName");
1285 QTest::addColumn<QByteArray>(name: "format");
1286
1287 QTest::newRow(dataTag: "pbm") << QString("image.pbm") << QByteArray("pbm");
1288 QTest::newRow(dataTag: "pgm") << QString("image.pgm") << QByteArray("pgm");
1289 QTest::newRow(dataTag: "ppm-1") << QString("image.ppm") << QByteArray("ppm");
1290
1291 QTest::newRow(dataTag: "jpeg-1") << QString("beavis.jpg") << QByteArray("jpeg");
1292 QTest::newRow(dataTag: "jpeg-2") << QString("YCbCr_cmyk.jpg") << QByteArray("jpeg");
1293 QTest::newRow(dataTag: "jpeg-3") << QString("YCbCr_rgb.jpg") << QByteArray("jpeg");
1294
1295 QTest::newRow(dataTag: "gif-1") << QString("earth.gif") << QByteArray("gif");
1296
1297 QTest::newRow(dataTag: "xbm") << QString("gnus.xbm") << QByteArray("xbm");
1298 QTest::newRow(dataTag: "xpm") << QString("marble.xpm") << QByteArray("xpm");
1299 QTest::newRow(dataTag: "bmp-1") << QString("colorful.bmp") << QByteArray("bmp");
1300 QTest::newRow(dataTag: "bmp-2") << QString("font.bmp") << QByteArray("bmp");
1301 QTest::newRow(dataTag: "bmp-3") << QString("test32bfv4.bmp") << QByteArray("bmp");
1302 QTest::newRow(dataTag: "bmp-4") << QString("test32v5.bmp") << QByteArray("bmp");
1303 QTest::newRow(dataTag: "png") << QString("kollada.png") << QByteArray("png");
1304 QTest::newRow(dataTag: "svg") << QString("rect.svg") << QByteArray("svg");
1305 QTest::newRow(dataTag: "svgz") << QString("rect.svgz") << QByteArray("svgz");
1306}
1307
1308void tst_QImageReader::devicePosition()
1309{
1310 QFETCH(QString, fileName);
1311 QFETCH(QByteArray, format);
1312
1313 SKIP_IF_UNSUPPORTED(format);
1314
1315 QImage expected(prefix + fileName);
1316 QVERIFY(!expected.isNull());
1317
1318 QFile imageFile(prefix + fileName);
1319 QVERIFY2(imageFile.open(QFile::ReadOnly), msgFileOpenReadFailed(imageFile).constData());
1320 QByteArray imageData = imageFile.readAll();
1321 QVERIFY(!imageData.isNull());
1322 int imageDataSize = imageData.size();
1323
1324 const char *preStr = "prebeef\n";
1325 int preLen = qstrlen(str: preStr);
1326 imageData.prepend(s: preStr);
1327 if (format != "svg" && format != "svgz") // Doesn't handle trailing data
1328 imageData.append(s: "\npostbeef");
1329 QBuffer buf(&imageData);
1330 buf.open(openMode: QIODevice::ReadOnly);
1331 buf.seek(off: preLen);
1332 QImageReader reader(&buf, format);
1333 QCOMPARE(expected, reader.read());
1334 if (format != "ppm" &&
1335 format != "pgm" &&
1336 format != "pbm" &&
1337 format != "gif") // Known not to work
1338 QCOMPARE(buf.pos(), qint64(preLen+imageDataSize));
1339}
1340
1341
1342void tst_QImageReader::readFromResources_data()
1343{
1344 QTest::addColumn<QString>(name: "fileName");
1345 QTest::addColumn<QByteArray>(name: "format");
1346 QTest::addColumn<QSize>(name: "size");
1347 QTest::addColumn<QString>(name: "message");
1348
1349 QTest::newRow(dataTag: "corrupt.bmp") << QString("corrupt.bmp")
1350 << QByteArray("bmp") << QSize(0, 0)
1351 << QString("");
1352 QTest::newRow(dataTag: "negativeheight.bmp") << QString("negativeheight.bmp")
1353 << QByteArray("bmp") << QSize(127, 64)
1354 << QString("");
1355 QTest::newRow(dataTag: "font.bmp") << QString("font.bmp")
1356 << QByteArray("bmp") << QSize(240, 8)
1357 << QString("");
1358 QTest::newRow(dataTag: "noclearcode.bmp") << QString("noclearcode.bmp")
1359 << QByteArray("bmp") << QSize(29, 18)
1360 << QString("");
1361 QTest::newRow(dataTag: "colorful.bmp") << QString("colorful.bmp")
1362 << QByteArray("bmp") << QSize(320, 200)
1363 << QString("");
1364 QTest::newRow(dataTag: "16bpp.bmp") << QString("16bpp.bmp")
1365 << QByteArray("bmp") << QSize(320, 240)
1366 << QString("");
1367 QTest::newRow(dataTag: "crash-signed-char.bmp") << QString("crash-signed-char.bmp")
1368 << QByteArray("bmp") << QSize(360, 280)
1369 << QString("");
1370 QTest::newRow(dataTag: "4bpp-rle.bmp") << QString("4bpp-rle.bmp")
1371 << QByteArray("bmp") << QSize(640, 480)
1372 << QString("");
1373 QTest::newRow(dataTag: "test32bfv4.bmp") << QString("test32bfv4.bmp")
1374 << QByteArray("bmp") << QSize(373, 156)
1375 << QString("");
1376 QTest::newRow(dataTag: "test32v5.bmp") << QString("test32v5.bmp")
1377 << QByteArray("bmp") << QSize(373, 156)
1378 << QString("");
1379 QTest::newRow(dataTag: "corrupt.gif") << QString("corrupt.gif")
1380 << QByteArray("gif") << QSize(0, 0)
1381 << QString("");
1382 QTest::newRow(dataTag: "trolltech.gif") << QString("trolltech.gif")
1383 << QByteArray("gif") << QSize(128, 64)
1384 << QString("");
1385 QTest::newRow(dataTag: "noclearcode.gif") << QString("noclearcode.gif")
1386 << QByteArray("gif") << QSize(29, 18)
1387 << QString("");
1388 QTest::newRow(dataTag: "earth.gif") << QString("earth.gif")
1389 << QByteArray("gif") << QSize(320, 200)
1390 << QString("");
1391 QTest::newRow(dataTag: "bat1.gif") << QString("bat1.gif")
1392 << QByteArray("gif") << QSize(32, 32)
1393 << QString("");
1394 QTest::newRow(dataTag: "bat2.gif") << QString("bat2.gif")
1395 << QByteArray("gif") << QSize(32, 32)
1396 << QString("");
1397 QTest::newRow(dataTag: "corrupt.jpg") << QString("corrupt.jpg")
1398 << QByteArray("jpg") << QSize(0, 0)
1399 << QString("JPEG datastream contains no image");
1400 QTest::newRow(dataTag: "beavis.jpg") << QString("beavis.jpg")
1401 << QByteArray("jpg") << QSize(350, 350)
1402 << QString("");
1403 QTest::newRow(dataTag: "YCbCr_cmyk.jpg") << QString("YCbCr_cmyk.jpg")
1404 << QByteArray("jpg") << QSize(75, 50)
1405 << QString("");
1406 QTest::newRow(dataTag: "YCbCr_rgb.jpg") << QString("YCbCr_rgb.jpg")
1407 << QByteArray("jpg") << QSize(75, 50)
1408 << QString("");
1409 QTest::newRow(dataTag: "qtbug13653-no_eoi.jpg") << QString("qtbug13653-no_eoi.jpg")
1410 << QByteArray("jpg") << QSize(240, 180)
1411 << QString("");
1412 QTest::newRow(dataTag: "rect.svg") << QString("rect.svg")
1413 << QByteArray("svg") << QSize(128, 128)
1414 << QString("");
1415 QTest::newRow(dataTag: "rect.svgz") << QString("rect.svgz")
1416 << QByteArray("svgz") << QSize(128, 128)
1417 << QString("");
1418 QTest::newRow(dataTag: "corrupt.svg") << QString("corrupt.svg")
1419 << QByteArray("svg") << QSize(0, 0)
1420 << QString("");
1421 QTest::newRow(dataTag: "corrupt.svgz") << QString("corrupt.svgz")
1422 << QByteArray("svgz") << QSize(0, 0)
1423 << QString("");
1424 QTest::newRow(dataTag: "image.pbm") << QString("image.pbm")
1425 << QByteArray("pbm") << QSize(16, 6)
1426 << QString("");
1427 QTest::newRow(dataTag: "image.pgm") << QString("image.pgm")
1428 << QByteArray("pgm") << QSize(24, 7)
1429 << QString("");
1430 QTest::newRow(dataTag: "corrupt.png") << QString("corrupt.png")
1431 << QByteArray("png") << QSize(0, 0)
1432 << QString("");
1433 QTest::newRow(dataTag: "away.png") << QString("away.png")
1434 << QByteArray("png") << QSize(16, 16)
1435 << QString("");
1436 QTest::newRow(dataTag: "image.png") << QString("image.png")
1437 << QByteArray("png") << QSize(22, 22)
1438 << QString("");
1439 QTest::newRow(dataTag: "kollada.png") << QString("kollada.png")
1440 << QByteArray("png") << QSize(436, 160)
1441 << QString("");
1442 QTest::newRow(dataTag: "black.png") << QString("black.png")
1443 << QByteArray("png") << QSize(48, 48)
1444 << QString("");
1445 QTest::newRow(dataTag: "YCbCr_cmyk.png") << QString("YCbCr_cmyk.png")
1446 << QByteArray("png") << QSize(75, 50)
1447 << QString("");
1448 QTest::newRow(dataTag: "teapot.ppm") << QString("teapot.ppm")
1449 << QByteArray("ppm") << QSize(256, 256)
1450 << QString("");
1451 QTest::newRow(dataTag: "image.ppm") << QString("image.ppm")
1452 << QByteArray("ppm") << QSize(4, 4)
1453 << QString("");
1454 QTest::newRow(dataTag: "runners.ppm") << QString("runners.ppm")
1455 << QByteArray("ppm") << QSize(400, 400)
1456 << QString("");
1457 QTest::newRow(dataTag: "test.ppm") << QString("test.ppm")
1458 << QByteArray("ppm") << QSize(10, 10)
1459 << QString("");
1460 QTest::newRow(dataTag: "gnus.xbm") << QString("gnus.xbm")
1461 << QByteArray("xbm") << QSize(271, 273)
1462 << QString("");
1463 QTest::newRow(dataTag: "corrupt-colors.xpm") << QString("corrupt-colors.xpm")
1464 << QByteArray("xpm") << QSize(0, 0)
1465 << QString("QImage: XPM color specification is missing: bla9an.n#x");
1466 QTest::newRow(dataTag: "corrupt-pixels.xpm") << QString("corrupt-pixels.xpm")
1467 << QByteArray("xpm") << QSize(0, 0)
1468 << QString("QImage: XPM pixels missing on image line 3");
1469 QTest::newRow(dataTag: "corrupt-pixel-count.xpm") << QString("corrupt-pixel-count.xpm")
1470 << QByteArray("xpm") << QSize(0, 0)
1471 << QString("");
1472 QTest::newRow(dataTag: "marble.xpm") << QString("marble.xpm")
1473 << QByteArray("xpm") << QSize(240, 240)
1474 << QString("");
1475 QTest::newRow(dataTag: "test.xpm") << QString("test.xpm")
1476 << QByteArray("xpm") << QSize(256, 256)
1477 << QString("");
1478 QTest::newRow(dataTag: "black.xpm") << QString("black.xpm")
1479 << QByteArray("xpm") << QSize(48, 48)
1480 << QString("");
1481 QTest::newRow(dataTag: "namedcolors.xpm") << QString("namedcolors.xpm")
1482 << QByteArray("xpm") << QSize(8, 8)
1483 << QString("");
1484 QTest::newRow(dataTag: "nontransparent.xpm") << QString("nontransparent.xpm")
1485 << QByteArray("xpm") << QSize(8, 8)
1486 << QString("");
1487 QTest::newRow(dataTag: "transparent.xpm") << QString("transparent.xpm")
1488 << QByteArray("xpm") << QSize(8, 8)
1489 << QString("");
1490}
1491
1492void tst_QImageReader::readFromResources()
1493{
1494 QFETCH(QString, fileName);
1495 QFETCH(QByteArray, format);
1496 QFETCH(QSize, size);
1497 QFETCH(QString, message);
1498
1499 SKIP_IF_UNSUPPORTED(format);
1500
1501 for (int i = 0; i < 2; ++i) {
1502 QString file = i ? QString(QStringLiteral(":/images/") + fileName) : QString(prefix + fileName);
1503 {
1504 // suppress warnings if we expect them
1505 if (!message.isEmpty()) {
1506 for (int j = 0; j < 5; ++j)
1507 QTest::ignoreMessage(type: QtWarningMsg, message: message.toLatin1());
1508 }
1509
1510 // 1) full filename, no format
1511 QImageReader reader(file);
1512 QImage image = reader.read();
1513 if (size.isNull())
1514 QVERIFY(image.isNull());
1515 else
1516 QVERIFY(!image.isNull());
1517 QCOMPARE(image.size(), size);
1518 }
1519 {
1520 // 2) full filename, with format
1521 QImageReader reader(file, format);
1522 QImage image = reader.read();
1523 if (size.isNull())
1524 QVERIFY(image.isNull());
1525 else
1526 QVERIFY(!image.isNull());
1527 QCOMPARE(image.size(), size);
1528 }
1529 {
1530 // 3) full filename, with uppercase format
1531 QImageReader reader(file, format.toUpper());
1532 QImage image = reader.read();
1533 if (size.isNull())
1534 QVERIFY(image.isNull());
1535 else
1536 QVERIFY(!image.isNull());
1537 QCOMPARE(image.size(), size);
1538 }
1539 {
1540 // 4) chopped filename, with format
1541 QImageReader reader(file.left(n: file.lastIndexOf(c: QLatin1Char('.'))), format);
1542 QImage image = reader.read();
1543 if (size.isNull())
1544 QVERIFY(image.isNull());
1545 else
1546 QVERIFY(!image.isNull());
1547 QCOMPARE(image.size(), size);
1548 }
1549 {
1550 // 5) chopped filename, with uppercase format
1551 QImageReader reader(file.left(n: file.lastIndexOf(c: QLatin1Char('.'))), format.toUpper());
1552 QImage image = reader.read();
1553 if (size.isNull())
1554 QVERIFY(image.isNull());
1555 else
1556 QVERIFY(!image.isNull());
1557 QCOMPARE(image.size(), size);
1558 }
1559 }
1560
1561 // Check that the results are identical
1562 if (!message.isEmpty()) {
1563 QTest::ignoreMessage(type: QtWarningMsg, message: message.toLatin1());
1564 QTest::ignoreMessage(type: QtWarningMsg, message: message.toLatin1());
1565 }
1566 QCOMPARE(QImageReader(prefix + fileName).read(), QImageReader(":/images/" + fileName).read());
1567}
1568
1569void tst_QImageReader::readCorruptImage_data()
1570{
1571 QTest::addColumn<QString>(name: "fileName");
1572 QTest::addColumn<bool>(name: "shouldFail");
1573 QTest::addColumn<QString>(name: "message");
1574 QTest::addColumn<QByteArray>(name: "format");
1575 QTest::newRow(dataTag: "corrupt jpeg") << QString("corrupt.jpg") << true
1576 << QString("JPEG datastream contains no image")
1577 << QByteArray("jpeg");
1578 QTest::newRow(dataTag: "corrupt gif") << QString("corrupt.gif") << true << QString("") << QByteArray("gif");
1579 QTest::newRow(dataTag: "corrupt png") << QString("corrupt.png") << true << QString("") << QByteArray("png");
1580 QTest::newRow(dataTag: "corrupt bmp") << QString("corrupt.bmp") << true << QString("") << QByteArray("bmp");
1581 QTest::newRow(dataTag: "corrupt bmp (clut)") << QString("corrupt_clut.bmp") << true << QString("") << QByteArray("bmp");
1582 QTest::newRow(dataTag: "corrupt xpm (colors)") << QString("corrupt-colors.xpm") << true
1583 << QString("QImage: XPM color specification is missing: bla9an.n#x")
1584 << QByteArray("xpm");
1585 QTest::newRow(dataTag: "corrupt xpm (pixels)") << QString("corrupt-pixels.xpm") << true
1586 << QString("QImage: XPM pixels missing on image line 3")
1587 << QByteArray("xpm");
1588 QTest::newRow(dataTag: "corrupt xbm") << QString("corrupt.xbm") << false << QString("") << QByteArray("xbm");
1589 QTest::newRow(dataTag: "corrupt svg") << QString("corrupt.svg") << true << QString("") << QByteArray("svg");
1590 QTest::newRow(dataTag: "corrupt svgz") << QString("corrupt.svgz") << true << QString("") << QByteArray("svgz");
1591}
1592
1593void tst_QImageReader::readCorruptImage()
1594{
1595 QFETCH(QString, fileName);
1596 QFETCH(bool, shouldFail);
1597 QFETCH(QString, message);
1598 QFETCH(QByteArray, format);
1599
1600 SKIP_IF_UNSUPPORTED(format);
1601
1602 if (!message.isEmpty())
1603 QTest::ignoreMessage(type: QtWarningMsg, message: message.toLatin1());
1604 QImageReader reader(prefix + fileName);
1605 QVERIFY(reader.canRead());
1606 QCOMPARE(reader.read().isNull(), shouldFail);
1607}
1608
1609void tst_QImageReader::readCorruptBmp()
1610{
1611 QCOMPARE(QImage(prefix + "tst7.bmp").convertToFormat(QImage::Format_ARGB32_Premultiplied), QImage(prefix + "tst7.png").convertToFormat(QImage::Format_ARGB32_Premultiplied));
1612}
1613
1614void tst_QImageReader::supportsOption_data()
1615{
1616 QTest::addColumn<QString>(name: "fileName");
1617 QTest::addColumn<QIntList>(name: "options");
1618
1619 QTest::newRow(dataTag: "png") << QString("black.png")
1620 << (QIntList() << QImageIOHandler::Gamma
1621 << QImageIOHandler::Description
1622 << QImageIOHandler::Quality
1623 << QImageIOHandler::CompressionRatio
1624 << QImageIOHandler::Size
1625 << QImageIOHandler::ScaledSize);
1626}
1627
1628void tst_QImageReader::supportsOption()
1629{
1630 QFETCH(QString, fileName);
1631 QFETCH(QIntList, options);
1632
1633 QSet<QImageIOHandler::ImageOption> allOptions;
1634 allOptions << QImageIOHandler::Size
1635 << QImageIOHandler::ClipRect
1636 << QImageIOHandler::Description
1637 << QImageIOHandler::ScaledClipRect
1638 << QImageIOHandler::ScaledSize
1639 << QImageIOHandler::CompressionRatio
1640 << QImageIOHandler::Gamma
1641 << QImageIOHandler::Quality
1642 << QImageIOHandler::Name
1643 << QImageIOHandler::SubType
1644 << QImageIOHandler::IncrementalReading
1645 << QImageIOHandler::Endianness
1646 << QImageIOHandler::Animation
1647 << QImageIOHandler::BackgroundColor;
1648
1649 QImageReader reader(prefix + fileName);
1650 for (int i = 0; i < options.size(); ++i) {
1651 QVERIFY(reader.supportsOption(QImageIOHandler::ImageOption(options.at(i))));
1652 allOptions.remove(value: QImageIOHandler::ImageOption(options.at(i)));
1653 }
1654
1655 foreach (QImageIOHandler::ImageOption option, allOptions)
1656 QVERIFY(!reader.supportsOption(option));
1657}
1658
1659void tst_QImageReader::autoDetectImageFormat()
1660{
1661 // Assume PNG is supported :-)
1662 {
1663 // Disables file name extension probing
1664 QImageReader reader(prefix + "kollada");
1665 reader.setAutoDetectImageFormat(false);
1666 QVERIFY(!reader.canRead());
1667 QVERIFY(reader.read().isNull());
1668 reader.setAutoDetectImageFormat(true);
1669 QVERIFY(reader.canRead());
1670 QVERIFY(!reader.read().isNull());
1671 }
1672 {
1673 // Disables detection based on suffix
1674 QImageReader reader(prefix + "kollada.png");
1675 reader.setAutoDetectImageFormat(false);
1676 QVERIFY(!reader.canRead());
1677 QVERIFY(reader.read().isNull());
1678 reader.setAutoDetectImageFormat(true);
1679 QVERIFY(reader.canRead());
1680 QVERIFY(!reader.read().isNull());
1681 }
1682 {
1683 // Disables detection based on content
1684 QImageReader reader(prefix + "kollada-noext");
1685 reader.setAutoDetectImageFormat(false);
1686 QVERIFY(!reader.canRead());
1687 QVERIFY(reader.read().isNull());
1688 reader.setAutoDetectImageFormat(true);
1689 QVERIFY(reader.canRead());
1690 QVERIFY(!reader.read().isNull());
1691 }
1692
1693 if (QImageReader::supportedImageFormats().contains(t: "jpeg")) {
1694 QImageReader io(prefix + "YCbCr_rgb.jpg");
1695 io.setAutoDetectImageFormat(false);
1696 // This should fail since no format string is given
1697 QImage image;
1698 QVERIFY(!io.read(&image));
1699 }
1700 if (QImageReader::supportedImageFormats().contains(t: "jpeg")) {
1701 QImageReader io(prefix + "YCbCr_rgb.jpg", "jpg");
1702 io.setAutoDetectImageFormat(false);
1703 QImage image;
1704 QVERIFY(io.read(&image));
1705 }
1706 {
1707 QImageReader io(prefix + "tst7.png");
1708 io.setAutoDetectImageFormat(false);
1709 // This should fail since no format string is given
1710 QImage image;
1711 QVERIFY(!io.read(&image));
1712 }
1713 {
1714 QImageReader io(prefix + "tst7.png", "png");
1715 io.setAutoDetectImageFormat(false);
1716 QImage image;
1717 QVERIFY(io.read(&image));
1718 }
1719}
1720
1721void tst_QImageReader::fileNameProbing()
1722{
1723 QString name("doesnotexist.png");
1724 QImageReader r;
1725 r.setFileName(name); // non-existing / non-readable file
1726 QCOMPARE(r.fileName(), name);
1727
1728 r.size();
1729 QCOMPARE(r.fileName(), name);
1730 r.read();
1731 QCOMPARE(r.fileName(), name);
1732}
1733
1734void tst_QImageReader::pixelCompareWithBaseline_data()
1735{
1736 QTest::addColumn<QString>(name: "fileName");
1737
1738 QTest::newRow(dataTag: "floppy (16px,32px - 16 colors)") << "35floppy.ico";
1739 QTest::newRow(dataTag: "semitransparent") << "semitransparent.ico";
1740 QTest::newRow(dataTag: "slightlybrokenBMPHeader") << "kde_favicon.ico";
1741 QTest::newRow(dataTag: "sightlybrokenIconHeader") << "connect.ico";
1742}
1743
1744void tst_QImageReader::pixelCompareWithBaseline()
1745{
1746 QFETCH(QString, fileName);
1747
1748 static int enteredCount = 0; // Used for better error diagnostics if something fails. We
1749 static int loadFailCount = 0; // don't know if the reason load() fails is that the plugin
1750 // does not exist or because of a bug in the plugin. But if at
1751 // least one file succeeded we know that the plugin was built.
1752 // The other failures are then real failures.
1753 QImage icoImg;
1754 const QString inputFileName(QLatin1String("images/") + fileName);
1755 QFileInfo fi(inputFileName);
1756
1757 ++enteredCount;
1758 // might fail if the plugin does not exist, which is ok.
1759 if (icoImg.load(fileName: inputFileName)) {
1760 icoImg = icoImg.convertToFormat(f: QImage::Format_ARGB32_Premultiplied);
1761 const QString baselineFileName(QLatin1String("baseline/") + fi.baseName() + QLatin1String(".png"));
1762#if 0
1763 icoImg.save(baselineFileName);
1764#else
1765 QImage baseImg;
1766 QVERIFY(baseImg.load(baselineFileName));
1767 baseImg = baseImg.convertToFormat(f: QImage::Format_ARGB32_Premultiplied);
1768 QCOMPARE(int(baseImg.format()), int(icoImg.format()));
1769 QCOMPARE(baseImg, icoImg);
1770#endif
1771 } else {
1772 ++loadFailCount;
1773 if (enteredCount != loadFailCount) {
1774 QFAIL("Plugin is built, but some did not load properly");
1775 } else {
1776 qWarning(msg: "loading failed, check if ico plugin is built");
1777 }
1778 }
1779}
1780
1781
1782void tst_QImageReader::testIgnoresFormatAndExtension_data()
1783{
1784 QTest::addColumn<QString>(name: "name");
1785 QTest::addColumn<QString>(name: "extension");
1786 QTest::addColumn<QString>(name: "expected");
1787
1788 QTest::newRow(dataTag: "black.png") << "black" << "png" << "png";
1789 QTest::newRow(dataTag: "black.xpm") << "black" << "xpm" << "xpm";
1790 QTest::newRow(dataTag: "colorful.bmp") << "colorful" << "bmp" << "bmp";
1791 QTest::newRow(dataTag: "image.ppm") << "image" << "ppm" << "ppm";
1792 QTest::newRow(dataTag: "image.pbm") << "image" << "pbm" << "pbm";
1793 QTest::newRow(dataTag: "image.pgm") << "image" << "pgm" << "pgm";
1794
1795 QTest::newRow(dataTag: "bat1.gif") << "bat1" << "gif" << "gif";
1796
1797 QTest::newRow(dataTag: "beavis.jpg") << "beavis" << "jpg" << "jpeg";
1798
1799 QTest::newRow(dataTag: "rect.svg") << "rect" << "svg" << "svg";
1800 QTest::newRow(dataTag: "rect.svgz") << "rect" << "svgz" << "svgz";
1801}
1802
1803static QByteArray msgIgnoreFormatAndExtensionFail(const QString &sourceFileName,
1804 const QString &targetFileName,
1805 const QString &detectedFormat)
1806{
1807 QByteArray result = "Failure for '";
1808 result += sourceFileName.toLocal8Bit();
1809 result += "' as '";
1810 result += targetFileName.toLocal8Bit();
1811 result += "', detected as: '";
1812 result += detectedFormat.toLocal8Bit();
1813 result += '\'';
1814 return result;
1815}
1816
1817void tst_QImageReader::testIgnoresFormatAndExtension()
1818{
1819 QFETCH(QString, name);
1820 QFETCH(QString, extension);
1821 QFETCH(QString, expected);
1822
1823 SKIP_IF_UNSUPPORTED(expected.toLatin1());
1824
1825 QList<QByteArray> formats = QImageReader::supportedImageFormats();
1826 QString fileNameBase = prefix + name + QLatin1Char('.');
1827 QString tempPath = m_temporaryDir.path();
1828 if (!tempPath.endsWith(c: QLatin1Char('/')))
1829 tempPath += QLatin1Char('/');
1830
1831 foreach (const QByteArray &f, formats) {
1832 if (f == extension.toLocal8Bit())
1833 continue;
1834
1835 QFile tmp(tempPath + name + QLatin1Char('_') + expected + QLatin1Char('.') + f);
1836 const QString sourceFileName = fileNameBase + extension;
1837 const QString tempFileName = QFileInfo(tmp).absoluteFilePath();
1838 QVERIFY(QFile::copy(sourceFileName, tempFileName));
1839
1840 QString format;
1841 QImage image;
1842 {
1843 // image reader needs to be scoped for the remove() to work..
1844 QImageReader r;
1845 r.setFileName(tempFileName);
1846 r.setDecideFormatFromContent(true);
1847 format = r.format();
1848 r.read(image: &image);
1849 }
1850
1851 tmp.remove();
1852
1853 QVERIFY2(!image.isNull(), msgIgnoreFormatAndExtensionFail(sourceFileName, tempFileName, format).constData());
1854 QCOMPARE(format, expected);
1855 }
1856}
1857
1858
1859void tst_QImageReader::saveFormat_data()
1860{
1861 QTest::addColumn<QImage::Format>(name: "format");
1862
1863 QTest::newRow(dataTag: "Format_Mono") << QImage::Format_Mono;
1864 QTest::newRow(dataTag: "Format_MonoLSB") << QImage::Format_MonoLSB;
1865 QTest::newRow(dataTag: "Format_Indexed8") << QImage::Format_Indexed8;
1866 QTest::newRow(dataTag: "Format_RGB32") << QImage::Format_RGB32;
1867 QTest::newRow(dataTag: "Format_ARGB32") << QImage::Format_ARGB32;
1868 QTest::newRow(dataTag: "Format_ARGB32_Premultiplied") << QImage::Format_ARGB32_Premultiplied;
1869 QTest::newRow(dataTag: "Format_RGB16") << QImage::Format_RGB16;
1870 QTest::newRow(dataTag: "Format_ARGB8565_Premultiplied") << QImage::Format_ARGB8565_Premultiplied;
1871 QTest::newRow(dataTag: "Format_RGB666") << QImage::Format_RGB666;
1872 QTest::newRow(dataTag: "Format_ARGB6666_Premultiplied") << QImage::Format_ARGB6666_Premultiplied;
1873 QTest::newRow(dataTag: "Format_RGB555") << QImage::Format_RGB555;
1874 QTest::newRow(dataTag: "Format_ARGB8555_Premultiplied") << QImage::Format_ARGB8555_Premultiplied;
1875 QTest::newRow(dataTag: "Format_RGB888") << QImage::Format_RGB888;
1876 QTest::newRow(dataTag: "Format_BGR888") << QImage::Format_BGR888;
1877 QTest::newRow(dataTag: "Format_RGB444") << QImage::Format_RGB444;
1878 QTest::newRow(dataTag: "Format_ARGB4444_Premultiplied") << QImage::Format_ARGB4444_Premultiplied;
1879 QTest::newRow(dataTag: "Format_RGBA64") << QImage::Format_RGBA64;
1880 QTest::newRow(dataTag: "Format_RGBA64_Premultiplied") << QImage::Format_RGBA64_Premultiplied;
1881}
1882
1883void tst_QImageReader::saveFormat()
1884{
1885 QFETCH(QImage::Format, format);
1886
1887 QImage orig(":/images/kollada.png");
1888
1889 QImage converted = orig.convertToFormat(f: format);
1890 QBuffer buf;
1891 buf.open(openMode: QIODevice::WriteOnly);
1892 QVERIFY(converted.save(&buf, "png"));
1893 buf.close();
1894 QImage stored = QImage::fromData(data: buf.buffer(), format: "png");
1895
1896 stored = stored.convertToFormat(f: QImage::Format_ARGB32);
1897 converted = converted.convertToFormat(f: QImage::Format_ARGB32);
1898 QCOMPARE(stored, converted);
1899}
1900
1901void tst_QImageReader::saveColorSpace_data()
1902{
1903 QTest::addColumn<QColorSpace::NamedColorSpace>(name: "namedColorSpace");
1904
1905 QTest::newRow(dataTag: "sRGB") << QColorSpace::SRgb;
1906 QTest::newRow(dataTag: "sRGB(linear)") << QColorSpace::SRgbLinear;
1907 QTest::newRow(dataTag: "AdobeRGB") << QColorSpace::AdobeRgb;
1908 QTest::newRow(dataTag: "DisplayP3") << QColorSpace::DisplayP3;
1909 QTest::newRow(dataTag: "ProPhotoRgb") << QColorSpace::ProPhotoRgb;
1910}
1911
1912void tst_QImageReader::saveColorSpace()
1913{
1914 QFETCH(QColorSpace::NamedColorSpace, namedColorSpace);
1915
1916 QImage orig(":/images/kollada.png");
1917
1918 orig.setColorSpace(namedColorSpace);
1919 QBuffer buf;
1920 buf.open(openMode: QIODevice::WriteOnly);
1921 QVERIFY(orig.save(&buf, "png"));
1922 buf.close();
1923 QImage stored = QImage::fromData(data: buf.buffer(), format: "png");
1924
1925 QCOMPARE(stored, orig);
1926 QCOMPARE(stored.colorSpace(), orig.colorSpace());
1927
1928 buf.open(openMode: QIODevice::WriteOnly);
1929 QVERIFY(orig.save(&buf, "jpeg"));
1930 buf.close();
1931 stored = QImage::fromData(data: buf.buffer(), format: "jpeg");
1932
1933 QCOMPARE(stored.colorSpace(), orig.colorSpace());
1934}
1935
1936void tst_QImageReader::readText_data()
1937{
1938 QTest::addColumn<QString>(name: "fileName");
1939 QTest::addColumn<QString>(name: "key");
1940 QTest::addColumn<QString>(name: "text");
1941
1942 QTest::newRow(dataTag: "png, tEXt before img") << "txts.png" << "Title" << "PNG";
1943 QTest::newRow(dataTag: "png, zTXt before img") << "txts.png" << "Comment" << "Some compressed text.";
1944 QTest::newRow(dataTag: "png, tEXt after img") << "txts.png" << "Disclaimer" << "For testing only.";
1945 QTest::newRow(dataTag: "png, zTXt after img") << "txts.png" << "Description" << "Rendered by Persistence of Vision (tm) Ray Tracer";
1946
1947 QTest::newRow(dataTag: "jpg, JPEG_COM Title") << "txts.jpg" << "Title" << "JPG";
1948 QTest::newRow(dataTag: "jpg, JPEG_COM Comment") << "txts.jpg" << "Comment" << "Some non-compressed text.";
1949 QTest::newRow(dataTag: "jpg, JPEG_COM Disclaimer") << "txts.jpg" << "Disclaimer" << "For testing only.";
1950 QTest::newRow(dataTag: "jpg, JPEG_COM Description") << "txts.jpg" << "Description" << "Rendered by Persistence of Vision (tm) Ray Tracer";
1951}
1952
1953
1954void tst_QImageReader::readText()
1955{
1956 QFETCH(QString, fileName);
1957 QFETCH(QString, key);
1958 QFETCH(QString, text);
1959
1960 QImage img(prefix + fileName);
1961 QVERIFY(img.textKeys().contains(key));
1962 QCOMPARE(img.text(key), text);
1963}
1964
1965
1966void tst_QImageReader::preserveTexts_data()
1967{
1968 QTest::addColumn<QString>(name: "fileName");
1969 QTest::addColumn<QString>(name: "text");
1970
1971 QString latin1set;
1972 for (int c = 0x20; c <= 0x7e; c++)
1973 latin1set.append(c: QLatin1Char(c));
1974 for (int c = 0xa0; c <= 0xff; c++)
1975 latin1set.append(c: QLatin1Char(c));
1976
1977 QStringList fileNames;
1978 fileNames << QLatin1String(":/images/kollada.png")
1979 << QLatin1String(":/images/txts.jpg");
1980 foreach (const QString &fileName, fileNames) {
1981 QTest::newRow(dataTag: "Simple") << fileName << "simpletext";
1982 QTest::newRow(dataTag: "Whitespace") << fileName << " A text with whitespace ";
1983 QTest::newRow(dataTag: "Newline") << fileName << "A text\nwith newlines\n";
1984 QTest::newRow(dataTag: "Double newlines") << fileName << "A text\n\nwith double newlines\n\n";
1985 QTest::newRow(dataTag: "Long") << fileName << QString("A rather long text, at least after many repetitions. ").repeated(times: 100);
1986 QTest::newRow(dataTag: "All Latin1 chars") << fileName << latin1set;
1987#if 0
1988 // Depends on iTXt support in libpng
1989 QTest::newRow("Multibyte string") << fileName << QString::fromUtf8("\341\233\222\341\233\226\341\232\251\341\232\271\341\232\242\341\233\232\341\232\240");
1990#endif
1991 }
1992}
1993
1994
1995void tst_QImageReader::preserveTexts()
1996{
1997 QFETCH(QString, fileName);
1998 QByteArray format = fileName.right(n: 3).toLatin1();
1999 QFETCH(QString, text);
2000 QString key("testkey");
2001 QString key2("testkey2");
2002 QString text2("Some other text.");
2003 QString key3("testkey3");
2004 QString text3("Some more other text.");
2005
2006 QImage img(fileName);
2007 img.setText(key, value: text);
2008 img.setText(key: key2, value: text2);
2009 QBuffer buf;
2010 buf.open(openMode: QIODevice::WriteOnly);
2011 QVERIFY(img.save(&buf, format.constData()));
2012 buf.close();
2013 QImage stored = QImage::fromData(data: buf.buffer(), format: format.constData());
2014 QCOMPARE(stored.text(key), text);
2015 QCOMPARE(stored.text(key2), text2);
2016
2017 QImage img2(fileName);
2018 img2.setText(key: key3, value: text3);
2019 QBuffer buf2;
2020 QImageWriter w(&buf2, format);
2021 w.setText(key, text);
2022 w.setText(key: key2, text: text2);
2023 QVERIFY(w.write(img2));
2024 buf2.close();
2025 QImageReader r(&buf2, format);
2026 QCOMPARE(r.text(key), text.simplified());
2027 QCOMPARE(r.text(key2), text2.simplified());
2028 QCOMPARE(r.text(key3), text3.simplified());
2029}
2030
2031void tst_QImageReader::devicePixelRatio_data()
2032{
2033 QTest::addColumn<QString>(name: "fileName");
2034 QTest::addColumn<QSize>(name: "size");
2035 QTest::addColumn<qreal>(name: "dpr");
2036
2037 QTest::newRow(dataTag: "1x") << "qticon16.png" << QSize(16, 16) << 1.0;
2038 QTest::newRow(dataTag: "2x") << "qticon16@2x.png" << QSize(32, 32) << 2.0;
2039 QTest::newRow(dataTag: "3x") << "qticon16@3x.png" << QSize(48, 48) << 3.0;
2040}
2041
2042void tst_QImageReader::devicePixelRatio()
2043{
2044 QFETCH(QString, fileName);
2045 QFETCH(QSize, size);
2046 QFETCH(qreal, dpr);
2047
2048 QImageReader r(":/images/" + fileName);
2049 QImage img = r.read();
2050 QCOMPARE(img.size(), size);
2051 QCOMPARE(img.devicePixelRatio(), dpr);
2052}
2053
2054void tst_QImageReader::xpmBufferOverflow()
2055{
2056 // Please note that the overflow only showed when Qt was configured with "-sanitize address".
2057 QImageReader(":/images/oss-fuzz-23988.xpm").read();
2058}
2059
2060void tst_QImageReader::xbmBufferHandling()
2061{
2062 uint8_t original_buffer[256];
2063 for (int i = 0; i < 256; ++i)
2064 original_buffer[i] = i;
2065
2066 QImage image(original_buffer, 256, 8, QImage::Format_MonoLSB);
2067 image.setColorTable({0xff000000, 0xffffffff});
2068
2069 QByteArray buffer;
2070 {
2071 QBuffer buf(&buffer);
2072 QImageWriter writer(&buf, "xbm");
2073 writer.write(image);
2074 }
2075
2076 QCOMPARE(QImage::fromData(buffer, "xbm"), image);
2077
2078 auto i = buffer.indexOf(c: ',');
2079 buffer.insert(i: i + 1, s: " ");
2080 QCOMPARE(QImage::fromData(buffer, "xbm"), image);
2081 buffer.insert(i: i + 1, s: " ");
2082 QCOMPARE(QImage::fromData(buffer, "xbm"), image);
2083 buffer.insert(i: i + 1, s: " ");
2084#if 0 // Lines longer than 300 chars not supported currently
2085 QCOMPARE(QImage::fromData(buffer, "xbm"), image);
2086#endif
2087
2088 i = buffer.lastIndexOf(c: "\n ");
2089 buffer.truncate(pos: i + 1);
2090 buffer.append(a: QByteArray(297, ' '));
2091 buffer.append(s: "0x");
2092 // Only check we get no buffer overflow
2093 QImage::fromData(data: buffer, format: "xbm");
2094}
2095
2096QTEST_MAIN(tst_QImageReader)
2097#include "tst_qimagereader.moc"
2098

source code of qtbase/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp