From 5a5eb18deb5239863a2cedb6b77f90e9a5be3113 Mon Sep 17 00:00:00 2001 From: Ivan Komissarov <ABBAPOH@gmail.com> Date: Tue, 7 Jan 2014 16:09:11 +0400 Subject: [PATCH] Add support for SubType and SupportedSubTypes options in DDS handler Change-Id: I2fa563bf023871e9e99ed32829f978577eaf2a68 Reviewed-by: Alex Char <prevedtest@gmail.com> Reviewed-by: Gunnar Sletta <gunnar.sletta@jollamobile.com> --- src/plugins/imageformats/dds/qddshandler.cpp | 144 ++++++++++++++++++- src/plugins/imageformats/dds/qddshandler.h | 1 + tests/auto/dds/tst_qdds.cpp | 11 ++ 3 files changed, 154 insertions(+), 2 deletions(-) diff --git a/src/plugins/imageformats/dds/qddshandler.cpp b/src/plugins/imageformats/dds/qddshandler.cpp index d5c8793e..05bf87bd 100644 --- a/src/plugins/imageformats/dds/qddshandler.cpp +++ b/src/plugins/imageformats/dds/qddshandler.cpp @@ -166,6 +166,101 @@ static const Format knownFourCCs[] = { }; static const size_t knownFourCCsSize = sizeof(knownFourCCs)/sizeof(Format); +struct FormatName +{ + Format format; + const char *const name; +}; +static const FormatName formatNames[] = { + { FormatUnknown, "unknown" }, + + { FormatR8G8B8, "R8G8B8" }, + { FormatA8R8G8B8, "A8R8G8B8" }, + { FormatX8R8G8B8, "X8R8G8B8" }, + { FormatR5G6B5, "R5G6B5" }, + { FormatX1R5G5B5, "X1R5G5B5" }, + { FormatA1R5G5B5, "A1R5G5B5" }, + { FormatA4R4G4B4, "A4R4G4B4" }, + { FormatR3G3B2, "R3G3B2" }, + { FormatA8, "A8" }, + { FormatA8R3G3B2, "A8R3G3B2" }, + { FormatX4R4G4B4, "X4R4G4B4" }, + { FormatA2B10G10R10, "A2B10G10R10" }, + { FormatA8B8G8R8, "A8B8G8R8" }, + { FormatX8B8G8R8, "X8B8G8R8" }, + { FormatG16R16, "G16R16" }, + { FormatA2R10G10B10, "A2R10G10B10" }, + { FormatA16B16G16R16, "A16B16G16R16" }, + + { FormatA8P8, "A8P8" }, + { FormatP8, "P8" }, + + { FormatL8, "L8" }, + { FormatA8L8, "A8L8" }, + { FormatA4L4, "A4L4" }, + + { FormatV8U8, "V8U8" }, + { FormatL6V5U5, "L6V5U5" }, + { FormatX8L8V8U8, "X8L8V8U8" }, + { FormatQ8W8V8U8, "Q8W8V8U8" }, + { FormatV16U16, "V16U16" }, + { FormatA2W10V10U10, "A2W10V10U10" }, + + { FormatUYVY, "UYVY" }, + { FormatR8G8B8G8, "R8G8_B8G8" }, + { FormatYUY2, "YUY2" }, + { FormatG8R8G8B8, "G8R8_G8B8" }, + { FormatDXT1, "DXT1" }, + { FormatDXT2, "DXT2" }, + { FormatDXT3, "DXT3" }, + { FormatDXT4, "DXT4" }, + { FormatDXT5, "DXT5" }, + { FormatRXGB, "RXGB" }, + { FormatATI2, "ATI2" }, + + { FormatD16Lockable, "D16Lockable" }, + { FormatD32, "D32" }, + { FormatD15S1, "D15S1" }, + { FormatD24S8, "D24S8" }, + { FormatD24X8, "D24X8" }, + { FormatD24X4S4, "D24X4S4" }, + { FormatD16, "D16" }, + + { FormatD32FLockable, "D32FLockable" }, + { FormatD24FS8, "D24FS8" }, + + { FormatD32Lockable, "D32Lockable" }, + { FormatS8Lockable, "S8Lockable" }, + + { FormatL16, "L16" }, + + { FormatVertexData, "VertexData" }, + { FormatIndex32, "Index32" }, + { FormatIndex32, "Index32" }, + + { FormatQ16W16V16U16, "Q16W16V16U16" }, + + { FormatMulti2ARGB8, "Multi2ARGB8" }, + + { FormatR16F, "R16F" }, + { FormatG16R16F, "G16R16F" }, + { FormatA16B16G16R16F, "A16B16G16R16F" }, + + { FormatR32F, "R32F" }, + { FormatG32R32F, "G32R32F" }, + { FormatA32B32G32R32F, "A32B32G32R32F" }, + + { FormatCxV8U8, "CxV8U8" }, + + { FormatA1, "A1" }, + { FormatA2B10G10R10_XR_BIAS, "A2B10G10R10_XR_BIAS" }, + { FormatBinaryBuffer, "BinaryBuffer" }, + + { FormatP4, "P4" }, + { FormatA4P4, "A4P4" } +}; +static const size_t formatNamesSize = sizeof(formatNames)/sizeof(FormatName); + static inline int maskToShift(quint32 mask) { if (mask == 0) @@ -1256,7 +1351,29 @@ static QImage readCubeMap(QDataStream &s, const DDSHeader &dds, const int fmt) return image; } +static QByteArray formatName(int format) +{ + for (size_t i = 0; i < formatNamesSize; ++i) { + if (formatNames[i].format == format) + return formatNames[i].name; + } + + return formatNames[0].name; +} + +static int formatByName(const QByteArray &name) +{ + const QByteArray loweredName = name.toLower(); + for (size_t i = 0; i < formatNamesSize; ++i) { + if (QByteArray(formatNames[i].name).toLower() == loweredName) + return formatNames[i].format; + } + + return FormatUnknown; +} + QDDSHandler::QDDSHandler() : + m_format(FormatA8R8G8B8), m_currentImage(0), m_scanState(ScanNotScanned) { @@ -1303,6 +1420,11 @@ bool QDDSHandler::read(QImage *outImage) bool QDDSHandler::write(const QImage &outImage) { + if (m_format != FormatA8R8G8B8) { + qWarning() << "Format" << formatName(m_format) << "is not supported"; + return false; + } + const QImage image = outImage.convertToFormat(QImage::Format_ARGB32); QDataStream s(device()); @@ -1362,6 +1484,10 @@ QVariant QDDSHandler::option(QImageIOHandler::ImageOption option) const switch (option) { case QImageIOHandler::Size: return QSize(m_header.width, m_header.height); + case QImageIOHandler::SubType: + return formatName(m_format); + case QImageIOHandler::SupportedSubTypes: + return QVariant::fromValue(QList<QByteArray>() << formatName(FormatA8R8G8B8)); default: break; } @@ -1369,9 +1495,21 @@ QVariant QDDSHandler::option(QImageIOHandler::ImageOption option) const return QVariant(); } +void QDDSHandler::setOption(QImageIOHandler::ImageOption option, const QVariant &value) +{ + if (option == QImageIOHandler::SubType) { + const QByteArray subType = value.toByteArray(); + m_format = formatByName(subType.toUpper()); + if (m_format == FormatUnknown) + qWarning() << "unknown format" << subType; + } +} + bool QDDSHandler::supportsOption(QImageIOHandler::ImageOption option) const { - return option == QImageIOHandler::Size; + return (option == QImageIOHandler::Size) + || (option == QImageIOHandler::SubType) + || (option == QImageIOHandler::SupportedSubTypes); } int QDDSHandler::imageCount() const @@ -1411,6 +1549,9 @@ bool QDDSHandler::ensureScanned() const m_scanState = ScanError; + QDDSHandler *that = const_cast<QDDSHandler *>(this); + that->m_format = FormatUnknown; + if (device()->isSequential()) { qWarning() << "Sequential devices are not supported"; return false; @@ -1419,7 +1560,6 @@ bool QDDSHandler::ensureScanned() const qint64 oldPos = device()->pos(); device()->seek(0); - QDDSHandler *that = const_cast<QDDSHandler *>(this); QDataStream s(device()); s.setByteOrder(QDataStream::LittleEndian); s >> that->m_header; diff --git a/src/plugins/imageformats/dds/qddshandler.h b/src/plugins/imageformats/dds/qddshandler.h index 582a0133..967a35d2 100644 --- a/src/plugins/imageformats/dds/qddshandler.h +++ b/src/plugins/imageformats/dds/qddshandler.h @@ -62,6 +62,7 @@ public: bool write(const QImage &image); QVariant option(QImageIOHandler::ImageOption option) const; + void setOption(ImageOption option, const QVariant &value); bool supportsOption(QImageIOHandler::ImageOption option) const; int imageCount() const; diff --git a/tests/auto/dds/tst_qdds.cpp b/tests/auto/dds/tst_qdds.cpp index 24746641..f3c69f86 100644 --- a/tests/auto/dds/tst_qdds.cpp +++ b/tests/auto/dds/tst_qdds.cpp @@ -118,8 +118,12 @@ void tst_qdds::readImage() QFETCH(QSize, size); const QString path = QStringLiteral(":/dds/") + fileName + QStringLiteral(".dds"); + const QByteArray subType = fileName.left(fileName.lastIndexOf(QLatin1Char('.'))).toLatin1(); QImageReader reader(path); QVERIFY(reader.canRead()); + QVERIFY(reader.supportsOption(QImageIOHandler::SubType)); + QCOMPARE(reader.subType(), subType); + QVERIFY(reader.supportsOption(QImageIOHandler::SupportedSubTypes)); QImage image = reader.read(); QVERIFY2(!image.isNull(), qPrintable(reader.errorString())); QCOMPARE(image.size(), size); @@ -169,6 +173,7 @@ void tst_qdds::testWriteImage() const QString path = fileName + QStringLiteral(".dds"); const QString sourcePath = QStringLiteral(":/dds/") + fileName + QStringLiteral(".dds"); + const QByteArray subType = fileName.left(fileName.lastIndexOf(QLatin1Char('.'))).toLatin1(); QImage image(sourcePath); QVERIFY(!image.isNull()); @@ -176,9 +181,15 @@ void tst_qdds::testWriteImage() QImageWriter writer(path, QByteArrayLiteral("dds")); QVERIFY2(writer.canWrite(), qPrintable(writer.errorString())); + writer.setSubType(subType); QVERIFY2(writer.write(image), qPrintable(writer.errorString())); QVERIFY(image == QImage(path)); + + QImageReader reader(path); + QVERIFY(reader.canRead()); + QCOMPARE(reader.size(), size); + QCOMPARE(reader.subType(), subType); } QTEST_MAIN(tst_qdds) -- GitLab