File indexing completed on 2024-04-28 15:25:42

0001 /*
0002     PIC_RW - Qt PIC Support
0003     SPDX-FileCopyrightText: 2007 Ruben Lopez <r.lopez@bren.es>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #ifndef KIMG_PIC_P_H
0009 #define KIMG_PIC_P_H
0010 
0011 #include <QDataStream>
0012 #include <QImageIOPlugin>
0013 
0014 /**
0015  * The magic number at the start of a SoftImage PIC file.
0016  */
0017 static const qint32 PIC_MAGIC_NUMBER = 0x5380f634;
0018 
0019 /**
0020  * How fields are distributed over the image.
0021  *
0022  * This information is not used by this image format code.
0023  */
0024 enum PicFields {
0025     NoPicture = 0, /**< No picture */
0026     OddScanlines = 1, /**< Odd scanlines */
0027     EvenScanlines = 2, /**< Even scanlines */
0028     BothScanlines = 3, /**< Every scanline */
0029 };
0030 
0031 /**
0032  * How the data for a channel is encoded.
0033  */
0034 enum PicChannelEncoding {
0035     Uncompressed = 0, /**< Image is uncompressed */
0036     MixedRLE = 2, /**< Run length compression */
0037 };
0038 
0039 /**
0040  * What components are encoded in a channel.
0041  */
0042 enum PicChannelCode {
0043     RED = 0x80, /**< Red channel */
0044     GREEN = 0x40, /**< Green channel */
0045     BLUE = 0x20, /**< Blue channel */
0046     ALPHA = 0x10, /**< Alpha channel */
0047 };
0048 
0049 /**
0050  * The header for a SoftImage PIC file.
0051  *
0052  * @private
0053  */
0054 struct PicHeader {
0055     /**
0056      * Construct a valid header for a SoftImage PIC file.
0057      *
0058      * Note that the comment will be truncated to 80 bytes when written.
0059      *
0060      * @param _width    The width of the image in pixels
0061      * @param _height   The height of the image in pixels
0062      * @param _comment  A comment to add to the image
0063      */
0064     PicHeader(quint16 _width, quint16 _height, const QByteArray &_comment = QByteArray())
0065         : magic(PIC_MAGIC_NUMBER)
0066         , version(3.71f)
0067         , comment(_comment)
0068         , id("PICT")
0069         , width(_width)
0070         , height(_height)
0071         , ratio(1.0f)
0072         , fields(BothScanlines)
0073     {
0074     }
0075     /** Construct an invalid header. */
0076     PicHeader()
0077     {
0078     }
0079 
0080     quint32 magic; /**< Should be PIC_MAGIC_NUMBER */
0081     float version; /**< Version of something (header? file format?) (ignored) */
0082     QByteArray comment; /**< A free comment field (truncated to 80 bytes when
0083                              written) */
0084     QByteArray id; /**< The file format ID (should be "PICT") */
0085     quint16 width; /**< The width of the image in pixels */
0086     quint16 height; /**< The height of the image in pixels */
0087     float ratio; /**< The aspect ratio: width/height of each individual pixel
0088                       (ignored) */
0089     PicFields fields; /**< The interlace type (ignored) */
0090 
0091     /**
0092      * Returns true if the @p magic and @p id fields are set correctly.
0093      */
0094     bool isValid() const
0095     {
0096         return magic == PIC_MAGIC_NUMBER && id == "PICT";
0097     }
0098 
0099     /**
0100      * The length of the encoded data, in bytes.
0101      */
0102     static const qint64 encodedLength = 104;
0103 };
0104 
0105 /**
0106  * Describes a channel in a SoftImage PIC file.
0107  *
0108  * @private
0109  */
0110 struct PicChannel {
0111     quint8 size; /**< Bits per component per pixel. */
0112     quint8 encoding; /**< How the channel's data is encoded. */
0113     quint8 code; /**< Flag field to describe which components are encoded in
0114                       this channel. */
0115 
0116     /**
0117      * Constructs a channel description for a SoftImage PIC file.
0118      *
0119      * @param _encoding  How the channel's data is or will be encoded.
0120      * @param _code      What components are or will be encoded by this
0121      *                   channel.
0122      * @param _size      The number of bits used to encoded a single component
0123      *                   for a single pixel in this channel (should be 8).
0124      */
0125     PicChannel(PicChannelEncoding _encoding, quint8 _code, quint8 _size = 8)
0126         : size(_size)
0127         , encoding(_encoding)
0128         , code(_code)
0129     {
0130     }
0131     /**
0132      * Constructs a default channel description for a SoftImage PIC file.
0133      *
0134      * This will have size set to 8, encoding set to Uncompressed and the code
0135      * set to 0 (so that the channel does not encode any information).
0136      *
0137      * The result of this should not be written to a file without setting the
0138      * encoding and channel fields correctly.
0139      */
0140     PicChannel()
0141         : size(8)
0142     {
0143     }
0144 };
0145 
0146 class SoftimagePICHandler : public QImageIOHandler
0147 {
0148 public:
0149     bool canRead() const override;
0150     bool read(QImage *image) override;
0151     bool write(const QImage &) override;
0152 
0153     QVariant option(ImageOption option) const override;
0154     void setOption(ImageOption option, const QVariant &value) override;
0155     bool supportsOption(ImageOption option) const override;
0156 
0157     static bool canRead(QIODevice *device);
0158 
0159     enum State {
0160         Error,
0161         Ready,
0162         ReadHeader,
0163         ReadChannels,
0164     };
0165 
0166     SoftimagePICHandler()
0167         : m_state(Ready)
0168         , m_compression(true)
0169     {
0170     }
0171 
0172     bool readHeader();
0173     bool readChannels();
0174 
0175 private:
0176     State m_state;
0177     QDataStream m_dataStream;
0178     PicHeader m_header;
0179     QList<PicChannel> m_channels;
0180     // mostly used for writing:
0181     bool m_compression;
0182     QByteArray m_description;
0183 };
0184 
0185 class SoftimagePICPlugin : public QImageIOPlugin
0186 {
0187     Q_OBJECT
0188     Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QImageIOHandlerFactoryInterface" FILE "pic.json")
0189 
0190 public:
0191     Capabilities capabilities(QIODevice *device, const QByteArray &format) const override;
0192     QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const override;
0193 };
0194 
0195 #endif // KIMG_PIC_P_H