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