| 1 | /* |
| 2 | The high dynamic range EXR format support for QImage. |
| 3 | |
| 4 | SPDX-FileCopyrightText: 2003 Brad Hards <bradh@frogmouth.net> |
| 5 | SPDX-FileCopyrightText: 2023 Mirco Miranda <mircomir@outlook.com> |
| 6 | |
| 7 | SPDX-License-Identifier: LGPL-2.0-or-later |
| 8 | */ |
| 9 | |
| 10 | #ifndef KIMG_EXR_P_H |
| 11 | #define KIMG_EXR_P_H |
| 12 | |
| 13 | #include <QImageIOPlugin> |
| 14 | |
| 15 | /*! |
| 16 | * \brief The EXRHandler class |
| 17 | * The handler uses the OpenEXR reference implementation of the EXR file format. |
| 18 | * |
| 19 | * The purpose of EXR format is to accurately and efficiently represent high-dynamic-range scene-linear |
| 20 | * image data and associated metadata. |
| 21 | * |
| 22 | * Both reading and writing of EXR files is supported. When saving, the image is converted to 16-bit |
| 23 | * and sRGB Linear color space (if not already so). If no color space is set in the image, sRGB is assumed. |
| 24 | * When the handler is compiled with the default compile options, the loaded image is a 16-bit image |
| 25 | * with linear color space. |
| 26 | * Multiview images are also supported (read only) via imageCount(), jumpToImage(), etc.... |
| 27 | * |
| 28 | * The following QImageIOHandler options are supported: |
| 29 | * - ImageFormat: The image's data format returned by the handler. |
| 30 | * - Size: The size of the image. |
| 31 | * - CompressionRatio: The compression ratio of the image data (see OpenEXR compression schemes). |
| 32 | * - Quality: The quality level of the image (see OpenEXR compression level of lossy codecs). |
| 33 | * |
| 34 | * The following metadata are set/get via QImage::setText()/QImage::text() in both read/write (if any): |
| 35 | * - Latitude, Longitude, Altitude: Geographic coordinates (Float converted to string). |
| 36 | * - CreationDate: Date the image was captured/created (QDateTime converted to string using Qt::ISODate). |
| 37 | * - Comment: Additional image information in human-readable form, for example a verbal description of the image (QString). |
| 38 | * - Owner: Name of the owner of the image (QString). |
| 39 | * |
| 40 | * In addition, information about image resolution is preserved and the preview is written for images larger |
| 41 | * than 1024px. |
| 42 | * |
| 43 | * The following compile options are supported (defines): |
| 44 | * - EXR_MAX_IMAGE_WIDTH: Maximum image width supported (read/write, default: 300000 px). |
| 45 | * - EXR_MAX_IMAGE_HEIGHT: Maximum image height supported (read/write, default: 300000 px). |
| 46 | * - EXR_LINES_PER_BLOCK: The number of scanlines buffered on both read and write operations.\n |
| 47 | * The higher the value, the greater the parallelization but the RAM consumption increases (default: 128) |
| 48 | * - EXR_USE_LEGACY_CONVERSIONS: The result image is an 8-bit RGB(A) converted without icc profiles (read, default: undefined). |
| 49 | * - EXR_CONVERT_TO_SRGB: The resulting image is convertef in the sRGB color space (read, default: undefined). |
| 50 | * - EXR_DISABLE_XMP_ATTRIBUTE: Disable the stores of XMP values in a non-standard attribute named "xmp".\n |
| 51 | * The QImage metadata used is "XML:com.adobe.xmp" (write, default: undefined). |
| 52 | */ |
| 53 | class EXRHandler : public QImageIOHandler |
| 54 | { |
| 55 | public: |
| 56 | EXRHandler(); |
| 57 | |
| 58 | bool canRead() const override; |
| 59 | bool read(QImage *outImage) override; |
| 60 | bool write(const QImage &image) override; |
| 61 | |
| 62 | void setOption(ImageOption option, const QVariant &value) override; |
| 63 | bool supportsOption(QImageIOHandler::ImageOption option) const override; |
| 64 | QVariant option(QImageIOHandler::ImageOption option) const override; |
| 65 | |
| 66 | bool jumpToNextImage() override; |
| 67 | bool jumpToImage(int imageNumber) override; |
| 68 | int imageCount() const override; |
| 69 | int currentImageNumber() const override; |
| 70 | |
| 71 | static bool canRead(QIODevice *device); |
| 72 | |
| 73 | private: |
| 74 | /*! |
| 75 | * \brief m_compressionRatio |
| 76 | * Value set by QImageWriter::setCompression(). |
| 77 | * |
| 78 | * The compression scheme is the same as defined by OpenEXR library: |
| 79 | * - 0: no compression |
| 80 | * - 1: run length encoding |
| 81 | * - 2: zlib compression, one scan line at a time |
| 82 | * - 3: zlib compression, in blocks of 16 scan lines |
| 83 | * - 4: piz-based wavelet compression (default) |
| 84 | * - 5: lossy 24-bit float compression |
| 85 | * - 6: lossy 4-by-4 pixel block compression, fixed compression rate |
| 86 | * - 7: lossy 4-by-4 pixel block compression, fields are compressed more |
| 87 | * - 8: lossy DCT based compression, in blocks of 32 scanlines. More efficient for partial buffer access. |
| 88 | * - 9: lossy DCT based compression, in blocks of 256 scanlines. More efficient space wise and faster to decode full frames than DWAA_COMPRESSION. |
| 89 | */ |
| 90 | qint32 m_compressionRatio; |
| 91 | |
| 92 | /*! |
| 93 | * \brief m_quality |
| 94 | * Value set by QImageWriter::setQuality(). |
| 95 | * |
| 96 | * The quality is used on DCT compression schemes only with a |
| 97 | * supposed value between 0 and 100 (default: 45). |
| 98 | */ |
| 99 | qint32 m_quality; |
| 100 | |
| 101 | /*! |
| 102 | * \brief m_imageNumber |
| 103 | * Value set by QImageReader::jumpToImage() or QImageReader::jumpToNextImage(). |
| 104 | * The number of view selected in a multiview image. |
| 105 | */ |
| 106 | qint32 m_imageNumber; |
| 107 | |
| 108 | /*! |
| 109 | * \brief m_imageCount |
| 110 | * The total number of views (cache value) |
| 111 | */ |
| 112 | mutable qint32 m_imageCount; |
| 113 | |
| 114 | /*! |
| 115 | * \brief m_startPos |
| 116 | * The initial device position to allow multi image load (cache value). |
| 117 | */ |
| 118 | qint64 m_startPos; |
| 119 | }; |
| 120 | |
| 121 | class EXRPlugin : public QImageIOPlugin |
| 122 | { |
| 123 | Q_OBJECT |
| 124 | Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QImageIOHandlerFactoryInterface" FILE "exr.json" ) |
| 125 | |
| 126 | public: |
| 127 | Capabilities capabilities(QIODevice *device, const QByteArray &format) const override; |
| 128 | QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const override; |
| 129 | }; |
| 130 | |
| 131 | #endif // KIMG_EXR_P_H |
| 132 | |