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