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