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 PicHeader { 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 PicHeader(quint16 _width, quint16 _height, const QByteArray &_comment = QByteArray()) magicPicHeader65 : 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. */ PicHeaderPicHeader76 PicHeader() 77 { 78 } 79 80 quint32 magic; /**< Should be PIC_MAGIC_NUMBER */ 81 float version; /**< Version of something (header? file format?) (ignored) */ 82 QByteArray comment; /**< A free comment field (truncated to 80 bytes when 83 written) */ 84 QByteArray id; /**< The file format ID (should be "PICT") */ 85 quint16 width; /**< The width of the image in pixels */ 86 quint16 height; /**< The height of the image in pixels */ 87 float ratio; /**< The aspect ratio: width/height of each individual pixel 88 (ignored) */ 89 PicFields fields; /**< The interlace type (ignored) */ 90 91 /** 92 * Returns true if the @p magic and @p id fields are set correctly. 93 */ isValidPicHeader94 bool isValid() 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 encodedLength = 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) sizePicChannel126 : 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 */ PicChannelPicChannel140 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 SoftimagePICHandler()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