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 */
17static 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 */
24enum 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 */
34enum 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 */
42enum 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 */
54struct 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())
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 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 */
94 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 */
110struct 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
146class SoftimagePICHandler : public QImageIOHandler
147{
148public:
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
175private:
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
185class SoftimagePICPlugin : public QImageIOPlugin
186{
187 Q_OBJECT
188 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QImageIOHandlerFactoryInterface" FILE "pic.json")
189
190public:
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

source code of kimageformats/src/imageformats/pic_p.h