From b94d6354cb0b24a92e674fc994919394c7549b5a Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Tue, 15 Sep 2009 09:48:43 +0200 Subject: Added support in qimagereader to base plugin selection on stream content Reviewed-by: Trond --- src/gui/image/qimagereader.cpp | 56 ++++++++++++++++++---- src/gui/image/qimagereader.h | 3 ++ tests/auto/qimagereader/tst_qimagereader.cpp | 71 ++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 10 deletions(-) diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index 41df852..5cd768f 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -195,7 +195,9 @@ static const _qt_BuiltInFormatStruct _qt_BuiltInFormats[] = { }; static QImageIOHandler *createReadHandlerHelper(QIODevice *device, - const QByteArray &format, bool autoDetectImageFormat) + const QByteArray &format, + bool autoDetectImageFormat, + bool ignoresFormatAndExtension) { if (!autoDetectImageFormat && format.isEmpty()) return 0; @@ -217,7 +219,7 @@ static QImageIOHandler *createReadHandlerHelper(QIODevice *device, #if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) int suffixPluginIndex = -1; - if (device && format.isEmpty() && autoDetectImageFormat) { + if (device && format.isEmpty() && autoDetectImageFormat && !ignoresFormatAndExtension) { // if there's no format, see if \a device is a file, and if so, find // the file suffix and find support for that format among our plugins. // this allows plugins to override our built-in handlers. @@ -241,6 +243,9 @@ static QImageIOHandler *createReadHandlerHelper(QIODevice *device, QByteArray testFormat = !form.isEmpty() ? form : suffix; + if (ignoresFormatAndExtension) + testFormat = QByteArray(); + #if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) if (suffixPluginIndex != -1) { // check if the plugin that claims support for this format can load @@ -258,7 +263,7 @@ static QImageIOHandler *createReadHandlerHelper(QIODevice *device, device->seek(pos); } - if (!handler && !testFormat.isEmpty() && autoDetectImageFormat) { + if (!handler && !testFormat.isEmpty() && autoDetectImageFormat && !ignoresFormatAndExtension) { // check if any plugin supports the format (they are not allowed to // read from the device yet). const qint64 pos = device ? device->pos() : 0; @@ -315,7 +320,7 @@ static QImageIOHandler *createReadHandlerHelper(QIODevice *device, } #if !defined (QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) - if (!handler && autoDetectImageFormat) { + if (!handler && (autoDetectImageFormat || ignoresFormatAndExtension)) { // check if any of our plugins recognize the file from its contents. const qint64 pos = device ? device->pos() : 0; for (int i = 0; i < keys.size(); ++i) { @@ -335,7 +340,7 @@ static QImageIOHandler *createReadHandlerHelper(QIODevice *device, } #endif - if (!handler && autoDetectImageFormat) { + if (!handler && (autoDetectImageFormat || ignoresFormatAndExtension)) { // check if any of our built-in handlers recognize the file from its // contents. int currentFormat = 0; @@ -434,6 +439,7 @@ public: // device QByteArray format; bool autoDetectImageFormat; + bool ignoresFormatAndExtension; QIODevice *device; bool deleteDevice; QImageIOHandler *handler; @@ -458,7 +464,7 @@ public: \internal */ QImageReaderPrivate::QImageReaderPrivate(QImageReader *qq) - : autoDetectImageFormat(true) + : autoDetectImageFormat(true), ignoresFormatAndExtension(false) { device = 0; deleteDevice = false; @@ -522,7 +528,7 @@ bool QImageReaderPrivate::initHandler() } // assign a handler - if (!handler && (handler = createReadHandlerHelper(device, format, autoDetectImageFormat)) == 0) { + if (!handler && (handler = createReadHandlerHelper(device, format, autoDetectImageFormat, ignoresFormatAndExtension)) == 0) { imageReaderError = QImageReader::UnsupportedFormatError; errorString = QLatin1String(QT_TRANSLATE_NOOP(QImageReader, "Unsupported image format")); return false; @@ -664,7 +670,7 @@ QByteArray QImageReader::format() const \o Finally, if all above approaches fail, QImageReader will report failure when trying to read the image. - \endlist + \endlist By disabling image format autodetection, QImageReader will only query the plugins and built-in handlers based on the format string (i.e., no file @@ -681,13 +687,43 @@ void QImageReader::setAutoDetectImageFormat(bool enabled) Returns true if image format autodetection is enabled on this image reader; otherwise returns false. By default, autodetection is enabled. - \sa setAutoDetectImageFormat() + \sa setAutoDetectImageFormat() */ bool QImageReader::autoDetectImageFormat() const { return d->autoDetectImageFormat; } + +/*! + + Specifies that the image reader should decide which plugin to use + solely based on the contents in the datastream. + + Setting this flag means that all image plugins gets loaded. Each + plugin will read the first bytes in the image data and decide if + the plugin is compatible or not. + + This also disables auto detecting image format. +*/ + +void QImageReader::setDecideFormatFromContent(bool ignored) +{ + d->ignoresFormatAndExtension = ignored; +} + + +/*! + Returns wether the image reader should decide which plugin to use + sloley based on the contents of the datastream +*/ + +bool QImageReader::decideFormatFromContent() const +{ + return d->ignoresFormatAndExtension; +} + + /*! Sets QImageReader's device to \a device. If a device has already been set, the old device is removed from QImageReader and is @@ -1309,7 +1345,7 @@ QByteArray QImageReader::imageFormat(const QString &fileName) QByteArray QImageReader::imageFormat(QIODevice *device) { QByteArray format; - QImageIOHandler *handler = createReadHandlerHelper(device, format, /* autoDetectImageFormat = */ true); + QImageIOHandler *handler = createReadHandlerHelper(device, format, /* autoDetectImageFormat = */ true, false); if (handler) { if (handler->canRead()) format = handler->format(); diff --git a/src/gui/image/qimagereader.h b/src/gui/image/qimagereader.h index 86031ec..11affb8 100644 --- a/src/gui/image/qimagereader.h +++ b/src/gui/image/qimagereader.h @@ -81,6 +81,9 @@ public: void setAutoDetectImageFormat(bool enabled); bool autoDetectImageFormat() const; + void setDecideFormatFromContent(bool ignored); + bool decideFormatFromContent() const; + void setDevice(QIODevice *device); QIODevice *device() const; diff --git a/tests/auto/qimagereader/tst_qimagereader.cpp b/tests/auto/qimagereader/tst_qimagereader.cpp index 8630021..cab8fda 100644 --- a/tests/auto/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/qimagereader/tst_qimagereader.cpp @@ -167,6 +167,10 @@ private slots: void task255627_setNullScaledSize_data(); void task255627_setNullScaledSize(); + + void testIgnoresFormatAndExtension_data(); + void testIgnoresFormatAndExtension(); + }; static const QLatin1String prefix(SRCDIR "/images/"); @@ -225,6 +229,7 @@ void tst_QImageReader::readImage_data() QTest::newRow("PPM: runners") << QString("runners.ppm") << true << QByteArray("ppm"); QTest::newRow("PPM: test") << QString("test.ppm") << true << QByteArray("ppm"); QTest::newRow("XBM: gnus") << QString("gnus.xbm") << true << QByteArray("xbm"); + #if defined QTEST_HAVE_JPEG QTest::newRow("JPEG: beavis") << QString("beavis.jpg") << true << QByteArray("jpeg"); #endif @@ -1495,5 +1500,71 @@ void tst_QImageReader::pixelCompareWithBaseline() } } + +void tst_QImageReader::testIgnoresFormatAndExtension_data() +{ + QTest::addColumn("name"); + QTest::addColumn("extension"); + QTest::addColumn("expected"); + + QTest::newRow("black.png") << "black" << "png" << "png"; + QTest::newRow("black.xpm") << "black" << "xpm" << "xpm"; + QTest::newRow("colorful.bmp") << "colorful" << "bmp" << "bmp"; + QTest::newRow("image.ppm") << "image" << "ppm" << "ppm"; + QTest::newRow("image.pbm") << "image" << "pbm" << "pbm"; + QTest::newRow("image.pgm") << "image" << "pgm" << "pgm"; + +#if defined QTEST_HAVE_GIF + QTest::newRow("bat1.gif") << "bat1" << "gif" << "gif"; +#endif + +#if defined QTEST_HAVE_JPEG + QTest::newRow("beavis.jpg") << "beavis" << "jpg" << "jpeg"; +#endif + +#if defined QTEST_HAVE_MNG + QTest::newRow("fire.mng") << "fire" << "mng" << "mng"; +#endif + +#if defined QTEST_HAVE_TIFF + QTest::newRow("image_100dpi.tif") << "image_100dpi" << "tif" << "tiff"; +#endif +} + + +void tst_QImageReader::testIgnoresFormatAndExtension() +{ + QFETCH(QString, name); + QFETCH(QString, extension); + QFETCH(QString, expected); + + QList formats = QImageReader::supportedImageFormats(); + QString fileNameBase = "images/" + name + "."; + + foreach (const QByteArray &f, formats) { + if (f == extension) + continue; + QFile tmp(QDir::tempPath() + "/" + name + "_" + expected + "." + f); + + QFile::copy(fileNameBase + extension, QFileInfo(tmp).absoluteFilePath()); + + QString format; + QImage image; + { + // image reader needs to be scoped for the remove() to work.. + QImageReader r; + r.setFileName(QFileInfo(tmp).absoluteFilePath()); + r.setDecideFormatFromContent(true); + format = r.format(); + r.read(&image); + } + + tmp.remove(); + + QVERIFY(!image.isNull()); + QCOMPARE(format, expected); + } +} + QTEST_MAIN(tst_QImageReader) #include "tst_qimagereader.moc" -- cgit v0.12