File indexing completed on 2024-04-28 03:54:48

0001 /*
0002     xcf.cpp: A Qt 5 plug-in for reading GIMP XCF image files
0003     SPDX-FileCopyrightText: 2001 lignum Computing Inc. <allen@lignumcomputing.com>
0004     SPDX-FileCopyrightText: 2004 Melchior FRANZ <mfranz@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.1-or-later
0007 */
0008 
0009 #include "util_p.h"
0010 #include "xcf_p.h"
0011 
0012 #include <QColorSpace>
0013 #include <QDebug>
0014 #include <QIODevice>
0015 #include <QImage>
0016 #include <QImageReader>
0017 #include <QList>
0018 #include <QLoggingCategory>
0019 #include <QPainter>
0020 #include <QStack>
0021 #include <QtEndian>
0022 
0023 #ifndef XCF_QT5_SUPPORT
0024 // Float images are not supported by Qt 5 and can be disabled in QT 6 to reduce memory usage.
0025 // Unfortunately enabling/disabling this define results in slightly different images, so leave the default if possible.
0026 #define USE_FLOAT_IMAGES // default uncommented
0027 
0028 // Let's set a "reasonable" maximum size
0029 #define MAX_IMAGE_WIDTH 300000
0030 #define MAX_IMAGE_HEIGHT 300000
0031 #else
0032 // While it is possible to have images larger than 32767 pixels, QPainter seems unable to go beyond this threshold using Qt 5.
0033 #define MAX_IMAGE_WIDTH 32767
0034 #define MAX_IMAGE_HEIGHT 32767
0035 #endif
0036 
0037 #ifdef USE_FLOAT_IMAGES
0038 #include <qrgbafloat.h>
0039 #endif
0040 
0041 #include <stdlib.h>
0042 #include <string.h>
0043 
0044 #include "gimp_p.h"
0045 
0046 Q_DECLARE_LOGGING_CATEGORY(XCFPLUGIN)
0047 Q_LOGGING_CATEGORY(XCFPLUGIN, "kf.imageformats.plugins.xcf", QtWarningMsg)
0048 
0049 //#define DISABLE_TILE_PROFILE // default commented (comment to use the conversion as intended by Martin)
0050 #define DISABLE_IMAGE_PROFILE // default uncommented (comment to use the conversion as intended by Martin)
0051 #define DISABLE_TILE_PROFILE_CONV // default uncommented (comment to use the conversion as intended by Martin)
0052 #define DISABLE_IMAGE_PROFILE_CONV // default uncommented (comment to use the conversion as intended by Martin)
0053 
0054 const float INCHESPERMETER = (100.0f / 2.54f);
0055 
0056 namespace
0057 {
0058 struct RandomTable {
0059     // From glibc
0060     static constexpr int rand_r(unsigned int *seed)
0061     {
0062         unsigned int next = *seed;
0063         int result = 0;
0064 
0065         next *= 1103515245;
0066         next += 12345;
0067         result = (unsigned int)(next / 65536) % 2048;
0068 
0069         next *= 1103515245;
0070         next += 12345;
0071         result <<= 10;
0072         result ^= (unsigned int)(next / 65536) % 1024;
0073 
0074         next *= 1103515245;
0075         next += 12345;
0076         result <<= 10;
0077         result ^= (unsigned int)(next / 65536) % 1024;
0078 
0079         *seed = next;
0080 
0081         return result;
0082     }
0083 
0084     constexpr RandomTable()
0085         : values{}
0086     {
0087         unsigned int next = RANDOM_SEED;
0088 
0089         for (int i = 0; i < RANDOM_TABLE_SIZE; i++) {
0090             values[i] = rand_r(&next);
0091         }
0092 
0093         for (int i = 0; i < RANDOM_TABLE_SIZE; i++) {
0094             int tmp{};
0095             int swap = i + rand_r(&next) % (RANDOM_TABLE_SIZE - i);
0096             tmp = values[i];
0097             values[i] = values[swap];
0098             values[swap] = tmp;
0099         }
0100     }
0101 
0102     int values[RANDOM_TABLE_SIZE]{};
0103 };
0104 } // namespace {
0105 
0106 /*!
0107  * Each layer in an XCF file is stored as a matrix of
0108  * 64-pixel by 64-pixel images. The GIMP has a sophisticated
0109  * method of handling very large images as well as implementing
0110  * parallel processing on a tile-by-tile basis. Here, though,
0111  * we just read them in en-masse and store them in a matrix.
0112  */
0113 typedef QList<QList<QImage>> Tiles;
0114 
0115 class XCFImageFormat
0116 {
0117     Q_GADGET
0118 public:
0119     //! Properties which can be stored in an XCF file.
0120     enum PropType {
0121         PROP_END = 0,
0122         PROP_COLORMAP = 1,
0123         PROP_ACTIVE_LAYER = 2,
0124         PROP_ACTIVE_CHANNEL = 3,
0125         PROP_SELECTION = 4,
0126         PROP_FLOATING_SELECTION = 5,
0127         PROP_OPACITY = 6,
0128         PROP_MODE = 7,
0129         PROP_VISIBLE = 8,
0130         PROP_LINKED = 9,
0131         PROP_LOCK_ALPHA = 10,
0132         PROP_APPLY_MASK = 11,
0133         PROP_EDIT_MASK = 12,
0134         PROP_SHOW_MASK = 13,
0135         PROP_SHOW_MASKED = 14,
0136         PROP_OFFSETS = 15,
0137         PROP_COLOR = 16,
0138         PROP_COMPRESSION = 17,
0139         PROP_GUIDES = 18,
0140         PROP_RESOLUTION = 19,
0141         PROP_TATTOO = 20,
0142         PROP_PARASITES = 21,
0143         PROP_UNIT = 22,
0144         PROP_PATHS = 23,
0145         PROP_USER_UNIT = 24,
0146         PROP_VECTORS = 25,
0147         PROP_TEXT_LAYER_FLAGS = 26,
0148         PROP_OLD_SAMPLE_POINTS = 27,
0149         PROP_LOCK_CONTENT = 28,
0150         PROP_GROUP_ITEM = 29,
0151         PROP_ITEM_PATH = 30,
0152         PROP_GROUP_ITEM_FLAGS = 31,
0153         PROP_LOCK_POSITION = 32,
0154         PROP_FLOAT_OPACITY = 33,
0155         PROP_COLOR_TAG = 34,
0156         PROP_COMPOSITE_MODE = 35,
0157         PROP_COMPOSITE_SPACE = 36,
0158         PROP_BLEND_SPACE = 37,
0159         PROP_FLOAT_COLOR = 38,
0160         PROP_SAMPLE_POINTS = 39,
0161         MAX_SUPPORTED_PROPTYPE, // should always be at the end so its value is last + 1
0162     };
0163     Q_ENUM(PropType)
0164 
0165     //! Compression type used in layer tiles.
0166     enum XcfCompressionType : qint8 {
0167         COMPRESS_INVALID = -1, /* our own */
0168         COMPRESS_NONE = 0,
0169         COMPRESS_RLE = 1,
0170         COMPRESS_ZLIB = 2, /* unused */
0171         COMPRESS_FRACTAL = 3, /* unused */
0172     };
0173     Q_ENUM(XcfCompressionType)
0174 
0175     enum LayerModeType : quint32 {
0176         GIMP_LAYER_MODE_NORMAL_LEGACY,
0177         GIMP_LAYER_MODE_DISSOLVE,
0178         GIMP_LAYER_MODE_BEHIND_LEGACY,
0179         GIMP_LAYER_MODE_MULTIPLY_LEGACY,
0180         GIMP_LAYER_MODE_SCREEN_LEGACY,
0181         GIMP_LAYER_MODE_OVERLAY_LEGACY,
0182         GIMP_LAYER_MODE_DIFFERENCE_LEGACY,
0183         GIMP_LAYER_MODE_ADDITION_LEGACY,
0184         GIMP_LAYER_MODE_SUBTRACT_LEGACY,
0185         GIMP_LAYER_MODE_DARKEN_ONLY_LEGACY,
0186         GIMP_LAYER_MODE_LIGHTEN_ONLY_LEGACY,
0187         GIMP_LAYER_MODE_HSV_HUE_LEGACY,
0188         GIMP_LAYER_MODE_HSV_SATURATION_LEGACY,
0189         GIMP_LAYER_MODE_HSL_COLOR_LEGACY,
0190         GIMP_LAYER_MODE_HSV_VALUE_LEGACY,
0191         GIMP_LAYER_MODE_DIVIDE_LEGACY,
0192         GIMP_LAYER_MODE_DODGE_LEGACY,
0193         GIMP_LAYER_MODE_BURN_LEGACY,
0194         GIMP_LAYER_MODE_HARDLIGHT_LEGACY,
0195         GIMP_LAYER_MODE_SOFTLIGHT_LEGACY,
0196         GIMP_LAYER_MODE_GRAIN_EXTRACT_LEGACY,
0197         GIMP_LAYER_MODE_GRAIN_MERGE_LEGACY,
0198         GIMP_LAYER_MODE_COLOR_ERASE_LEGACY,
0199         GIMP_LAYER_MODE_OVERLAY,
0200         GIMP_LAYER_MODE_LCH_HUE,
0201         GIMP_LAYER_MODE_LCH_CHROMA,
0202         GIMP_LAYER_MODE_LCH_COLOR,
0203         GIMP_LAYER_MODE_LCH_LIGHTNESS,
0204         GIMP_LAYER_MODE_NORMAL,
0205         GIMP_LAYER_MODE_BEHIND,
0206         GIMP_LAYER_MODE_MULTIPLY,
0207         GIMP_LAYER_MODE_SCREEN,
0208         GIMP_LAYER_MODE_DIFFERENCE,
0209         GIMP_LAYER_MODE_ADDITION,
0210         GIMP_LAYER_MODE_SUBTRACT,
0211         GIMP_LAYER_MODE_DARKEN_ONLY,
0212         GIMP_LAYER_MODE_LIGHTEN_ONLY,
0213         GIMP_LAYER_MODE_HSV_HUE,
0214         GIMP_LAYER_MODE_HSV_SATURATION,
0215         GIMP_LAYER_MODE_HSL_COLOR,
0216         GIMP_LAYER_MODE_HSV_VALUE,
0217         GIMP_LAYER_MODE_DIVIDE,
0218         GIMP_LAYER_MODE_DODGE,
0219         GIMP_LAYER_MODE_BURN,
0220         GIMP_LAYER_MODE_HARDLIGHT,
0221         GIMP_LAYER_MODE_SOFTLIGHT,
0222         GIMP_LAYER_MODE_GRAIN_EXTRACT,
0223         GIMP_LAYER_MODE_GRAIN_MERGE,
0224         GIMP_LAYER_MODE_VIVID_LIGHT,
0225         GIMP_LAYER_MODE_PIN_LIGHT,
0226         GIMP_LAYER_MODE_LINEAR_LIGHT,
0227         GIMP_LAYER_MODE_HARD_MIX,
0228         GIMP_LAYER_MODE_EXCLUSION,
0229         GIMP_LAYER_MODE_LINEAR_BURN,
0230         GIMP_LAYER_MODE_LUMA_DARKEN_ONLY,
0231         GIMP_LAYER_MODE_LUMA_LIGHTEN_ONLY,
0232         GIMP_LAYER_MODE_LUMINANCE,
0233         GIMP_LAYER_MODE_COLOR_ERASE,
0234         GIMP_LAYER_MODE_ERASE,
0235         GIMP_LAYER_MODE_MERGE,
0236         GIMP_LAYER_MODE_SPLIT,
0237         GIMP_LAYER_MODE_PASS_THROUGH,
0238         GIMP_LAYER_MODE_COUNT,
0239     };
0240     Q_ENUM(LayerModeType)
0241 
0242     //! Type of individual layers in an XCF file.
0243     enum GimpImageType : qint32 {
0244         RGB_GIMAGE,
0245         RGBA_GIMAGE,
0246         GRAY_GIMAGE,
0247         GRAYA_GIMAGE,
0248         INDEXED_GIMAGE,
0249         INDEXEDA_GIMAGE,
0250     };
0251     Q_ENUM(GimpImageType)
0252 
0253     //! Type of individual layers in an XCF file.
0254     enum GimpColorSpace : qint32 {
0255         AutoColorSpace,
0256         RgbLinearSpace,
0257         RgbPerceptualSpace,
0258         LabSpace,
0259     };
0260     Q_ENUM(GimpColorSpace);
0261 
0262     //! Mode to use when compositing layer
0263     enum GimpCompositeMode : qint32 {
0264         CompositeAuto,
0265         CompositeUnion,
0266         CompositeClipBackdrop,
0267         CompositeClipLayer,
0268         CompositeIntersect,
0269     };
0270     Q_ENUM(GimpCompositeMode);
0271 
0272     enum GimpPrecision : qint32 {
0273         GIMP_PRECISION_U8_LINEAR = 100, /*< desc="8-bit linear integer"         >*/
0274         GIMP_PRECISION_U8_NON_LINEAR = 150, /*< desc="8-bit non-linear integer"          >*/
0275         GIMP_PRECISION_U8_PERCEPTUAL = 175, /*< desc="8-bit perceptual integer"          >*/
0276         GIMP_PRECISION_U16_LINEAR = 200, /*< desc="16-bit linear integer"        >*/
0277         GIMP_PRECISION_U16_NON_LINEAR = 250, /*< desc="16-bit non-linear integer"         >*/
0278         GIMP_PRECISION_U16_PERCEPTUAL = 275, /*< desc="16-bit perceptual integer"         >*/
0279         GIMP_PRECISION_U32_LINEAR = 300, /*< desc="32-bit linear integer"        >*/
0280         GIMP_PRECISION_U32_NON_LINEAR = 350, /*< desc="32-bit non-linear integer"         >*/
0281         GIMP_PRECISION_U32_PERCEPTUAL = 375, /*< desc="32-bit perceptual integer"         >*/
0282         GIMP_PRECISION_HALF_LINEAR = 500, /*< desc="16-bit linear floating point" >*/
0283         GIMP_PRECISION_HALF_NON_LINEAR = 550, /*< desc="16-bit non-linear floating point"  >*/
0284         GIMP_PRECISION_HALF_PERCEPTUAL = 575, /*< desc="16-bit perceptual floating point"  >*/
0285         GIMP_PRECISION_FLOAT_LINEAR = 600, /*< desc="32-bit linear floating point" >*/
0286         GIMP_PRECISION_FLOAT_NON_LINEAR = 650, /*< desc="32-bit non-linear floating point"  >*/
0287         GIMP_PRECISION_FLOAT_PERCEPTUAL = 675, /*< desc="32-bit perceptual floating point"  >*/
0288         GIMP_PRECISION_DOUBLE_LINEAR = 700, /*< desc="64-bit linear floating point" >*/
0289         GIMP_PRECISION_DOUBLE_NON_LINEAR = 750, /*< desc="64-bit non-linear floating point"  >*/
0290         GIMP_PRECISION_DOUBLE_PERCEPTUAL = 775, /*< desc="64-bit perceptual floating point"  >*/
0291     };
0292     Q_ENUM(GimpPrecision);
0293 
0294     XCFImageFormat();
0295     bool readXCF(QIODevice *device, QImage *image);
0296 
0297     /*!
0298      * Each GIMP image is composed of one or more layers. A layer can
0299      * be one of any three basic types: RGB, grayscale or indexed. With an
0300      * optional alpha channel, there are six possible types altogether.
0301      *
0302      * Note: there is only ever one instance of this structure. The
0303      * layer info is discarded after it is merged into the final QImage.
0304      */
0305     class Layer
0306     {
0307     public:
0308         quint32 width; //!< Width of the layer
0309         quint32 height; //!< Height of the layer
0310         GimpImageType type; //!< Type of the layer (GimpImageType)
0311         char *name; //!< Name of the layer
0312         qint64 hierarchy_offset; //!< File position of Tile hierarchy
0313         qint64 mask_offset; //!< File position of mask image
0314 
0315         uint nrows; //!< Number of rows of tiles (y direction)
0316         uint ncols; //!< Number of columns of tiles (x direction)
0317 
0318         Tiles image_tiles; //!< The basic image
0319         //! For Grayscale and Indexed images, the alpha channel is stored
0320         //! separately (in this data structure, anyway).
0321         Tiles alpha_tiles;
0322         Tiles mask_tiles; //!< The layer mask (optional)
0323 
0324         //! Additional information about a layer mask.
0325         struct {
0326             quint32 opacity;
0327             float opacityFloat = 1.f;
0328             quint32 visible;
0329             quint32 show_masked;
0330             uchar red, green, blue;
0331             float redF, greenF, blueF; // Floats should override
0332             quint32 tattoo;
0333         } mask_channel;
0334 
0335         XcfCompressionType compression = COMPRESS_INVALID; //!< tile compression method (CompressionType)
0336 
0337         bool active; //!< Is this layer the active layer?
0338         quint32 opacity = 255; //!< The opacity of the layer
0339         float opacityFloat = 1.f; //!< The opacity of the layer, but floating point (both are set)
0340         quint32 visible = 1; //!< Is the layer visible?
0341         quint32 linked; //!< Is this layer linked (geometrically)
0342         quint32 preserve_transparency; //!< Preserve alpha when drawing on layer?
0343         quint32 apply_mask = 9; //!< Apply the layer mask? Use 9 as "uninitilized". Spec says "If the property does not appear for a layer which has a layer
0344                                 //!< mask, it defaults to true (1).
0345                                 //   Robust readers should force this to false if the layer has no layer mask.
0346         quint32 edit_mask; //!< Is the layer mask the being edited?
0347         quint32 show_mask; //!< Show the layer mask rather than the image?
0348         qint32 x_offset = 0; //!< x offset of the layer relative to the image
0349         qint32 y_offset = 0; //!< y offset of the layer relative to the image
0350         LayerModeType mode = GIMP_LAYER_MODE_NORMAL_LEGACY; //!< Combining mode of layer (LayerModeEffects)
0351         quint32 tattoo; //!< (unique identifier?)
0352         GimpColorSpace blendSpace = RgbLinearSpace; //!< What colorspace to use when blending
0353         GimpColorSpace compositeSpace = RgbLinearSpace; //!< What colorspace to use when compositing
0354         GimpCompositeMode compositeMode = CompositeUnion; //!< How to composite layer (union, clip, etc.)
0355 
0356         //! As each tile is read from the file, it is buffered here.
0357 #ifdef USE_FLOAT_IMAGES
0358         uchar tile[quint64(TILE_WIDTH * TILE_HEIGHT * sizeof(QRgbaFloat32) * 1.5)];
0359 #else
0360         uchar tile[quint64(TILE_WIDTH * TILE_HEIGHT * sizeof(QRgba64) * 1.5)];
0361 #endif
0362 
0363         //! The data from tile buffer is copied to the Tile by this
0364         //! method.  Depending on the type of the tile (RGB, Grayscale,
0365         //! Indexed) and use (image or mask), the bytes in the buffer are
0366         //! copied in different ways.
0367         bool (*assignBytes)(Layer &layer, uint i, uint j, const GimpPrecision &precision);
0368 
0369         Layer(void)
0370             : name(nullptr)
0371         {
0372         }
0373         ~Layer(void)
0374         {
0375             delete[] name;
0376         }
0377 
0378         Layer(const Layer &) = delete;
0379         Layer &operator=(const Layer &) = delete;
0380 
0381         QImage::Format qimageFormat(const GimpPrecision precision, uint num_colors = 0, bool legacyMode = false) const
0382         {
0383             int bpc = bytesPerChannel(precision);
0384 #ifdef USE_FLOAT_IMAGES
0385             bool float16 = !legacyMode && precision >= GIMP_PRECISION_HALF_LINEAR && precision <= GIMP_PRECISION_HALF_PERCEPTUAL;
0386             bool float32 = !legacyMode && precision >= GIMP_PRECISION_FLOAT_LINEAR && precision <= GIMP_PRECISION_FLOAT_PERCEPTUAL;
0387 #endif
0388 
0389             if (legacyMode) {
0390                 bpc = std::min(bpc, 1);
0391             }
0392 
0393             switch (type) {
0394             case RGB_GIMAGE:
0395                 if (opacity == OPAQUE_OPACITY) {
0396 #ifdef USE_FLOAT_IMAGES
0397                     if (float16) {
0398                         return QImage::Format_RGBX16FPx4;
0399                     }
0400                     if (float32) {
0401                         return QImage::QImage::Format_RGBX32FPx4;
0402                     }
0403 #endif
0404 
0405                     if (bpc == 1) {
0406                         return QImage::Format_RGBX8888;
0407                     } else if (bpc == 2 || bpc == 4) {
0408                         return QImage::Format_RGBX64;
0409                     } else {
0410                         qCDebug(XCFPLUGIN) << "Layer has invalid bpc" << bpc << precision;
0411                         return QImage::Format_Invalid;
0412                     }
0413                 }
0414                 Q_FALLTHROUGH();
0415             case RGBA_GIMAGE:
0416 #ifdef USE_FLOAT_IMAGES
0417                 if (float16) {
0418                     return QImage::Format_RGBA16FPx4;
0419                 }
0420                 if (float32) {
0421                     return QImage::QImage::Format_RGBA32FPx4;
0422                 }
0423 #endif
0424                 if (bpc == 1) {
0425                     return QImage::Format_RGBA8888;
0426                 } else if (bpc == 2 || bpc == 4) {
0427                     return QImage::Format_RGBA64;
0428                 } else {
0429                     qCDebug(XCFPLUGIN) << "Layer has invalid bpc" << bpc;
0430                     return QImage::Format_Invalid;
0431                 }
0432                 break;
0433 
0434             case GRAY_GIMAGE:
0435                 if (opacity == OPAQUE_OPACITY) {
0436                     return QImage::Format_Indexed8;
0437                 } // else, fall through to 32-bit representation
0438                 Q_FALLTHROUGH();
0439             case GRAYA_GIMAGE:
0440                 return QImage::Format_RGBA8888;
0441                 break;
0442 
0443             case INDEXED_GIMAGE:
0444                 // As noted in the table above, there are quite a few combinations
0445                 // which are possible with indexed images, depending on the
0446                 // presence of transparency (note: not translucency, which is not
0447                 // supported by The GIMP for indexed images) and the number of
0448                 // individual colors.
0449 
0450                 // Note: Qt treats a bitmap with a Black and White color palette
0451                 // as a mask, so only the "on" bits are drawn, regardless of the
0452                 // order color table entries. Otherwise (i.e., at least one of the
0453                 // color table entries is not black or white), it obeys the one-
0454                 // or two-color palette. Have to ask about this...
0455 
0456                 if (num_colors == 1 || num_colors == 2) {
0457                     return QImage::Format_MonoLSB;
0458                 } else {
0459                     return QImage::Format_Indexed8;
0460                 }
0461                 break;
0462 
0463             case INDEXEDA_GIMAGE:
0464                 if (num_colors == 1) {
0465                     return QImage::Format_MonoLSB;
0466                 } else {
0467                     return QImage::Format_Indexed8;
0468                 }
0469             }
0470             qCWarning(XCFPLUGIN) << "Unhandled layer mode" << XCFImageFormat::LayerModeType(type);
0471             return QImage::Format_Invalid;
0472         }
0473     };
0474 
0475     /*!
0476      * The in-memory representation of the XCF Image. It contains a few
0477      * metadata items, but is mostly a container for the layer information.
0478      */
0479     class XCFImage
0480     {
0481     public:
0482         struct Header {
0483             GimpPrecision precision = GIMP_PRECISION_U8_LINEAR; //!< Default precision (GimpPrecision)
0484             quint32 width; //!< width of the XCF image
0485             quint32 height; //!< height of the XCF image
0486             qint32 type; //!< type of the XCF image (GimpImageBaseType)
0487         } header;
0488 
0489         XcfCompressionType compression = COMPRESS_RLE; //!< tile compression method (CompressionType)
0490         float x_resolution = -1; //!< x resolution in dots per inch
0491         float y_resolution = -1; //!< y resolution in dots per inch
0492         qint32 tattoo; //!< (unique identifier?)
0493         quint32 unit; //!< Units of The GIMP (inch, mm, pica, etc...)
0494         qint32 num_colors = 0; //!< number of colors in an indexed image
0495         QList<QRgb> palette; //!< indexed image color palette
0496 
0497         int num_layers; //!< number of layers
0498         Layer layer; //!< most recently read layer
0499 
0500         bool initialized; //!< Is the QImage initialized?
0501         QImage image; //!< final QImage
0502 
0503         QHash<QString,QByteArray> parasites;    //!< parasites data
0504 
0505         XCFImage(void)
0506             : initialized(false)
0507         {
0508         }
0509 
0510         QImage::Format qimageFormat() const
0511         {
0512             return layer.qimageFormat(header.precision, num_colors, true);
0513         }
0514 
0515         uint bytesPerChannel() const
0516         {
0517             return XCFImageFormat::bytesPerChannel(header.precision);
0518         }
0519     };
0520 
0521 private:
0522     static qint64 readOffsetPtr(QDataStream &stream)
0523     {
0524         if (stream.version() >= 11) {
0525             qint64 ret;
0526             stream >> ret;
0527             return ret;
0528         } else {
0529             quint32 ret;
0530             stream >> ret;
0531             return ret;
0532         }
0533     }
0534 
0535     //! In layer DISSOLVE mode, a random number is chosen to compare to a
0536     //! pixel's alpha. If the alpha is greater than the random number, the
0537     //! pixel is drawn. This table merely contains the random number seeds
0538     //! for each ROW of an image. Therefore, the random numbers chosen
0539     //! are consistent from run to run.
0540     static int random_table[RANDOM_TABLE_SIZE];
0541     static bool random_table_initialized;
0542 
0543     static constexpr RandomTable randomTable{};
0544 
0545     //! This table is used as a shared grayscale ramp to be set on grayscale
0546     //! images. This is because Qt does not differentiate between indexed and
0547     //! grayscale images.
0548     static QList<QRgb> grayTable;
0549 
0550     //! This table provides the add_pixel saturation values (i.e. 250 + 250 = 255).
0551     // static int add_lut[256][256]; - this is so lame waste of 256k of memory
0552     static int add_lut(int, int);
0553 
0554     //! The bottom-most layer is copied into the final QImage by this
0555     //! routine.
0556     typedef void (*PixelCopyOperation)(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
0557 
0558     //! Higher layers are merged into the final QImage by this routine.
0559     typedef bool (*PixelMergeOperation)(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
0560 
0561     static bool modeAffectsSourceAlpha(const quint32 type);
0562 
0563     bool loadImageProperties(QDataStream &xcf_io, XCFImage &image);
0564     bool loadProperty(QDataStream &xcf_io, PropType &type, QByteArray &bytes, quint32 &rawType);
0565     bool loadLayer(QDataStream &xcf_io, XCFImage &xcf_image);
0566     bool loadLayerProperties(QDataStream &xcf_io, Layer &layer);
0567     bool composeTiles(XCFImage &xcf_image);
0568     void setGrayPalette(QImage &image);
0569     void setPalette(XCFImage &xcf_image, QImage &image);
0570     void setImageParasites(const XCFImage &xcf_image, QImage &image);
0571     static bool assignImageBytes(Layer &layer, uint i, uint j, const GimpPrecision &precision);
0572     bool loadHierarchy(QDataStream &xcf_io, Layer &layer, const GimpPrecision precision);
0573     bool loadLevel(QDataStream &xcf_io, Layer &layer, qint32 bpp, const GimpPrecision precision);
0574     static bool assignMaskBytes(Layer &layer, uint i, uint j, const GimpPrecision &precision);
0575     bool loadMask(QDataStream &xcf_io, Layer &layer, const GimpPrecision precision);
0576     bool loadChannelProperties(QDataStream &xcf_io, Layer &layer);
0577     bool initializeImage(XCFImage &xcf_image);
0578     bool loadTileRLE(QDataStream &xcf_io, uchar *tile, int size, int data_length, qint32 bpp, qint64 *bytesParsed);
0579 
0580     static void copyLayerToImage(XCFImage &xcf_image);
0581     static void copyRGBToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
0582     static void copyGrayToGray(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
0583     static void copyGrayToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
0584     static void copyGrayAToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
0585     static void copyIndexedToIndexed(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
0586     static void copyIndexedAToIndexed(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
0587     static void copyIndexedAToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
0588 
0589     static void mergeLayerIntoImage(XCFImage &xcf_image);
0590     static bool mergeRGBToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
0591     static bool mergeGrayToGray(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
0592     static bool mergeGrayAToGray(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
0593     static bool mergeGrayToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
0594     static bool mergeGrayAToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
0595     static bool mergeIndexedToIndexed(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
0596     static bool mergeIndexedAToIndexed(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
0597     static bool mergeIndexedAToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
0598 
0599     static void initializeRandomTable();
0600     static void dissolveRGBPixels(QImage &image, int x, int y);
0601     static void dissolveAlphaPixels(QImage &image, int x, int y);
0602 
0603     static uint bytesPerChannel(const GimpPrecision precision)
0604     {
0605         switch (precision) {
0606         case GIMP_PRECISION_U8_LINEAR:
0607         case GIMP_PRECISION_U8_NON_LINEAR:
0608         case GIMP_PRECISION_U8_PERCEPTUAL:
0609             return 1;
0610             break;
0611         case GIMP_PRECISION_U16_LINEAR:
0612         case GIMP_PRECISION_U16_NON_LINEAR:
0613         case GIMP_PRECISION_U16_PERCEPTUAL:
0614         case GIMP_PRECISION_HALF_LINEAR:
0615         case GIMP_PRECISION_HALF_NON_LINEAR:
0616         case GIMP_PRECISION_HALF_PERCEPTUAL:
0617             return 2;
0618             break;
0619 
0620         case GIMP_PRECISION_U32_LINEAR:
0621         case GIMP_PRECISION_U32_NON_LINEAR:
0622         case GIMP_PRECISION_U32_PERCEPTUAL:
0623         case GIMP_PRECISION_FLOAT_LINEAR:
0624         case GIMP_PRECISION_FLOAT_NON_LINEAR:
0625         case GIMP_PRECISION_FLOAT_PERCEPTUAL:
0626             return 4;
0627             break;
0628         case GIMP_PRECISION_DOUBLE_LINEAR:
0629         case GIMP_PRECISION_DOUBLE_NON_LINEAR:
0630         case GIMP_PRECISION_DOUBLE_PERCEPTUAL:
0631             return 8;
0632             break;
0633 
0634         default:
0635             qCDebug(XCFPLUGIN) << "Layer has invalid precision" << precision;
0636             return 0;
0637         }
0638     }
0639 
0640 public:
0641     static bool readXCFHeader(QDataStream &ds, XCFImage::Header *header);
0642 };
0643 
0644 int XCFImageFormat::random_table[RANDOM_TABLE_SIZE];
0645 bool XCFImageFormat::random_table_initialized;
0646 
0647 constexpr RandomTable XCFImageFormat::randomTable;
0648 
0649 QList<QRgb> XCFImageFormat::grayTable;
0650 
0651 bool XCFImageFormat::modeAffectsSourceAlpha(const quint32 type)
0652 {
0653     switch (type) {
0654     case GIMP_LAYER_MODE_NORMAL_LEGACY:
0655     case GIMP_LAYER_MODE_DISSOLVE:
0656     case GIMP_LAYER_MODE_BEHIND_LEGACY:
0657         return true;
0658 
0659     case GIMP_LAYER_MODE_MULTIPLY_LEGACY:
0660     case GIMP_LAYER_MODE_SCREEN_LEGACY:
0661     case GIMP_LAYER_MODE_OVERLAY_LEGACY:
0662     case GIMP_LAYER_MODE_DIFFERENCE_LEGACY:
0663     case GIMP_LAYER_MODE_ADDITION_LEGACY:
0664     case GIMP_LAYER_MODE_SUBTRACT_LEGACY:
0665     case GIMP_LAYER_MODE_DARKEN_ONLY_LEGACY:
0666     case GIMP_LAYER_MODE_LIGHTEN_ONLY_LEGACY:
0667     case GIMP_LAYER_MODE_HSV_HUE_LEGACY:
0668     case GIMP_LAYER_MODE_HSV_SATURATION_LEGACY:
0669     case GIMP_LAYER_MODE_HSL_COLOR_LEGACY:
0670     case GIMP_LAYER_MODE_HSV_VALUE_LEGACY:
0671     case GIMP_LAYER_MODE_DIVIDE_LEGACY:
0672     case GIMP_LAYER_MODE_DODGE_LEGACY:
0673     case GIMP_LAYER_MODE_BURN_LEGACY:
0674     case GIMP_LAYER_MODE_HARDLIGHT_LEGACY:
0675     case GIMP_LAYER_MODE_SOFTLIGHT_LEGACY:
0676     case GIMP_LAYER_MODE_GRAIN_EXTRACT_LEGACY:
0677     case GIMP_LAYER_MODE_GRAIN_MERGE_LEGACY:
0678         return false;
0679 
0680     case GIMP_LAYER_MODE_COLOR_ERASE_LEGACY:
0681     case GIMP_LAYER_MODE_OVERLAY:
0682     case GIMP_LAYER_MODE_LCH_HUE:
0683     case GIMP_LAYER_MODE_LCH_CHROMA:
0684     case GIMP_LAYER_MODE_LCH_COLOR:
0685     case GIMP_LAYER_MODE_LCH_LIGHTNESS:
0686         return false;
0687 
0688     case GIMP_LAYER_MODE_NORMAL:
0689         return true;
0690 
0691     case GIMP_LAYER_MODE_BEHIND:
0692     case GIMP_LAYER_MODE_MULTIPLY:
0693     case GIMP_LAYER_MODE_SCREEN:
0694     case GIMP_LAYER_MODE_DIFFERENCE:
0695     case GIMP_LAYER_MODE_ADDITION:
0696     case GIMP_LAYER_MODE_SUBTRACT:
0697     case GIMP_LAYER_MODE_DARKEN_ONLY:
0698     case GIMP_LAYER_MODE_LIGHTEN_ONLY:
0699     case GIMP_LAYER_MODE_HSV_HUE:
0700     case GIMP_LAYER_MODE_HSV_SATURATION:
0701     case GIMP_LAYER_MODE_HSL_COLOR:
0702     case GIMP_LAYER_MODE_HSV_VALUE:
0703     case GIMP_LAYER_MODE_DIVIDE:
0704     case GIMP_LAYER_MODE_DODGE:
0705     case GIMP_LAYER_MODE_BURN:
0706     case GIMP_LAYER_MODE_HARDLIGHT:
0707     case GIMP_LAYER_MODE_SOFTLIGHT:
0708     case GIMP_LAYER_MODE_GRAIN_EXTRACT:
0709     case GIMP_LAYER_MODE_GRAIN_MERGE:
0710     case GIMP_LAYER_MODE_VIVID_LIGHT:
0711     case GIMP_LAYER_MODE_PIN_LIGHT:
0712     case GIMP_LAYER_MODE_LINEAR_LIGHT:
0713     case GIMP_LAYER_MODE_HARD_MIX:
0714     case GIMP_LAYER_MODE_EXCLUSION:
0715     case GIMP_LAYER_MODE_LINEAR_BURN:
0716     case GIMP_LAYER_MODE_LUMA_DARKEN_ONLY:
0717     case GIMP_LAYER_MODE_LUMA_LIGHTEN_ONLY:
0718     case GIMP_LAYER_MODE_LUMINANCE:
0719     case GIMP_LAYER_MODE_COLOR_ERASE:
0720     case GIMP_LAYER_MODE_ERASE:
0721     case GIMP_LAYER_MODE_MERGE:
0722     case GIMP_LAYER_MODE_SPLIT:
0723     case GIMP_LAYER_MODE_PASS_THROUGH:
0724         return false;
0725 
0726     default:
0727         qCWarning(XCFPLUGIN) << "Unhandled layer mode" << XCFImageFormat::LayerModeType(type);
0728         return false;
0729     }
0730 }
0731 
0732 //! Change a QRgb value's alpha only.
0733 inline QRgb qRgba(const QRgb rgb, int a)
0734 {
0735     return ((a & 0xff) << 24 | (rgb & RGB_MASK));
0736 }
0737 
0738 /*!
0739  * The constructor for the XCF image loader.
0740  */
0741 XCFImageFormat::XCFImageFormat()
0742 {
0743     static_assert(sizeof(QRgb) == 4, "the code assumes sizeof(QRgb) == 4, if that's not your case, help us fix it :)");
0744 }
0745 
0746 /*!
0747  * This initializes the tables used in the layer dissolving routines.
0748  */
0749 void XCFImageFormat::initializeRandomTable()
0750 {
0751     // From GIMP "paint_funcs.c" v1.2
0752     srand(RANDOM_SEED);
0753 
0754     for (int i = 0; i < RANDOM_TABLE_SIZE; i++) {
0755         random_table[i] = rand();
0756     }
0757 
0758     for (int i = 0; i < RANDOM_TABLE_SIZE; i++) {
0759         int tmp;
0760         int swap = i + rand() % (RANDOM_TABLE_SIZE - i);
0761         tmp = random_table[i];
0762         random_table[i] = random_table[swap];
0763         random_table[swap] = tmp;
0764     }
0765 }
0766 
0767 inline int XCFImageFormat::add_lut(int a, int b)
0768 {
0769     return qMin(a + b, 255);
0770 }
0771 
0772 bool XCFImageFormat::readXCFHeader(QDataStream &xcf_io, XCFImage::Header *header)
0773 {
0774     QByteArray tag(14, '\0');
0775 
0776     if (xcf_io.readRawData(tag.data(), tag.size()) != tag.size()) {
0777         qCDebug(XCFPLUGIN) << "XCF: read failure on header tag";
0778         return false;
0779     }
0780     if (!tag.startsWith("gimp xcf") || !tag.endsWith('\0')) {
0781         qCDebug(XCFPLUGIN) << "XCF: read called on non-XCF file";
0782         return false;
0783     }
0784 
0785     // Remove null terminator
0786     tag.chop(1);
0787 
0788     if (tag.right(4) == "file") {
0789         xcf_io.setVersion(0);
0790     } else {
0791         // Version 1 and onwards use the format "gimp xcf v###" instead of "gimp xcf file"
0792         bool ok;
0793         xcf_io.setVersion(tag.right(3).toInt(&ok));
0794         if (!ok) {
0795             qCDebug(XCFPLUGIN) << "Failed to parse version" << tag;
0796             return false;
0797         }
0798     }
0799     qCDebug(XCFPLUGIN) << "version" << xcf_io.version();
0800 
0801     if (xcf_io.version() > 12) {
0802         qCDebug(XCFPLUGIN) << "Unsupported version" << xcf_io.version();
0803         return false;
0804     }
0805 
0806     xcf_io >> header->width >> header->height >> header->type;
0807 
0808     if (xcf_io.version() >= 4) {
0809         int precision;
0810         xcf_io >> precision;
0811         qCDebug(XCFPLUGIN) << "Precision" << GimpPrecision(precision);
0812         if (xcf_io.version() < 7) {
0813             switch (precision) {
0814             case 0:
0815                 precision = GIMP_PRECISION_U8_NON_LINEAR;
0816                 break;
0817             case 1:
0818                 precision = GIMP_PRECISION_U16_NON_LINEAR;
0819                 break;
0820             case 2:
0821                 precision = GIMP_PRECISION_U32_LINEAR;
0822                 break;
0823             case 3:
0824                 precision = GIMP_PRECISION_HALF_LINEAR;
0825                 break;
0826             case 4:
0827                 precision = GIMP_PRECISION_FLOAT_LINEAR;
0828                 break;
0829             default:
0830                 if (precision < GIMP_PRECISION_U8_LINEAR) {
0831                     qCWarning(XCFPLUGIN) << "Invalid precision read" << precision;
0832                     return false;
0833                 } else {
0834                     qCDebug(XCFPLUGIN) << "Unexpected precision" << precision << "in version" << xcf_io.version();
0835                 }
0836             }
0837         }
0838         header->precision = GimpPrecision(precision);
0839     }
0840     qCDebug(XCFPLUGIN) << "tag:" << tag << " height: " << header->width << " width: " << header->height << " type: " << header->type;
0841 
0842     if ((sizeof(void *) == 4 && qint64(header->width) * header->height > 16384 * 16384)) {
0843         qCWarning(XCFPLUGIN) << "On 32-bits programs the maximum image size is limited to" << 16384 << "x" << 16384 << "px";
0844         return false;
0845     }
0846 
0847     if (header->width > MAX_IMAGE_WIDTH || header->height > MAX_IMAGE_HEIGHT) {
0848         qCWarning(XCFPLUGIN) << "The maximum image size is limited to" << MAX_IMAGE_WIDTH << "x" << MAX_IMAGE_HEIGHT << "px";
0849         return false;
0850     }
0851 
0852     return true;
0853 }
0854 
0855 bool XCFImageFormat::readXCF(QIODevice *device, QImage *outImage)
0856 {
0857     XCFImage xcf_image;
0858     QDataStream xcf_io(device);
0859 
0860     if (!readXCFHeader(xcf_io, &xcf_image.header)) {
0861         return false;
0862     }
0863 
0864     if (!loadImageProperties(xcf_io, xcf_image)) {
0865         return false;
0866     }
0867 
0868     // The layers appear to be stored in top-to-bottom order. This is
0869     // the reverse of how a merged image must be computed. So, the layer
0870     // offsets are pushed onto a LIFO stack (thus, we don't have to load
0871     // all the data of all layers before beginning to construct the
0872     // merged image).
0873 
0874     QStack<qint64> layer_offsets;
0875 
0876     while (true) {
0877         const qint64 layer_offset = readOffsetPtr(xcf_io);
0878 
0879         if (layer_offset == 0) {
0880             break;
0881         }
0882 
0883         if (layer_offset < 0) {
0884             qCDebug(XCFPLUGIN) << "XCF: negative layer offset";
0885             return false;
0886         }
0887 
0888         layer_offsets.push(layer_offset);
0889     }
0890 
0891     xcf_image.num_layers = layer_offsets.size();
0892 
0893     if (layer_offsets.size() == 0) {
0894         qCDebug(XCFPLUGIN) << "XCF: no layers!";
0895         return false;
0896     }
0897     qCDebug(XCFPLUGIN) << xcf_image.num_layers << "layers";
0898 
0899     // Load each layer and add it to the image
0900     while (!layer_offsets.isEmpty()) {
0901         qint64 layer_offset = layer_offsets.pop();
0902 
0903         xcf_io.device()->seek(layer_offset);
0904 
0905         if (!loadLayer(xcf_io, xcf_image)) {
0906             return false;
0907         }
0908     }
0909 
0910     if (!xcf_image.initialized) {
0911         qCDebug(XCFPLUGIN) << "XCF: no visible layers!";
0912         return false;
0913     }
0914 
0915     // The image was created: now I can set metadata and ICC color profile inside it.
0916     setImageParasites(xcf_image, xcf_image.image);
0917 
0918     *outImage = xcf_image.image;
0919     return true;
0920 }
0921 
0922 /*!
0923  * An XCF file can contain an arbitrary number of properties associated
0924  * with the image (and layer and mask).
0925  * \param xcf_io the data stream connected to the XCF image
0926  * \param xcf_image XCF image data.
0927  * \return true if there were no I/O errors.
0928  */
0929 bool XCFImageFormat::loadImageProperties(QDataStream &xcf_io, XCFImage &xcf_image)
0930 {
0931     while (true) {
0932         PropType type;
0933         QByteArray bytes;
0934         quint32 rawType;
0935 
0936         if (!loadProperty(xcf_io, type, bytes, rawType)) {
0937             qCDebug(XCFPLUGIN) << "XCF: error loading global image properties";
0938             return false;
0939         }
0940 
0941         QDataStream property(bytes);
0942 
0943         switch (type) {
0944         case PROP_END:
0945             return true;
0946 
0947         case PROP_COMPRESSION:
0948             property >> xcf_image.compression;
0949             break;
0950 
0951         case PROP_RESOLUTION:
0952             property.setFloatingPointPrecision(QDataStream::SinglePrecision);
0953             property >> xcf_image.x_resolution >> xcf_image.y_resolution;
0954             break;
0955 
0956         case PROP_TATTOO:
0957             property >> xcf_image.tattoo;
0958             break;
0959 
0960         case PROP_PARASITES:
0961             while (!property.atEnd()) {
0962                 char *tag;
0963 #if QT_VERSION < QT_VERSION_CHECK(6, 7, 0)
0964                 quint32 size;
0965 #else
0966                 qsizetype size;
0967 #endif
0968 
0969                 property.readBytes(tag, size);
0970 
0971                 quint32 flags;
0972                 QByteArray data;
0973                 property >> flags >> data;
0974 
0975                 // WARNING: you cannot add metadata to QImage here because it can be null.
0976                 // Adding a metadata to a QImage when it is null, does nothing (metas are lost).
0977                 if (tag) // store metadata for future use
0978                     xcf_image.parasites.insert(QString::fromUtf8(tag), data);
0979 
0980                 delete[] tag;
0981             }
0982             break;
0983 
0984         case PROP_UNIT:
0985             property >> xcf_image.unit;
0986             break;
0987 
0988         case PROP_PATHS: // This property is ignored.
0989             break;
0990 
0991         case PROP_USER_UNIT: // This property is ignored.
0992             break;
0993 
0994         case PROP_COLORMAP:
0995             property >> xcf_image.num_colors;
0996             if (xcf_image.num_colors < 0 || xcf_image.num_colors > 65535) {
0997                 return false;
0998             }
0999 
1000             xcf_image.palette = QList<QRgb>();
1001             xcf_image.palette.reserve(xcf_image.num_colors);
1002 
1003             for (int i = 0; i < xcf_image.num_colors; i++) {
1004                 uchar r;
1005                 uchar g;
1006                 uchar b;
1007                 property >> r >> g >> b;
1008                 xcf_image.palette.push_back(qRgb(r, g, b));
1009             }
1010             break;
1011 
1012         default:
1013             qCDebug(XCFPLUGIN) << "XCF: unimplemented image property" << type << "(" << rawType << ")"
1014                                << ", size " << bytes.size();
1015             break;
1016         }
1017     }
1018 }
1019 
1020 /*!
1021  * Read a single property from the image file. The property type is returned
1022  * in type and the data is returned in bytes.
1023  * \param xcf the image file data stream.
1024  * \param type returns with the property type.
1025  * \param bytes returns with the property data.
1026  * \return true if there were no IO errors.  */
1027 bool XCFImageFormat::loadProperty(QDataStream &xcf_io, PropType &type, QByteArray &bytes, quint32 &rawType)
1028 {
1029     quint32 size;
1030 
1031     xcf_io >> rawType;
1032     if (rawType >= MAX_SUPPORTED_PROPTYPE) {
1033         type = MAX_SUPPORTED_PROPTYPE;
1034         // we don't support the property, but we still need to read from the device, assume it's like all the
1035         // non custom properties that is data_length + data
1036         xcf_io >> size;
1037         xcf_io.skipRawData(size);
1038         // return true because we don't really want to totally fail on an unsupported property since it may not be fatal
1039         return true;
1040     }
1041 
1042     type = PropType(rawType);
1043 
1044     char *data = nullptr;
1045 
1046     // The colormap property size is not the correct number of bytes:
1047     // The GIMP source xcf.c has size = 4 + ncolors, but it should be
1048     // 4 + 3 * ncolors
1049 
1050     if (type == PROP_COLORMAP) {
1051         xcf_io >> size;
1052         quint32 ncolors;
1053         xcf_io >> ncolors;
1054 
1055         size = 3 * ncolors + 4;
1056 
1057         if (size > 65535 || size < 4) {
1058             return false;
1059         }
1060 
1061         data = new char[size];
1062 
1063         // since we already read "ncolors" from the stream, we put that data back
1064         data[0] = 0;
1065         data[1] = 0;
1066         data[2] = ncolors >> 8;
1067         data[3] = ncolors & 255;
1068 
1069         // ... and read the remaining bytes from the stream
1070         xcf_io.readRawData(data + 4, size - 4);
1071     } else if (type == PROP_USER_UNIT) {
1072         // The USER UNIT property size is not correct. I'm not sure why, though.
1073         float factor;
1074         qint32 digits;
1075 
1076         xcf_io >> size >> factor >> digits;
1077 
1078         for (int i = 0; i < 5; i++) {
1079             char *unit_strings;
1080 
1081             xcf_io >> unit_strings;
1082 
1083             delete[] unit_strings;
1084 
1085             if (xcf_io.device()->atEnd()) {
1086                 qCDebug(XCFPLUGIN) << "XCF: read failure on property " << type;
1087                 return false;
1088             }
1089         }
1090 
1091         size = 0;
1092     } else {
1093         xcf_io >> size;
1094         if (size > 256000) {
1095             return false;
1096         }
1097         data = new char[size];
1098         const quint32 dataRead = xcf_io.readRawData(data, size);
1099         if (dataRead < size) {
1100             qCDebug(XCFPLUGIN) << "XCF: loadProperty read less data than expected" << size << dataRead;
1101             memset(&data[dataRead], 0, size - dataRead);
1102         }
1103     }
1104 
1105     if (size != 0 && data) {
1106         bytes = QByteArray(data, size);
1107     }
1108 
1109     delete[] data;
1110 
1111     return true;
1112 }
1113 
1114 /*!
1115  * Load a layer from the XCF file. The data stream must be positioned at
1116  * the beginning of the layer data.
1117  * \param xcf_io the image file data stream.
1118  * \param xcf_image contains the layer and the color table
1119  * (if the image is indexed).
1120  * \return true if there were no I/O errors.
1121  */
1122 bool XCFImageFormat::loadLayer(QDataStream &xcf_io, XCFImage &xcf_image)
1123 {
1124     Layer &layer(xcf_image.layer);
1125     delete[] layer.name;
1126 
1127     xcf_io >> layer.width >> layer.height >> layer.type >> layer.name;
1128 
1129     // Don't want to keep passing this around, dumb XCF format
1130     layer.compression = XcfCompressionType(xcf_image.compression);
1131 
1132     if (!loadLayerProperties(xcf_io, layer)) {
1133         return false;
1134     }
1135 
1136     qCDebug(XCFPLUGIN) << "layer: \"" << layer.name << "\", size: " << layer.width << " x " << layer.height << ", type: " << layer.type
1137                        << ", mode: " << layer.mode << ", opacity: " << layer.opacity << ", visible: " << layer.visible << ", offset: " << layer.x_offset << ", "
1138                        << layer.y_offset << ", compression" << layer.compression;
1139 
1140     // Skip reading the rest of it if it is not visible. Typically, when
1141     // you export an image from the The GIMP it flattens (or merges) only
1142     // the visible layers into the output image.
1143 
1144     if (layer.visible == 0) {
1145         return true;
1146     }
1147 
1148     // If there are any more layers, merge them into the final QImage.
1149 
1150     layer.hierarchy_offset = readOffsetPtr(xcf_io);
1151     layer.mask_offset = readOffsetPtr(xcf_io);
1152 
1153     if (layer.hierarchy_offset < 0) {
1154         qCDebug(XCFPLUGIN) << "XCF: negative layer hierarchy_offset";
1155         return false;
1156     }
1157 
1158     if (layer.mask_offset < 0) {
1159         qCDebug(XCFPLUGIN) << "XCF: negative layer mask_offset";
1160         return false;
1161     }
1162 
1163     // Allocate the individual tile QImages based on the size and type
1164     // of this layer.
1165 
1166     if (!composeTiles(xcf_image)) {
1167         return false;
1168     }
1169     xcf_io.device()->seek(layer.hierarchy_offset);
1170 
1171     // As tiles are loaded, they are copied into the layers tiles by
1172     // this routine. (loadMask(), below, uses a slightly different
1173     // version of assignBytes().)
1174 
1175     layer.assignBytes = assignImageBytes;
1176 
1177     if (!loadHierarchy(xcf_io, layer, xcf_image.header.precision)) {
1178         return false;
1179     }
1180 
1181     if (layer.mask_offset != 0) {
1182         // 9 means its not on the file. Spec says "If the property does not appear for a layer which has a layer mask, it defaults to true (1).
1183         if (layer.apply_mask == 9) {
1184             layer.apply_mask = 1;
1185         }
1186 
1187         xcf_io.device()->seek(layer.mask_offset);
1188 
1189         if (!loadMask(xcf_io, layer, xcf_image.header.precision)) {
1190             return false;
1191         }
1192     } else {
1193         // Spec says "Robust readers should force this to false if the layer has no layer mask."
1194         layer.apply_mask = 0;
1195     }
1196 
1197     // Now we should have enough information to initialize the final
1198     // QImage. The first visible layer determines the attributes
1199     // of the QImage.
1200 
1201     if (!xcf_image.initialized) {
1202         if (!initializeImage(xcf_image)) {
1203             return false;
1204         }
1205         copyLayerToImage(xcf_image);
1206         xcf_image.initialized = true;
1207     } else {
1208         const QColorSpace colorspaceBefore = xcf_image.image.colorSpace();
1209         mergeLayerIntoImage(xcf_image);
1210         if (xcf_image.image.colorSpace() != colorspaceBefore) {
1211             qCDebug(XCFPLUGIN) << "Converting color space back to" << colorspaceBefore << "after layer composition";
1212             xcf_image.image.convertToColorSpace(colorspaceBefore);
1213         }
1214     }
1215 
1216     return true;
1217 }
1218 
1219 /*!
1220  * An XCF file can contain an arbitrary number of properties associated
1221  * with a layer.
1222  * \param xcf_io the data stream connected to the XCF image.
1223  * \param layer layer to collect the properties.
1224  * \return true if there were no I/O errors.
1225  */
1226 bool XCFImageFormat::loadLayerProperties(QDataStream &xcf_io, Layer &layer)
1227 {
1228     while (true) {
1229         PropType type;
1230         QByteArray bytes;
1231         quint32 rawType;
1232 
1233         if (!loadProperty(xcf_io, type, bytes, rawType)) {
1234             qCDebug(XCFPLUGIN) << "XCF: error loading layer properties";
1235             return false;
1236         }
1237 
1238         QDataStream property(bytes);
1239 
1240         switch (type) {
1241         case PROP_END:
1242             return true;
1243 
1244         case PROP_ACTIVE_LAYER:
1245             layer.active = true;
1246             break;
1247 
1248         case PROP_OPACITY:
1249             property >> layer.opacity;
1250             layer.opacity = std::min(layer.opacity, 255u);
1251             break;
1252 
1253         case PROP_FLOAT_OPACITY:
1254             // For some reason QDataStream isn't able to read the float (tried
1255             // setting the endianness manually)
1256             if (bytes.size() == 4) {
1257                 layer.opacityFloat = qFromBigEndian(*reinterpret_cast<float *>(bytes.data()));
1258             } else {
1259                 qCDebug(XCFPLUGIN) << "XCF: Invalid data size for float:" << bytes.size();
1260             }
1261             break;
1262 
1263         case PROP_VISIBLE:
1264             property >> layer.visible;
1265             break;
1266 
1267         case PROP_LINKED:
1268             property >> layer.linked;
1269             break;
1270 
1271         case PROP_LOCK_ALPHA:
1272             property >> layer.preserve_transparency;
1273             break;
1274 
1275         case PROP_APPLY_MASK:
1276             property >> layer.apply_mask;
1277             break;
1278 
1279         case PROP_EDIT_MASK:
1280             property >> layer.edit_mask;
1281             break;
1282 
1283         case PROP_SHOW_MASK:
1284             property >> layer.show_mask;
1285             break;
1286 
1287         case PROP_OFFSETS:
1288             property >> layer.x_offset >> layer.y_offset;
1289             break;
1290 
1291         case PROP_MODE:
1292             property >> layer.mode;
1293             if (layer.mode >= GIMP_LAYER_MODE_COUNT) {
1294                 qCDebug(XCFPLUGIN) << "Found layer with unsupported mode" << LayerModeType(layer.mode) << "Defaulting to mode 0";
1295                 layer.mode = GIMP_LAYER_MODE_NORMAL_LEGACY;
1296             }
1297             break;
1298 
1299         case PROP_TATTOO:
1300             property >> layer.tattoo;
1301             break;
1302 
1303         case PROP_COMPOSITE_SPACE:
1304             property >> layer.compositeSpace;
1305             if (layer.compositeSpace < 0) {
1306                 layer.compositeSpace = GimpColorSpace(-layer.compositeSpace);
1307             }
1308             break;
1309 
1310         case PROP_COMPOSITE_MODE:
1311             property >> layer.compositeMode;
1312             if (layer.compositeMode < 0) {
1313                 layer.compositeMode = XCFImageFormat::GimpCompositeMode(-layer.compositeMode);
1314             }
1315             break;
1316 
1317         case PROP_BLEND_SPACE:
1318             property >> layer.blendSpace;
1319             if (layer.blendSpace) {
1320                 layer.blendSpace = GimpColorSpace(-layer.blendSpace);
1321             }
1322             break;
1323 
1324         // Just for organization in the UI, doesn't influence rendering
1325         case PROP_COLOR_TAG:
1326             break;
1327 
1328         // We don't support editing, so for now just ignore locking
1329         case PROP_LOCK_CONTENT:
1330         case PROP_LOCK_POSITION:
1331             break;
1332 
1333         default:
1334             qCDebug(XCFPLUGIN) << "XCF: unimplemented layer property " << type << "(" << rawType << ")"
1335                                << ", size " << bytes.size();
1336             break;
1337         }
1338     }
1339 }
1340 
1341 /*!
1342  * Compute the number of tiles in the current layer and allocate
1343  * QImage structures for each of them.
1344  * \param xcf_image contains the current layer.
1345  */
1346 bool XCFImageFormat::composeTiles(XCFImage &xcf_image)
1347 {
1348     Layer &layer(xcf_image.layer);
1349 
1350     layer.nrows = (layer.height + TILE_HEIGHT - 1) / TILE_HEIGHT;
1351     layer.ncols = (layer.width + TILE_WIDTH - 1) / TILE_WIDTH;
1352 
1353     qCDebug(XCFPLUGIN) << "IMAGE: height=" << xcf_image.header.height << ", width=" << xcf_image.header.width;
1354     qCDebug(XCFPLUGIN) << "LAYER: height=" << layer.height << ", width=" << layer.width;
1355     qCDebug(XCFPLUGIN) << "LAYER: rows=" << layer.nrows << ", columns=" << layer.ncols;
1356 
1357     // NOTE: starting from GIMP 2.10, images can be very large. The 32K limit for width and height is obsolete
1358     //       and it was changed to 300000 (the same as Photoshop Big image). This plugin was able to open an RGB
1359     //       image of 108000x40000 pixels saved with GIMP 2.10
1360     // SANITY CHECK: Catch corrupted XCF image file where the width or height
1361     //               of a tile is reported are bogus. See Bug# 234030.
1362     if ((sizeof(void *) == 4 && qint64(layer.width) * layer.height > 16384 * 16384)) {
1363         qCWarning(XCFPLUGIN) << "On 32-bits programs the maximum layer size is limited to" << 16384 << "x" << 16384 << "px";
1364         return false;
1365     }
1366     if (layer.width > MAX_IMAGE_WIDTH || layer.height > MAX_IMAGE_HEIGHT) {
1367         qCWarning(XCFPLUGIN) << "The maximum layer size is limited to" << MAX_IMAGE_WIDTH << "x" << MAX_IMAGE_HEIGHT << "px";
1368         return false;
1369     }
1370 
1371     // NOTE: A layer is a named rectangular area of pixels which has a definite position with respect to the canvas.
1372     //       It may extend beyond the canvas or (more commonly) only cover some of it.
1373     // SANITY CHECK: Avoid to load XCF with a layer grater than 10 times the final image
1374     if (qint64(layer.width) * layer.height / 10 > qint64(xcf_image.header.width) * xcf_image.header.height) {
1375         if (qint64(layer.width) * layer.height > 16384 * 16384) { // large layers only
1376             qCWarning(XCFPLUGIN) << "Euristic sanity check: the image may be corrupted!";
1377             return false;
1378         }
1379     }
1380 
1381 #ifndef XCF_QT5_SUPPORT
1382     // Qt 6 image allocation limit calculation: we have to check the limit here because the image is splitted in
1383     // tiles of 64x64 pixels. The required memory to build the image is at least doubled because tiles are loaded
1384     // and then the final image is created by copying the tiles inside it.
1385     // NOTE: on Windows to open a 10GiB image the plugin uses 28GiB of RAM
1386     qint64 channels = 1 + (layer.type == RGB_GIMAGE ? 2 : 0) + (layer.type == RGBA_GIMAGE ? 3 : 0);
1387     if (qint64(layer.width) * qint64(layer.height) * channels * 2ll / 1024ll / 1024ll > QImageReader::allocationLimit()) {
1388         qCDebug(XCFPLUGIN) << "Rejecting image as it exceeds the current allocation limit of" << QImageReader::allocationLimit() << "megabytes";
1389         return false;
1390     }
1391 #endif
1392 
1393     layer.image_tiles.resize(layer.nrows);
1394 
1395     if (layer.type == GRAYA_GIMAGE || layer.type == INDEXEDA_GIMAGE) {
1396         layer.alpha_tiles.resize(layer.nrows);
1397     }
1398 
1399     if (layer.mask_offset != 0) {
1400         layer.mask_tiles.resize(layer.nrows);
1401     }
1402 
1403     for (uint j = 0; j < layer.nrows; j++) {
1404         layer.image_tiles[j].resize(layer.ncols);
1405 
1406         if (layer.type == GRAYA_GIMAGE || layer.type == INDEXEDA_GIMAGE) {
1407             layer.alpha_tiles[j].resize(layer.ncols);
1408         }
1409 
1410         if (layer.mask_offset != 0) {
1411             layer.mask_tiles[j].resize(layer.ncols);
1412         }
1413     }
1414 
1415     const QImage::Format format = layer.qimageFormat(xcf_image.header.precision);
1416 
1417     for (uint j = 0; j < layer.nrows; j++) {
1418         for (uint i = 0; i < layer.ncols; i++) {
1419             uint tile_width = (i + 1) * TILE_WIDTH <= layer.width ? TILE_WIDTH : layer.width - i * TILE_WIDTH;
1420 
1421             uint tile_height = (j + 1) * TILE_HEIGHT <= layer.height ? TILE_HEIGHT : layer.height - j * TILE_HEIGHT;
1422 
1423             // Try to create the most appropriate QImage (each GIMP layer
1424             // type is treated slightly differently)
1425 
1426             switch (layer.type) {
1427             case RGB_GIMAGE:
1428             case RGBA_GIMAGE:
1429                 layer.image_tiles[j][i] = QImage(tile_width, tile_height, format);
1430                 if (layer.image_tiles[j][i].isNull()) {
1431                     return false;
1432                 }
1433                 layer.image_tiles[j][i].setColorCount(0);
1434                 break;
1435 
1436             case GRAY_GIMAGE:
1437                 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
1438                 if (layer.image_tiles[j][i].isNull()) {
1439                     return false;
1440                 }
1441                 layer.image_tiles[j][i].setColorCount(256);
1442                 setGrayPalette(layer.image_tiles[j][i]);
1443                 break;
1444 
1445             case GRAYA_GIMAGE:
1446                 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
1447                 layer.image_tiles[j][i].setColorCount(256);
1448                 if (layer.image_tiles[j][i].isNull()) {
1449                     return false;
1450                 }
1451                 setGrayPalette(layer.image_tiles[j][i]);
1452 
1453                 layer.alpha_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
1454                 if (layer.alpha_tiles[j][i].isNull()) {
1455                     return false;
1456                 }
1457                 layer.alpha_tiles[j][i].setColorCount(256);
1458                 setGrayPalette(layer.alpha_tiles[j][i]);
1459                 break;
1460 
1461             case INDEXED_GIMAGE:
1462                 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
1463                 layer.image_tiles[j][i].setColorCount(xcf_image.num_colors);
1464                 if (layer.image_tiles[j][i].isNull()) {
1465                     return false;
1466                 }
1467                 setPalette(xcf_image, layer.image_tiles[j][i]);
1468                 break;
1469 
1470             case INDEXEDA_GIMAGE:
1471                 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
1472                 if (layer.image_tiles[j][i].isNull()) {
1473                     return false;
1474                 }
1475                 layer.image_tiles[j][i].setColorCount(xcf_image.num_colors);
1476                 setPalette(xcf_image, layer.image_tiles[j][i]);
1477 
1478                 layer.alpha_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
1479                 if (layer.alpha_tiles[j][i].isNull()) {
1480                     return false;
1481                 }
1482                 layer.alpha_tiles[j][i].setColorCount(256);
1483                 setGrayPalette(layer.alpha_tiles[j][i]);
1484             }
1485             if (layer.type != GRAYA_GIMAGE && layer.image_tiles[j][i].format() != format) {
1486                 qCWarning(XCFPLUGIN) << "Selected wrong tile format" << layer.image_tiles[j][i].format() << "expected" << format;
1487                 return false;
1488             }
1489 
1490 #ifndef DISABLE_TILE_PROFILE
1491             switch (xcf_image.header.precision) {
1492             case XCFImageFormat::GIMP_PRECISION_HALF_LINEAR:
1493             case XCFImageFormat::GIMP_PRECISION_FLOAT_LINEAR:
1494             case XCFImageFormat::GIMP_PRECISION_DOUBLE_LINEAR:
1495             case XCFImageFormat::GIMP_PRECISION_U8_LINEAR:
1496             case XCFImageFormat::GIMP_PRECISION_U16_LINEAR:
1497             case XCFImageFormat::GIMP_PRECISION_U32_LINEAR:
1498                 layer.image_tiles[j][i].setColorSpace(QColorSpace::SRgbLinear);
1499                 break;
1500             case XCFImageFormat::GIMP_PRECISION_HALF_NON_LINEAR:
1501             case XCFImageFormat::GIMP_PRECISION_FLOAT_NON_LINEAR:
1502             case XCFImageFormat::GIMP_PRECISION_DOUBLE_NON_LINEAR:
1503             case XCFImageFormat::GIMP_PRECISION_U8_NON_LINEAR:
1504             case XCFImageFormat::GIMP_PRECISION_U16_NON_LINEAR:
1505             case XCFImageFormat::GIMP_PRECISION_U32_NON_LINEAR:
1506                 layer.image_tiles[j][i].setColorSpace(QColorSpace::SRgb);
1507                 break;
1508             case XCFImageFormat::GIMP_PRECISION_HALF_PERCEPTUAL:
1509             case XCFImageFormat::GIMP_PRECISION_FLOAT_PERCEPTUAL:
1510             case XCFImageFormat::GIMP_PRECISION_DOUBLE_PERCEPTUAL:
1511             case XCFImageFormat::GIMP_PRECISION_U8_PERCEPTUAL:
1512             case XCFImageFormat::GIMP_PRECISION_U16_PERCEPTUAL:
1513             case XCFImageFormat::GIMP_PRECISION_U32_PERCEPTUAL:
1514                 layer.image_tiles[j][i].setColorSpace(QColorSpace::SRgb);
1515                 break;
1516             }
1517 #endif
1518             if (layer.mask_offset != 0) {
1519                 layer.mask_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
1520                 layer.mask_tiles[j][i].setColorCount(256);
1521                 if (layer.mask_tiles[j][i].isNull()) {
1522                     return false;
1523                 }
1524                 setGrayPalette(layer.mask_tiles[j][i]);
1525             }
1526         }
1527     }
1528     return true;
1529 }
1530 
1531 /*!
1532  * Apply a grayscale palette to the QImage. Note that Qt does not distinguish
1533  * between grayscale and indexed images. A grayscale image is just
1534  * an indexed image with a 256-color, grayscale palette.
1535  * \param image image to set to a grayscale palette.
1536  */
1537 void XCFImageFormat::setGrayPalette(QImage &image)
1538 {
1539     if (grayTable.isEmpty()) {
1540         grayTable.resize(256);
1541 
1542         for (int i = 0; i < 256; i++) {
1543             grayTable[i] = qRgb(i, i, i);
1544         }
1545     }
1546 
1547     image.setColorTable(grayTable);
1548 }
1549 
1550 /*!
1551  * Copy the indexed palette from the XCF image into the QImage.
1552  * \param xcf_image XCF image containing the palette read from the data stream.
1553  * \param image image to apply the palette to.
1554  */
1555 void XCFImageFormat::setPalette(XCFImage &xcf_image, QImage &image)
1556 {
1557     Q_ASSERT(xcf_image.num_colors == xcf_image.palette.size());
1558 
1559     image.setColorTable(xcf_image.palette);
1560 }
1561 
1562 /*!
1563  * Copy the parasites info to QImage.
1564  * \param xcf_image XCF image containing the parasites read from the data stream.
1565  * \param image image to apply the parasites data.
1566  * \note Some comment taken from https://gitlab.gnome.org/GNOME/gimp/-/blob/master/devel-docs/parasites.txt
1567  */
1568 void XCFImageFormat::setImageParasites(const XCFImage &xcf_image, QImage &image)
1569 {
1570     auto&& p = xcf_image.parasites;
1571     auto keys = p.keys();
1572     for (auto &&key : std::as_const(keys)) {
1573         auto value = p.value(key);
1574         if (value.isEmpty())
1575             continue;
1576 
1577         // "icc-profile" (IMAGE, PERSISTENT | UNDOABLE)
1578         //     This contains an ICC profile describing the color space the
1579         //     image was produced in. TIFF images stored in PhotoShop do
1580         //     oftentimes contain embedded profiles. An experimental color
1581         //     manager exists to use this parasite, and it will be used
1582         //     for interchange between TIFF and PNG (identical profiles)
1583         if (key == QStringLiteral("icc-profile")) {
1584             auto cs = QColorSpace::fromIccProfile(value);
1585             if (cs.isValid())
1586                 image.setColorSpace(cs);
1587             continue;
1588         }
1589 
1590         // "gimp-comment" (IMAGE, PERSISTENT)
1591         //    Standard GIF-style image comments.  This parasite should be
1592         //    human-readable text in UTF-8 encoding.  A trailing \0 might
1593         //    be included and is not part of the comment.  Note that image
1594         //    comments may also be present in the "gimp-metadata" parasite.
1595         if (key == QStringLiteral("gimp-comment")) {
1596             value.replace('\0', QByteArray());
1597             image.setText(QStringLiteral("Comment"), QString::fromUtf8(value));
1598             continue;
1599         }
1600 
1601         // "gimp-image-metadata"
1602         //     Saved by GIMP 2.10.30 but it is not mentioned in the specification.
1603         //     It is an XML block with the properties set using GIMP.
1604         if (key == QStringLiteral("gimp-image-metadata")) {
1605             // NOTE: I arbitrary defined the metadata "XML:org.gimp.xml" because it seems
1606             //       a GIMP proprietary XML format (no xmlns defined)
1607             value.replace('\0', QByteArray());
1608             image.setText(QStringLiteral("XML:org.gimp.xml"), QString::fromUtf8(value));
1609             continue;
1610         }
1611 
1612 #if 0   // Unable to generate it using latest GIMP version
1613         // "gimp-metadata" (IMAGE, PERSISTENT)
1614         //     The metadata associated with the image, serialized as one XMP
1615         //     packet.  This metadata includes the contents of any XMP, EXIF
1616         //     and IPTC blocks from the original image, as well as
1617         //     user-specified values such as image comment, copyright,
1618         //     license, etc.
1619         if (key == QStringLiteral("gimp-metadata")) {
1620             // NOTE: "XML:com.adobe.xmp" is the meta set by Qt reader when an
1621             //       XMP packet is found (e.g. when reading a PNG saved by Photoshop).
1622             //       I reused the same key because some programs could search for it.
1623             value.replace('\0', QByteArray());
1624             image.setText(QStringLiteral("XML:com.adobe.xmp"), QString::fromUtf8(value));
1625             continue;
1626         }
1627 #endif
1628     }
1629 
1630 #ifdef DISABLE_IMAGE_PROFILE
1631     // final colorspace checks
1632     if (!image.colorSpace().isValid()) {
1633         switch (xcf_image.header.precision) {
1634         case XCFImageFormat::GIMP_PRECISION_HALF_LINEAR:
1635         case XCFImageFormat::GIMP_PRECISION_FLOAT_LINEAR:
1636         case XCFImageFormat::GIMP_PRECISION_DOUBLE_LINEAR:
1637         case XCFImageFormat::GIMP_PRECISION_U8_LINEAR:
1638         case XCFImageFormat::GIMP_PRECISION_U16_LINEAR:
1639         case XCFImageFormat::GIMP_PRECISION_U32_LINEAR:
1640             image.setColorSpace(QColorSpace::SRgbLinear);
1641             break;
1642         default:
1643             image.setColorSpace(QColorSpace::SRgb);
1644             break;
1645         }
1646     }
1647 #endif
1648 }
1649 
1650 /*!
1651  * Copy the bytes from the tile buffer into the image tile QImage, taking into
1652  * account all the myriad different modes.
1653  * \param layer layer containing the tile buffer and the image tile matrix.
1654  * \param i column index of current tile.
1655  * \param j row index of current tile.
1656  */
1657 bool XCFImageFormat::assignImageBytes(Layer &layer, uint i, uint j, const GimpPrecision &precision)
1658 {
1659     QImage &image = layer.image_tiles[j][i];
1660 
1661     const uchar *tile = layer.tile;
1662     const int width = image.width();
1663     const int height = image.height();
1664     const int bytesPerLine = image.bytesPerLine();
1665     uchar *bits = image.bits();
1666 
1667     // Handle the special cases
1668     if (layer.type == GRAYA_GIMAGE || layer.type == GRAY_GIMAGE || layer.type == INDEXEDA_GIMAGE) {
1669         auto bpc = bytesPerChannel(precision);
1670         for (int y = 0; y < height; y++) {
1671             uchar *dataPtr = bits + y * bytesPerLine;
1672             uchar *alphaPtr = nullptr;
1673             if (!layer.alpha_tiles.isEmpty())
1674                 alphaPtr = layer.alpha_tiles[j][i].scanLine(y);
1675             if (bpc == 4) {
1676 #ifdef USE_FLOAT_IMAGES
1677                 if (precision < GimpPrecision::GIMP_PRECISION_HALF_LINEAR) {
1678                     for (int x = 0; x < width; x++) {
1679                         auto src = (const quint16 *)tile;
1680                         *dataPtr++ = qFromBigEndian<quint16>(src[0]) / 257;
1681                         if (alphaPtr) {
1682                             *alphaPtr++ = qFromBigEndian<quint16>(src[1]) / 257;
1683                             tile += sizeof(quint16) * 2;
1684                         } else {
1685                             tile += sizeof(quint16);
1686                         }
1687                     }
1688                 } else {
1689                     for (int x = 0; x < width; x++) {
1690                         auto src = (const float *)tile;
1691                         *dataPtr++ = qFromBigEndian<float>(src[0]) * 255;
1692                         if (alphaPtr) {
1693                             *alphaPtr++ = qFromBigEndian<float>(src[1]) * 255;
1694                             tile += sizeof(float) * 2;
1695                         } else {
1696                             tile += sizeof(float);
1697                         }
1698                     }
1699                 }
1700 #else
1701                 for (int x = 0; x < width; x++) {
1702                     auto src = (const quint16 *)tile;
1703                     *dataPtr++ = qFromBigEndian<quint16>(src[0]) / 257;
1704                     if (alphaPtr) {
1705                         *alphaPtr++ = qFromBigEndian<quint16>(src[1]) / 257;
1706                         tile += sizeof(quint16) * 2;
1707                     } else {
1708                         tile += sizeof(quint16);
1709                     }
1710                 }
1711 #endif
1712             } else if (bpc == 2) {
1713 #ifdef USE_FLOAT_IMAGES
1714                 if (precision < GimpPrecision::GIMP_PRECISION_HALF_LINEAR) {
1715                     for (int x = 0; x < width; x++) {
1716                         auto src = (const quint16 *)tile;
1717                         *dataPtr++ = qFromBigEndian<quint16>(src[0]) / 257;
1718                         if (alphaPtr)
1719                             *alphaPtr++ = qFromBigEndian<quint16>(src[1]) / 257;
1720                         tile += sizeof(QRgb);
1721                     }
1722                 } else {
1723                     for (int x = 0; x < width; x++) {
1724                         auto src = (const qfloat16 *)tile;
1725                         *dataPtr++ = qFromBigEndian<qfloat16>(src[0]) * 255;
1726                         if (alphaPtr)
1727                             *alphaPtr++ = qFromBigEndian<qfloat16>(src[1]) * 255;
1728                         tile += sizeof(QRgb);
1729                     }
1730                 }
1731 #else
1732                 for (int x = 0; x < width; x++) {
1733                     auto src = (const quint16 *)tile;
1734                     *dataPtr++ = qFromBigEndian<quint16>(src[0]) / 257;
1735                     if (alphaPtr)
1736                         *alphaPtr++ = qFromBigEndian<quint16>(src[1]) / 257;
1737                     tile += sizeof(QRgb);
1738                 }
1739 #endif
1740             } else {
1741                 for (int x = 0; x < width; x++) {
1742                     if (tile[0] < image.colorCount())
1743                         *dataPtr++ = tile[0];
1744                     if (alphaPtr)
1745                         *alphaPtr++ = tile[1];
1746                     tile += sizeof(QRgb);
1747                 }
1748             }
1749         }
1750         return true;
1751     }
1752 
1753     switch (image.format()) {
1754     case QImage::Format_RGBX8888:
1755         for (int y = 0; y < height; y++) {
1756             uchar *dataPtr = image.scanLine(y);
1757             for (int x = 0; x < width * 4; x += 4, tile += 4) {
1758                 dataPtr[x + 0] = tile[0];
1759                 dataPtr[x + 1] = tile[1];
1760                 dataPtr[x + 2] = tile[2];
1761                 dataPtr[x + 3] = 255;
1762             }
1763         }
1764         break;
1765     case QImage::Format_RGBA8888:
1766         for (int y = 0; y < height; y++) {
1767             const size_t bpl = width * 4;
1768             memcpy(image.scanLine(y), tile + y * bpl, bpl);
1769         }
1770         break;
1771     case QImage::Format_RGBX64:
1772         for (int y = 0; y < height; y++) {
1773             quint16 *dataPtr = (quint16 *)image.scanLine(y);
1774             const size_t bpl = width * sizeof(QRgba64);
1775             const quint16 *src = (const quint16 *)(tile + y * bpl);
1776             for (int x = 0; x < width * 4; x += 4) {
1777                 dataPtr[x + 0] = qFromBigEndian(src[x + 0]);
1778                 dataPtr[x + 1] = qFromBigEndian(src[x + 1]);
1779                 dataPtr[x + 2] = qFromBigEndian(src[x + 2]);
1780                 dataPtr[x + 3] = 65535;
1781             }
1782         }
1783         break;
1784 #ifdef USE_FLOAT_IMAGES
1785     case QImage::Format_RGBX16FPx4:
1786         for (int y = 0; y < height; y++) {
1787             qfloat16 *dataPtr = (qfloat16 *)image.scanLine(y);
1788             const qfloat16 *src = (const qfloat16 *)(tile + y * width * sizeof(QRgbaFloat16));
1789             for (int x = 0; x < width * 4; x += 4) {
1790                 dataPtr[x + 0] = qFromBigEndian(src[x + 0]);
1791                 dataPtr[x + 1] = qFromBigEndian(src[x + 1]);
1792                 dataPtr[x + 2] = qFromBigEndian(src[x + 2]);
1793                 dataPtr[x + 3] = qfloat16(1);
1794             }
1795         }
1796         break;
1797     case QImage::Format_RGBA16FPx4:
1798         static_assert(sizeof(QRgbaFloat16) == sizeof(QRgba64), "Different sizes for float and int 16 bit pixels");
1799 #endif
1800     case QImage::Format_RGBA64:
1801         for (int y = 0; y < height; y++) {
1802             const size_t bpl = width * sizeof(QRgba64);
1803             qFromBigEndian<qint16>(tile + y * bpl, width * 4, image.scanLine(y));
1804         }
1805         break;
1806 #ifdef USE_FLOAT_IMAGES
1807     case QImage::Format_RGBA32FPx4:
1808         for (int y = 0; y < height; y++) {
1809             const size_t bpl = width * sizeof(QRgbaFloat32);
1810             qFromBigEndian<qint32>(tile + y * bpl, width * 4, image.scanLine(y));
1811         }
1812         break;
1813     case QImage::Format_RGBX32FPx4:
1814         for (int y = 0; y < height; y++) {
1815             float *dataPtr = (float *)image.scanLine(y);
1816             const float *src = (const float *)(tile + y * width * sizeof(QRgbaFloat32));
1817             for (int x = 0; x < width * 4; x += 4) {
1818                 dataPtr[x + 0] = qFromBigEndian(src[x + 0]);
1819                 dataPtr[x + 1] = qFromBigEndian(src[x + 1]);
1820                 dataPtr[x + 2] = qFromBigEndian(src[x + 2]);
1821                 dataPtr[x + 3] = 1.f;
1822             }
1823         }
1824         break;
1825 #endif
1826     case QImage::Format_Indexed8:
1827         for (int y = 0; y < height; y++) {
1828             uchar *dataPtr = bits + y * bytesPerLine;
1829             for (int x = 0; x < width; x++) {
1830                 *dataPtr++ = tile[0];
1831                 tile += sizeof(QRgb);
1832             }
1833         }
1834         break;
1835     default:
1836         qCWarning(XCFPLUGIN) << "Unhandled image format" << image.format() << "and/or layer type" << layer.type;
1837         return false;
1838     }
1839 
1840     return true;
1841 }
1842 
1843 /*!
1844  * The GIMP stores images in a "mipmap"-like hierarchy. As far as the QImage
1845  * is concerned, however, only the top level (i.e., the full resolution image)
1846  * is used.
1847  * \param xcf_io the data stream connected to the XCF image.
1848  * \param layer the layer to collect the image.
1849  * \return true if there were no I/O errors.
1850  */
1851 bool XCFImageFormat::loadHierarchy(QDataStream &xcf_io, Layer &layer, const GimpPrecision precision)
1852 {
1853     qint32 width;
1854     qint32 height;
1855     quint32 bpp;
1856 
1857     xcf_io >> width >> height >> bpp;
1858     const qint64 offset = readOffsetPtr(xcf_io);
1859 
1860     qCDebug(XCFPLUGIN) << "width" << width << "height" << height << "bpp" << bpp << "offset" << offset;
1861 
1862     if (offset < 0) {
1863         qCDebug(XCFPLUGIN) << "XCF: negative hierarchy offset";
1864         return false;
1865     }
1866 
1867     const bool isMask = layer.assignBytes == assignMaskBytes;
1868 
1869     // make sure bpp is correct and complain if it is not
1870     switch (layer.type) {
1871     case RGB_GIMAGE:
1872         if (bpp != 3 * bytesPerChannel(precision)) {
1873             qCDebug(XCFPLUGIN) << "Found layer of type RGB but with bpp != 3" << bpp;
1874 
1875             if (!isMask) {
1876                 return false;
1877             }
1878         }
1879         break;
1880     case RGBA_GIMAGE:
1881         if (bpp != 4 * bytesPerChannel(precision)) {
1882             qCDebug(XCFPLUGIN) << "Found layer of type RGBA but with bpp != 4, got" << bpp << "bpp";
1883 
1884             if (!isMask) {
1885                 return false;
1886             }
1887         }
1888         break;
1889     case GRAY_GIMAGE:
1890         if (bpp != 1 * bytesPerChannel(precision)) {
1891             qCDebug(XCFPLUGIN) << "Found layer of type Gray but with bpp != 1" << bpp;
1892             return false;
1893         }
1894         break;
1895     case GRAYA_GIMAGE:
1896         if (bpp != 2 * bytesPerChannel(precision)) {
1897             qCDebug(XCFPLUGIN) << "Found layer of type Gray+Alpha but with bpp != 2" << bpp;
1898 
1899             if (!isMask) {
1900                 return false;
1901             }
1902         }
1903         break;
1904     case INDEXED_GIMAGE:
1905         if (bpp != 1 * bytesPerChannel(precision)) {
1906             qCDebug(XCFPLUGIN) << "Found layer of type Indexed but with bpp != 1" << bpp;
1907             return false;
1908         }
1909         break;
1910     case INDEXEDA_GIMAGE:
1911         if (bpp != 2 * bytesPerChannel(precision)) {
1912             qCDebug(XCFPLUGIN) << "Found layer of type Indexed+Alpha but with bpp != 2" << bpp;
1913 
1914             if (!isMask) {
1915                 return false;
1916             }
1917         }
1918         break;
1919     }
1920 
1921     if (bpp > 4 * bytesPerChannel(precision)) {
1922         qCDebug(XCFPLUGIN) << "bpp is" << bpp << "We don't support layers with bpp > 4";
1923         return false;
1924     }
1925 
1926     // GIMP stores images in a "mipmap"-like format (multiple levels of
1927     // increasingly lower resolution). Only the top level is used here,
1928     // however.
1929 
1930     quint32 junk;
1931     do {
1932         xcf_io >> junk;
1933 
1934         if (xcf_io.device()->atEnd()) {
1935             qCDebug(XCFPLUGIN) << "XCF: read failure on layer " << layer.name << " level offsets";
1936             return false;
1937         }
1938     } while (junk != 0);
1939 
1940     qint64 saved_pos = xcf_io.device()->pos();
1941 
1942     xcf_io.device()->seek(offset);
1943     if (!loadLevel(xcf_io, layer, bpp, precision)) {
1944         return false;
1945     }
1946 
1947     xcf_io.device()->seek(saved_pos);
1948     return true;
1949 }
1950 
1951 template<typename SourceFormat>
1952 static bool convertFloatTo16Bit(uchar *output, quint64 outputSize, uchar *input)
1953 {
1954     SourceFormat *source = (SourceFormat *)(input);
1955     for (quint64 offset = 0; offset < outputSize; offset++) {
1956         ((uint16_t *)output)[offset] = qToBigEndian(quint16(qBound(0., qFromBigEndian<SourceFormat>(source[offset]) * 65535. + 0.5, 65535.)));
1957     }
1958     return true;
1959 }
1960 
1961 /*!
1962  * Load one level of the image hierarchy (but only the top level is ever used).
1963  * \param xcf_io the data stream connected to the XCF image.
1964  * \param layer the layer to collect the image.
1965  * \param bpp the number of bytes in a pixel.
1966  * \return true if there were no I/O errors.
1967  * \sa loadTileRLE().
1968  */
1969 bool XCFImageFormat::loadLevel(QDataStream &xcf_io, Layer &layer, qint32 bpp, const GimpPrecision precision)
1970 {
1971     qint32 width;
1972     qint32 height;
1973 
1974     xcf_io >> width >> height;
1975     qint64 offset = readOffsetPtr(xcf_io);
1976 
1977     if (offset < 0) {
1978         qCDebug(XCFPLUGIN) << "XCF: negative level offset";
1979         return false;
1980     }
1981 
1982     if (offset == 0) {
1983         // offset 0 with rowsxcols != 0 is probably an error since it means we have tiles
1984         // without data but just clear the bits for now instead of returning false
1985         for (uint j = 0; j < layer.nrows; j++) {
1986             for (uint i = 0; i < layer.ncols; i++) {
1987                 layer.image_tiles[j][i].fill(Qt::transparent);
1988                 if (layer.type == GRAYA_GIMAGE || layer.type == INDEXEDA_GIMAGE) {
1989                     layer.alpha_tiles[j][i].fill(Qt::transparent);
1990                 }
1991             }
1992         }
1993         return true;
1994     }
1995 
1996     bool needConvert = true;
1997     switch (precision) {
1998 #ifdef USE_FLOAT_IMAGES
1999     case GIMP_PRECISION_HALF_LINEAR:
2000     case GIMP_PRECISION_HALF_NON_LINEAR:
2001     case GIMP_PRECISION_HALF_PERCEPTUAL:
2002     case GIMP_PRECISION_FLOAT_LINEAR:
2003     case GIMP_PRECISION_FLOAT_NON_LINEAR:
2004     case GIMP_PRECISION_FLOAT_PERCEPTUAL:
2005 #endif
2006     case GIMP_PRECISION_U8_LINEAR:
2007     case GIMP_PRECISION_U8_NON_LINEAR:
2008     case GIMP_PRECISION_U8_PERCEPTUAL:
2009     case GIMP_PRECISION_U16_LINEAR:
2010     case GIMP_PRECISION_U16_NON_LINEAR:
2011     case GIMP_PRECISION_U16_PERCEPTUAL:
2012         needConvert = false;
2013         break;
2014     default:
2015         break;
2016     }
2017 
2018     const uint blockSize = TILE_WIDTH * TILE_HEIGHT * bpp * 1.5;
2019 
2020     QList<uchar> buffer;
2021     if (needConvert) {
2022         buffer.resize(blockSize * (bpp == 2 ? 2 : 1));
2023     }
2024     for (uint j = 0; j < layer.nrows; j++) {
2025         for (uint i = 0; i < layer.ncols; i++) {
2026             if (offset == 0) {
2027                 qCDebug(XCFPLUGIN) << "XCF: incorrect number of tiles in layer " << layer.name;
2028                 return false;
2029             }
2030 
2031             qint64 saved_pos = xcf_io.device()->pos();
2032             qint64 offset2 = readOffsetPtr(xcf_io);
2033 
2034             if (offset2 < 0) {
2035                 qCDebug(XCFPLUGIN) << "XCF: negative level offset";
2036                 return false;
2037             }
2038 
2039             // Evidently, RLE can occasionally expand a tile instead of compressing it!
2040             if (offset2 == 0) {
2041                 offset2 = offset + blockSize;
2042             }
2043 
2044             xcf_io.device()->seek(offset);
2045             qint64 bytesParsed = 0;
2046 
2047             switch (layer.compression) {
2048             case COMPRESS_NONE: {
2049                 if (xcf_io.version() > 11 || size_t(bpp) > sizeof(QRgba64)) {
2050                     qCDebug(XCFPLUGIN) << "Component reading not supported yet";
2051                     return false;
2052                 }
2053                 const int data_size = bpp * TILE_WIDTH * TILE_HEIGHT;
2054                 if (data_size > int(blockSize)) {
2055                     qCDebug(XCFPLUGIN) << "Tile data too big, we can only fit" << sizeof(layer.tile) << "but need" << data_size;
2056                     return false;
2057                 }
2058                 int dataRead = xcf_io.readRawData(reinterpret_cast<char *>(layer.tile), data_size);
2059                 if (dataRead < data_size) {
2060                     qCDebug(XCFPLUGIN) << "short read, expected" << data_size << "got" << dataRead;
2061                     return false;
2062                 }
2063                 bytesParsed = dataRead;
2064                 break;
2065             }
2066             case COMPRESS_RLE: {
2067                 int size = layer.image_tiles[j][i].width() * layer.image_tiles[j][i].height();
2068                 const uint data_size = size * bpp;
2069                 if (needConvert) {
2070                     if (data_size >= unsigned(buffer.size())) {
2071                         qCDebug(XCFPLUGIN) << "Tile data too big, we can only fit" << buffer.size() << "but need" << data_size;
2072                         return false;
2073                     }
2074                 } else {
2075                     if (data_size > sizeof(layer.tile)) {
2076                         qCDebug(XCFPLUGIN) << "Tile data too big, we can only fit" << sizeof(layer.tile) << "but need" << data_size;
2077                         return false;
2078                     }
2079                     if (blockSize > sizeof(layer.tile)) {
2080                         qCWarning(XCFPLUGIN) << "Too small tiles" << sizeof(layer.tile) << "this image requires" << blockSize << sizeof(QRgba64) << bpp;
2081                         return false;
2082                     }
2083                 }
2084                 if (!loadTileRLE(xcf_io, needConvert ? buffer.data() : layer.tile, size, offset2 - offset, bpp, &bytesParsed)) {
2085                     qCDebug(XCFPLUGIN) << "Failed to read RLE";
2086                     return false;
2087                 }
2088                 break;
2089             }
2090             default:
2091                 qCDebug(XCFPLUGIN) << "Unhandled compression" << layer.compression;
2092                 return false;
2093             }
2094 
2095             if (needConvert) {
2096                 if (bytesParsed > buffer.size()) {
2097                     qCDebug(XCFPLUGIN) << "Invalid number of bytes parsed" << bytesParsed << buffer.size();
2098                     return false;
2099                 }
2100 
2101                 switch (precision) {
2102                 case GIMP_PRECISION_U32_LINEAR:
2103                 case GIMP_PRECISION_U32_NON_LINEAR:
2104                 case GIMP_PRECISION_U32_PERCEPTUAL: {
2105                     quint32 *source = (quint32 *)(buffer.data());
2106                     for (quint64 offset = 0, len = buffer.size() / sizeof(quint32); offset < len; ++offset) {
2107                         ((quint16 *)layer.tile)[offset] = qToBigEndian<quint16>(qFromBigEndian(source[offset]) / 65537);
2108                     }
2109                     break;
2110                 }
2111 #ifndef USE_FLOAT_IMAGES
2112                 case GIMP_PRECISION_HALF_LINEAR:
2113                 case GIMP_PRECISION_HALF_NON_LINEAR:
2114                 case GIMP_PRECISION_HALF_PERCEPTUAL:
2115                     convertFloatTo16Bit<qfloat16>(layer.tile, buffer.size() / sizeof(qfloat16), buffer.data());
2116                     break;
2117                 case GIMP_PRECISION_FLOAT_LINEAR:
2118                 case GIMP_PRECISION_FLOAT_NON_LINEAR:
2119                 case GIMP_PRECISION_FLOAT_PERCEPTUAL:
2120                     convertFloatTo16Bit<float>(layer.tile, buffer.size() / sizeof(float), buffer.data());
2121                     break;
2122                 case GIMP_PRECISION_DOUBLE_LINEAR:
2123                 case GIMP_PRECISION_DOUBLE_NON_LINEAR:
2124                 case GIMP_PRECISION_DOUBLE_PERCEPTUAL:
2125                     convertFloatTo16Bit<double>(layer.tile, buffer.size() / sizeof(double), buffer.data());
2126                     break;
2127 #else
2128                 case GIMP_PRECISION_DOUBLE_LINEAR:
2129                 case GIMP_PRECISION_DOUBLE_NON_LINEAR:
2130                 case GIMP_PRECISION_DOUBLE_PERCEPTUAL: {
2131                     double *source = (double *)(buffer.data());
2132                     for (quint64 offset = 0, len = buffer.size() / sizeof(double); offset < len; ++offset) {
2133                         ((float *)layer.tile)[offset] = qToBigEndian<float>(float(qFromBigEndian(source[offset])));
2134                     }
2135                     break;
2136                 }
2137 #endif
2138                 default:
2139                     qCWarning(XCFPLUGIN) << "Unsupported precision" << precision;
2140                     return false;
2141                 }
2142             }
2143 
2144             // The bytes in the layer tile are juggled differently depending on
2145             // the target QImage. The caller has set layer.assignBytes to the
2146             // appropriate routine.
2147             if (!layer.assignBytes(layer, i, j, precision)) {
2148                 return false;
2149             }
2150 
2151             xcf_io.device()->seek(saved_pos);
2152             offset = readOffsetPtr(xcf_io);
2153 
2154             if (offset < 0) {
2155                 qCDebug(XCFPLUGIN) << "XCF: negative level offset";
2156                 return false;
2157             }
2158         }
2159     }
2160 
2161     return true;
2162 }
2163 
2164 /*!
2165  * A layer can have a one channel image which is used as a mask.
2166  * \param xcf_io the data stream connected to the XCF image.
2167  * \param layer the layer to collect the mask image.
2168  * \return true if there were no I/O errors.
2169  */
2170 bool XCFImageFormat::loadMask(QDataStream &xcf_io, Layer &layer, const GimpPrecision precision)
2171 {
2172     qint32 width;
2173     qint32 height;
2174     char *name;
2175 
2176     xcf_io >> width >> height >> name;
2177 
2178     delete[] name;
2179 
2180     if (!loadChannelProperties(xcf_io, layer)) {
2181         return false;
2182     }
2183 
2184     const qint64 hierarchy_offset = readOffsetPtr(xcf_io);
2185 
2186     if (hierarchy_offset < 0) {
2187         qCDebug(XCFPLUGIN) << "XCF: negative mask hierarchy_offset";
2188         return false;
2189     }
2190 
2191     xcf_io.device()->seek(hierarchy_offset);
2192     layer.assignBytes = assignMaskBytes;
2193 
2194     if (!loadHierarchy(xcf_io, layer, precision)) {
2195         return false;
2196     }
2197 
2198     return true;
2199 }
2200 
2201 /*!
2202  * This is the routine for which all the other code is simply
2203  * infrastructure. Read the image bytes out of the file and
2204  * store them in the tile buffer. This is passed a full 32-bit deep
2205  * buffer, even if bpp is smaller. The caller can figure out what to
2206  * do with the bytes.
2207  *
2208  * The tile is stored in "channels", i.e. the red component of all
2209  * pixels, then the green component of all pixels, then blue then
2210  * alpha, or, for indexed images, the color indices of all pixels then
2211  * the alpha of all pixels.
2212  *
2213  * The data is compressed with "run length encoding". Some simple data
2214  * integrity checks are made.
2215  *
2216  * \param xcf_io the data stream connected to the XCF image.
2217  * \param tile the buffer to expand the RLE into.
2218  * \param image_size number of bytes expected to be in the image tile.
2219  * \param data_length number of bytes expected in the RLE.
2220  * \param bpp number of bytes per pixel.
2221  * \return true if there were no I/O errors and no obvious corruption of
2222  * the RLE data.
2223  */
2224 bool XCFImageFormat::loadTileRLE(QDataStream &xcf_io, uchar *tile, int image_size, int data_length, qint32 bpp, qint64 *bytesParsed)
2225 {
2226     uchar *data = tile;
2227 
2228     uchar *xcfdata;
2229     uchar *xcfodata;
2230     uchar *xcfdatalimit;
2231 
2232     int step = sizeof(QRgb);
2233     switch (bpp) {
2234     case 1:
2235     case 2:
2236     case 3:
2237     case 4:
2238         step = sizeof(QRgb);
2239         break;
2240     case 6:
2241     case 8:
2242         step = sizeof(QRgb) * 2;
2243         break;
2244     case 12:
2245     case 16:
2246         step = sizeof(QRgb) * 4;
2247         break;
2248     default:
2249         qCDebug(XCFPLUGIN) << "XCF: unhandled bit depth" << bpp;
2250         return false;
2251     }
2252 
2253     if (data_length < 0 || data_length > int(TILE_WIDTH * TILE_HEIGHT * step * 1.5)) {
2254         qCDebug(XCFPLUGIN) << "XCF: invalid tile data length" << data_length;
2255         return false;
2256     }
2257 
2258     xcfdata = xcfodata = new uchar[data_length];
2259 
2260     const int dataRead = xcf_io.readRawData((char *)xcfdata, data_length);
2261     if (dataRead <= 0) {
2262         delete[] xcfodata;
2263         qCDebug(XCFPLUGIN) << "XCF: read failure on tile" << dataRead;
2264         return false;
2265     }
2266 
2267     if (dataRead < data_length) {
2268         memset(&xcfdata[dataRead], 0, data_length - dataRead);
2269     }
2270 
2271     if (!xcf_io.device()->isOpen()) {
2272         delete[] xcfodata;
2273         qCDebug(XCFPLUGIN) << "XCF: read failure on tile";
2274         return false;
2275     }
2276 
2277     xcfdatalimit = &xcfodata[data_length - 1];
2278 
2279     for (int i = 0; i < bpp; ++i) {
2280         data = tile + i;
2281 
2282         int size = image_size;
2283 
2284         while (size > 0) {
2285             if (xcfdata > xcfdatalimit) {
2286                 goto bogus_rle;
2287             }
2288 
2289             uchar val = *xcfdata++;
2290             uint length = val;
2291 
2292             if (length >= 128) {
2293                 length = 255 - (length - 1);
2294                 if (length == 128) {
2295                     if (xcfdata >= xcfdatalimit) {
2296                         goto bogus_rle;
2297                     }
2298 
2299                     length = (*xcfdata << 8) + xcfdata[1];
2300 
2301                     xcfdata += 2;
2302                 }
2303 
2304                 size -= length;
2305 
2306                 if (size < 0) {
2307                     goto bogus_rle;
2308                 }
2309 
2310                 if (&xcfdata[length - 1] > xcfdatalimit) {
2311                     goto bogus_rle;
2312                 }
2313 
2314                 while (length-- > 0) {
2315                     *data = *xcfdata++;
2316                     data += step;
2317                 }
2318             } else {
2319                 length += 1;
2320                 if (length == 128) {
2321                     if (xcfdata >= xcfdatalimit) {
2322                         goto bogus_rle;
2323                     }
2324 
2325                     length = (*xcfdata << 8) + xcfdata[1];
2326                     xcfdata += 2;
2327                 }
2328 
2329                 size -= length;
2330 
2331                 if (size < 0) {
2332                     goto bogus_rle;
2333                 }
2334 
2335                 if (xcfdata > xcfdatalimit) {
2336                     goto bogus_rle;
2337                 }
2338 
2339                 qintptr totalLength = qintptr(data - tile) + length * step;
2340                 if (totalLength >= image_size * step * 1.5) {
2341                     qCDebug(XCFPLUGIN) << "Ran out of space when trying to unpack image, over:" << totalLength - image_size << totalLength << image_size
2342                                        << length;
2343                     goto bogus_rle;
2344                 }
2345 
2346                 val = *xcfdata++;
2347 
2348                 while (length-- > 0) {
2349                     *data = val;
2350                     data += step;
2351                 }
2352             }
2353         }
2354     }
2355     *bytesParsed = qintptr(data - tile);
2356 
2357     delete[] xcfodata;
2358     return true;
2359 
2360 bogus_rle:
2361 
2362     qCDebug(XCFPLUGIN) << "The run length encoding could not be decoded properly";
2363     delete[] xcfodata;
2364     return false;
2365 }
2366 
2367 /*!
2368  * An XCF file can contain an arbitrary number of properties associated
2369  * with a channel. Note that this routine only reads mask channel properties.
2370  * \param xcf_io the data stream connected to the XCF image.
2371  * \param layer layer containing the mask channel to collect the properties.
2372  * \return true if there were no I/O errors.
2373  */
2374 bool XCFImageFormat::loadChannelProperties(QDataStream &xcf_io, Layer &layer)
2375 {
2376     while (true) {
2377         PropType type;
2378         QByteArray bytes;
2379         quint32 rawType;
2380 
2381         if (!loadProperty(xcf_io, type, bytes, rawType)) {
2382             qCDebug(XCFPLUGIN) << "XCF: error loading channel properties";
2383             return false;
2384         }
2385 
2386         QDataStream property(bytes);
2387 
2388         switch (type) {
2389         case PROP_END:
2390             return true;
2391 
2392         case PROP_OPACITY:
2393             property >> layer.mask_channel.opacity;
2394             layer.mask_channel.opacity = std::min(layer.mask_channel.opacity, 255u);
2395             break;
2396 
2397         case PROP_FLOAT_OPACITY:
2398             // For some reason QDataStream isn't able to read the float (tried
2399             // setting the endianness manually)
2400             if (bytes.size() == 4) {
2401                 layer.mask_channel.opacityFloat = qFromBigEndian(*reinterpret_cast<float *>(bytes.data()));
2402             } else {
2403                 qCDebug(XCFPLUGIN) << "XCF: Invalid data size for float:" << bytes.size();
2404             }
2405             break;
2406 
2407         case PROP_VISIBLE:
2408             property >> layer.mask_channel.visible;
2409             break;
2410 
2411         case PROP_SHOW_MASKED:
2412             property >> layer.mask_channel.show_masked;
2413             break;
2414 
2415         case PROP_COLOR:
2416             property >> layer.mask_channel.red >> layer.mask_channel.green >> layer.mask_channel.blue;
2417             break;
2418 
2419         case PROP_FLOAT_COLOR:
2420             property >> layer.mask_channel.redF >> layer.mask_channel.greenF >> layer.mask_channel.blueF;
2421             break;
2422 
2423         case PROP_TATTOO:
2424             property >> layer.mask_channel.tattoo;
2425             break;
2426 
2427         // Only used in edit mode
2428         case PROP_LINKED:
2429             break;
2430 
2431         // Just for organization in the UI, doesn't influence rendering
2432         case PROP_COLOR_TAG:
2433             break;
2434 
2435         // We don't support editing, so for now just ignore locking
2436         case PROP_LOCK_CONTENT:
2437         case PROP_LOCK_POSITION:
2438             break;
2439 
2440         default:
2441             qCDebug(XCFPLUGIN) << "XCF: unimplemented channel property " << type << "(" << rawType << ")"
2442                                << ", size " << bytes.size();
2443             break;
2444         }
2445     }
2446 }
2447 
2448 /*!
2449  * Copy the bytes from the tile buffer into the mask tile QImage.
2450  * \param layer layer containing the tile buffer and the mask tile matrix.
2451  * \param i column index of current tile.
2452  * \param j row index of current tile.
2453  */
2454 bool XCFImageFormat::assignMaskBytes(Layer &layer, uint i, uint j, const GimpPrecision &precision)
2455 {
2456     QImage &image = layer.mask_tiles[j][i];
2457     if (image.depth() != 8) {
2458         qCWarning(XCFPLUGIN) << "invalid bytes per pixel, we only do 8 bit masks" << image.depth();
2459         return false;
2460     }
2461 
2462     uchar *tile = layer.tile;
2463     const int width = image.width();
2464     const int height = image.height();
2465     const int bytesPerLine = image.bytesPerLine();
2466     uchar *bits = image.bits();
2467     auto bpc = bytesPerChannel(precision);
2468 
2469     // mask management is a house of cards: the mask is always treated as 8 bit by the plugin
2470     // (I don't want to twist the code) so it needs a conversion here.
2471     // If previously converted the step is the type size, otherwise is the one set in loadTileRLE().
2472     for (int y = 0; y < height; y++) {
2473         uchar *dataPtr = bits + y * bytesPerLine;
2474 #ifdef USE_FLOAT_IMAGES
2475         if (bpc == 4) {
2476             if (precision < GimpPrecision::GIMP_PRECISION_HALF_LINEAR) {
2477                 for (int x = 0; x < width; x++) {
2478                     *dataPtr++ = qFromBigEndian<quint16>(*(const quint16 *)tile) / 257;
2479                     tile += sizeof(quint16); // was converted to 16 bits in loadLevel()
2480                 }
2481             } else {
2482                 for (int x = 0; x < width; x++) {
2483                     *dataPtr++ = qFromBigEndian<float>(*(const float *)tile) * 255;
2484                     tile += sizeof(QRgb); // yeah! see loadTileRLE()
2485                 }
2486             }
2487         } else if (bpc == 2) {
2488             // when not converted, the step of a
2489             if (precision < GimpPrecision::GIMP_PRECISION_HALF_LINEAR) {
2490                 for (int x = 0; x < width; x++) {
2491                     *dataPtr++ = qFromBigEndian<quint16>(*(const quint16 *)tile) / 257;
2492                     tile += sizeof(QRgb); // yeah! see loadTileRLE()
2493                 }
2494             } else {
2495                 for (int x = 0; x < width; x++) {
2496                     *dataPtr++ = qFromBigEndian<qfloat16>(*(const qfloat16 *)tile) * 255;
2497                     tile += sizeof(QRgb); // yeah! see loadTileRLE()
2498                 }
2499             }
2500         }
2501 #else
2502         if (bpc == 2) {
2503             for (int x = 0; x < width; x++) {
2504                 *dataPtr++ = qFromBigEndian<quint16>(*(const quint16 *)tile) / 257;
2505                 tile += sizeof(QRgb); // yeah! see loadTileRLE() / loadLevel()
2506             }
2507         } else if (bpc == 4) {
2508             for (int x = 0; x < width; x++) {
2509                 *dataPtr++ = qFromBigEndian<quint16>(*(const quint16 *)tile) / 257;
2510                 tile += sizeof(quint16); // was converted to 16 bits in loadLevel()
2511             }
2512         }
2513 #endif
2514         else {
2515             for (int x = 0; x < width; x++) {
2516                 *dataPtr++ = tile[0];
2517                 tile += sizeof(QRgb); // yeah! see loadTileRLE()
2518             }
2519         }
2520     }
2521 
2522     return true;
2523 }
2524 
2525 /*!
2526  * Construct the QImage which will eventually be returned to the QImage
2527  * loader.
2528  *
2529  * There are a couple of situations which require that the QImage is not
2530  * exactly the same as The GIMP's representation. The full table is:
2531  * \verbatim
2532  *  Grayscale  opaque      :  8 bpp indexed
2533  *  Grayscale  translucent : 32 bpp + alpha
2534  *  Indexed    opaque      :  1 bpp if num_colors <= 2
2535  *                         :  8 bpp indexed otherwise
2536  *  Indexed    translucent :  8 bpp indexed + alpha if num_colors < 256
2537  *                         : 32 bpp + alpha otherwise
2538  *  RGB        opaque      : 32 bpp
2539  *  RGBA       translucent : 32 bpp + alpha
2540  * \endverbatim
2541  * Whether the image is translucent or not is determined by the bottom layer's
2542  * alpha channel. However, even if the bottom layer lacks an alpha channel,
2543  * it can still have an opacity < 1. In this case, the QImage is promoted
2544  * to 32-bit. (Note this is different from the output from the GIMP image
2545  * exporter, which seems to ignore this attribute.)
2546  *
2547  * Independently, higher layers can be translucent, but the background of
2548  * the image will not show through if the bottom layer is opaque.
2549  *
2550  * For indexed images, translucency is an all or nothing effect.
2551  * \param xcf_image contains image info and bottom-most layer.
2552  */
2553 bool XCFImageFormat::initializeImage(XCFImage &xcf_image)
2554 {
2555     // (Aliases to make the code look a little better.)
2556     Layer &layer(xcf_image.layer);
2557     QImage &image(xcf_image.image);
2558 
2559     switch (layer.type) {
2560     case GRAY_GIMAGE:
2561         if (layer.opacity == OPAQUE_OPACITY) {
2562             image = imageAlloc(xcf_image.header.width, xcf_image.header.height, QImage::Format_Indexed8);
2563             image.setColorCount(256);
2564             if (image.isNull()) {
2565                 return false;
2566             }
2567             setGrayPalette(image);
2568             image.fill(255);
2569             break;
2570         } // else, fall through to 32-bit representation
2571         Q_FALLTHROUGH();
2572     case GRAYA_GIMAGE:
2573     case RGB_GIMAGE:
2574     case RGBA_GIMAGE:
2575         image = imageAlloc(xcf_image.header.width, xcf_image.header.height, xcf_image.qimageFormat());
2576         if (image.isNull()) {
2577             return false;
2578         }
2579         if (image.hasAlphaChannel()) {
2580             image.fill(Qt::transparent);
2581         } else {
2582             image.fill(Qt::white);
2583         }
2584         break;
2585 
2586     case INDEXED_GIMAGE:
2587         // As noted in the table above, there are quite a few combinations
2588         // which are possible with indexed images, depending on the
2589         // presence of transparency (note: not translucency, which is not
2590         // supported by The GIMP for indexed images) and the number of
2591         // individual colors.
2592 
2593         // Note: Qt treats a bitmap with a Black and White color palette
2594         // as a mask, so only the "on" bits are drawn, regardless of the
2595         // order color table entries. Otherwise (i.e., at least one of the
2596         // color table entries is not black or white), it obeys the one-
2597         // or two-color palette. Have to ask about this...
2598 
2599         if (xcf_image.num_colors <= 2) {
2600             image = imageAlloc(xcf_image.header.width, xcf_image.header.height, QImage::Format_MonoLSB);
2601             image.setColorCount(xcf_image.num_colors);
2602             if (image.isNull()) {
2603                 return false;
2604             }
2605             image.fill(0);
2606             setPalette(xcf_image, image);
2607         } else if (xcf_image.num_colors <= 256) {
2608             image = imageAlloc(xcf_image.header.width, xcf_image.header.height, QImage::Format_Indexed8);
2609             image.setColorCount(xcf_image.num_colors);
2610             if (image.isNull()) {
2611                 return false;
2612             }
2613             image.fill(0);
2614             setPalette(xcf_image, image);
2615         }
2616         break;
2617 
2618     case INDEXEDA_GIMAGE:
2619         if (xcf_image.num_colors == 1) {
2620             // Plenty(!) of room to add a transparent color
2621             xcf_image.num_colors++;
2622             xcf_image.palette.resize(xcf_image.num_colors);
2623             xcf_image.palette[1] = xcf_image.palette[0];
2624             xcf_image.palette[0] = qRgba(255, 255, 255, 0);
2625 
2626             image = imageAlloc(xcf_image.header.width, xcf_image.header.height, QImage::Format_MonoLSB);
2627             image.setColorCount(xcf_image.num_colors);
2628             if (image.isNull()) {
2629                 return false;
2630             }
2631             image.fill(0);
2632             setPalette(xcf_image, image);
2633         } else if (xcf_image.num_colors < 256) {
2634             // Plenty of room to add a transparent color
2635             xcf_image.num_colors++;
2636             xcf_image.palette.resize(xcf_image.num_colors);
2637             for (int c = xcf_image.num_colors - 1; c >= 1; c--) {
2638                 xcf_image.palette[c] = xcf_image.palette[c - 1];
2639             }
2640 
2641             xcf_image.palette[0] = qRgba(255, 255, 255, 0);
2642             image = imageAlloc(xcf_image.header.width, xcf_image.header.height, QImage::Format_Indexed8);
2643             image.setColorCount(xcf_image.num_colors);
2644             if (image.isNull()) {
2645                 return false;
2646             }
2647             image.fill(0);
2648             setPalette(xcf_image, image);
2649         } else {
2650             // No room for a transparent color, so this has to be promoted to
2651             // true color. (There is no equivalent PNG representation output
2652             // from The GIMP as of v1.2.)
2653             image = imageAlloc(xcf_image.header.width, xcf_image.header.height, QImage::Format_ARGB32);
2654             if (image.isNull()) {
2655                 return false;
2656             }
2657             image.fill(qRgba(255, 255, 255, 0));
2658         }
2659         break;
2660     }
2661     if (image.format() != xcf_image.qimageFormat()) {
2662         qCWarning(XCFPLUGIN) << "Selected wrong format:" << image.format() << "expected" << layer.qimageFormat(xcf_image.header.precision);
2663         return false;
2664     }
2665 
2666     // The final profile should be the one in the Parasite
2667     // NOTE: if not set here, the colorSpace is aet in setImageParasites() (if no one defined in the parasites)
2668 #ifndef DISABLE_IMAGE_PROFILE
2669     switch (xcf_image.header.precision) {
2670     case XCFImageFormat::GIMP_PRECISION_HALF_LINEAR:
2671     case XCFImageFormat::GIMP_PRECISION_FLOAT_LINEAR:
2672     case XCFImageFormat::GIMP_PRECISION_DOUBLE_LINEAR:
2673     case XCFImageFormat::GIMP_PRECISION_U8_LINEAR:
2674     case XCFImageFormat::GIMP_PRECISION_U16_LINEAR:
2675     case XCFImageFormat::GIMP_PRECISION_U32_LINEAR:
2676         image.setColorSpace(QColorSpace::SRgbLinear);
2677         break;
2678     case XCFImageFormat::GIMP_PRECISION_HALF_NON_LINEAR:
2679     case XCFImageFormat::GIMP_PRECISION_FLOAT_NON_LINEAR:
2680     case XCFImageFormat::GIMP_PRECISION_DOUBLE_NON_LINEAR:
2681     case XCFImageFormat::GIMP_PRECISION_U8_NON_LINEAR:
2682     case XCFImageFormat::GIMP_PRECISION_U16_NON_LINEAR:
2683     case XCFImageFormat::GIMP_PRECISION_U32_NON_LINEAR:
2684         image.setColorSpace(QColorSpace::SRgb);
2685         break;
2686     case XCFImageFormat::GIMP_PRECISION_HALF_PERCEPTUAL:
2687     case XCFImageFormat::GIMP_PRECISION_FLOAT_PERCEPTUAL:
2688     case XCFImageFormat::GIMP_PRECISION_DOUBLE_PERCEPTUAL:
2689     case XCFImageFormat::GIMP_PRECISION_U8_PERCEPTUAL:
2690     case XCFImageFormat::GIMP_PRECISION_U16_PERCEPTUAL:
2691     case XCFImageFormat::GIMP_PRECISION_U32_PERCEPTUAL:
2692         image.setColorSpace(QColorSpace::SRgb);
2693         break;
2694     }
2695 #endif
2696 
2697     if (xcf_image.x_resolution > 0 && xcf_image.y_resolution > 0) {
2698         const float dpmx = xcf_image.x_resolution * INCHESPERMETER;
2699         if (dpmx > float(std::numeric_limits<int>::max())) {
2700             return false;
2701         }
2702         const float dpmy = xcf_image.y_resolution * INCHESPERMETER;
2703         if (dpmy > float(std::numeric_limits<int>::max())) {
2704             return false;
2705         }
2706         image.setDotsPerMeterX((int)dpmx);
2707         image.setDotsPerMeterY((int)dpmy);
2708     }
2709     return true;
2710 }
2711 
2712 /*!
2713  * Copy a layer into an image, taking account of the manifold modes. The
2714  * contents of the image are replaced.
2715  * \param xcf_image contains the layer and image to be replaced.
2716  */
2717 void XCFImageFormat::copyLayerToImage(XCFImage &xcf_image)
2718 {
2719     Layer &layer(xcf_image.layer);
2720     QImage &image(xcf_image.image);
2721     PixelCopyOperation copy = nullptr;
2722 
2723     switch (layer.type) {
2724     case RGB_GIMAGE:
2725     case RGBA_GIMAGE:
2726         copy = copyRGBToRGB;
2727         break;
2728     case GRAY_GIMAGE:
2729         if (layer.opacity == OPAQUE_OPACITY) {
2730             copy = copyGrayToGray;
2731         } else {
2732             copy = copyGrayToRGB;
2733         }
2734         break;
2735     case GRAYA_GIMAGE:
2736         copy = copyGrayAToRGB;
2737         break;
2738     case INDEXED_GIMAGE:
2739         copy = copyIndexedToIndexed;
2740         break;
2741     case INDEXEDA_GIMAGE:
2742         if (xcf_image.image.depth() <= 8) {
2743             copy = copyIndexedAToIndexed;
2744         } else {
2745             copy = copyIndexedAToRGB;
2746         }
2747     }
2748 
2749     if (!copy) {
2750         return;
2751     }
2752 
2753     // For each tile...
2754 
2755     for (uint j = 0; j < layer.nrows; j++) {
2756         uint y = j * TILE_HEIGHT;
2757 
2758         for (uint i = 0; i < layer.ncols; i++) {
2759             uint x = i * TILE_WIDTH;
2760 
2761             // This seems the best place to apply the dissolve because it
2762             // depends on the global position of each tile's
2763             // pixels. Apparently it's the only mode which can apply to a
2764             // single layer.
2765 
2766             if (layer.mode == GIMP_LAYER_MODE_DISSOLVE) {
2767                 if (!random_table_initialized) {
2768                     initializeRandomTable();
2769                     random_table_initialized = true;
2770                 }
2771                 if (layer.type == RGBA_GIMAGE) {
2772                     dissolveRGBPixels(layer.image_tiles[j][i], x, y);
2773                 }
2774 
2775                 else if (layer.type == GRAYA_GIMAGE) {
2776                     dissolveAlphaPixels(layer.alpha_tiles[j][i], x, y);
2777                 }
2778             }
2779 
2780             // Shortcut for common case
2781             if (copy == copyRGBToRGB && layer.apply_mask != 1) {
2782                 QPainter painter(&image);
2783                 painter.setOpacity(layer.opacity / 255.0);
2784                 painter.setCompositionMode(QPainter::CompositionMode_Source);
2785                 if (x + layer.x_offset < MAX_IMAGE_WIDTH &&
2786                     y + layer.y_offset < MAX_IMAGE_HEIGHT) {
2787                     painter.drawImage(x + layer.x_offset, y + layer.y_offset, layer.image_tiles[j][i]);
2788                 }
2789                 continue;
2790             }
2791 
2792             for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
2793                 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
2794                     int m = x + k + layer.x_offset;
2795                     int n = y + l + layer.y_offset;
2796 
2797                     if (m < 0 || m >= image.width() || n < 0 || n >= image.height()) {
2798                         continue;
2799                     }
2800 
2801                     (*copy)(layer, i, j, k, l, image, m, n);
2802                 }
2803             }
2804         }
2805     }
2806 }
2807 
2808 /*!
2809  * Copy an RGB pixel from the layer to the RGB image. Straight-forward.
2810  * The only thing this has to take account of is the opacity of the
2811  * layer. Evidently, the GIMP exporter itself does not actually do this.
2812  * \param layer source layer.
2813  * \param i x tile index.
2814  * \param j y tile index.
2815  * \param k x pixel index of tile i,j.
2816  * \param l y pixel index of tile i,j.
2817  * \param image destination image.
2818  * \param m x pixel of destination image.
2819  * \param n y pixel of destination image.
2820  */
2821 void XCFImageFormat::copyRGBToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
2822 {
2823     if (image.depth() == 32) {
2824         QRgb src = layer.image_tiles[j][i].pixel(k, l);
2825         uchar src_a = layer.opacity;
2826 
2827         if (layer.type == RGBA_GIMAGE) {
2828             src_a = INT_MULT(src_a, qAlpha(src));
2829         }
2830 
2831         // Apply the mask (if any)
2832 
2833         if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
2834             src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
2835         }
2836 
2837         image.setPixel(m, n, qRgba(src, src_a));
2838     } else if (image.depth() == 64) {
2839         QRgba64 src = layer.image_tiles[j][i].pixelColor(k, l).rgba64();
2840         quint16 src_a = layer.opacity;
2841 
2842         if (layer.type == RGBA_GIMAGE) {
2843             src_a = INT_MULT(src_a, qAlpha(src));
2844         }
2845 
2846         // Apply the mask (if any)
2847 
2848         if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
2849             src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
2850         }
2851         src.setAlpha(src_a);
2852 
2853         image.setPixel(m, n, src);
2854     }
2855 }
2856 
2857 /*!
2858  * Copy a Gray pixel from the layer to the Gray image. Straight-forward.
2859  * \param layer source layer.
2860  * \param i x tile index.
2861  * \param j y tile index.
2862  * \param k x pixel index of tile i,j.
2863  * \param l y pixel index of tile i,j.
2864  * \param image destination image.
2865  * \param m x pixel of destination image.
2866  * \param n y pixel of destination image.
2867  */
2868 void XCFImageFormat::copyGrayToGray(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
2869 {
2870     int src = layer.image_tiles[j][i].pixelIndex(k, l);
2871     image.setPixel(m, n, src);
2872 }
2873 
2874 /*!
2875  * Copy a Gray pixel from the layer to an RGB image. Straight-forward.
2876  * The only thing this has to take account of is the opacity of the
2877  * layer. Evidently, the GIMP exporter itself does not actually do this.
2878  * \param layer source layer.
2879  * \param i x tile index.
2880  * \param j y tile index.
2881  * \param k x pixel index of tile i,j.
2882  * \param l y pixel index of tile i,j.
2883  * \param image destination image.
2884  * \param m x pixel of destination image.
2885  * \param n y pixel of destination image.
2886  */
2887 void XCFImageFormat::copyGrayToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
2888 {
2889     QRgb src = layer.image_tiles[j][i].pixel(k, l);
2890     uchar src_a = layer.opacity;
2891     image.setPixel(m, n, qRgba(src, src_a));
2892 }
2893 
2894 /*!
2895  * Copy a GrayA pixel from the layer to an RGB image. Straight-forward.
2896  * The only thing this has to take account of is the opacity of the
2897  * layer. Evidently, the GIMP exporter itself does not actually do this.
2898  * \param layer source layer.
2899  * \param i x tile index.
2900  * \param j y tile index.
2901  * \param k x pixel index of tile i,j.
2902  * \param l y pixel index of tile i,j.
2903  * \param image destination image.
2904  * \param m x pixel of destination image.
2905  * \param n y pixel of destination image.
2906  */
2907 void XCFImageFormat::copyGrayAToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
2908 {
2909     QRgb src = layer.image_tiles[j][i].pixel(k, l);
2910     uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
2911     src_a = INT_MULT(src_a, layer.opacity);
2912 
2913     // Apply the mask (if any)
2914 
2915     if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
2916         src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
2917     }
2918 
2919     image.setPixel(m, n, qRgba(src, src_a));
2920 }
2921 
2922 /*!
2923  * Copy an Indexed pixel from the layer to the Indexed image. Straight-forward.
2924  * \param layer source layer.
2925  * \param i x tile index.
2926  * \param j y tile index.
2927  * \param k x pixel index of tile i,j.
2928  * \param l y pixel index of tile i,j.
2929  * \param image destination image.
2930  * \param m x pixel of destination image.
2931  * \param n y pixel of destination image.
2932  */
2933 void XCFImageFormat::copyIndexedToIndexed(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
2934 {
2935     int src = layer.image_tiles[j][i].pixelIndex(k, l);
2936     image.setPixel(m, n, src);
2937 }
2938 
2939 /*!
2940  * Copy an IndexedA pixel from the layer to the Indexed image. Straight-forward.
2941  * \param layer source layer.
2942  * \param i x tile index.
2943  * \param j y tile index.
2944  * \param k x pixel index of tile i,j.
2945  * \param l y pixel index of tile i,j.
2946  * \param image destination image.
2947  * \param m x pixel of destination image.
2948  * \param n y pixel of destination image.
2949  */
2950 void XCFImageFormat::copyIndexedAToIndexed(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
2951 {
2952     uchar src = layer.image_tiles[j][i].pixelIndex(k, l);
2953     uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
2954     src_a = INT_MULT(src_a, layer.opacity);
2955 
2956     if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
2957         src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
2958     }
2959 
2960     if (src_a > 127) {
2961         src++;
2962     } else {
2963         src = 0;
2964     }
2965 
2966     image.setPixel(m, n, src);
2967 }
2968 
2969 /*!
2970  * Copy an IndexedA pixel from the layer to an RGB image. Straight-forward.
2971  * The only thing this has to take account of is the opacity of the
2972  * layer. Evidently, the GIMP exporter itself does not actually do this.
2973  * \param layer source layer.
2974  * \param i x tile index.
2975  * \param j y tile index.
2976  * \param k x pixel index of tile i,j.
2977  * \param l y pixel index of tile i,j.
2978  * \param image destination image.
2979  * \param m x pixel of destination image.
2980  * \param n y pixel of destination image.
2981  */
2982 void XCFImageFormat::copyIndexedAToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
2983 {
2984     QRgb src = layer.image_tiles[j][i].pixel(k, l);
2985     uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
2986     src_a = INT_MULT(src_a, layer.opacity);
2987 
2988     // Apply the mask (if any)
2989     if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
2990         src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
2991     }
2992 
2993     // This is what appears in the GIMP window
2994     if (src_a <= 127) {
2995         src_a = 0;
2996     } else {
2997         src_a = OPAQUE_OPACITY;
2998     }
2999 
3000     image.setPixel(m, n, qRgba(src, src_a));
3001 }
3002 
3003 /*!
3004  * Merge a layer into an image, taking account of the manifold modes.
3005  * \param xcf_image contains the layer and image to merge.
3006  */
3007 void XCFImageFormat::mergeLayerIntoImage(XCFImage &xcf_image)
3008 {
3009     Layer &layer(xcf_image.layer);
3010     QImage &image(xcf_image.image);
3011 
3012     PixelMergeOperation merge = nullptr;
3013 
3014     if (!layer.opacity) {
3015         return; // don't bother doing anything
3016     }
3017 
3018     if (layer.blendSpace == XCFImageFormat::AutoColorSpace) {
3019         qCDebug(XCFPLUGIN) << "Auto blend space, defaulting to RgbLinearSpace (same as Gimp when writing this)";
3020         layer.blendSpace = XCFImageFormat::RgbLinearSpace;
3021     }
3022 
3023     if (layer.blendSpace != XCFImageFormat::RgbLinearSpace) {
3024         qCDebug(XCFPLUGIN) << "Unimplemented blend color space" << layer.blendSpace;
3025     }
3026     qCDebug(XCFPLUGIN) << "Blend color space" << layer.blendSpace;
3027 
3028     if (layer.compositeSpace == XCFImageFormat::AutoColorSpace) {
3029         qCDebug(XCFPLUGIN) << "Auto composite space, defaulting to RgbLinearSpace (same as Gimp when writing this)";
3030         layer.compositeSpace = XCFImageFormat::RgbLinearSpace;
3031     }
3032 
3033     if (layer.compositeSpace != XCFImageFormat::RgbLinearSpace) {
3034         qCDebug(XCFPLUGIN) << "Unimplemented composite color space" << layer.compositeSpace;
3035     }
3036     if (layer.compositeMode != XCFImageFormat::CompositeUnion) {
3037         qCDebug(XCFPLUGIN) << "Unhandled composite mode" << layer.compositeMode;
3038     }
3039 
3040     switch (layer.type) {
3041     case RGB_GIMAGE:
3042     case RGBA_GIMAGE:
3043         merge = mergeRGBToRGB;
3044         break;
3045     case GRAY_GIMAGE:
3046         if (layer.opacity == OPAQUE_OPACITY) {
3047             merge = mergeGrayToGray;
3048         } else {
3049             merge = mergeGrayToRGB;
3050         }
3051         break;
3052     case GRAYA_GIMAGE:
3053         if (xcf_image.image.depth() <= 8) {
3054             merge = mergeGrayAToGray;
3055         } else {
3056             merge = mergeGrayAToRGB;
3057         }
3058         break;
3059     case INDEXED_GIMAGE:
3060         merge = mergeIndexedToIndexed;
3061         break;
3062     case INDEXEDA_GIMAGE:
3063         if (xcf_image.image.depth() <= 8) {
3064             merge = mergeIndexedAToIndexed;
3065         } else {
3066             merge = mergeIndexedAToRGB;
3067         }
3068     }
3069 
3070     if (!merge) {
3071         return;
3072     }
3073 
3074     if (merge == mergeRGBToRGB && layer.apply_mask != 1) {
3075         int painterMode = -1;
3076         switch (layer.mode) {
3077         case GIMP_LAYER_MODE_NORMAL:
3078         case GIMP_LAYER_MODE_NORMAL_LEGACY:
3079             painterMode = QPainter::CompositionMode_SourceOver;
3080             break;
3081         case GIMP_LAYER_MODE_MULTIPLY:
3082         case GIMP_LAYER_MODE_MULTIPLY_LEGACY:
3083             painterMode = QPainter::CompositionMode_Multiply;
3084             break;
3085         case GIMP_LAYER_MODE_SCREEN:
3086         case GIMP_LAYER_MODE_SCREEN_LEGACY:
3087             painterMode = QPainter::CompositionMode_Screen;
3088             break;
3089         case GIMP_LAYER_MODE_OVERLAY:
3090         case GIMP_LAYER_MODE_OVERLAY_LEGACY:
3091             painterMode = QPainter::CompositionMode_Overlay;
3092             break;
3093         case GIMP_LAYER_MODE_DIFFERENCE:
3094         case GIMP_LAYER_MODE_DIFFERENCE_LEGACY:
3095             painterMode = QPainter::CompositionMode_Difference;
3096             break;
3097         case GIMP_LAYER_MODE_DARKEN_ONLY:
3098         case GIMP_LAYER_MODE_DARKEN_ONLY_LEGACY:
3099             painterMode = QPainter::CompositionMode_Darken;
3100             break;
3101         case GIMP_LAYER_MODE_LIGHTEN_ONLY:
3102         case GIMP_LAYER_MODE_LIGHTEN_ONLY_LEGACY:
3103             painterMode = QPainter::CompositionMode_Lighten;
3104             break;
3105         case GIMP_LAYER_MODE_DODGE:
3106         case GIMP_LAYER_MODE_DODGE_LEGACY:
3107             painterMode = QPainter::CompositionMode_ColorDodge;
3108             break;
3109         case GIMP_LAYER_MODE_BURN:
3110         case GIMP_LAYER_MODE_BURN_LEGACY:
3111             painterMode = QPainter::CompositionMode_ColorBurn;
3112             break;
3113         case GIMP_LAYER_MODE_HARDLIGHT:
3114         case GIMP_LAYER_MODE_HARDLIGHT_LEGACY:
3115             painterMode = QPainter::CompositionMode_HardLight;
3116             break;
3117         case GIMP_LAYER_MODE_SOFTLIGHT:
3118         case GIMP_LAYER_MODE_SOFTLIGHT_LEGACY:
3119             painterMode = QPainter::CompositionMode_SoftLight;
3120             break;
3121         case GIMP_LAYER_MODE_ADDITION:
3122         case GIMP_LAYER_MODE_ADDITION_LEGACY:
3123             painterMode = QPainter::CompositionMode_Plus;
3124             break;
3125         case GIMP_LAYER_MODE_EXCLUSION:
3126             painterMode = QPainter::CompositionMode_Exclusion;
3127             break;
3128 
3129             // Not bothered to find what the QPainter equivalent is, or there is none
3130         case GIMP_LAYER_MODE_GRAIN_EXTRACT:
3131         case GIMP_LAYER_MODE_GRAIN_EXTRACT_LEGACY:
3132         case GIMP_LAYER_MODE_GRAIN_MERGE:
3133         case GIMP_LAYER_MODE_GRAIN_MERGE_LEGACY:
3134         case GIMP_LAYER_MODE_COLOR_ERASE:
3135         case GIMP_LAYER_MODE_COLOR_ERASE_LEGACY:
3136         case GIMP_LAYER_MODE_LCH_HUE:
3137         case GIMP_LAYER_MODE_LCH_CHROMA:
3138         case GIMP_LAYER_MODE_LCH_COLOR:
3139         case GIMP_LAYER_MODE_LCH_LIGHTNESS:
3140         case GIMP_LAYER_MODE_BEHIND:
3141         case GIMP_LAYER_MODE_BEHIND_LEGACY:
3142         case GIMP_LAYER_MODE_SUBTRACT:
3143         case GIMP_LAYER_MODE_SUBTRACT_LEGACY:
3144         case GIMP_LAYER_MODE_HSV_HUE:
3145         case GIMP_LAYER_MODE_HSV_SATURATION:
3146         case GIMP_LAYER_MODE_HSL_COLOR:
3147         case GIMP_LAYER_MODE_HSV_VALUE:
3148         case GIMP_LAYER_MODE_DIVIDE:
3149         case GIMP_LAYER_MODE_VIVID_LIGHT:
3150         case GIMP_LAYER_MODE_PIN_LIGHT:
3151         case GIMP_LAYER_MODE_LINEAR_LIGHT:
3152         case GIMP_LAYER_MODE_HARD_MIX:
3153         case GIMP_LAYER_MODE_LINEAR_BURN:
3154         case GIMP_LAYER_MODE_LUMA_DARKEN_ONLY:
3155         case GIMP_LAYER_MODE_LUMA_LIGHTEN_ONLY:
3156         case GIMP_LAYER_MODE_LUMINANCE:
3157         case GIMP_LAYER_MODE_ERASE:
3158         case GIMP_LAYER_MODE_MERGE:
3159         case GIMP_LAYER_MODE_SPLIT:
3160         case GIMP_LAYER_MODE_PASS_THROUGH:
3161         case GIMP_LAYER_MODE_HSV_HUE_LEGACY:
3162         case GIMP_LAYER_MODE_HSV_SATURATION_LEGACY:
3163         case GIMP_LAYER_MODE_HSL_COLOR_LEGACY:
3164         case GIMP_LAYER_MODE_HSV_VALUE_LEGACY:
3165         case GIMP_LAYER_MODE_DIVIDE_LEGACY:
3166             qCDebug(XCFPLUGIN) << "No QPainter equivalent to" << layer.mode;
3167             break;
3168 
3169             // Special
3170         case GIMP_LAYER_MODE_DISSOLVE:
3171         case GIMP_LAYER_MODE_COUNT:
3172             break;
3173         }
3174 
3175         if (painterMode != -1) {
3176             QPainter painter(&image);
3177             painter.setOpacity(layer.opacity / 255.0);
3178             painter.setCompositionMode(QPainter::CompositionMode(painterMode));
3179             qCDebug(XCFPLUGIN) << "Using QPainter for mode" << layer.mode;
3180 
3181             for (uint j = 0; j < layer.nrows; j++) {
3182                 uint y = j * TILE_HEIGHT;
3183 
3184                 for (uint i = 0; i < layer.ncols; i++) {
3185                     uint x = i * TILE_WIDTH;
3186 
3187                     QImage &tile = layer.image_tiles[j][i];
3188                     if (x + layer.x_offset < MAX_IMAGE_WIDTH &&
3189                         y + layer.y_offset < MAX_IMAGE_HEIGHT) {
3190                         painter.drawImage(x + layer.x_offset, y + layer.y_offset, tile);
3191                     }
3192                 }
3193             }
3194 
3195             return;
3196         }
3197     }
3198 
3199 #ifndef DISABLE_IMAGE_PROFILE_CONV // The final profile should be the one in the Parasite
3200     if (layer.compositeSpace == XCFImageFormat::RgbPerceptualSpace && image.colorSpace() != QColorSpace::SRgb) {
3201         qCDebug(XCFPLUGIN) << "Converting to composite color space" << layer.compositeSpace;
3202         image.convertToColorSpace(QColorSpace::SRgb);
3203     }
3204     if (layer.compositeSpace == XCFImageFormat::RgbLinearSpace && image.colorSpace() != QColorSpace::SRgbLinear) {
3205         qCDebug(XCFPLUGIN) << "Converting to composite color space" << layer.compositeSpace;
3206         image.convertToColorSpace(QColorSpace::SRgbLinear);
3207     }
3208 #endif
3209 
3210     for (uint j = 0; j < layer.nrows; j++) {
3211         uint y = j * TILE_HEIGHT;
3212 
3213         for (uint i = 0; i < layer.ncols; i++) {
3214             uint x = i * TILE_WIDTH;
3215 
3216             // This seems the best place to apply the dissolve because it
3217             // depends on the global position of each tile's
3218             // pixels. Apparently it's the only mode which can apply to a
3219             // single layer.
3220 
3221             if (layer.mode == GIMP_LAYER_MODE_DISSOLVE) {
3222                 if (!random_table_initialized) {
3223                     initializeRandomTable();
3224                     random_table_initialized = true;
3225                 }
3226                 if (layer.type == RGBA_GIMAGE) {
3227                     dissolveRGBPixels(layer.image_tiles[j][i], x, y);
3228                 }
3229 
3230                 else if (layer.type == GRAYA_GIMAGE) {
3231                     dissolveAlphaPixels(layer.alpha_tiles[j][i], x, y);
3232                 }
3233             }
3234 
3235             // Shortcut for common case
3236             if (merge == mergeRGBToRGB && layer.apply_mask != 1 && layer.mode == GIMP_LAYER_MODE_NORMAL_LEGACY) {
3237                 QPainter painter(&image);
3238                 painter.setOpacity(layer.opacity / 255.0);
3239                 painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
3240                 if (x + layer.x_offset < MAX_IMAGE_WIDTH &&
3241                     y + layer.y_offset < MAX_IMAGE_HEIGHT) {
3242                     painter.drawImage(x + layer.x_offset, y + layer.y_offset, layer.image_tiles[j][i]);
3243                 }
3244                 continue;
3245             }
3246 
3247 #ifndef DISABLE_TILE_PROFILE_CONV // not sure about that: left as old plugin
3248             QImage &tile = layer.image_tiles[j][i];
3249             if (layer.compositeSpace == XCFImageFormat::RgbPerceptualSpace && tile.colorSpace() != QColorSpace::SRgb) {
3250                 tile.convertToColorSpace(QColorSpace::SRgb);
3251             }
3252             if (layer.compositeSpace == XCFImageFormat::RgbLinearSpace && tile.colorSpace() != QColorSpace::SRgbLinear) {
3253                 tile.convertToColorSpace(QColorSpace::SRgbLinear);
3254             }
3255 #endif
3256 
3257             for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
3258                 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
3259                     int m = x + k + layer.x_offset;
3260                     int n = y + l + layer.y_offset;
3261 
3262                     if (m < 0 || m >= image.width() || n < 0 || n >= image.height()) {
3263                         continue;
3264                     }
3265 
3266                     if (!(*merge)(layer, i, j, k, l, image, m, n)) {
3267                         return;
3268                     }
3269                 }
3270             }
3271         }
3272     }
3273 }
3274 
3275 /*!
3276  * Merge an RGB pixel from the layer to the RGB image. Straight-forward.
3277  * The only thing this has to take account of is the opacity of the
3278  * layer. Evidently, the GIMP exporter itself does not actually do this.
3279  * \param layer source layer.
3280  * \param i x tile index.
3281  * \param j y tile index.
3282  * \param k x pixel index of tile i,j.
3283  * \param l y pixel index of tile i,j.
3284  * \param image destination image.
3285  * \param m x pixel of destination image.
3286  * \param n y pixel of destination image.
3287  */
3288 bool XCFImageFormat::mergeRGBToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
3289 {
3290     QRgb src = layer.image_tiles[j][i].pixel(k, l);
3291     QRgb dst = image.pixel(m, n);
3292 
3293     uchar src_r = qRed(src);
3294     uchar src_g = qGreen(src);
3295     uchar src_b = qBlue(src);
3296     uchar src_a = qAlpha(src);
3297 
3298     uchar dst_r = qRed(dst);
3299     uchar dst_g = qGreen(dst);
3300     uchar dst_b = qBlue(dst);
3301     uchar dst_a = qAlpha(dst);
3302 
3303     if (!src_a) {
3304         return false; // nothing to merge
3305     }
3306 
3307     switch (layer.mode) {
3308     case GIMP_LAYER_MODE_NORMAL:
3309     case GIMP_LAYER_MODE_NORMAL_LEGACY:
3310         break;
3311     case GIMP_LAYER_MODE_MULTIPLY:
3312     case GIMP_LAYER_MODE_MULTIPLY_LEGACY:
3313         src_r = INT_MULT(src_r, dst_r);
3314         src_g = INT_MULT(src_g, dst_g);
3315         src_b = INT_MULT(src_b, dst_b);
3316         src_a = qMin(src_a, dst_a);
3317         break;
3318     case GIMP_LAYER_MODE_DIVIDE:
3319     case GIMP_LAYER_MODE_DIVIDE_LEGACY:
3320         src_r = qMin((dst_r * 256) / (1 + src_r), 255);
3321         src_g = qMin((dst_g * 256) / (1 + src_g), 255);
3322         src_b = qMin((dst_b * 256) / (1 + src_b), 255);
3323         src_a = qMin(src_a, dst_a);
3324         break;
3325     case GIMP_LAYER_MODE_SCREEN:
3326     case GIMP_LAYER_MODE_SCREEN_LEGACY:
3327         src_r = 255 - INT_MULT(255 - dst_r, 255 - src_r);
3328         src_g = 255 - INT_MULT(255 - dst_g, 255 - src_g);
3329         src_b = 255 - INT_MULT(255 - dst_b, 255 - src_b);
3330         src_a = qMin(src_a, dst_a);
3331         break;
3332     case GIMP_LAYER_MODE_OVERLAY:
3333     case GIMP_LAYER_MODE_OVERLAY_LEGACY:
3334         src_r = INT_MULT(dst_r, dst_r + INT_MULT(2 * src_r, 255 - dst_r));
3335         src_g = INT_MULT(dst_g, dst_g + INT_MULT(2 * src_g, 255 - dst_g));
3336         src_b = INT_MULT(dst_b, dst_b + INT_MULT(2 * src_b, 255 - dst_b));
3337         src_a = qMin(src_a, dst_a);
3338         break;
3339     case GIMP_LAYER_MODE_DIFFERENCE:
3340     case GIMP_LAYER_MODE_DIFFERENCE_LEGACY:
3341         src_r = dst_r > src_r ? dst_r - src_r : src_r - dst_r;
3342         src_g = dst_g > src_g ? dst_g - src_g : src_g - dst_g;
3343         src_b = dst_b > src_b ? dst_b - src_b : src_b - dst_b;
3344         src_a = qMin(src_a, dst_a);
3345         break;
3346     case GIMP_LAYER_MODE_ADDITION:
3347     case GIMP_LAYER_MODE_ADDITION_LEGACY:
3348         src_r = add_lut(dst_r, src_r);
3349         src_g = add_lut(dst_g, src_g);
3350         src_b = add_lut(dst_b, src_b);
3351         src_a = qMin(src_a, dst_a);
3352         break;
3353     case GIMP_LAYER_MODE_SUBTRACT:
3354     case GIMP_LAYER_MODE_SUBTRACT_LEGACY:
3355         src_r = dst_r > src_r ? dst_r - src_r : 0;
3356         src_g = dst_g > src_g ? dst_g - src_g : 0;
3357         src_b = dst_b > src_b ? dst_b - src_b : 0;
3358         src_a = qMin(src_a, dst_a);
3359         break;
3360     case GIMP_LAYER_MODE_DARKEN_ONLY:
3361     case GIMP_LAYER_MODE_DARKEN_ONLY_LEGACY:
3362         src_r = dst_r < src_r ? dst_r : src_r;
3363         src_g = dst_g < src_g ? dst_g : src_g;
3364         src_b = dst_b < src_b ? dst_b : src_b;
3365         src_a = qMin(src_a, dst_a);
3366         break;
3367     case GIMP_LAYER_MODE_LIGHTEN_ONLY:
3368     case GIMP_LAYER_MODE_LIGHTEN_ONLY_LEGACY:
3369         src_r = dst_r < src_r ? src_r : dst_r;
3370         src_g = dst_g < src_g ? src_g : dst_g;
3371         src_b = dst_b < src_b ? src_b : dst_b;
3372         src_a = qMin(src_a, dst_a);
3373         break;
3374     case GIMP_LAYER_MODE_HSV_HUE:
3375     case GIMP_LAYER_MODE_HSV_HUE_LEGACY: {
3376         uchar new_r = dst_r;
3377         uchar new_g = dst_g;
3378         uchar new_b = dst_b;
3379 
3380         RGBTOHSV(src_r, src_g, src_b);
3381         RGBTOHSV(new_r, new_g, new_b);
3382 
3383         new_r = src_r;
3384 
3385         HSVTORGB(new_r, new_g, new_b);
3386 
3387         src_r = new_r;
3388         src_g = new_g;
3389         src_b = new_b;
3390         src_a = qMin(src_a, dst_a);
3391     } break;
3392     case GIMP_LAYER_MODE_HSV_SATURATION:
3393     case GIMP_LAYER_MODE_HSV_SATURATION_LEGACY: {
3394         uchar new_r = dst_r;
3395         uchar new_g = dst_g;
3396         uchar new_b = dst_b;
3397 
3398         RGBTOHSV(src_r, src_g, src_b);
3399         RGBTOHSV(new_r, new_g, new_b);
3400 
3401         new_g = src_g;
3402 
3403         HSVTORGB(new_r, new_g, new_b);
3404 
3405         src_r = new_r;
3406         src_g = new_g;
3407         src_b = new_b;
3408         src_a = qMin(src_a, dst_a);
3409     } break;
3410     case GIMP_LAYER_MODE_HSV_VALUE:
3411     case GIMP_LAYER_MODE_HSV_VALUE_LEGACY: {
3412         uchar new_r = dst_r;
3413         uchar new_g = dst_g;
3414         uchar new_b = dst_b;
3415 
3416         RGBTOHSV(src_r, src_g, src_b);
3417         RGBTOHSV(new_r, new_g, new_b);
3418 
3419         new_b = src_b;
3420 
3421         HSVTORGB(new_r, new_g, new_b);
3422 
3423         src_r = new_r;
3424         src_g = new_g;
3425         src_b = new_b;
3426         src_a = qMin(src_a, dst_a);
3427     } break;
3428     case GIMP_LAYER_MODE_HSL_COLOR:
3429     case GIMP_LAYER_MODE_HSL_COLOR_LEGACY: {
3430         uchar new_r = dst_r;
3431         uchar new_g = dst_g;
3432         uchar new_b = dst_b;
3433 
3434         RGBTOHLS(src_r, src_g, src_b);
3435         RGBTOHLS(new_r, new_g, new_b);
3436 
3437         new_r = src_r;
3438         new_b = src_b;
3439 
3440         HLSTORGB(new_r, new_g, new_b);
3441 
3442         src_r = new_r;
3443         src_g = new_g;
3444         src_b = new_b;
3445         src_a = qMin(src_a, dst_a);
3446     } break;
3447     case GIMP_LAYER_MODE_DODGE:
3448     case GIMP_LAYER_MODE_DODGE_LEGACY: {
3449         uint tmp;
3450 
3451         tmp = dst_r << 8;
3452         tmp /= 256 - src_r;
3453         src_r = (uchar)qMin(tmp, 255u);
3454 
3455         tmp = dst_g << 8;
3456         tmp /= 256 - src_g;
3457         src_g = (uchar)qMin(tmp, 255u);
3458 
3459         tmp = dst_b << 8;
3460         tmp /= 256 - src_b;
3461         src_b = (uchar)qMin(tmp, 255u);
3462 
3463         src_a = qMin(src_a, dst_a);
3464     } break;
3465     case GIMP_LAYER_MODE_BURN:
3466     case GIMP_LAYER_MODE_BURN_LEGACY: {
3467         uint tmp;
3468 
3469         tmp = (255 - dst_r) << 8;
3470         tmp /= src_r + 1;
3471         src_r = (uchar)qMin(tmp, 255u);
3472         src_r = 255 - src_r;
3473 
3474         tmp = (255 - dst_g) << 8;
3475         tmp /= src_g + 1;
3476         src_g = (uchar)qMin(tmp, 255u);
3477         src_g = 255 - src_g;
3478 
3479         tmp = (255 - dst_b) << 8;
3480         tmp /= src_b + 1;
3481         src_b = (uchar)qMin(tmp, 255u);
3482         src_b = 255 - src_b;
3483 
3484         src_a = qMin(src_a, dst_a);
3485     } break;
3486     case GIMP_LAYER_MODE_HARDLIGHT:
3487     case GIMP_LAYER_MODE_HARDLIGHT_LEGACY: {
3488         uint tmp;
3489         if (src_r > 128) {
3490             tmp = ((int)255 - dst_r) * ((int)255 - ((src_r - 128) << 1));
3491             src_r = (uchar)qMin(255 - (tmp >> 8), 255u);
3492         } else {
3493             tmp = (int)dst_r * ((int)src_r << 1);
3494             src_r = (uchar)qMin(tmp >> 8, 255u);
3495         }
3496 
3497         if (src_g > 128) {
3498             tmp = ((int)255 - dst_g) * ((int)255 - ((src_g - 128) << 1));
3499             src_g = (uchar)qMin(255 - (tmp >> 8), 255u);
3500         } else {
3501             tmp = (int)dst_g * ((int)src_g << 1);
3502             src_g = (uchar)qMin(tmp >> 8, 255u);
3503         }
3504 
3505         if (src_b > 128) {
3506             tmp = ((int)255 - dst_b) * ((int)255 - ((src_b - 128) << 1));
3507             src_b = (uchar)qMin(255 - (tmp >> 8), 255u);
3508         } else {
3509             tmp = (int)dst_b * ((int)src_b << 1);
3510             src_b = (uchar)qMin(tmp >> 8, 255u);
3511         }
3512         src_a = qMin(src_a, dst_a);
3513     } break;
3514     case GIMP_LAYER_MODE_SOFTLIGHT:
3515     case GIMP_LAYER_MODE_SOFTLIGHT_LEGACY: {
3516         uint tmpS;
3517         uint tmpM;
3518 
3519         tmpM = INT_MULT(dst_r, src_r);
3520         tmpS = 255 - INT_MULT((255 - dst_r), (255 - src_r));
3521         src_r = INT_MULT((255 - dst_r), tmpM) + INT_MULT(dst_r, tmpS);
3522 
3523         tmpM = INT_MULT(dst_g, src_g);
3524         tmpS = 255 - INT_MULT((255 - dst_g), (255 - src_g));
3525         src_g = INT_MULT((255 - dst_g), tmpM) + INT_MULT(dst_g, tmpS);
3526 
3527         tmpM = INT_MULT(dst_b, src_b);
3528         tmpS = 255 - INT_MULT((255 - dst_b), (255 - src_b));
3529         src_b = INT_MULT((255 - dst_b), tmpM) + INT_MULT(dst_b, tmpS);
3530 
3531         src_a = qMin(src_a, dst_a);
3532     } break;
3533     case GIMP_LAYER_MODE_GRAIN_EXTRACT:
3534     case GIMP_LAYER_MODE_GRAIN_EXTRACT_LEGACY: {
3535         int tmp;
3536 
3537         tmp = dst_r - src_r + 128;
3538         tmp = qMin(tmp, 255);
3539         tmp = qMax(tmp, 0);
3540         src_r = (uchar)tmp;
3541 
3542         tmp = dst_g - src_g + 128;
3543         tmp = qMin(tmp, 255);
3544         tmp = qMax(tmp, 0);
3545         src_g = (uchar)tmp;
3546 
3547         tmp = dst_b - src_b + 128;
3548         tmp = qMin(tmp, 255);
3549         tmp = qMax(tmp, 0);
3550         src_b = (uchar)tmp;
3551 
3552         src_a = qMin(src_a, dst_a);
3553     } break;
3554     case GIMP_LAYER_MODE_GRAIN_MERGE:
3555     case GIMP_LAYER_MODE_GRAIN_MERGE_LEGACY: {
3556         int tmp;
3557 
3558         tmp = dst_r + src_r - 128;
3559         tmp = qMin(tmp, 255);
3560         tmp = qMax(tmp, 0);
3561         src_r = (uchar)tmp;
3562 
3563         tmp = dst_g + src_g - 128;
3564         tmp = qMin(tmp, 255);
3565         tmp = qMax(tmp, 0);
3566         src_g = (uchar)tmp;
3567 
3568         tmp = dst_b + src_b - 128;
3569         tmp = qMin(tmp, 255);
3570         tmp = qMax(tmp, 0);
3571         src_b = (uchar)tmp;
3572 
3573         src_a = qMin(src_a, dst_a);
3574     } break;
3575     case GIMP_LAYER_MODE_LINEAR_LIGHT: {
3576         if (src_r <= 128) {
3577             src_r = qBound(0, dst_r + 2 * src_r - 255, 255);
3578         } else {
3579             src_r = qBound(0, dst_r + 2 * (src_r - 128), 255);
3580         }
3581         if (src_g <= 128) {
3582             src_g = qBound(0, dst_g + 2 * src_g - 255, 255);
3583         } else {
3584             src_g = qBound(0, dst_g + 2 * (src_g - 127), 255);
3585         }
3586         if (src_b <= 128) {
3587             src_b = qBound(0, dst_b + 2 * src_b - 255, 255);
3588         } else {
3589             src_b = qBound(0, dst_b + 2 * (src_b - 127), 255);
3590         }
3591     } break;
3592     case GIMP_LAYER_MODE_VIVID_LIGHT: {
3593         // From http://www.simplefilter.de/en/basics/mixmods.html
3594         float A[3];
3595         A[0] = src_r / 255.;
3596         A[1] = src_g / 255.;
3597         A[2] = src_b / 255.;
3598         float B[3];
3599         B[0] = dst_r / 255.;
3600         B[1] = dst_g / 255.;
3601         B[2] = dst_b / 255.;
3602         float C[3]{};
3603         for (int i = 0; i < 3; i++) {
3604             if (A[i] <= 0.5f) {
3605                 if (A[i] > 0.f) {
3606                     C[i] = 1.f - (1.f - B[i]) / (2.f * A[i]);
3607                 }
3608             } else {
3609                 if (A[i] < 1.f) {
3610                     C[i] = B[i] / (2.f * (1.f - A[i]));
3611                 }
3612             }
3613         }
3614         src_r = qBound(0.f, C[0] * 255.f, 255.f);
3615         src_g = qBound(0.f, C[1] * 255.f, 255.f);
3616         src_b = qBound(0.f, C[2] * 255.f, 255.f);
3617     } break;
3618     default:
3619         qCWarning(XCFPLUGIN) << "Unhandled mode" << layer.mode;
3620         return false;
3621     }
3622 
3623     src_a = INT_MULT(src_a, layer.opacity);
3624 
3625     // Apply the mask (if any)
3626 
3627     if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
3628         src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
3629     }
3630 
3631     uchar new_r;
3632     uchar new_g;
3633     uchar new_b;
3634     uchar new_a;
3635     new_a = dst_a + INT_MULT(OPAQUE_OPACITY - dst_a, src_a);
3636 
3637     const float src_ratio = new_a == 0 ? 1.0 : (float)src_a / new_a;
3638     float dst_ratio = 1.0 - src_ratio;
3639 
3640     new_r = (uchar)(src_ratio * src_r + dst_ratio * dst_r + EPSILON);
3641     new_g = (uchar)(src_ratio * src_g + dst_ratio * dst_g + EPSILON);
3642     new_b = (uchar)(src_ratio * src_b + dst_ratio * dst_b + EPSILON);
3643 
3644     if (!modeAffectsSourceAlpha(layer.mode)) {
3645         new_a = dst_a;
3646     }
3647 
3648     image.setPixel(m, n, qRgba(new_r, new_g, new_b, new_a));
3649     return true;
3650 }
3651 
3652 /*!
3653  * Merge a Gray pixel from the layer to the Gray image. Straight-forward.
3654  * \param layer source layer.
3655  * \param i x tile index.
3656  * \param j y tile index.
3657  * \param k x pixel index of tile i,j.
3658  * \param l y pixel index of tile i,j.
3659  * \param image destination image.
3660  * \param m x pixel of destination image.
3661  * \param n y pixel of destination image.
3662  */
3663 bool XCFImageFormat::mergeGrayToGray(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
3664 {
3665     int src = layer.image_tiles[j][i].pixelIndex(k, l);
3666     image.setPixel(m, n, src);
3667     return true;
3668 }
3669 
3670 /*!
3671  * Merge a GrayA pixel from the layer to the Gray image. Straight-forward.
3672  * \param layer source layer.
3673  * \param i x tile index.
3674  * \param j y tile index.
3675  * \param k x pixel index of tile i,j.
3676  * \param l y pixel index of tile i,j.
3677  * \param image destination image.
3678  * \param m x pixel of destination image.
3679  * \param n y pixel of destination image.
3680  */
3681 bool XCFImageFormat::mergeGrayAToGray(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
3682 {
3683     int src = qGray(layer.image_tiles[j][i].pixel(k, l));
3684     int dst = image.pixelIndex(m, n);
3685 
3686     uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
3687 
3688     if (!src_a) {
3689         return false; // nothing to merge
3690     }
3691 
3692     switch (layer.mode) {
3693     case GIMP_LAYER_MODE_MULTIPLY:
3694     case GIMP_LAYER_MODE_MULTIPLY_LEGACY: {
3695         src = INT_MULT(src, dst);
3696     } break;
3697     case GIMP_LAYER_MODE_DIVIDE:
3698     case GIMP_LAYER_MODE_DIVIDE_LEGACY: {
3699         src = qMin((dst * 256) / (1 + src), 255);
3700     } break;
3701     case GIMP_LAYER_MODE_SCREEN:
3702     case GIMP_LAYER_MODE_SCREEN_LEGACY: {
3703         src = 255 - INT_MULT(255 - dst, 255 - src);
3704     } break;
3705     case GIMP_LAYER_MODE_OVERLAY:
3706     case GIMP_LAYER_MODE_OVERLAY_LEGACY: {
3707         src = INT_MULT(dst, dst + INT_MULT(2 * src, 255 - dst));
3708     } break;
3709     case GIMP_LAYER_MODE_DIFFERENCE:
3710     case GIMP_LAYER_MODE_DIFFERENCE_LEGACY: {
3711         src = dst > src ? dst - src : src - dst;
3712     } break;
3713     case GIMP_LAYER_MODE_ADDITION:
3714     case GIMP_LAYER_MODE_ADDITION_LEGACY: {
3715         src = add_lut(dst, src);
3716     } break;
3717     case GIMP_LAYER_MODE_SUBTRACT:
3718     case GIMP_LAYER_MODE_SUBTRACT_LEGACY: {
3719         src = dst > src ? dst - src : 0;
3720     } break;
3721     case GIMP_LAYER_MODE_DARKEN_ONLY:
3722     case GIMP_LAYER_MODE_DARKEN_ONLY_LEGACY: {
3723         src = dst < src ? dst : src;
3724     } break;
3725     case GIMP_LAYER_MODE_LIGHTEN_ONLY:
3726     case GIMP_LAYER_MODE_LIGHTEN_ONLY_LEGACY: {
3727         src = dst < src ? src : dst;
3728     } break;
3729     case GIMP_LAYER_MODE_DODGE:
3730     case GIMP_LAYER_MODE_DODGE_LEGACY: {
3731         uint tmp = dst << 8;
3732         tmp /= 256 - src;
3733         src = (uchar)qMin(tmp, 255u);
3734     } break;
3735     case GIMP_LAYER_MODE_BURN:
3736     case GIMP_LAYER_MODE_BURN_LEGACY: {
3737         uint tmp = (255 - dst) << 8;
3738         tmp /= src + 1;
3739         src = (uchar)qMin(tmp, 255u);
3740         src = 255 - src;
3741     } break;
3742     case GIMP_LAYER_MODE_HARDLIGHT:
3743     case GIMP_LAYER_MODE_HARDLIGHT_LEGACY: {
3744         uint tmp;
3745         if (src > 128) {
3746             tmp = ((int)255 - dst) * ((int)255 - ((src - 128) << 1));
3747             src = (uchar)qMin(255 - (tmp >> 8), 255u);
3748         } else {
3749             tmp = (int)dst * ((int)src << 1);
3750             src = (uchar)qMin(tmp >> 8, 255u);
3751         }
3752     } break;
3753     case GIMP_LAYER_MODE_SOFTLIGHT:
3754     case GIMP_LAYER_MODE_SOFTLIGHT_LEGACY: {
3755         uint tmpS;
3756         uint tmpM;
3757 
3758         tmpM = INT_MULT(dst, src);
3759         tmpS = 255 - INT_MULT((255 - dst), (255 - src));
3760         src = INT_MULT((255 - dst), tmpM) + INT_MULT(dst, tmpS);
3761 
3762     } break;
3763     case GIMP_LAYER_MODE_GRAIN_EXTRACT:
3764     case GIMP_LAYER_MODE_GRAIN_EXTRACT_LEGACY: {
3765         int tmp;
3766 
3767         tmp = dst - src + 128;
3768         tmp = qMin(tmp, 255);
3769         tmp = qMax(tmp, 0);
3770 
3771         src = (uchar)tmp;
3772     } break;
3773     case GIMP_LAYER_MODE_GRAIN_MERGE:
3774     case GIMP_LAYER_MODE_GRAIN_MERGE_LEGACY: {
3775         int tmp;
3776 
3777         tmp = dst + src - 128;
3778         tmp = qMin(tmp, 255);
3779         tmp = qMax(tmp, 0);
3780 
3781         src = (uchar)tmp;
3782     } break;
3783     default:
3784         qCWarning(XCFPLUGIN) << "Unhandled mode" << layer.mode;
3785         return false;
3786     }
3787 
3788     src_a = INT_MULT(src_a, layer.opacity);
3789 
3790     // Apply the mask (if any)
3791 
3792     if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
3793         src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
3794     }
3795 
3796     uchar new_a = OPAQUE_OPACITY;
3797 
3798     const float src_ratio = new_a == 0 ? 1.0 : (float)src_a / new_a;
3799     float dst_ratio = 1.0 - src_ratio;
3800 
3801     uchar new_g = (uchar)(src_ratio * src + dst_ratio * dst + EPSILON);
3802 
3803     image.setPixel(m, n, new_g);
3804     return true;
3805 }
3806 
3807 /*!
3808  * Merge a Gray pixel from the layer to an RGB image. Straight-forward.
3809  * The only thing this has to take account of is the opacity of the
3810  * layer. Evidently, the GIMP exporter itself does not actually do this.
3811  * \param layer source layer.
3812  * \param i x tile index.
3813  * \param j y tile index.
3814  * \param k x pixel index of tile i,j.
3815  * \param l y pixel index of tile i,j.
3816  * \param image destination image.
3817  * \param m x pixel of destination image.
3818  * \param n y pixel of destination image.
3819  */
3820 bool XCFImageFormat::mergeGrayToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
3821 {
3822     QRgb src = layer.image_tiles[j][i].pixel(k, l);
3823     uchar src_a = layer.opacity;
3824     image.setPixel(m, n, qRgba(src, src_a));
3825     return true;
3826 }
3827 
3828 /*!
3829  * Merge a GrayA pixel from the layer to an RGB image. Straight-forward.
3830  * The only thing this has to take account of is the opacity of the
3831  * layer. Evidently, the GIMP exporter itself does not actually do this.
3832  * \param layer source layer.
3833  * \param i x tile index.
3834  * \param j y tile index.
3835  * \param k x pixel index of tile i,j.
3836  * \param l y pixel index of tile i,j.
3837  * \param image destination image.
3838  * \param m x pixel of destination image.
3839  * \param n y pixel of destination image.
3840  */
3841 bool XCFImageFormat::mergeGrayAToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
3842 {
3843     int src = qGray(layer.image_tiles[j][i].pixel(k, l));
3844     int dst = qGray(image.pixel(m, n));
3845 
3846     uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
3847     uchar dst_a = qAlpha(image.pixel(m, n));
3848 
3849     if (!src_a) {
3850         return false; // nothing to merge
3851     }
3852 
3853     switch (layer.mode) {
3854     case GIMP_LAYER_MODE_MULTIPLY:
3855     case GIMP_LAYER_MODE_MULTIPLY_LEGACY: {
3856         src = INT_MULT(src, dst);
3857         src_a = qMin(src_a, dst_a);
3858     } break;
3859     case GIMP_LAYER_MODE_DIVIDE:
3860     case GIMP_LAYER_MODE_DIVIDE_LEGACY: {
3861         src = qMin((dst * 256) / (1 + src), 255);
3862         src_a = qMin(src_a, dst_a);
3863     } break;
3864     case GIMP_LAYER_MODE_SCREEN:
3865     case GIMP_LAYER_MODE_SCREEN_LEGACY: {
3866         src = 255 - INT_MULT(255 - dst, 255 - src);
3867         src_a = qMin(src_a, dst_a);
3868     } break;
3869     case GIMP_LAYER_MODE_OVERLAY:
3870     case GIMP_LAYER_MODE_OVERLAY_LEGACY: {
3871         src = INT_MULT(dst, dst + INT_MULT(2 * src, 255 - dst));
3872         src_a = qMin(src_a, dst_a);
3873     } break;
3874     case GIMP_LAYER_MODE_DIFFERENCE:
3875     case GIMP_LAYER_MODE_DIFFERENCE_LEGACY: {
3876         src = dst > src ? dst - src : src - dst;
3877         src_a = qMin(src_a, dst_a);
3878     } break;
3879     case GIMP_LAYER_MODE_ADDITION:
3880     case GIMP_LAYER_MODE_ADDITION_LEGACY: {
3881         src = add_lut(dst, src);
3882         src_a = qMin(src_a, dst_a);
3883     } break;
3884     case GIMP_LAYER_MODE_SUBTRACT:
3885     case GIMP_LAYER_MODE_SUBTRACT_LEGACY: {
3886         src = dst > src ? dst - src : 0;
3887         src_a = qMin(src_a, dst_a);
3888     } break;
3889     case GIMP_LAYER_MODE_DARKEN_ONLY:
3890     case GIMP_LAYER_MODE_DARKEN_ONLY_LEGACY: {
3891         src = dst < src ? dst : src;
3892         src_a = qMin(src_a, dst_a);
3893     } break;
3894     case GIMP_LAYER_MODE_LIGHTEN_ONLY:
3895     case GIMP_LAYER_MODE_LIGHTEN_ONLY_LEGACY: {
3896         src = dst < src ? src : dst;
3897         src_a = qMin(src_a, dst_a);
3898     } break;
3899     case GIMP_LAYER_MODE_DODGE:
3900     case GIMP_LAYER_MODE_DODGE_LEGACY: {
3901         uint tmp = dst << 8;
3902         tmp /= 256 - src;
3903         src = (uchar)qMin(tmp, 255u);
3904         src_a = qMin(src_a, dst_a);
3905     } break;
3906     case GIMP_LAYER_MODE_BURN:
3907     case GIMP_LAYER_MODE_BURN_LEGACY: {
3908         uint tmp = (255 - dst) << 8;
3909         tmp /= src + 1;
3910         src = (uchar)qMin(tmp, 255u);
3911         src = 255 - src;
3912         src_a = qMin(src_a, dst_a);
3913     } break;
3914     case GIMP_LAYER_MODE_HARDLIGHT:
3915     case GIMP_LAYER_MODE_HARDLIGHT_LEGACY: {
3916         uint tmp;
3917         if (src > 128) {
3918             tmp = ((int)255 - dst) * ((int)255 - ((src - 128) << 1));
3919             src = (uchar)qMin(255 - (tmp >> 8), 255u);
3920         } else {
3921             tmp = (int)dst * ((int)src << 1);
3922             src = (uchar)qMin(tmp >> 8, 255u);
3923         }
3924         src_a = qMin(src_a, dst_a);
3925     } break;
3926     case GIMP_LAYER_MODE_SOFTLIGHT:
3927     case GIMP_LAYER_MODE_SOFTLIGHT_LEGACY: {
3928         uint tmpS;
3929         uint tmpM;
3930 
3931         tmpM = INT_MULT(dst, src);
3932         tmpS = 255 - INT_MULT((255 - dst), (255 - src));
3933         src = INT_MULT((255 - dst), tmpM) + INT_MULT(dst, tmpS);
3934 
3935         src_a = qMin(src_a, dst_a);
3936     } break;
3937     case GIMP_LAYER_MODE_GRAIN_EXTRACT:
3938     case GIMP_LAYER_MODE_GRAIN_EXTRACT_LEGACY: {
3939         int tmp;
3940 
3941         tmp = dst - src + 128;
3942         tmp = qMin(tmp, 255);
3943         tmp = qMax(tmp, 0);
3944 
3945         src = (uchar)tmp;
3946         src_a = qMin(src_a, dst_a);
3947     } break;
3948     case GIMP_LAYER_MODE_GRAIN_MERGE:
3949     case GIMP_LAYER_MODE_GRAIN_MERGE_LEGACY: {
3950         int tmp;
3951 
3952         tmp = dst + src - 128;
3953         tmp = qMin(tmp, 255);
3954         tmp = qMax(tmp, 0);
3955 
3956         src = (uchar)tmp;
3957         src_a = qMin(src_a, dst_a);
3958     } break;
3959     default:
3960         qCWarning(XCFPLUGIN) << "Unhandled mode" << layer.mode;
3961         return false;
3962     }
3963 
3964     src_a = INT_MULT(src_a, layer.opacity);
3965 
3966     // Apply the mask (if any)
3967     if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
3968         src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
3969     }
3970 
3971     uchar new_a = dst_a + INT_MULT(OPAQUE_OPACITY - dst_a, src_a);
3972 
3973     const float src_ratio = new_a == 0 ? 1.0 : (float)src_a / new_a;
3974     float dst_ratio = 1.0 - src_ratio;
3975 
3976     uchar new_g = (uchar)(src_ratio * src + dst_ratio * dst + EPSILON);
3977 
3978     if (!modeAffectsSourceAlpha(layer.mode)) {
3979         new_a = dst_a;
3980     }
3981 
3982     image.setPixel(m, n, qRgba(new_g, new_g, new_g, new_a));
3983     return true;
3984 }
3985 
3986 /*!
3987  * Merge an Indexed pixel from the layer to the Indexed image. Straight-forward.
3988  * \param layer source layer.
3989  * \param i x tile index.
3990  * \param j y tile index.
3991  * \param k x pixel index of tile i,j.
3992  * \param l y pixel index of tile i,j.
3993  * \param image destination image.
3994  * \param m x pixel of destination image.
3995  * \param n y pixel of destination image.
3996  */
3997 bool XCFImageFormat::mergeIndexedToIndexed(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
3998 {
3999     int src = layer.image_tiles[j][i].pixelIndex(k, l);
4000     image.setPixel(m, n, src);
4001     return true;
4002 }
4003 
4004 /*!
4005  * Merge an IndexedA pixel from the layer to the Indexed image. Straight-forward.
4006  * \param layer source layer.
4007  * \param i x tile index.
4008  * \param j y tile index.
4009  * \param k x pixel index of tile i,j.
4010  * \param l y pixel index of tile i,j.
4011  * \param image destination image.
4012  * \param m x pixel of destination image.
4013  * \param n y pixel of destination image.
4014  */
4015 bool XCFImageFormat::mergeIndexedAToIndexed(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
4016 {
4017     uchar src = layer.image_tiles[j][i].pixelIndex(k, l);
4018     uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
4019     src_a = INT_MULT(src_a, layer.opacity);
4020 
4021     if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
4022         src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
4023     }
4024 
4025     if (src_a > 127) {
4026         src++;
4027         image.setPixel(m, n, src);
4028     }
4029     return true;
4030 }
4031 
4032 /*!
4033  * Merge an IndexedA pixel from the layer to an RGB image. Straight-forward.
4034  * The only thing this has to take account of is the opacity of the
4035  * layer. Evidently, the GIMP exporter itself does not actually do this.
4036  * \param layer source layer.
4037  * \param i x tile index.
4038  * \param j y tile index.
4039  * \param k x pixel index of tile i,j.
4040  * \param l y pixel index of tile i,j.
4041  * \param image destination image.
4042  * \param m x pixel of destination image.
4043  * \param n y pixel of destination image.
4044  */
4045 bool XCFImageFormat::mergeIndexedAToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
4046 {
4047     QRgb src = layer.image_tiles[j][i].pixel(k, l);
4048     uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
4049     src_a = INT_MULT(src_a, layer.opacity);
4050 
4051     // Apply the mask (if any)
4052     if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
4053         src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
4054     }
4055 
4056     // This is what appears in the GIMP window
4057     if (src_a <= 127) {
4058         src_a = 0;
4059     } else {
4060         src_a = OPAQUE_OPACITY;
4061     }
4062 
4063     image.setPixel(m, n, qRgba(src, src_a));
4064     return true;
4065 }
4066 
4067 /*!
4068  * Dissolving pixels: pick a random number between 0 and 255. If the pixel's
4069  * alpha is less than that, make it transparent.
4070  * \param image the image tile to dissolve.
4071  * \param x the global x position of the tile.
4072  * \param y the global y position of the tile.
4073  */
4074 void XCFImageFormat::dissolveRGBPixels(QImage &image, int x, int y)
4075 {
4076     // The apparently spurious rand() calls are to wind the random
4077     // numbers up to the same point for each tile.
4078 
4079     for (int l = 0; l < image.height(); l++) {
4080         unsigned int next = randomTable.values[(l + y) % RANDOM_TABLE_SIZE];
4081 
4082         for (int k = 0; k < x; k++) {
4083             RandomTable::rand_r(&next);
4084         }
4085 
4086         for (int k = 0; k < image.width(); k++) {
4087             int rand_val = RandomTable::rand_r(&next) & 0xff;
4088             QRgb pixel = image.pixel(k, l);
4089 
4090             if (rand_val > qAlpha(pixel)) {
4091                 image.setPixel(k, l, qRgba(pixel, 0));
4092             }
4093         }
4094     }
4095 }
4096 
4097 /*!
4098  * Dissolving pixels: pick a random number between 0 and 255. If the pixel's
4099  * alpha is less than that, make it transparent. This routine works for
4100  * the GRAYA and INDEXEDA image types where the pixel alpha's are stored
4101  * separately from the pixel themselves.
4102  * \param image the alpha tile to dissolve.
4103  * \param x the global x position of the tile.
4104  * \param y the global y position of the tile.
4105  */
4106 void XCFImageFormat::dissolveAlphaPixels(QImage &image, int x, int y)
4107 {
4108     // The apparently spurious rand() calls are to wind the random
4109     // numbers up to the same point for each tile.
4110 
4111     for (int l = 0; l < image.height(); l++) {
4112         unsigned int next = randomTable.values[(l + y) % RANDOM_TABLE_SIZE];
4113 
4114         for (int k = 0; k < x; k++) {
4115             RandomTable::rand_r(&next);
4116         }
4117 
4118         for (int k = 0; k < image.width(); k++) {
4119             int rand_val = RandomTable::rand_r(&next) & 0xff;
4120             uchar alpha = image.pixelIndex(k, l);
4121 
4122             if (rand_val > alpha) {
4123                 image.setPixel(k, l, 0);
4124             }
4125         }
4126     }
4127 }
4128 
4129 ///////////////////////////////////////////////////////////////////////////////
4130 
4131 XCFHandler::XCFHandler()
4132 {
4133 }
4134 
4135 bool XCFHandler::canRead() const
4136 {
4137     if (canRead(device())) {
4138         setFormat("xcf");
4139         return true;
4140     }
4141     return false;
4142 }
4143 
4144 bool XCFHandler::read(QImage *image)
4145 {
4146     XCFImageFormat xcfif;
4147     return xcfif.readXCF(device(), image);
4148 }
4149 
4150 bool XCFHandler::write(const QImage &)
4151 {
4152     return false;
4153 }
4154 
4155 bool XCFHandler::supportsOption(ImageOption option) const
4156 {
4157     if (option == QImageIOHandler::Size)
4158         return true;
4159     return false;
4160 }
4161 
4162 QVariant XCFHandler::option(ImageOption option) const
4163 {
4164     QVariant v;
4165 
4166     if (option == QImageIOHandler::Size) {
4167         /*
4168          * The image structure always starts at offset 0 in the XCF file.
4169          * byte[9]     "gimp xcf " File type identification
4170          * byte[4]     version     XCF version
4171          *                          "file": version 0
4172          *                          "v001": version 1
4173          *                          "v002": version 2
4174          *                          "v003": version 3
4175          * byte        0            Zero marks the end of the version tag.
4176          * uint32      width        Width of canvas
4177          * uint32      height       Height of canvas
4178          */
4179         if (auto d = device()) {
4180             // transactions works on both random and sequential devices
4181             d->startTransaction();
4182             auto ba9 = d->read(9);      // "gimp xcf "
4183             auto ba5 = d->read(4+1);    // version + null terminator
4184             auto ba = d->read(8);       // width and height
4185             d->rollbackTransaction();
4186             if (ba9 == QByteArray("gimp xcf ") && ba5.size() == 5) {
4187                 QDataStream ds(ba);
4188                 quint32 width;
4189                 ds >> width;
4190                 quint32 height;
4191                 ds >> height;
4192                 if (ds.status() == QDataStream::Ok)
4193                     v = QVariant::fromValue(QSize(width, height));
4194             }
4195         }
4196     }
4197 
4198     return v;
4199 }
4200 
4201 bool XCFHandler::canRead(QIODevice *device)
4202 {
4203     if (!device) {
4204         qCDebug(XCFPLUGIN) << "XCFHandler::canRead() called with no device";
4205         return false;
4206     }
4207     if (device->isSequential()) {
4208         return false;
4209     }
4210 
4211     const qint64 oldPos = device->pos();
4212     if (!device->isSequential()) {
4213         QDataStream ds(device);
4214         XCFImageFormat::XCFImage::Header header;
4215         bool failed = !XCFImageFormat::readXCFHeader(ds, &header);
4216         ds.setDevice(nullptr);
4217         device->seek(oldPos);
4218         if (failed) {
4219             return false;
4220         }
4221 
4222         switch (header.precision) {
4223         case XCFImageFormat::GIMP_PRECISION_HALF_LINEAR:
4224         case XCFImageFormat::GIMP_PRECISION_HALF_NON_LINEAR:
4225         case XCFImageFormat::GIMP_PRECISION_HALF_PERCEPTUAL:
4226         case XCFImageFormat::GIMP_PRECISION_FLOAT_LINEAR:
4227         case XCFImageFormat::GIMP_PRECISION_FLOAT_NON_LINEAR:
4228         case XCFImageFormat::GIMP_PRECISION_FLOAT_PERCEPTUAL:
4229         case XCFImageFormat::GIMP_PRECISION_U8_LINEAR:
4230         case XCFImageFormat::GIMP_PRECISION_U8_NON_LINEAR:
4231         case XCFImageFormat::GIMP_PRECISION_U8_PERCEPTUAL:
4232         case XCFImageFormat::GIMP_PRECISION_U16_LINEAR:
4233         case XCFImageFormat::GIMP_PRECISION_U16_NON_LINEAR:
4234         case XCFImageFormat::GIMP_PRECISION_U16_PERCEPTUAL:
4235         case XCFImageFormat::GIMP_PRECISION_U32_LINEAR:
4236         case XCFImageFormat::GIMP_PRECISION_U32_NON_LINEAR:
4237         case XCFImageFormat::GIMP_PRECISION_U32_PERCEPTUAL:
4238             break;
4239         case XCFImageFormat::GIMP_PRECISION_DOUBLE_LINEAR:
4240         case XCFImageFormat::GIMP_PRECISION_DOUBLE_NON_LINEAR:
4241         case XCFImageFormat::GIMP_PRECISION_DOUBLE_PERCEPTUAL:
4242         default:
4243             qCDebug(XCFPLUGIN) << "unsupported precision" << header.precision;
4244             return false;
4245         }
4246 
4247         return true;
4248     }
4249 
4250     char head[8];
4251     qint64 readBytes = device->read(head, sizeof(head));
4252     if (readBytes != sizeof(head)) {
4253         if (device->isSequential()) {
4254             while (readBytes > 0) {
4255                 device->ungetChar(head[readBytes-- - 1]);
4256             }
4257         } else {
4258             device->seek(oldPos);
4259         }
4260         return false;
4261     }
4262 
4263     if (device->isSequential()) {
4264         while (readBytes > 0) {
4265             device->ungetChar(head[readBytes-- - 1]);
4266         }
4267     } else {
4268         device->seek(oldPos);
4269     }
4270 
4271     return qstrncmp(head, "gimp xcf", 8) == 0;
4272 }
4273 
4274 QImageIOPlugin::Capabilities XCFPlugin::capabilities(QIODevice *device, const QByteArray &format) const
4275 {
4276     if (format == "xcf") {
4277         return Capabilities(CanRead);
4278     }
4279     if (!format.isEmpty()) {
4280         return {};
4281     }
4282     if (!device->isOpen()) {
4283         return {};
4284     }
4285 
4286     Capabilities cap;
4287     if (device->isReadable() && XCFHandler::canRead(device)) {
4288         cap |= CanRead;
4289     }
4290     return cap;
4291 }
4292 
4293 QImageIOHandler *XCFPlugin::create(QIODevice *device, const QByteArray &format) const
4294 {
4295     QImageIOHandler *handler = new XCFHandler;
4296     handler->setDevice(device);
4297     handler->setFormat(format);
4298     return handler;
4299 }
4300 
4301 // Just so I can get enum values printed
4302 #include "xcf.moc"
4303 
4304 #include "moc_xcf_p.cpp"