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 | |