| 1 | /* |
| 2 | PIC_RW - Qt PIC Support |
| 3 | SPDX-FileCopyrightText: 2007 Ruben Lopez <r.lopez@bren.es> |
| 4 | |
| 5 | SPDX-License-Identifier: LGPL-2.0-or-later |
| 6 | */ |
| 7 | |
| 8 | #ifndef KIMG_PIC_P_H |
| 9 | #define KIMG_PIC_P_H |
| 10 | |
| 11 | #include <QDataStream> |
| 12 | #include <QImageIOPlugin> |
| 13 | |
| 14 | /** |
| 15 | * The magic number at the start of a SoftImage PIC file. |
| 16 | */ |
| 17 | static const qint32 PIC_MAGIC_NUMBER = 0x5380f634; |
| 18 | |
| 19 | /** |
| 20 | * How fields are distributed over the image. |
| 21 | * |
| 22 | * This information is not used by this image format code. |
| 23 | */ |
| 24 | enum PicFields { |
| 25 | NoPicture = 0, /**< No picture */ |
| 26 | OddScanlines = 1, /**< Odd scanlines */ |
| 27 | EvenScanlines = 2, /**< Even scanlines */ |
| 28 | BothScanlines = 3, /**< Every scanline */ |
| 29 | }; |
| 30 | |
| 31 | /** |
| 32 | * How the data for a channel is encoded. |
| 33 | */ |
| 34 | enum PicChannelEncoding { |
| 35 | Uncompressed = 0, /**< Image is uncompressed */ |
| 36 | MixedRLE = 2, /**< Run length compression */ |
| 37 | }; |
| 38 | |
| 39 | /** |
| 40 | * What components are encoded in a channel. |
| 41 | */ |
| 42 | enum PicChannelCode { |
| 43 | RED = 0x80, /**< Red channel */ |
| 44 | GREEN = 0x40, /**< Green channel */ |
| 45 | BLUE = 0x20, /**< Blue channel */ |
| 46 | ALPHA = 0x10, /**< Alpha channel */ |
| 47 | }; |
| 48 | |
| 49 | /** |
| 50 | * The header for a SoftImage PIC file. |
| 51 | * |
| 52 | * @private |
| 53 | */ |
| 54 | struct { |
| 55 | /** |
| 56 | * Construct a valid header for a SoftImage PIC file. |
| 57 | * |
| 58 | * Note that the comment will be truncated to 80 bytes when written. |
| 59 | * |
| 60 | * @param _width The width of the image in pixels |
| 61 | * @param _height The height of the image in pixels |
| 62 | * @param _comment A comment to add to the image |
| 63 | */ |
| 64 | (quint16 _width, quint16 _height, const QByteArray & = QByteArray()) |
| 65 | : magic(PIC_MAGIC_NUMBER) |
| 66 | , version(3.71f) |
| 67 | , comment(_comment) |
| 68 | , id("PICT" ) |
| 69 | , width(_width) |
| 70 | , height(_height) |
| 71 | , ratio(1.0f) |
| 72 | , fields(BothScanlines) |
| 73 | { |
| 74 | } |
| 75 | /** Construct an invalid header. */ |
| 76 | () |
| 77 | { |
| 78 | } |
| 79 | |
| 80 | quint32 ; /**< Should be PIC_MAGIC_NUMBER */ |
| 81 | float ; /**< Version of something (header? file format?) (ignored) */ |
| 82 | QByteArray ; /**< A free comment field (truncated to 80 bytes when |
| 83 | written) */ |
| 84 | QByteArray ; /**< The file format ID (should be "PICT") */ |
| 85 | quint16 ; /**< The width of the image in pixels */ |
| 86 | quint16 ; /**< The height of the image in pixels */ |
| 87 | float ; /**< The aspect ratio: width/height of each individual pixel |
| 88 | (ignored) */ |
| 89 | PicFields ; /**< The interlace type (ignored) */ |
| 90 | |
| 91 | /** |
| 92 | * Returns true if the @p magic and @p id fields are set correctly. |
| 93 | */ |
| 94 | bool () const |
| 95 | { |
| 96 | return magic == PIC_MAGIC_NUMBER && id == "PICT" ; |
| 97 | } |
| 98 | |
| 99 | /** |
| 100 | * The length of the encoded data, in bytes. |
| 101 | */ |
| 102 | static const qint64 = 104; |
| 103 | }; |
| 104 | |
| 105 | /** |
| 106 | * Describes a channel in a SoftImage PIC file. |
| 107 | * |
| 108 | * @private |
| 109 | */ |
| 110 | struct PicChannel { |
| 111 | quint8 size; /**< Bits per component per pixel. */ |
| 112 | quint8 encoding; /**< How the channel's data is encoded. */ |
| 113 | quint8 code; /**< Flag field to describe which components are encoded in |
| 114 | this channel. */ |
| 115 | |
| 116 | /** |
| 117 | * Constructs a channel description for a SoftImage PIC file. |
| 118 | * |
| 119 | * @param _encoding How the channel's data is or will be encoded. |
| 120 | * @param _code What components are or will be encoded by this |
| 121 | * channel. |
| 122 | * @param _size The number of bits used to encoded a single component |
| 123 | * for a single pixel in this channel (should be 8). |
| 124 | */ |
| 125 | PicChannel(PicChannelEncoding _encoding, quint8 _code, quint8 _size = 8) |
| 126 | : size(_size) |
| 127 | , encoding(_encoding) |
| 128 | , code(_code) |
| 129 | { |
| 130 | } |
| 131 | /** |
| 132 | * Constructs a default channel description for a SoftImage PIC file. |
| 133 | * |
| 134 | * This will have size set to 8, encoding set to Uncompressed and the code |
| 135 | * set to 0 (so that the channel does not encode any information). |
| 136 | * |
| 137 | * The result of this should not be written to a file without setting the |
| 138 | * encoding and channel fields correctly. |
| 139 | */ |
| 140 | PicChannel() |
| 141 | : size(8) |
| 142 | { |
| 143 | } |
| 144 | }; |
| 145 | |
| 146 | class SoftimagePICHandler : public QImageIOHandler |
| 147 | { |
| 148 | public: |
| 149 | bool canRead() const override; |
| 150 | bool read(QImage *image) override; |
| 151 | bool write(const QImage &) override; |
| 152 | |
| 153 | QVariant option(ImageOption option) const override; |
| 154 | void setOption(ImageOption option, const QVariant &value) override; |
| 155 | bool supportsOption(ImageOption option) const override; |
| 156 | |
| 157 | static bool canRead(QIODevice *device); |
| 158 | |
| 159 | enum State { |
| 160 | Error, |
| 161 | Ready, |
| 162 | ReadHeader, |
| 163 | ReadChannels, |
| 164 | }; |
| 165 | |
| 166 | SoftimagePICHandler() |
| 167 | : m_state(Ready) |
| 168 | , m_compression(true) |
| 169 | { |
| 170 | } |
| 171 | |
| 172 | bool readHeader(); |
| 173 | bool readChannels(); |
| 174 | |
| 175 | private: |
| 176 | State m_state; |
| 177 | QDataStream m_dataStream; |
| 178 | PicHeader m_header; |
| 179 | QList<PicChannel> m_channels; |
| 180 | // mostly used for writing: |
| 181 | bool m_compression; |
| 182 | QByteArray m_description; |
| 183 | }; |
| 184 | |
| 185 | class SoftimagePICPlugin : public QImageIOPlugin |
| 186 | { |
| 187 | Q_OBJECT |
| 188 | Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QImageIOHandlerFactoryInterface" FILE "pic.json" ) |
| 189 | |
| 190 | public: |
| 191 | Capabilities capabilities(QIODevice *device, const QByteArray &format) const override; |
| 192 | QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const override; |
| 193 | }; |
| 194 | |
| 195 | #endif // KIMG_PIC_P_H |
| 196 | |