Mirco Miranda adc5c7ae9a DDS: improved read/write support
The following changes have been made:

- Improved writing speed by using scanLine() instead of pixel()
- Optimized memory usage on writing by using ScanlineConverter class
- Added native write support for RGBA32FPx4, RGBA16FPx4, RGB8, Grayscale8 and Indexed8 uncompressed formats
- Grayscale DDS without alpha are loaded in a Grayscale8 image
- Fixed warnings about wrong PITCH reported by GIMP on DDSs saved by this plugin
- Initial support for loading DX10 formats (R16F, RG16F, RGBA16F, RGBPreMulA16F, R32F, RG32F, RGBA32F, RGBPreMulA32F)
- Fixed alignment issues and A8P8 format support of the attached images*

Tested using GIMP and [NVIDIA Texture Tools](https://developer.nvidia.com/texture-tools-exporter) plugin for Photoshop.

(*) The following images (taken from [here](https://github.com/walbourn/directxtexmedia)) cannot be added to read tests due to license issue:
[test8_DWORD.dds](/uploads/449b5a0d886aaf6764af554fe38e2b09/test8_DWORD.dds)
[dx5_logo.dds](/uploads/6f5f27df752890b227ef07e0195435d4/dx5_logo.dds)
[test888_DWORD.dds](/uploads/c8bc355c5749cf203d47e0b3073ad419/test888_DWORD.dds)
2024-12-17 23:08:43 +00:00

145 lines
3.6 KiB
C++

/*
This file is part of the KDE project
SPDX-FileCopyrightText: 2015 The Qt Company Ltd
SPDX-FileCopyrightText: 2013 Ivan Komissarov
SPDX-FileCopyrightText: 2024 Mirco Miranda
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only
*/
#ifndef QDDSHANDLER_H
#define QDDSHANDLER_H
#include <QImageIOPlugin>
struct DDSPixelFormat
{
enum DDSPixelFormatFlags {
FlagAlphaPixels = 0x00000001,
FlagAlpha = 0x00000002,
FlagFourCC = 0x00000004,
FlagPaletteIndexed4 = 0x00000008,
FlagPaletteIndexed8 = 0x00000020,
FlagRGB = 0x00000040,
FlagYUV = 0x00000200,
FlagLuminance = 0x00020000,
FlagNormal = 0x00080000,
FlagRGBA = FlagAlphaPixels | FlagRGB,
FlagLA = FlagAlphaPixels | FlagLuminance
};
quint32 size;
quint32 flags;
quint32 fourCC;
quint32 rgbBitCount;
quint32 rBitMask;
quint32 gBitMask;
quint32 bBitMask;
quint32 aBitMask;
};
struct DDSHeaderDX10
{
quint32 dxgiFormat = 0;
quint32 resourceDimension = 0;
quint32 miscFlag = 0;
quint32 arraySize = 0;
quint32 miscFlags2 = 0;
};
struct DDSHeader
{
enum DDSFlags {
FlagCaps = 0x000001,
FlagHeight = 0x000002,
FlagWidth = 0x000004,
FlagPitch = 0x000008,
FlagPixelFormat = 0x001000,
FlagMipmapCount = 0x020000,
FlagLinearSize = 0x080000,
FlagDepth = 0x800000
};
enum DDSCapsFlags {
CapsComplex = 0x000008,
CapsTexture = 0x001000,
CapsMipmap = 0x400000
};
enum DDSCaps2Flags {
Caps2CubeMap = 0x0200,
Caps2CubeMapPositiveX = 0x0400,
Caps2CubeMapNegativeX = 0x0800,
Caps2CubeMapPositiveY = 0x1000,
Caps2CubeMapNegativeY = 0x2000,
Caps2CubeMapPositiveZ = 0x4000,
Caps2CubeMapNegativeZ = 0x8000,
Caps2Volume = 0x200000
};
enum { ReservedCount = 11 };
quint32 magic;
quint32 size;
quint32 flags;
quint32 height;
quint32 width;
quint32 pitchOrLinearSize;
quint32 depth;
quint32 mipMapCount;
quint32 reserved1[ReservedCount];
DDSPixelFormat pixelFormat;
quint32 caps;
quint32 caps2;
quint32 caps3;
quint32 caps4;
quint32 reserved2;
DDSHeaderDX10 header10;
};
class QDDSHandler : public QImageIOHandler
{
public:
QDDSHandler();
bool canRead() const override;
bool read(QImage *image) override;
bool write(const QImage &image) override;
QVariant option(QImageIOHandler::ImageOption option) const override;
void setOption(ImageOption option, const QVariant &value) override;
bool supportsOption(QImageIOHandler::ImageOption option) const override;
int imageCount() const override;
bool jumpToImage(int imageNumber) override;
static bool canRead(QIODevice *device);
private:
bool ensureScanned() const;
bool verifyHeader(const DDSHeader &dds) const;
private:
enum ScanState {
ScanError = -1,
ScanNotScanned = 0,
ScanSuccess = 1,
};
DDSHeader m_header;
int m_format;
int m_currentImage;
mutable ScanState m_scanState;
};
class QDDSPlugin : public QImageIOPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QImageIOHandlerFactoryInterface" FILE "dds.json")
public:
Capabilities capabilities(QIODevice *device, const QByteArray &format) const override;
QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const override;
};
#endif // QDDSHANDLER_H