KImageFormats

xcf.cpp
1 /*
2  xcf.cpp: A Qt 5 plug-in for reading GIMP XCF image files
3  SPDX-FileCopyrightText: 2001 lignum Computing Inc. <[email protected]>
4  SPDX-FileCopyrightText: 2004 Melchior FRANZ <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.1-or-later
7 */
8 
9 #include "xcf_p.h"
10 
11 #include <QDebug>
12 #include <QIODevice>
13 #include <QImage>
14 #include <QLoggingCategory>
15 #include <QPainter>
16 #include <QStack>
17 #include <QVector>
18 #include <QtEndian>
19 #include <stdlib.h>
20 
21 #include <string.h>
22 
23 #include "gimp_p.h"
24 
25 Q_DECLARE_LOGGING_CATEGORY(XCFPLUGIN)
26 Q_LOGGING_CATEGORY(XCFPLUGIN, "kf.imageformats.plugins.xcf", QtWarningMsg)
27 
28 const float INCHESPERMETER = (100.0f / 2.54f);
29 
30 namespace
31 {
32 struct RandomTable {
33  // From glibc
34  static constexpr int rand_r(unsigned int *seed)
35  {
36  unsigned int next = *seed;
37  int result = 0;
38 
39  next *= 1103515245;
40  next += 12345;
41  result = (unsigned int)(next / 65536) % 2048;
42 
43  next *= 1103515245;
44  next += 12345;
45  result <<= 10;
46  result ^= (unsigned int)(next / 65536) % 1024;
47 
48  next *= 1103515245;
49  next += 12345;
50  result <<= 10;
51  result ^= (unsigned int)(next / 65536) % 1024;
52 
53  *seed = next;
54 
55  return result;
56  }
57 
58  constexpr RandomTable()
59  : values{}
60  {
61  unsigned int next = RANDOM_SEED;
62 
63  for (int i = 0; i < RANDOM_TABLE_SIZE; i++) {
64  values[i] = rand_r(&next);
65  }
66 
67  for (int i = 0; i < RANDOM_TABLE_SIZE; i++) {
68  int tmp{};
69  int swap = i + rand_r(&next) % (RANDOM_TABLE_SIZE - i);
70  tmp = values[i];
71  values[i] = values[swap];
72  values[swap] = tmp;
73  }
74  }
75 
76  int values[RANDOM_TABLE_SIZE]{};
77 };
78 } // namespace {
79 
80 /*!
81  * Each layer in an XCF file is stored as a matrix of
82  * 64-pixel by 64-pixel images. The GIMP has a sophisticated
83  * method of handling very large images as well as implementing
84  * parallel processing on a tile-by-tile basis. Here, though,
85  * we just read them in en-masse and store them in a matrix.
86  */
88 
89 class XCFImageFormat
90 {
91  Q_GADGET
92 public:
93  //! Properties which can be stored in an XCF file.
94  enum PropType {
95  PROP_END = 0,
96  PROP_COLORMAP = 1,
97  PROP_ACTIVE_LAYER = 2,
98  PROP_ACTIVE_CHANNEL = 3,
99  PROP_SELECTION = 4,
100  PROP_FLOATING_SELECTION = 5,
101  PROP_OPACITY = 6,
102  PROP_MODE = 7,
103  PROP_VISIBLE = 8,
104  PROP_LINKED = 9,
105  PROP_LOCK_ALPHA = 10,
106  PROP_APPLY_MASK = 11,
107  PROP_EDIT_MASK = 12,
108  PROP_SHOW_MASK = 13,
109  PROP_SHOW_MASKED = 14,
110  PROP_OFFSETS = 15,
111  PROP_COLOR = 16,
112  PROP_COMPRESSION = 17,
113  PROP_GUIDES = 18,
114  PROP_RESOLUTION = 19,
115  PROP_TATTOO = 20,
116  PROP_PARASITES = 21,
117  PROP_UNIT = 22,
118  PROP_PATHS = 23,
119  PROP_USER_UNIT = 24,
120  PROP_VECTORS = 25,
121  PROP_TEXT_LAYER_FLAGS = 26,
122  PROP_OLD_SAMPLE_POINTS = 27,
123  PROP_LOCK_CONTENT = 28,
124  PROP_GROUP_ITEM = 29,
125  PROP_ITEM_PATH = 30,
126  PROP_GROUP_ITEM_FLAGS = 31,
127  PROP_LOCK_POSITION = 32,
128  PROP_FLOAT_OPACITY = 33,
129  PROP_COLOR_TAG = 34,
130  PROP_COMPOSITE_MODE = 35,
131  PROP_COMPOSITE_SPACE = 36,
132  PROP_BLEND_SPACE = 37,
133  PROP_FLOAT_COLOR = 38,
134  PROP_SAMPLE_POINTS = 39,
135  MAX_SUPPORTED_PROPTYPE, // should always be at the end so its value is last + 1
136  };
137  Q_ENUM(PropType);
138 
139  //! Compression type used in layer tiles.
140  enum XcfCompressionType {
141  COMPRESS_INVALID = -1, /* our own */
142  COMPRESS_NONE = 0,
143  COMPRESS_RLE = 1,
144  COMPRESS_ZLIB = 2, /* unused */
145  COMPRESS_FRACTAL = 3, /* unused */
146  };
147  Q_ENUM(XcfCompressionType);
148 
149  enum LayerModeType {
150  GIMP_LAYER_MODE_NORMAL_LEGACY,
151  GIMP_LAYER_MODE_DISSOLVE,
152  GIMP_LAYER_MODE_BEHIND_LEGACY,
153  GIMP_LAYER_MODE_MULTIPLY_LEGACY,
154  GIMP_LAYER_MODE_SCREEN_LEGACY,
155  GIMP_LAYER_MODE_OVERLAY_LEGACY,
156  GIMP_LAYER_MODE_DIFFERENCE_LEGACY,
157  GIMP_LAYER_MODE_ADDITION_LEGACY,
158  GIMP_LAYER_MODE_SUBTRACT_LEGACY,
159  GIMP_LAYER_MODE_DARKEN_ONLY_LEGACY,
160  GIMP_LAYER_MODE_LIGHTEN_ONLY_LEGACY,
161  GIMP_LAYER_MODE_HSV_HUE_LEGACY,
162  GIMP_LAYER_MODE_HSV_SATURATION_LEGACY,
163  GIMP_LAYER_MODE_HSL_COLOR_LEGACY,
164  GIMP_LAYER_MODE_HSV_VALUE_LEGACY,
165  GIMP_LAYER_MODE_DIVIDE_LEGACY,
166  GIMP_LAYER_MODE_DODGE_LEGACY,
167  GIMP_LAYER_MODE_BURN_LEGACY,
168  GIMP_LAYER_MODE_HARDLIGHT_LEGACY,
169  GIMP_LAYER_MODE_SOFTLIGHT_LEGACY,
170  GIMP_LAYER_MODE_GRAIN_EXTRACT_LEGACY,
171  GIMP_LAYER_MODE_GRAIN_MERGE_LEGACY,
172  GIMP_LAYER_MODE_COLOR_ERASE_LEGACY,
173  GIMP_LAYER_MODE_OVERLAY,
174  GIMP_LAYER_MODE_LCH_HUE,
175  GIMP_LAYER_MODE_LCH_CHROMA,
176  GIMP_LAYER_MODE_LCH_COLOR,
177  GIMP_LAYER_MODE_LCH_LIGHTNESS,
178  GIMP_LAYER_MODE_NORMAL,
179  GIMP_LAYER_MODE_BEHIND,
180  GIMP_LAYER_MODE_MULTIPLY,
181  GIMP_LAYER_MODE_SCREEN,
182  GIMP_LAYER_MODE_DIFFERENCE,
183  GIMP_LAYER_MODE_ADDITION,
184  GIMP_LAYER_MODE_SUBTRACT,
185  GIMP_LAYER_MODE_DARKEN_ONLY,
186  GIMP_LAYER_MODE_LIGHTEN_ONLY,
187  GIMP_LAYER_MODE_HSV_HUE,
188  GIMP_LAYER_MODE_HSV_SATURATION,
189  GIMP_LAYER_MODE_HSL_COLOR,
190  GIMP_LAYER_MODE_HSV_VALUE,
191  GIMP_LAYER_MODE_DIVIDE,
192  GIMP_LAYER_MODE_DODGE,
193  GIMP_LAYER_MODE_BURN,
194  GIMP_LAYER_MODE_HARDLIGHT,
195  GIMP_LAYER_MODE_SOFTLIGHT,
196  GIMP_LAYER_MODE_GRAIN_EXTRACT,
197  GIMP_LAYER_MODE_GRAIN_MERGE,
198  GIMP_LAYER_MODE_VIVID_LIGHT,
199  GIMP_LAYER_MODE_PIN_LIGHT,
200  GIMP_LAYER_MODE_LINEAR_LIGHT,
201  GIMP_LAYER_MODE_HARD_MIX,
202  GIMP_LAYER_MODE_EXCLUSION,
203  GIMP_LAYER_MODE_LINEAR_BURN,
204  GIMP_LAYER_MODE_LUMA_DARKEN_ONLY,
205  GIMP_LAYER_MODE_LUMA_LIGHTEN_ONLY,
206  GIMP_LAYER_MODE_LUMINANCE,
207  GIMP_LAYER_MODE_COLOR_ERASE,
208  GIMP_LAYER_MODE_ERASE,
209  GIMP_LAYER_MODE_MERGE,
210  GIMP_LAYER_MODE_SPLIT,
211  GIMP_LAYER_MODE_PASS_THROUGH,
212  GIMP_LAYER_MODE_COUNT,
213  };
214  Q_ENUM(LayerModeType);
215 
216  //! Type of individual layers in an XCF file.
217  enum GimpImageType {
218  RGB_GIMAGE,
219  RGBA_GIMAGE,
220  GRAY_GIMAGE,
221  GRAYA_GIMAGE,
222  INDEXED_GIMAGE,
223  INDEXEDA_GIMAGE,
224  };
225  Q_ENUM(GimpImageType);
226 
227  //! Type of individual layers in an XCF file.
228  enum GimpColorSpace {
229  RgbLinearSpace,
230  RgbPerceptualSpace,
231  LabSpace,
232  };
233 
234  //! Mode to use when compositing layer
235  enum GimpCompositeMode {
236  CompositeOver,
237  CompositeUnion,
238  CompositeClipBackdrop,
239  CompositeClipLayer,
240  CompositeIntersect,
241  };
242 
243  XCFImageFormat();
244  bool readXCF(QIODevice *device, QImage *image);
245 
246 private:
247  /*!
248  * Each GIMP image is composed of one or more layers. A layer can
249  * be one of any three basic types: RGB, grayscale or indexed. With an
250  * optional alpha channel, there are six possible types altogether.
251  *
252  * Note: there is only ever one instance of this structure. The
253  * layer info is discarded after it is merged into the final QImage.
254  */
255  class Layer
256  {
257  public:
258  quint32 width; //!< Width of the layer
259  quint32 height; //!< Height of the layer
260  qint32 type; //!< Type of the layer (GimpImageType)
261  char *name; //!< Name of the layer
262  qint64 hierarchy_offset; //!< File position of Tile hierarchy
263  qint64 mask_offset; //!< File position of mask image
264 
265  uint nrows; //!< Number of rows of tiles (y direction)
266  uint ncols; //!< Number of columns of tiles (x direction)
267 
268  Tiles image_tiles; //!< The basic image
269  //! For Grayscale and Indexed images, the alpha channel is stored
270  //! separately (in this data structure, anyway).
271  Tiles alpha_tiles;
272  Tiles mask_tiles; //!< The layer mask (optional)
273 
274  //! Additional information about a layer mask.
275  struct {
276  quint32 opacity;
277  float opacityFloat = 1.f;
278  quint32 visible;
279  quint32 show_masked;
280  uchar red, green, blue;
281  float redF, greenF, blueF; // Floats should override
282  quint32 tattoo;
283  } mask_channel;
284 
285  XcfCompressionType compression = COMPRESS_INVALID; //!< tile compression method (CompressionType)
286 
287  bool active; //!< Is this layer the active layer?
288  quint32 opacity = 255; //!< The opacity of the layer
289  float opacityFloat = 1.f; //!< The opacity of the layer, but floating point (both are set)
290  quint32 visible = 1; //!< Is the layer visible?
291  quint32 linked; //!< Is this layer linked (geometrically)
292  quint32 preserve_transparency; //!< Preserve alpha when drawing on layer?
293  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
294  //!< mask, it defaults to true (1).
295  // Robust readers should force this to false if the layer has no layer mask.
296  quint32 edit_mask; //!< Is the layer mask the being edited?
297  quint32 show_mask; //!< Show the layer mask rather than the image?
298  qint32 x_offset = 0; //!< x offset of the layer relative to the image
299  qint32 y_offset = 0; //!< y offset of the layer relative to the image
300  quint32 mode = 0; //!< Combining mode of layer (LayerModeEffects)
301  quint32 tattoo; //!< (unique identifier?)
302  qint32 blendSpace = 0; //!< What colorspace to use when blending
303  qint32 compositeSpace = 0; //!< What colorspace to use when compositing
304  qint32 compositeMode = 0; //!< How to composite layer (union, clip, etc.)
305 
306  //! As each tile is read from the file, it is buffered here.
307  uchar tile[TILE_WIDTH * TILE_HEIGHT * sizeof(QRgb)];
308 
309  //! The data from tile buffer is copied to the Tile by this
310  //! method. Depending on the type of the tile (RGB, Grayscale,
311  //! Indexed) and use (image or mask), the bytes in the buffer are
312  //! copied in different ways.
313  void (*assignBytes)(Layer &layer, uint i, uint j);
314 
315  Layer(void)
316  : name(nullptr)
317  {
318  }
319  ~Layer(void)
320  {
321  delete[] name;
322  }
323 
324  Layer(const Layer &) = delete;
325  Layer &operator=(const Layer &) = delete;
326  };
327 
328  /*!
329  * The in-memory representation of the XCF Image. It contains a few
330  * metadata items, but is mostly a container for the layer information.
331  */
332  class XCFImage
333  {
334  public:
335  qint32 precision = 0;
336  quint32 width; //!< width of the XCF image
337  quint32 height; //!< height of the XCF image
338  qint32 type; //!< type of the XCF image (GimpImageBaseType)
339 
340  quint8 compression = COMPRESS_RLE; //!< tile compression method (CompressionType)
341  float x_resolution = -1; //!< x resolution in dots per inch
342  float y_resolution = -1; //!< y resolution in dots per inch
343  qint32 tattoo; //!< (unique identifier?)
344  quint32 unit; //!< Units of The GIMP (inch, mm, pica, etc...)
345  qint32 num_colors = 0; //!< number of colors in an indexed image
346  QVector<QRgb> palette; //!< indexed image color palette
347 
348  int num_layers; //!< number of layers
349  Layer layer; //!< most recently read layer
350 
351  bool initialized; //!< Is the QImage initialized?
352  QImage image; //!< final QImage
353 
354  XCFImage(void)
355  : initialized(false)
356  {
357  }
358  };
359 
360  static qint64 readOffsetPtr(QDataStream &stream)
361  {
362  if (stream.version() >= 11) {
363  qint64 ret;
364  stream >> ret;
365  return ret;
366  } else {
367  quint32 ret;
368  stream >> ret;
369  return ret;
370  }
371  }
372 
373  //! In layer DISSOLVE mode, a random number is chosen to compare to a
374  //! pixel's alpha. If the alpha is greater than the random number, the
375  //! pixel is drawn. This table merely contains the random number seeds
376  //! for each ROW of an image. Therefore, the random numbers chosen
377  //! are consistent from run to run.
378  static int random_table[RANDOM_TABLE_SIZE];
379  static bool random_table_initialized;
380 
381  static constexpr RandomTable randomTable{};
382 
383  //! This table is used as a shared grayscale ramp to be set on grayscale
384  //! images. This is because Qt does not differentiate between indexed and
385  //! grayscale images.
386  static QVector<QRgb> grayTable;
387 
388  //! This table provides the add_pixel saturation values (i.e. 250 + 250 = 255).
389  // static int add_lut[256][256]; - this is so lame waste of 256k of memory
390  static int add_lut(int, int);
391 
392  //! The bottom-most layer is copied into the final QImage by this
393  //! routine.
394  typedef void (*PixelCopyOperation)(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
395 
396  //! Higher layers are merged into the final QImage by this routine.
397  typedef void (*PixelMergeOperation)(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
398 
399  static bool modeAffectsSourceAlpha(const quint32 type);
400 
401  bool loadImageProperties(QDataStream &xcf_io, XCFImage &image);
402  bool loadProperty(QDataStream &xcf_io, PropType &type, QByteArray &bytes, quint32 &rawType);
403  bool loadLayer(QDataStream &xcf_io, XCFImage &xcf_image);
404  bool loadLayerProperties(QDataStream &xcf_io, Layer &layer);
405  bool composeTiles(XCFImage &xcf_image);
406  void setGrayPalette(QImage &image);
407  void setPalette(XCFImage &xcf_image, QImage &image);
408  static void assignImageBytes(Layer &layer, uint i, uint j);
409  bool loadHierarchy(QDataStream &xcf_io, Layer &layer);
410  bool loadLevel(QDataStream &xcf_io, Layer &layer, qint32 bpp);
411  static void assignMaskBytes(Layer &layer, uint i, uint j);
412  bool loadMask(QDataStream &xcf_io, Layer &layer);
413  bool loadChannelProperties(QDataStream &xcf_io, Layer &layer);
414  bool initializeImage(XCFImage &xcf_image);
415  bool loadTileRLE(QDataStream &xcf_io, uchar *tile, int size, int data_length, qint32 bpp);
416 
417  static void copyLayerToImage(XCFImage &xcf_image);
418  static void copyRGBToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
419  static void copyGrayToGray(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
420  static void copyGrayToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
421  static void copyGrayAToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
422  static void copyIndexedToIndexed(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
423  static void copyIndexedAToIndexed(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
424  static void copyIndexedAToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
425 
426  static void mergeLayerIntoImage(XCFImage &xcf_image);
427  static void mergeRGBToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
428  static void mergeGrayToGray(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
429  static void mergeGrayAToGray(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
430  static void mergeGrayToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
431  static void mergeGrayAToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
432  static void mergeIndexedToIndexed(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
433  static void mergeIndexedAToIndexed(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
434  static void mergeIndexedAToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n);
435 
436  static void initializeRandomTable();
437  static void dissolveRGBPixels(QImage &image, int x, int y);
438  static void dissolveAlphaPixels(QImage &image, int x, int y);
439 };
440 
441 int XCFImageFormat::random_table[RANDOM_TABLE_SIZE];
442 bool XCFImageFormat::random_table_initialized;
443 
444 constexpr RandomTable XCFImageFormat::randomTable;
445 
446 QVector<QRgb> XCFImageFormat::grayTable;
447 
448 bool XCFImageFormat::modeAffectsSourceAlpha(const quint32 type)
449 {
450  switch (type) {
451  case GIMP_LAYER_MODE_NORMAL_LEGACY:
452  case GIMP_LAYER_MODE_DISSOLVE:
453  case GIMP_LAYER_MODE_BEHIND_LEGACY:
454  return true;
455 
456  case GIMP_LAYER_MODE_MULTIPLY_LEGACY:
457  case GIMP_LAYER_MODE_SCREEN_LEGACY:
458  case GIMP_LAYER_MODE_OVERLAY_LEGACY:
459  case GIMP_LAYER_MODE_DIFFERENCE_LEGACY:
460  case GIMP_LAYER_MODE_ADDITION_LEGACY:
461  case GIMP_LAYER_MODE_SUBTRACT_LEGACY:
462  case GIMP_LAYER_MODE_DARKEN_ONLY_LEGACY:
463  case GIMP_LAYER_MODE_LIGHTEN_ONLY_LEGACY:
464  case GIMP_LAYER_MODE_HSV_HUE_LEGACY:
465  case GIMP_LAYER_MODE_HSV_SATURATION_LEGACY:
466  case GIMP_LAYER_MODE_HSL_COLOR_LEGACY:
467  case GIMP_LAYER_MODE_HSV_VALUE_LEGACY:
468  case GIMP_LAYER_MODE_DIVIDE_LEGACY:
469  case GIMP_LAYER_MODE_DODGE_LEGACY:
470  case GIMP_LAYER_MODE_BURN_LEGACY:
471  case GIMP_LAYER_MODE_HARDLIGHT_LEGACY:
472  case GIMP_LAYER_MODE_SOFTLIGHT_LEGACY:
473  case GIMP_LAYER_MODE_GRAIN_EXTRACT_LEGACY:
474  case GIMP_LAYER_MODE_GRAIN_MERGE_LEGACY:
475  return false;
476 
477  case GIMP_LAYER_MODE_COLOR_ERASE_LEGACY:
478  case GIMP_LAYER_MODE_OVERLAY:
479  case GIMP_LAYER_MODE_LCH_HUE:
480  case GIMP_LAYER_MODE_LCH_CHROMA:
481  case GIMP_LAYER_MODE_LCH_COLOR:
482  case GIMP_LAYER_MODE_LCH_LIGHTNESS:
483  return false;
484 
485  case GIMP_LAYER_MODE_NORMAL:
486  return true;
487 
488  case GIMP_LAYER_MODE_BEHIND:
489  case GIMP_LAYER_MODE_MULTIPLY:
490  case GIMP_LAYER_MODE_SCREEN:
491  case GIMP_LAYER_MODE_DIFFERENCE:
492  case GIMP_LAYER_MODE_ADDITION:
493  case GIMP_LAYER_MODE_SUBTRACT:
494  case GIMP_LAYER_MODE_DARKEN_ONLY:
495  case GIMP_LAYER_MODE_LIGHTEN_ONLY:
496  case GIMP_LAYER_MODE_HSV_HUE:
497  case GIMP_LAYER_MODE_HSV_SATURATION:
498  case GIMP_LAYER_MODE_HSL_COLOR:
499  case GIMP_LAYER_MODE_HSV_VALUE:
500  case GIMP_LAYER_MODE_DIVIDE:
501  case GIMP_LAYER_MODE_DODGE:
502  case GIMP_LAYER_MODE_BURN:
503  case GIMP_LAYER_MODE_HARDLIGHT:
504  case GIMP_LAYER_MODE_SOFTLIGHT:
505  case GIMP_LAYER_MODE_GRAIN_EXTRACT:
506  case GIMP_LAYER_MODE_GRAIN_MERGE:
507  case GIMP_LAYER_MODE_VIVID_LIGHT:
508  case GIMP_LAYER_MODE_PIN_LIGHT:
509  case GIMP_LAYER_MODE_LINEAR_LIGHT:
510  case GIMP_LAYER_MODE_HARD_MIX:
511  case GIMP_LAYER_MODE_EXCLUSION:
512  case GIMP_LAYER_MODE_LINEAR_BURN:
513  case GIMP_LAYER_MODE_LUMA_DARKEN_ONLY:
514  case GIMP_LAYER_MODE_LUMA_LIGHTEN_ONLY:
515  case GIMP_LAYER_MODE_LUMINANCE:
516  case GIMP_LAYER_MODE_COLOR_ERASE:
517  case GIMP_LAYER_MODE_ERASE:
518  case GIMP_LAYER_MODE_MERGE:
519  case GIMP_LAYER_MODE_SPLIT:
520  case GIMP_LAYER_MODE_PASS_THROUGH:
521  return false;
522 
523  default:
524  qCWarning(XCFPLUGIN) << "Unhandled layer mode" << XCFImageFormat::LayerModeType(type);
525  return false;
526  }
527 }
528 
529 //! Change a QRgb value's alpha only.
530 inline QRgb qRgba(const QRgb rgb, int a)
531 {
532  return ((a & 0xff) << 24 | (rgb & RGB_MASK));
533 }
534 
535 /*!
536  * The constructor for the XCF image loader.
537  */
538 XCFImageFormat::XCFImageFormat()
539 {
540  static_assert(sizeof(QRgb) == 4, "the code assumes sizeof(QRgb) == 4, if that's not your case, help us fix it :)");
541 }
542 
543 /*!
544  * This initializes the tables used in the layer dissolving routines.
545  */
546 void XCFImageFormat::initializeRandomTable()
547 {
548  // From GIMP "paint_funcs.c" v1.2
549  srand(RANDOM_SEED);
550 
551  for (int i = 0; i < RANDOM_TABLE_SIZE; i++) {
552  random_table[i] = rand();
553  }
554 
555  for (int i = 0; i < RANDOM_TABLE_SIZE; i++) {
556  int tmp;
557  int swap = i + rand() % (RANDOM_TABLE_SIZE - i);
558  tmp = random_table[i];
559  random_table[i] = random_table[swap];
560  random_table[swap] = tmp;
561  }
562 }
563 
564 inline int XCFImageFormat::add_lut(int a, int b)
565 {
566  return qMin(a + b, 255);
567 }
568 
569 bool XCFImageFormat::readXCF(QIODevice *device, QImage *outImage)
570 {
571  XCFImage xcf_image;
572  QDataStream xcf_io(device);
573 
574  QByteArray tag(14, '\0');
575 
576  if (xcf_io.readRawData(tag.data(), tag.size()) != tag.size()) {
577  qCDebug(XCFPLUGIN) << "XCF: read failure on header tag";
578  return false;
579  }
580  if (!tag.startsWith("gimp xcf") || !tag.endsWith('\0')) {
581  qCDebug(XCFPLUGIN) << "XCF: read called on non-XCF file";
582  return false;
583  }
584 
585  // Remove null terminator
586  tag.chop(1);
587 
588  if (tag.right(4) == "file") {
589  xcf_io.setVersion(0);
590  } else {
591  // Version 1 and onwards use the format "gimp xcf v###" instead of "gimp xcf file"
592  bool ok;
593  xcf_io.setVersion(tag.right(3).toInt(&ok));
594  if (!ok) {
595  qCDebug(XCFPLUGIN) << "Failed to parse version" << tag;
596  return false;
597  }
598  }
599  qCDebug(XCFPLUGIN) << "version" << xcf_io.version();
600 
601  if (xcf_io.version() > 11) {
602  qCDebug(XCFPLUGIN) << "Unsupported version" << xcf_io.version();
603  return false;
604  }
605 
606  xcf_io >> xcf_image.width >> xcf_image.height >> xcf_image.type;
607 
608  if (xcf_io.version() >= 4) {
609  xcf_io >> xcf_image.precision;
610  qCDebug(XCFPLUGIN) << "Precision" << xcf_image.precision;
611  if (xcf_io.version() < 7) {
612  qCDebug(XCFPLUGIN) << "Conversion of image precision not supported";
613  }
614  }
615 
616  qCDebug(XCFPLUGIN) << tag << " " << xcf_image.width << " " << xcf_image.height << " " << xcf_image.type;
617  if (!loadImageProperties(xcf_io, xcf_image)) {
618  return false;
619  }
620 
621  // The layers appear to be stored in top-to-bottom order. This is
622  // the reverse of how a merged image must be computed. So, the layer
623  // offsets are pushed onto a LIFO stack (thus, we don't have to load
624  // all the data of all layers before beginning to construct the
625  // merged image).
626 
627  QStack<qint64> layer_offsets;
628 
629  while (true) {
630  const qint64 layer_offset = readOffsetPtr(xcf_io);
631 
632  if (layer_offset == 0) {
633  break;
634  }
635 
636  if (layer_offset < 0) {
637  qCDebug(XCFPLUGIN) << "XCF: negative layer offset";
638  return false;
639  }
640 
641  layer_offsets.push(layer_offset);
642  }
643 
644  xcf_image.num_layers = layer_offsets.size();
645 
646  if (layer_offsets.size() == 0) {
647  qCDebug(XCFPLUGIN) << "XCF: no layers!";
648  return false;
649  }
650  qCDebug(XCFPLUGIN) << xcf_image.num_layers << "layers";
651 
652  // Load each layer and add it to the image
653  while (!layer_offsets.isEmpty()) {
654  qint64 layer_offset = layer_offsets.pop();
655 
656  xcf_io.device()->seek(layer_offset);
657 
658  if (!loadLayer(xcf_io, xcf_image)) {
659  return false;
660  }
661  }
662 
663  if (!xcf_image.initialized) {
664  qCDebug(XCFPLUGIN) << "XCF: no visible layers!";
665  return false;
666  }
667 
668  *outImage = xcf_image.image;
669  return true;
670 }
671 
672 /*!
673  * An XCF file can contain an arbitrary number of properties associated
674  * with the image (and layer and mask).
675  * \param xcf_io the data stream connected to the XCF image
676  * \param xcf_image XCF image data.
677  * \return true if there were no I/O errors.
678  */
679 bool XCFImageFormat::loadImageProperties(QDataStream &xcf_io, XCFImage &xcf_image)
680 {
681  while (true) {
682  PropType type;
683  QByteArray bytes;
684  quint32 rawType;
685 
686  if (!loadProperty(xcf_io, type, bytes, rawType)) {
687  qCDebug(XCFPLUGIN) << "XCF: error loading global image properties";
688  return false;
689  }
690 
691  QDataStream property(bytes);
692 
693  switch (type) {
694  case PROP_END:
695  return true;
696 
697  case PROP_COMPRESSION:
698  property >> xcf_image.compression;
699  break;
700 
701  case PROP_RESOLUTION:
702  property.setFloatingPointPrecision(QDataStream::SinglePrecision);
703  property >> xcf_image.x_resolution >> xcf_image.y_resolution;
704  break;
705 
706  case PROP_TATTOO:
707  property >> xcf_image.tattoo;
708  break;
709 
710  case PROP_PARASITES:
711  while (!property.atEnd()) {
712  char *tag;
713  quint32 size;
714 
715  property.readBytes(tag, size);
716 
717  quint32 flags;
718  char *data = nullptr;
719  property >> flags >> data;
720 
721  if (tag && strncmp(tag, "gimp-comment", strlen("gimp-comment")) == 0) {
722  xcf_image.image.setText(QStringLiteral("Comment"), QString::fromUtf8(data));
723  }
724 
725  delete[] tag;
726  delete[] data;
727  }
728  break;
729 
730  case PROP_UNIT:
731  property >> xcf_image.unit;
732  break;
733 
734  case PROP_PATHS: // This property is ignored.
735  break;
736 
737  case PROP_USER_UNIT: // This property is ignored.
738  break;
739 
740  case PROP_COLORMAP:
741  property >> xcf_image.num_colors;
742  if (xcf_image.num_colors < 0 || xcf_image.num_colors > 65535) {
743  return false;
744  }
745 
746  xcf_image.palette = QVector<QRgb>();
747  xcf_image.palette.reserve(xcf_image.num_colors);
748 
749  for (int i = 0; i < xcf_image.num_colors; i++) {
750  uchar r;
751  uchar g;
752  uchar b;
753  property >> r >> g >> b;
754  xcf_image.palette.push_back(qRgb(r, g, b));
755  }
756  break;
757 
758  default:
759  qCDebug(XCFPLUGIN) << "XCF: unimplemented image property" << type << "(" << rawType << ")"
760  << ", size " << bytes.size();
761  break;
762  }
763  }
764 }
765 
766 /*!
767  * Read a single property from the image file. The property type is returned
768  * in type and the data is returned in bytes.
769  * \param xcf the image file data stream.
770  * \param type returns with the property type.
771  * \param bytes returns with the property data.
772  * \return true if there were no IO errors. */
773 bool XCFImageFormat::loadProperty(QDataStream &xcf_io, PropType &type, QByteArray &bytes, quint32 &rawType)
774 {
775  quint32 size;
776 
777  xcf_io >> rawType;
778  if (rawType >= MAX_SUPPORTED_PROPTYPE) {
779  type = MAX_SUPPORTED_PROPTYPE;
780  // we don't support the property, but we still need to read from the device, assume it's like all the
781  // non custom properties that is data_length + data
782  xcf_io >> size;
783  xcf_io.skipRawData(size);
784  // return true because we don't really want to totally fail on an unsupported property since it may not be fatal
785  return true;
786  }
787 
788  type = PropType(rawType);
789 
790  char *data = nullptr;
791 
792  // The colormap property size is not the correct number of bytes:
793  // The GIMP source xcf.c has size = 4 + ncolors, but it should be
794  // 4 + 3 * ncolors
795 
796  if (type == PROP_COLORMAP) {
797  xcf_io >> size;
798  quint32 ncolors;
799  xcf_io >> ncolors;
800 
801  size = 3 * ncolors + 4;
802 
803  if (size > 65535 || size < 4) {
804  return false;
805  }
806 
807  data = new char[size];
808 
809  // since we already read "ncolors" from the stream, we put that data back
810  data[0] = 0;
811  data[1] = 0;
812  data[2] = ncolors >> 8;
813  data[3] = ncolors & 255;
814 
815  // ... and read the remaining bytes from the stream
816  xcf_io.readRawData(data + 4, size - 4);
817  } else if (type == PROP_USER_UNIT) {
818  // The USER UNIT property size is not correct. I'm not sure why, though.
819  float factor;
820  qint32 digits;
821 
822  xcf_io >> size >> factor >> digits;
823 
824  for (int i = 0; i < 5; i++) {
825  char *unit_strings;
826 
827  xcf_io >> unit_strings;
828 
829  delete[] unit_strings;
830 
831  if (xcf_io.device()->atEnd()) {
832  qCDebug(XCFPLUGIN) << "XCF: read failure on property " << type;
833  return false;
834  }
835  }
836 
837  size = 0;
838  } else {
839  xcf_io >> size;
840  if (size > 256000) {
841  return false;
842  }
843  data = new char[size];
844  const quint32 dataRead = xcf_io.readRawData(data, size);
845  if (dataRead < size) {
846  qCDebug(XCFPLUGIN) << "XCF: loadProperty read less data than expected" << size << dataRead;
847  memset(&data[dataRead], 0, size - dataRead);
848  }
849  }
850 
851  if (size != 0 && data) {
852  bytes = QByteArray(data, size);
853  }
854 
855  delete[] data;
856 
857  return true;
858 }
859 
860 /*!
861  * Load a layer from the XCF file. The data stream must be positioned at
862  * the beginning of the layer data.
863  * \param xcf_io the image file data stream.
864  * \param xcf_image contains the layer and the color table
865  * (if the image is indexed).
866  * \return true if there were no I/O errors.
867  */
868 bool XCFImageFormat::loadLayer(QDataStream &xcf_io, XCFImage &xcf_image)
869 {
870  Layer &layer(xcf_image.layer);
871  delete[] layer.name;
872 
873  xcf_io >> layer.width >> layer.height >> layer.type >> layer.name;
874 
875  // Don't want to keep passing this around, dumb XCF format
876  layer.compression = XcfCompressionType(xcf_image.compression);
877 
878  if (!loadLayerProperties(xcf_io, layer)) {
879  return false;
880  }
881 
882  qCDebug(XCFPLUGIN) << "layer: \"" << layer.name << "\", size: " << layer.width << " x " << layer.height << ", type: " << GimpImageType(layer.type)
883  << ", mode: " << layer.mode << ", opacity: " << layer.opacity << ", visible: " << layer.visible << ", offset: " << layer.x_offset << ", "
884  << layer.y_offset;
885 
886  // Skip reading the rest of it if it is not visible. Typically, when
887  // you export an image from the The GIMP it flattens (or merges) only
888  // the visible layers into the output image.
889 
890  if (layer.visible == 0) {
891  return true;
892  }
893 
894  // If there are any more layers, merge them into the final QImage.
895 
896  layer.hierarchy_offset = readOffsetPtr(xcf_io);
897  layer.mask_offset = readOffsetPtr(xcf_io);
898 
899  if (layer.hierarchy_offset < 0) {
900  qCDebug(XCFPLUGIN) << "XCF: negative layer hierarchy_offset";
901  return false;
902  }
903 
904  if (layer.mask_offset < 0) {
905  qCDebug(XCFPLUGIN) << "XCF: negative layer mask_offset";
906  return false;
907  }
908 
909  // Allocate the individual tile QImages based on the size and type
910  // of this layer.
911 
912  if (!composeTiles(xcf_image)) {
913  return false;
914  }
915  xcf_io.device()->seek(layer.hierarchy_offset);
916 
917  // As tiles are loaded, they are copied into the layers tiles by
918  // this routine. (loadMask(), below, uses a slightly different
919  // version of assignBytes().)
920 
921  layer.assignBytes = assignImageBytes;
922 
923  if (!loadHierarchy(xcf_io, layer)) {
924  return false;
925  }
926 
927  if (layer.mask_offset != 0) {
928  // 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).
929  if (layer.apply_mask == 9) {
930  layer.apply_mask = 1;
931  }
932 
933  xcf_io.device()->seek(layer.mask_offset);
934 
935  if (!loadMask(xcf_io, layer)) {
936  return false;
937  }
938  } else {
939  // Spec says "Robust readers should force this to false if the layer has no layer mask."
940  layer.apply_mask = 0;
941  }
942 
943  // Now we should have enough information to initialize the final
944  // QImage. The first visible layer determines the attributes
945  // of the QImage.
946 
947  if (!xcf_image.initialized) {
948  if (!initializeImage(xcf_image)) {
949  return false;
950  }
951  copyLayerToImage(xcf_image);
952  xcf_image.initialized = true;
953  } else {
954  mergeLayerIntoImage(xcf_image);
955  }
956 
957  return true;
958 }
959 
960 /*!
961  * An XCF file can contain an arbitrary number of properties associated
962  * with a layer.
963  * \param xcf_io the data stream connected to the XCF image.
964  * \param layer layer to collect the properties.
965  * \return true if there were no I/O errors.
966  */
967 bool XCFImageFormat::loadLayerProperties(QDataStream &xcf_io, Layer &layer)
968 {
969  while (true) {
970  PropType type;
971  QByteArray bytes;
972  quint32 rawType;
973 
974  if (!loadProperty(xcf_io, type, bytes, rawType)) {
975  qCDebug(XCFPLUGIN) << "XCF: error loading layer properties";
976  return false;
977  }
978 
979  QDataStream property(bytes);
980 
981  switch (type) {
982  case PROP_END:
983  return true;
984 
985  case PROP_ACTIVE_LAYER:
986  layer.active = true;
987  break;
988 
989  case PROP_OPACITY:
990  property >> layer.opacity;
991  layer.opacity = std::min(layer.opacity, 255u);
992  break;
993 
994  case PROP_FLOAT_OPACITY:
995  // For some reason QDataStream isn't able to read the float (tried
996  // setting the endianness manually)
997  if (bytes.size() == 4) {
998  layer.opacityFloat = qFromBigEndian(*reinterpret_cast<float *>(bytes.data()));
999  } else {
1000  qCDebug(XCFPLUGIN) << "XCF: Invalid data size for float:" << bytes.size();
1001  }
1002  break;
1003 
1004  case PROP_VISIBLE:
1005  property >> layer.visible;
1006  break;
1007 
1008  case PROP_LINKED:
1009  property >> layer.linked;
1010  break;
1011 
1012  case PROP_LOCK_ALPHA:
1013  property >> layer.preserve_transparency;
1014  break;
1015 
1016  case PROP_APPLY_MASK:
1017  property >> layer.apply_mask;
1018  break;
1019 
1020  case PROP_EDIT_MASK:
1021  property >> layer.edit_mask;
1022  break;
1023 
1024  case PROP_SHOW_MASK:
1025  property >> layer.show_mask;
1026  break;
1027 
1028  case PROP_OFFSETS:
1029  property >> layer.x_offset >> layer.y_offset;
1030  break;
1031 
1032  case PROP_MODE:
1033  property >> layer.mode;
1034  if (layer.mode >= GIMP_LAYER_MODE_COUNT) {
1035  qCDebug(XCFPLUGIN) << "Found layer with unsupported mode" << LayerModeType(layer.mode) << "Defaulting to mode 0";
1036  layer.mode = 0;
1037  }
1038  break;
1039 
1040  case PROP_TATTOO:
1041  property >> layer.tattoo;
1042  break;
1043 
1044  case PROP_COMPOSITE_SPACE:
1045  property >> layer.compositeSpace;
1046  break;
1047 
1048  case PROP_COMPOSITE_MODE:
1049  property >> layer.compositeMode;
1050  break;
1051 
1052  case PROP_BLEND_SPACE:
1053  property >> layer.blendSpace;
1054  break;
1055 
1056  // Just for organization in the UI, doesn't influence rendering
1057  case PROP_COLOR_TAG:
1058  break;
1059 
1060  // We don't support editing, so for now just ignore locking
1061  case PROP_LOCK_CONTENT:
1062  case PROP_LOCK_POSITION:
1063  break;
1064 
1065  default:
1066  qCDebug(XCFPLUGIN) << "XCF: unimplemented layer property " << type << "(" << rawType << ")"
1067  << ", size " << bytes.size();
1068  break;
1069  }
1070  }
1071 }
1072 
1073 /*!
1074  * Compute the number of tiles in the current layer and allocate
1075  * QImage structures for each of them.
1076  * \param xcf_image contains the current layer.
1077  */
1078 bool XCFImageFormat::composeTiles(XCFImage &xcf_image)
1079 {
1080  Layer &layer(xcf_image.layer);
1081 
1082  layer.nrows = (layer.height + TILE_HEIGHT - 1) / TILE_HEIGHT;
1083  layer.ncols = (layer.width + TILE_WIDTH - 1) / TILE_WIDTH;
1084 
1085  qCDebug(XCFPLUGIN) << "IMAGE: height=" << xcf_image.height << ", width=" << xcf_image.width;
1086  qCDebug(XCFPLUGIN) << "LAYER: height=" << layer.height << ", width=" << layer.width;
1087  qCDebug(XCFPLUGIN) << "LAYER: rows=" << layer.nrows << ", columns=" << layer.ncols;
1088 
1089  // SANITY CHECK: Catch corrupted XCF image file where the width or height
1090  // of a tile is reported are bogus. See Bug# 234030.
1091  if (layer.width > 32767 || layer.height > 32767 || (sizeof(void *) == 4 && layer.width * layer.height > 16384 * 16384)) {
1092  return false;
1093  }
1094 
1095  layer.image_tiles.resize(layer.nrows);
1096 
1097  if (layer.type == GRAYA_GIMAGE || layer.type == INDEXEDA_GIMAGE) {
1098  layer.alpha_tiles.resize(layer.nrows);
1099  }
1100 
1101  if (layer.mask_offset != 0) {
1102  layer.mask_tiles.resize(layer.nrows);
1103  }
1104 
1105  for (uint j = 0; j < layer.nrows; j++) {
1106  layer.image_tiles[j].resize(layer.ncols);
1107 
1108  if (layer.type == GRAYA_GIMAGE || layer.type == INDEXEDA_GIMAGE) {
1109  layer.alpha_tiles[j].resize(layer.ncols);
1110  }
1111 
1112  if (layer.mask_offset != 0) {
1113  layer.mask_tiles[j].resize(layer.ncols);
1114  }
1115  }
1116 
1117  for (uint j = 0; j < layer.nrows; j++) {
1118  for (uint i = 0; i < layer.ncols; i++) {
1119  uint tile_width = (i + 1) * TILE_WIDTH <= layer.width ? TILE_WIDTH : layer.width - i * TILE_WIDTH;
1120 
1121  uint tile_height = (j + 1) * TILE_HEIGHT <= layer.height ? TILE_HEIGHT : layer.height - j * TILE_HEIGHT;
1122 
1123  // Try to create the most appropriate QImage (each GIMP layer
1124  // type is treated slightly differently)
1125 
1126  switch (layer.type) {
1127  case RGB_GIMAGE:
1128  layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_RGB32);
1129  layer.image_tiles[j][i].setColorCount(0);
1130  if (layer.image_tiles[j][i].isNull()) {
1131  return false;
1132  }
1133  break;
1134 
1135  case RGBA_GIMAGE:
1136  layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_ARGB32);
1137  layer.image_tiles[j][i].setColorCount(0);
1138  if (layer.image_tiles[j][i].isNull()) {
1139  return false;
1140  }
1141  break;
1142 
1143  case GRAY_GIMAGE:
1144  layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
1145  layer.image_tiles[j][i].setColorCount(256);
1146  if (layer.image_tiles[j][i].isNull()) {
1147  return false;
1148  }
1149  setGrayPalette(layer.image_tiles[j][i]);
1150  break;
1151 
1152  case GRAYA_GIMAGE:
1153  layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
1154  layer.image_tiles[j][i].setColorCount(256);
1155  if (layer.image_tiles[j][i].isNull()) {
1156  return false;
1157  }
1158  setGrayPalette(layer.image_tiles[j][i]);
1159 
1160  layer.alpha_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
1161  layer.alpha_tiles[j][i].setColorCount(256);
1162  if (layer.alpha_tiles[j][i].isNull()) {
1163  return false;
1164  }
1165  setGrayPalette(layer.alpha_tiles[j][i]);
1166  break;
1167 
1168  case INDEXED_GIMAGE:
1169  layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
1170  layer.image_tiles[j][i].setColorCount(xcf_image.num_colors);
1171  if (layer.image_tiles[j][i].isNull()) {
1172  return false;
1173  }
1174  setPalette(xcf_image, layer.image_tiles[j][i]);
1175  break;
1176 
1177  case INDEXEDA_GIMAGE:
1178  layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
1179  layer.image_tiles[j][i].setColorCount(xcf_image.num_colors);
1180  if (layer.image_tiles[j][i].isNull()) {
1181  return false;
1182  }
1183  setPalette(xcf_image, layer.image_tiles[j][i]);
1184 
1185  layer.alpha_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
1186  layer.alpha_tiles[j][i].setColorCount(256);
1187  if (layer.alpha_tiles[j][i].isNull()) {
1188  return false;
1189  }
1190  setGrayPalette(layer.alpha_tiles[j][i]);
1191  }
1192 
1193  if (layer.mask_offset != 0) {
1194  layer.mask_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
1195  layer.mask_tiles[j][i].setColorCount(256);
1196  if (layer.mask_tiles[j][i].isNull()) {
1197  return false;
1198  }
1199  setGrayPalette(layer.mask_tiles[j][i]);
1200  }
1201  }
1202  }
1203  return true;
1204 }
1205 
1206 /*!
1207  * Apply a grayscale palette to the QImage. Note that Qt does not distinguish
1208  * between grayscale and indexed images. A grayscale image is just
1209  * an indexed image with a 256-color, grayscale palette.
1210  * \param image image to set to a grayscale palette.
1211  */
1212 void XCFImageFormat::setGrayPalette(QImage &image)
1213 {
1214  if (grayTable.isEmpty()) {
1215  grayTable.resize(256);
1216 
1217  for (int i = 0; i < 256; i++) {
1218  grayTable[i] = qRgb(i, i, i);
1219  }
1220  }
1221 
1222  image.setColorTable(grayTable);
1223 }
1224 
1225 /*!
1226  * Copy the indexed palette from the XCF image into the QImage.
1227  * \param xcf_image XCF image containing the palette read from the data stream.
1228  * \param image image to apply the palette to.
1229  */
1230 void XCFImageFormat::setPalette(XCFImage &xcf_image, QImage &image)
1231 {
1232  Q_ASSERT(xcf_image.num_colors == xcf_image.palette.size());
1233 
1234  image.setColorTable(xcf_image.palette);
1235 }
1236 
1237 /*!
1238  * Copy the bytes from the tile buffer into the image tile QImage, taking into
1239  * account all the myriad different modes.
1240  * \param layer layer containing the tile buffer and the image tile matrix.
1241  * \param i column index of current tile.
1242  * \param j row index of current tile.
1243  */
1244 void XCFImageFormat::assignImageBytes(Layer &layer, uint i, uint j)
1245 {
1246  QImage &image = layer.image_tiles[j][i];
1247  const uchar *tile = layer.tile;
1248  const int width = image.width();
1249  const int height = image.height();
1250  const int bytesPerLine = image.bytesPerLine();
1251  uchar *bits = image.bits();
1252 
1253  switch (layer.type) {
1254  case RGB_GIMAGE:
1255  for (int y = 0; y < height; y++) {
1256  QRgb *dataPtr = (QRgb *)(bits + y * bytesPerLine);
1257  for (int x = 0; x < width; x++) {
1258  *dataPtr++ = qRgb(tile[0], tile[1], tile[2]);
1259  tile += sizeof(QRgb);
1260  }
1261  }
1262  break;
1263 
1264  case RGBA_GIMAGE:
1265  for (int y = 0; y < height; y++) {
1266  QRgb *dataPtr = (QRgb *)(bits + y * bytesPerLine);
1267  for (int x = 0; x < width; x++) {
1268  *dataPtr++ = qRgba(tile[0], tile[1], tile[2], tile[3]);
1269  tile += sizeof(QRgb);
1270  }
1271  }
1272  break;
1273 
1274  case GRAY_GIMAGE:
1275  case INDEXED_GIMAGE:
1276  for (int y = 0; y < height; y++) {
1277  uchar *dataPtr = bits + y * bytesPerLine;
1278  for (int x = 0; x < width; x++) {
1279  *dataPtr++ = tile[0];
1280  tile += sizeof(QRgb);
1281  }
1282  }
1283  break;
1284 
1285  case GRAYA_GIMAGE:
1286  case INDEXEDA_GIMAGE:
1287  for (int y = 0; y < height; y++) {
1288  uchar *dataPtr = bits + y * bytesPerLine;
1289  uchar *alphaPtr = layer.alpha_tiles[j][i].scanLine(y);
1290  for (int x = 0; x < width; x++) {
1291  // The "if" here should not be necessary, but apparently there
1292  // are some cases where the image can contain larger indices
1293  // than there are colors in the palette. (A bug in The GIMP?)
1294 
1295  if (tile[0] < image.colorCount()) {
1296  *dataPtr = tile[0];
1297  }
1298 
1299  *alphaPtr = tile[1];
1300  dataPtr += 1;
1301  alphaPtr += 1;
1302  tile += sizeof(QRgb);
1303  }
1304  }
1305  break;
1306  }
1307 }
1308 
1309 /*!
1310  * The GIMP stores images in a "mipmap"-like hierarchy. As far as the QImage
1311  * is concerned, however, only the top level (i.e., the full resolution image)
1312  * is used.
1313  * \param xcf_io the data stream connected to the XCF image.
1314  * \param layer the layer to collect the image.
1315  * \return true if there were no I/O errors.
1316  */
1317 bool XCFImageFormat::loadHierarchy(QDataStream &xcf_io, Layer &layer)
1318 {
1319  qint32 width;
1320  qint32 height;
1321  quint32 bpp;
1322 
1323  xcf_io >> width >> height >> bpp;
1324  const qint64 offset = readOffsetPtr(xcf_io);
1325 
1326  qCDebug(XCFPLUGIN) << "width" << width << "height" << height << "bpp" << bpp << "offset" << offset;
1327 
1328  if (offset < 0) {
1329  qCDebug(XCFPLUGIN) << "XCF: negative hierarchy offset";
1330  return false;
1331  }
1332 
1333  const bool isMask = layer.assignBytes == assignMaskBytes;
1334 
1335  // make sure bpp is correct and complain if it is not
1336  switch (layer.type) {
1337  case RGB_GIMAGE:
1338  if (bpp != 3) {
1339  qCDebug(XCFPLUGIN) << "Found layer of type RGB but with bpp != 3" << bpp;
1340 
1341  if (!isMask) {
1342  return false;
1343  }
1344  }
1345  break;
1346  case RGBA_GIMAGE:
1347  if (bpp != 4) {
1348  qCDebug(XCFPLUGIN) << "Found layer of type RGBA but with bpp != 4, got" << bpp << "bpp";
1349 
1350  if (!isMask) {
1351  return false;
1352  }
1353  }
1354  break;
1355  case GRAY_GIMAGE:
1356  if (bpp != 1) {
1357  qCDebug(XCFPLUGIN) << "Found layer of type Gray but with bpp != 1" << bpp;
1358  return false;
1359  }
1360  break;
1361  case GRAYA_GIMAGE:
1362  if (bpp != 2) {
1363  qCDebug(XCFPLUGIN) << "Found layer of type Gray+Alpha but with bpp != 2" << bpp;
1364 
1365  if (!isMask) {
1366  return false;
1367  }
1368  }
1369  break;
1370  case INDEXED_GIMAGE:
1371  if (bpp != 1) {
1372  qCDebug(XCFPLUGIN) << "Found layer of type Indexed but with bpp != 1" << bpp;
1373  return false;
1374  }
1375  break;
1376  case INDEXEDA_GIMAGE:
1377  if (bpp != 2) {
1378  qCDebug(XCFPLUGIN) << "Found layer of type Indexed+Alpha but with bpp != 2" << bpp;
1379 
1380  if (!isMask) {
1381  return false;
1382  }
1383  }
1384  break;
1385  }
1386 
1387  if (bpp > 4) {
1388  qCDebug(XCFPLUGIN) << "bpp is" << bpp << "We don't support layers with bpp > 4";
1389  return false;
1390  }
1391 
1392  // GIMP stores images in a "mipmap"-like format (multiple levels of
1393  // increasingly lower resolution). Only the top level is used here,
1394  // however.
1395 
1396  quint32 junk;
1397  do {
1398  xcf_io >> junk;
1399 
1400  if (xcf_io.device()->atEnd()) {
1401  qCDebug(XCFPLUGIN) << "XCF: read failure on layer " << layer.name << " level offsets";
1402  return false;
1403  }
1404  } while (junk != 0);
1405 
1406  qint64 saved_pos = xcf_io.device()->pos();
1407 
1408  xcf_io.device()->seek(offset);
1409  if (!loadLevel(xcf_io, layer, bpp)) {
1410  return false;
1411  }
1412 
1413  xcf_io.device()->seek(saved_pos);
1414  return true;
1415 }
1416 
1417 /*!
1418  * Load one level of the image hierarchy (but only the top level is ever used).
1419  * \param xcf_io the data stream connected to the XCF image.
1420  * \param layer the layer to collect the image.
1421  * \param bpp the number of bytes in a pixel.
1422  * \return true if there were no I/O errors.
1423  * \sa loadTileRLE().
1424  */
1425 bool XCFImageFormat::loadLevel(QDataStream &xcf_io, Layer &layer, qint32 bpp)
1426 {
1427  qint32 width;
1428  qint32 height;
1429 
1430  xcf_io >> width >> height;
1431  qint64 offset = readOffsetPtr(xcf_io);
1432 
1433  if (offset < 0) {
1434  qCDebug(XCFPLUGIN) << "XCF: negative level offset";
1435  return false;
1436  }
1437 
1438  if (offset == 0) {
1439  // offset 0 with rowsxcols != 0 is probably an error since it means we have tiles
1440  // without data but just clear the bits for now instead of returning false
1441  for (uint j = 0; j < layer.nrows; j++) {
1442  for (uint i = 0; i < layer.ncols; i++) {
1443  layer.image_tiles[j][i].fill(Qt::transparent);
1444  if (layer.type == GRAYA_GIMAGE || layer.type == INDEXEDA_GIMAGE) {
1445  layer.alpha_tiles[j][i].fill(Qt::transparent);
1446  }
1447  }
1448  }
1449  return true;
1450  }
1451 
1452  for (uint j = 0; j < layer.nrows; j++) {
1453  for (uint i = 0; i < layer.ncols; i++) {
1454  if (offset == 0) {
1455  qCDebug(XCFPLUGIN) << "XCF: incorrect number of tiles in layer " << layer.name;
1456  return false;
1457  }
1458 
1459  qint64 saved_pos = xcf_io.device()->pos();
1460  qint64 offset2 = readOffsetPtr(xcf_io);
1461 
1462  if (offset2 < 0) {
1463  qCDebug(XCFPLUGIN) << "XCF: negative level offset";
1464  return false;
1465  }
1466 
1467  // Evidently, RLE can occasionally expand a tile instead of compressing it!
1468  if (offset2 == 0) {
1469  offset2 = offset + (uint)(TILE_WIDTH * TILE_HEIGHT * 4 * 1.5);
1470  }
1471 
1472  xcf_io.device()->seek(offset);
1473 
1474  switch (layer.compression) {
1475  case COMPRESS_NONE: {
1476  if (xcf_io.version() > 11) {
1477  qCDebug(XCFPLUGIN) << "Component reading not supported yet";
1478  return false;
1479  }
1480  const int data_size = bpp * TILE_WIDTH * TILE_HEIGHT;
1481  if (data_size > int(sizeof(layer.tile))) {
1482  qCDebug(XCFPLUGIN) << "Tile data too big, we can only fit" << sizeof(layer.tile) << "but need" << data_size;
1483  return false;
1484  }
1485  int dataRead = xcf_io.readRawData(reinterpret_cast<char *>(layer.tile), data_size);
1486  if (dataRead < data_size) {
1487  qCDebug(XCFPLUGIN) << "short read, expected" << data_size << "got" << dataRead;
1488  return false;
1489  }
1490  break;
1491  }
1492  case COMPRESS_RLE: {
1493  int size = layer.image_tiles[j][i].width() * layer.image_tiles[j][i].height();
1494  if (!loadTileRLE(xcf_io, layer.tile, size, offset2 - offset, bpp)) {
1495  return true;
1496  }
1497  break;
1498  }
1499  default:
1500  qCDebug(XCFPLUGIN) << "Unhandled compression" << layer.compression;
1501  return false;
1502  }
1503 
1504  // The bytes in the layer tile are juggled differently depending on
1505  // the target QImage. The caller has set layer.assignBytes to the
1506  // appropriate routine.
1507 
1508  layer.assignBytes(layer, i, j);
1509 
1510  xcf_io.device()->seek(saved_pos);
1511  offset = readOffsetPtr(xcf_io);
1512 
1513  if (offset < 0) {
1514  qCDebug(XCFPLUGIN) << "XCF: negative level offset";
1515  return false;
1516  }
1517  }
1518  }
1519 
1520  return true;
1521 }
1522 
1523 /*!
1524  * A layer can have a one channel image which is used as a mask.
1525  * \param xcf_io the data stream connected to the XCF image.
1526  * \param layer the layer to collect the mask image.
1527  * \return true if there were no I/O errors.
1528  */
1529 bool XCFImageFormat::loadMask(QDataStream &xcf_io, Layer &layer)
1530 {
1531  qint32 width;
1532  qint32 height;
1533  char *name;
1534 
1535  xcf_io >> width >> height >> name;
1536 
1537  delete[] name;
1538 
1539  if (!loadChannelProperties(xcf_io, layer)) {
1540  return false;
1541  }
1542 
1543  const qint64 hierarchy_offset = readOffsetPtr(xcf_io);
1544 
1545  if (hierarchy_offset < 0) {
1546  qCDebug(XCFPLUGIN) << "XCF: negative mask hierarchy_offset";
1547  return false;
1548  }
1549 
1550  xcf_io.device()->seek(hierarchy_offset);
1551  layer.assignBytes = assignMaskBytes;
1552 
1553  if (!loadHierarchy(xcf_io, layer)) {
1554  return false;
1555  }
1556 
1557  return true;
1558 }
1559 
1560 /*!
1561  * This is the routine for which all the other code is simply
1562  * infrastructure. Read the image bytes out of the file and
1563  * store them in the tile buffer. This is passed a full 32-bit deep
1564  * buffer, even if bpp is smaller. The caller can figure out what to
1565  * do with the bytes.
1566  *
1567  * The tile is stored in "channels", i.e. the red component of all
1568  * pixels, then the green component of all pixels, then blue then
1569  * alpha, or, for indexed images, the color indices of all pixels then
1570  * the alpha of all pixels.
1571  *
1572  * The data is compressed with "run length encoding". Some simple data
1573  * integrity checks are made.
1574  *
1575  * \param xcf_io the data stream connected to the XCF image.
1576  * \param tile the buffer to expand the RLE into.
1577  * \param image_size number of bytes expected to be in the image tile.
1578  * \param data_length number of bytes expected in the RLE.
1579  * \param bpp number of bytes per pixel.
1580  * \return true if there were no I/O errors and no obvious corruption of
1581  * the RLE data.
1582  */
1583 bool XCFImageFormat::loadTileRLE(QDataStream &xcf_io, uchar *tile, int image_size, int data_length, qint32 bpp)
1584 {
1585  uchar *data;
1586 
1587  uchar *xcfdata;
1588  uchar *xcfodata;
1589  uchar *xcfdatalimit;
1590 
1591  if (data_length < 0 || data_length > int(TILE_WIDTH * TILE_HEIGHT * 4 * 1.5)) {
1592  qCDebug(XCFPLUGIN) << "XCF: invalid tile data length" << data_length;
1593  return false;
1594  }
1595 
1596  xcfdata = xcfodata = new uchar[data_length];
1597 
1598  const int dataRead = xcf_io.readRawData((char *)xcfdata, data_length);
1599  if (dataRead <= 0) {
1600  delete[] xcfodata;
1601  qCDebug(XCFPLUGIN) << "XCF: read failure on tile" << dataRead;
1602  return false;
1603  }
1604 
1605  if (dataRead < data_length) {
1606  memset(&xcfdata[dataRead], 0, data_length - dataRead);
1607  }
1608 
1609  if (!xcf_io.device()->isOpen()) {
1610  delete[] xcfodata;
1611  qCDebug(XCFPLUGIN) << "XCF: read failure on tile";
1612  return false;
1613  }
1614 
1615  xcfdatalimit = &xcfodata[data_length - 1];
1616 
1617  for (int i = 0; i < bpp; ++i) {
1618  data = tile + i;
1619 
1620  int count = 0;
1621  int size = image_size;
1622 
1623  while (size > 0) {
1624  if (xcfdata > xcfdatalimit) {
1625  goto bogus_rle;
1626  }
1627 
1628  uchar val = *xcfdata++;
1629  uint length = val;
1630 
1631  if (length >= 128) {
1632  length = 255 - (length - 1);
1633  if (length == 128) {
1634  if (xcfdata >= xcfdatalimit) {
1635  goto bogus_rle;
1636  }
1637 
1638  length = (*xcfdata << 8) + xcfdata[1];
1639 
1640  xcfdata += 2;
1641  }
1642 
1643  count += length;
1644  size -= length;
1645 
1646  if (size < 0) {
1647  goto bogus_rle;
1648  }
1649 
1650  if (&xcfdata[length - 1] > xcfdatalimit) {
1651  goto bogus_rle;
1652  }
1653 
1654  while (length-- > 0) {
1655  *data = *xcfdata++;
1656  data += sizeof(QRgb);
1657  }
1658  } else {
1659  length += 1;
1660  if (length == 128) {
1661  if (xcfdata >= xcfdatalimit) {
1662  goto bogus_rle;
1663  }
1664 
1665  length = (*xcfdata << 8) + xcfdata[1];
1666  xcfdata += 2;
1667  }
1668 
1669  count += length;
1670  size -= length;
1671 
1672  if (size < 0) {
1673  goto bogus_rle;
1674  }
1675 
1676  if (xcfdata > xcfdatalimit) {
1677  goto bogus_rle;
1678  }
1679 
1680  val = *xcfdata++;
1681 
1682  while (length-- > 0) {
1683  *data = val;
1684  data += sizeof(QRgb);
1685  }
1686  }
1687  }
1688  }
1689 
1690  delete[] xcfodata;
1691  return true;
1692 
1693 bogus_rle:
1694 
1695  qCDebug(XCFPLUGIN) << "The run length encoding could not be decoded properly";
1696  delete[] xcfodata;
1697  return false;
1698 }
1699 
1700 /*!
1701  * An XCF file can contain an arbitrary number of properties associated
1702  * with a channel. Note that this routine only reads mask channel properties.
1703  * \param xcf_io the data stream connected to the XCF image.
1704  * \param layer layer containing the mask channel to collect the properties.
1705  * \return true if there were no I/O errors.
1706  */
1707 bool XCFImageFormat::loadChannelProperties(QDataStream &xcf_io, Layer &layer)
1708 {
1709  while (true) {
1710  PropType type;
1711  QByteArray bytes;
1712  quint32 rawType;
1713 
1714  if (!loadProperty(xcf_io, type, bytes, rawType)) {
1715  qCDebug(XCFPLUGIN) << "XCF: error loading channel properties";
1716  return false;
1717  }
1718 
1719  QDataStream property(bytes);
1720 
1721  switch (type) {
1722  case PROP_END:
1723  return true;
1724 
1725  case PROP_OPACITY:
1726  property >> layer.mask_channel.opacity;
1727  layer.mask_channel.opacity = std::min(layer.mask_channel.opacity, 255u);
1728  break;
1729 
1730  case PROP_FLOAT_OPACITY:
1731  // For some reason QDataStream isn't able to read the float (tried
1732  // setting the endianness manually)
1733  if (bytes.size() == 4) {
1734  layer.mask_channel.opacityFloat = qFromBigEndian(*reinterpret_cast<float *>(bytes.data()));
1735  } else {
1736  qCDebug(XCFPLUGIN) << "XCF: Invalid data size for float:" << bytes.size();
1737  }
1738  break;
1739 
1740  case PROP_VISIBLE:
1741  property >> layer.mask_channel.visible;
1742  break;
1743 
1744  case PROP_SHOW_MASKED:
1745  property >> layer.mask_channel.show_masked;
1746  break;
1747 
1748  case PROP_COLOR:
1749  property >> layer.mask_channel.red >> layer.mask_channel.green >> layer.mask_channel.blue;
1750  break;
1751 
1752  case PROP_FLOAT_COLOR:
1753  property >> layer.mask_channel.redF >> layer.mask_channel.greenF >> layer.mask_channel.blueF;
1754  break;
1755 
1756  case PROP_TATTOO:
1757  property >> layer.mask_channel.tattoo;
1758  break;
1759 
1760  // Only used in edit mode
1761  case PROP_LINKED:
1762  break;
1763 
1764  // Just for organization in the UI, doesn't influence rendering
1765  case PROP_COLOR_TAG:
1766  break;
1767 
1768  // We don't support editing, so for now just ignore locking
1769  case PROP_LOCK_CONTENT:
1770  case PROP_LOCK_POSITION:
1771  break;
1772 
1773  default:
1774  qCDebug(XCFPLUGIN) << "XCF: unimplemented channel property " << type << "(" << rawType << ")"
1775  << ", size " << bytes.size();
1776  break;
1777  }
1778  }
1779 }
1780 
1781 /*!
1782  * Copy the bytes from the tile buffer into the mask tile QImage.
1783  * \param layer layer containing the tile buffer and the mask tile matrix.
1784  * \param i column index of current tile.
1785  * \param j row index of current tile.
1786  */
1787 void XCFImageFormat::assignMaskBytes(Layer &layer, uint i, uint j)
1788 {
1789  QImage &image = layer.mask_tiles[j][i];
1790  uchar *tile = layer.tile;
1791  const int width = image.width();
1792  const int height = image.height();
1793  const int bytesPerLine = image.bytesPerLine();
1794  uchar *bits = image.bits();
1795 
1796  for (int y = 0; y < height; y++) {
1797  uchar *dataPtr = bits + y * bytesPerLine;
1798  for (int x = 0; x < width; x++) {
1799  *dataPtr++ = tile[0];
1800  tile += sizeof(QRgb);
1801  }
1802  }
1803 }
1804 
1805 /*!
1806  * Construct the QImage which will eventually be returned to the QImage
1807  * loader.
1808  *
1809  * There are a couple of situations which require that the QImage is not
1810  * exactly the same as The GIMP's representation. The full table is:
1811  * \verbatim
1812  * Grayscale opaque : 8 bpp indexed
1813  * Grayscale translucent : 32 bpp + alpha
1814  * Indexed opaque : 1 bpp if num_colors <= 2
1815  * : 8 bpp indexed otherwise
1816  * Indexed translucent : 8 bpp indexed + alpha if num_colors < 256
1817  * : 32 bpp + alpha otherwise
1818  * RGB opaque : 32 bpp
1819  * RGBA translucent : 32 bpp + alpha
1820  * \endverbatim
1821  * Whether the image is translucent or not is determined by the bottom layer's
1822  * alpha channel. However, even if the bottom layer lacks an alpha channel,
1823  * it can still have an opacity < 1. In this case, the QImage is promoted
1824  * to 32-bit. (Note this is different from the output from the GIMP image
1825  * exporter, which seems to ignore this attribute.)
1826  *
1827  * Independently, higher layers can be translucent, but the background of
1828  * the image will not show through if the bottom layer is opaque.
1829  *
1830  * For indexed images, translucency is an all or nothing effect.
1831  * \param xcf_image contains image info and bottom-most layer.
1832  */
1833 bool XCFImageFormat::initializeImage(XCFImage &xcf_image)
1834 {
1835  // (Aliases to make the code look a little better.)
1836  Layer &layer(xcf_image.layer);
1837  QImage &image(xcf_image.image);
1838 
1839  switch (layer.type) {
1840  case RGB_GIMAGE:
1841  if (layer.opacity == OPAQUE_OPACITY) {
1842  image = QImage(xcf_image.width, xcf_image.height, QImage::Format_RGB32);
1843  if (image.isNull()) {
1844  return false;
1845  }
1846  image.fill(qRgb(255, 255, 255));
1847  break;
1848  } // else, fall through to 32-bit representation
1849  Q_FALLTHROUGH();
1850  case RGBA_GIMAGE:
1851  image = QImage(xcf_image.width, xcf_image.height, QImage::Format_ARGB32);
1852  if (image.isNull()) {
1853  return false;
1854  }
1855  image.fill(qRgba(255, 255, 255, 0));
1856  break;
1857 
1858  case GRAY_GIMAGE:
1859  if (layer.opacity == OPAQUE_OPACITY) {
1860  image = QImage(xcf_image.width, xcf_image.height, QImage::Format_Indexed8);
1861  image.setColorCount(256);
1862  if (image.isNull()) {
1863  return false;
1864  }
1865  setGrayPalette(image);
1866  image.fill(255);
1867  break;
1868  } // else, fall through to 32-bit representation
1869  Q_FALLTHROUGH();
1870  case GRAYA_GIMAGE:
1871  image = QImage(xcf_image.width, xcf_image.height, QImage::Format_ARGB32);
1872  if (image.isNull()) {
1873  return false;
1874  }
1875  image.fill(qRgba(255, 255, 255, 0));
1876  break;
1877 
1878  case INDEXED_GIMAGE:
1879  // As noted in the table above, there are quite a few combinations
1880  // which are possible with indexed images, depending on the
1881  // presence of transparency (note: not translucency, which is not
1882  // supported by The GIMP for indexed images) and the number of
1883  // individual colors.
1884 
1885  // Note: Qt treats a bitmap with a Black and White color palette
1886  // as a mask, so only the "on" bits are drawn, regardless of the
1887  // order color table entries. Otherwise (i.e., at least one of the
1888  // color table entries is not black or white), it obeys the one-
1889  // or two-color palette. Have to ask about this...
1890 
1891  if (xcf_image.num_colors <= 2) {
1892  image = QImage(xcf_image.width, xcf_image.height, QImage::Format_MonoLSB);
1893  image.setColorCount(xcf_image.num_colors);
1894  if (image.isNull()) {
1895  return false;
1896  }
1897  image.fill(0);
1898  setPalette(xcf_image, image);
1899  } else if (xcf_image.num_colors <= 256) {
1900  image = QImage(xcf_image.width, xcf_image.height, QImage::Format_Indexed8);
1901  image.setColorCount(xcf_image.num_colors);
1902  if (image.isNull()) {
1903  return false;
1904  }
1905  image.fill(0);
1906  setPalette(xcf_image, image);
1907  }
1908  break;
1909 
1910  case INDEXEDA_GIMAGE:
1911  if (xcf_image.num_colors == 1) {
1912  // Plenty(!) of room to add a transparent color
1913  xcf_image.num_colors++;
1914  xcf_image.palette.resize(xcf_image.num_colors);
1915  xcf_image.palette[1] = xcf_image.palette[0];
1916  xcf_image.palette[0] = qRgba(255, 255, 255, 0);
1917 
1918  image = QImage(xcf_image.width, xcf_image.height, QImage::Format_MonoLSB);
1919  image.setColorCount(xcf_image.num_colors);
1920  if (image.isNull()) {
1921  return false;
1922  }
1923  image.fill(0);
1924  setPalette(xcf_image, image);
1925  } else if (xcf_image.num_colors < 256) {
1926  // Plenty of room to add a transparent color
1927  xcf_image.num_colors++;
1928  xcf_image.palette.resize(xcf_image.num_colors);
1929  for (int c = xcf_image.num_colors - 1; c >= 1; c--) {
1930  xcf_image.palette[c] = xcf_image.palette[c - 1];
1931  }
1932 
1933  xcf_image.palette[0] = qRgba(255, 255, 255, 0);
1934  image = QImage(xcf_image.width, xcf_image.height, QImage::Format_Indexed8);
1935  image.setColorCount(xcf_image.num_colors);
1936  if (image.isNull()) {
1937  return false;
1938  }
1939  image.fill(0);
1940  setPalette(xcf_image, image);
1941  } else {
1942  // No room for a transparent color, so this has to be promoted to
1943  // true color. (There is no equivalent PNG representation output
1944  // from The GIMP as of v1.2.)
1945  image = QImage(xcf_image.width, xcf_image.height, QImage::Format_ARGB32);
1946  if (image.isNull()) {
1947  return false;
1948  }
1949  image.fill(qRgba(255, 255, 255, 0));
1950  }
1951  break;
1952  }
1953 
1954  if (xcf_image.x_resolution > 0 && xcf_image.y_resolution > 0) {
1955  const float dpmx = xcf_image.x_resolution * INCHESPERMETER;
1956  if (dpmx > std::numeric_limits<int>::max()) {
1957  return false;
1958  }
1959  const float dpmy = xcf_image.y_resolution * INCHESPERMETER;
1960  if (dpmy > std::numeric_limits<int>::max()) {
1961  return false;
1962  }
1963  image.setDotsPerMeterX((int)dpmx);
1964  image.setDotsPerMeterY((int)dpmy);
1965  }
1966  return true;
1967 }
1968 
1969 /*!
1970  * Copy a layer into an image, taking account of the manifold modes. The
1971  * contents of the image are replaced.
1972  * \param xcf_image contains the layer and image to be replaced.
1973  */
1974 void XCFImageFormat::copyLayerToImage(XCFImage &xcf_image)
1975 {
1976  Layer &layer(xcf_image.layer);
1977  QImage &image(xcf_image.image);
1978  PixelCopyOperation copy = nullptr;
1979 
1980  switch (layer.type) {
1981  case RGB_GIMAGE:
1982  case RGBA_GIMAGE:
1983  copy = copyRGBToRGB;
1984  break;
1985  case GRAY_GIMAGE:
1986  if (layer.opacity == OPAQUE_OPACITY) {
1987  copy = copyGrayToGray;
1988  } else {
1989  copy = copyGrayToRGB;
1990  }
1991  break;
1992  case GRAYA_GIMAGE:
1993  copy = copyGrayAToRGB;
1994  break;
1995  case INDEXED_GIMAGE:
1996  copy = copyIndexedToIndexed;
1997  break;
1998  case INDEXEDA_GIMAGE:
1999  if (xcf_image.image.depth() <= 8) {
2000  copy = copyIndexedAToIndexed;
2001  } else {
2002  copy = copyIndexedAToRGB;
2003  }
2004  }
2005 
2006  if (!copy) {
2007  return;
2008  }
2009 
2010  // For each tile...
2011 
2012  for (uint j = 0; j < layer.nrows; j++) {
2013  uint y = j * TILE_HEIGHT;
2014 
2015  for (uint i = 0; i < layer.ncols; i++) {
2016  uint x = i * TILE_WIDTH;
2017 
2018  // This seems the best place to apply the dissolve because it
2019  // depends on the global position of each tile's
2020  // pixels. Apparently it's the only mode which can apply to a
2021  // single layer.
2022 
2023  if (layer.mode == DISSOLVE_MODE) {
2024  if (!random_table_initialized) {
2025  initializeRandomTable();
2026  random_table_initialized = true;
2027  }
2028  if (layer.type == RGBA_GIMAGE) {
2029  dissolveRGBPixels(layer.image_tiles[j][i], x, y);
2030  }
2031 
2032  else if (layer.type == GRAYA_GIMAGE) {
2033  dissolveAlphaPixels(layer.alpha_tiles[j][i], x, y);
2034  }
2035  }
2036 
2037  // Shortcut for common case
2038  if (copy == copyRGBToRGB && layer.apply_mask != 1) {
2039  QPainter painter(&image);
2040  painter.setOpacity(layer.opacity / 255.0);
2041  painter.setCompositionMode(QPainter::CompositionMode_Source);
2042  painter.drawImage(x + layer.x_offset, y + layer.y_offset, layer.image_tiles[j][i]);
2043  continue;
2044  }
2045 
2046  for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
2047  for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
2048  int m = x + k + layer.x_offset;
2049  int n = y + l + layer.y_offset;
2050 
2051  if (m < 0 || m >= image.width() || n < 0 || n >= image.height()) {
2052  continue;
2053  }
2054 
2055  (*copy)(layer, i, j, k, l, image, m, n);
2056  }
2057  }
2058  }
2059  }
2060 }
2061 
2062 /*!
2063  * Copy an RGB pixel from the layer to the RGB image. Straight-forward.
2064  * The only thing this has to take account of is the opacity of the
2065  * layer. Evidently, the GIMP exporter itself does not actually do this.
2066  * \param layer source layer.
2067  * \param i x tile index.
2068  * \param j y tile index.
2069  * \param k x pixel index of tile i,j.
2070  * \param l y pixel index of tile i,j.
2071  * \param image destination image.
2072  * \param m x pixel of destination image.
2073  * \param n y pixel of destination image.
2074  */
2075 void XCFImageFormat::copyRGBToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
2076 {
2077  QRgb src = layer.image_tiles[j][i].pixel(k, l);
2078  uchar src_a = layer.opacity;
2079 
2080  if (layer.type == RGBA_GIMAGE) {
2081  src_a = INT_MULT(src_a, qAlpha(src));
2082  }
2083 
2084  // Apply the mask (if any)
2085 
2086  if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
2087  src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
2088  }
2089 
2090  image.setPixel(m, n, qRgba(src, src_a));
2091 }
2092 
2093 /*!
2094  * Copy a Gray pixel from the layer to the Gray image. Straight-forward.
2095  * \param layer source layer.
2096  * \param i x tile index.
2097  * \param j y tile index.
2098  * \param k x pixel index of tile i,j.
2099  * \param l y pixel index of tile i,j.
2100  * \param image destination image.
2101  * \param m x pixel of destination image.
2102  * \param n y pixel of destination image.
2103  */
2104 void XCFImageFormat::copyGrayToGray(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
2105 {
2106  int src = layer.image_tiles[j][i].pixelIndex(k, l);
2107  image.setPixel(m, n, src);
2108 }
2109 
2110 /*!
2111  * Copy a Gray pixel from the layer to an RGB image. Straight-forward.
2112  * The only thing this has to take account of is the opacity of the
2113  * layer. Evidently, the GIMP exporter itself does not actually do this.
2114  * \param layer source layer.
2115  * \param i x tile index.
2116  * \param j y tile index.
2117  * \param k x pixel index of tile i,j.
2118  * \param l y pixel index of tile i,j.
2119  * \param image destination image.
2120  * \param m x pixel of destination image.
2121  * \param n y pixel of destination image.
2122  */
2123 void XCFImageFormat::copyGrayToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
2124 {
2125  QRgb src = layer.image_tiles[j][i].pixel(k, l);
2126  uchar src_a = layer.opacity;
2127  image.setPixel(m, n, qRgba(src, src_a));
2128 }
2129 
2130 /*!
2131  * Copy a GrayA pixel from the layer to an RGB image. Straight-forward.
2132  * The only thing this has to take account of is the opacity of the
2133  * layer. Evidently, the GIMP exporter itself does not actually do this.
2134  * \param layer source layer.
2135  * \param i x tile index.
2136  * \param j y tile index.
2137  * \param k x pixel index of tile i,j.
2138  * \param l y pixel index of tile i,j.
2139  * \param image destination image.
2140  * \param m x pixel of destination image.
2141  * \param n y pixel of destination image.
2142  */
2143 void XCFImageFormat::copyGrayAToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
2144 {
2145  QRgb src = layer.image_tiles[j][i].pixel(k, l);
2146  uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
2147  src_a = INT_MULT(src_a, layer.opacity);
2148 
2149  // Apply the mask (if any)
2150 
2151  if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
2152  src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
2153  }
2154 
2155  image.setPixel(m, n, qRgba(src, src_a));
2156 }
2157 
2158 /*!
2159  * Copy an Indexed pixel from the layer to the Indexed image. Straight-forward.
2160  * \param layer source layer.
2161  * \param i x tile index.
2162  * \param j y tile index.
2163  * \param k x pixel index of tile i,j.
2164  * \param l y pixel index of tile i,j.
2165  * \param image destination image.
2166  * \param m x pixel of destination image.
2167  * \param n y pixel of destination image.
2168  */
2169 void XCFImageFormat::copyIndexedToIndexed(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
2170 {
2171  int src = layer.image_tiles[j][i].pixelIndex(k, l);
2172  image.setPixel(m, n, src);
2173 }
2174 
2175 /*!
2176  * Copy an IndexedA pixel from the layer to the Indexed image. Straight-forward.
2177  * \param layer source layer.
2178  * \param i x tile index.
2179  * \param j y tile index.
2180  * \param k x pixel index of tile i,j.
2181  * \param l y pixel index of tile i,j.
2182  * \param image destination image.
2183  * \param m x pixel of destination image.
2184  * \param n y pixel of destination image.
2185  */
2186 void XCFImageFormat::copyIndexedAToIndexed(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
2187 {
2188  uchar src = layer.image_tiles[j][i].pixelIndex(k, l);
2189  uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
2190  src_a = INT_MULT(src_a, layer.opacity);
2191 
2192  if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
2193  src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
2194  }
2195 
2196  if (src_a > 127) {
2197  src++;
2198  } else {
2199  src = 0;
2200  }
2201 
2202  image.setPixel(m, n, src);
2203 }
2204 
2205 /*!
2206  * Copy an IndexedA pixel from the layer to an RGB image. Straight-forward.
2207  * The only thing this has to take account of is the opacity of the
2208  * layer. Evidently, the GIMP exporter itself does not actually do this.
2209  * \param layer source layer.
2210  * \param i x tile index.
2211  * \param j y tile index.
2212  * \param k x pixel index of tile i,j.
2213  * \param l y pixel index of tile i,j.
2214  * \param image destination image.
2215  * \param m x pixel of destination image.
2216  * \param n y pixel of destination image.
2217  */
2218 void XCFImageFormat::copyIndexedAToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
2219 {
2220  QRgb src = layer.image_tiles[j][i].pixel(k, l);
2221  uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
2222  src_a = INT_MULT(src_a, layer.opacity);
2223 
2224  // Apply the mask (if any)
2225  if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
2226  src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
2227  }
2228 
2229  // This is what appears in the GIMP window
2230  if (src_a <= 127) {
2231  src_a = 0;
2232  } else {
2233  src_a = OPAQUE_OPACITY;
2234  }
2235 
2236  image.setPixel(m, n, qRgba(src, src_a));
2237 }
2238 
2239 /*!
2240  * Merge a layer into an image, taking account of the manifold modes.
2241  * \param xcf_image contains the layer and image to merge.
2242  */
2243 void XCFImageFormat::mergeLayerIntoImage(XCFImage &xcf_image)
2244 {
2245  Layer &layer(xcf_image.layer);
2246  QImage &image(xcf_image.image);
2247 
2248  PixelMergeOperation merge = nullptr;
2249 
2250  if (!layer.opacity) {
2251  return; // don't bother doing anything
2252  }
2253  XCFImageFormat::GimpColorSpace blendSpace = XCFImageFormat::RgbLinearSpace;
2254  switch (layer.blendSpace) {
2255  case 0:
2256  layer.blendSpace = XCFImageFormat::RgbLinearSpace;
2257  break;
2258  case 1:
2259  layer.blendSpace = XCFImageFormat::RgbPerceptualSpace;
2260  break;
2261  case 2:
2262  layer.blendSpace = XCFImageFormat::LabSpace;
2263  break;
2264  default:
2265  if (layer.blendSpace < 0) {
2266  qCDebug(XCFPLUGIN) << "Auto blendspace not handled" << layer.blendSpace;
2267  } else {
2268  qCDebug(XCFPLUGIN) << "Unknown blend space" << layer.blendSpace;
2269  }
2270  break;
2271  }
2272 
2273  if (blendSpace != XCFImageFormat::RgbLinearSpace) {
2274  qCDebug(XCFPLUGIN) << "Unimplemented blend color space" << blendSpace;
2275  }
2276 
2277  if (layer.compositeSpace < 0) {
2278  qCDebug(XCFPLUGIN) << "Auto composite space not handled" << layer.compositeSpace;
2279  }
2280  XCFImageFormat::GimpColorSpace compositeSpace = XCFImageFormat::RgbLinearSpace;
2281  switch (qAbs(layer.compositeSpace)) {
2282  case 0:
2283  layer.compositeSpace = XCFImageFormat::RgbLinearSpace;
2284  break;
2285  case 1:
2286  layer.compositeSpace = XCFImageFormat::RgbPerceptualSpace;
2287  break;
2288  case 2:
2289  layer.compositeSpace = XCFImageFormat::LabSpace;
2290  break;
2291  default:
2292  qCDebug(XCFPLUGIN) << "Unknown composite space" << layer.compositeSpace;
2293  break;
2294  }
2295 
2296  if (compositeSpace != XCFImageFormat::RgbLinearSpace) {
2297  qCDebug(XCFPLUGIN) << "Unimplemented composite color space" << compositeSpace;
2298  }
2299 
2300  if (layer.compositeMode < 0) {
2301  qCDebug(XCFPLUGIN) << "Auto composite mode not handled" << layer.compositeMode;
2302  }
2303 
2304  XCFImageFormat::GimpCompositeMode compositeMode = XCFImageFormat::CompositeOver;
2305  switch (qAbs(layer.compositeMode)) {
2306  case 0:
2307  compositeMode = XCFImageFormat::CompositeOver;
2308  break;
2309  case 1:
2310  compositeMode = XCFImageFormat::CompositeUnion;
2311  break;
2312  case 2:
2313  compositeMode = XCFImageFormat::CompositeClipBackdrop;
2314  break;
2315  case 3:
2316  compositeMode = XCFImageFormat::CompositeClipLayer;
2317  break;
2318  case 4:
2319  compositeMode = XCFImageFormat::CompositeIntersect;
2320  break;
2321  default:
2322  qCDebug(XCFPLUGIN) << "Unknown composite mode" << layer.compositeMode;
2323  break;
2324  }
2325  if (compositeMode != XCFImageFormat::CompositeOver) {
2326  qCDebug(XCFPLUGIN) << "Unhandled composite mode" << compositeMode;
2327  }
2328 
2329  switch (layer.type) {
2330  case RGB_GIMAGE:
2331  case RGBA_GIMAGE:
2332  merge = mergeRGBToRGB;
2333  break;
2334  case GRAY_GIMAGE:
2335  if (layer.opacity == OPAQUE_OPACITY) {
2336  merge = mergeGrayToGray;
2337  } else {
2338  merge = mergeGrayToRGB;
2339  }
2340  break;
2341  case GRAYA_GIMAGE:
2342  if (xcf_image.image.depth() <= 8) {
2343  merge = mergeGrayAToGray;
2344  } else {
2345  merge = mergeGrayAToRGB;
2346  }
2347  break;
2348  case INDEXED_GIMAGE:
2349  merge = mergeIndexedToIndexed;
2350  break;
2351  case INDEXEDA_GIMAGE:
2352  if (xcf_image.image.depth() <= 8) {
2353  merge = mergeIndexedAToIndexed;
2354  } else {
2355  merge = mergeIndexedAToRGB;
2356  }
2357  }
2358 
2359  if (!merge) {
2360  return;
2361  }
2362 
2363  for (uint j = 0; j < layer.nrows; j++) {
2364  uint y = j * TILE_HEIGHT;
2365 
2366  for (uint i = 0; i < layer.ncols; i++) {
2367  uint x = i * TILE_WIDTH;
2368 
2369  // This seems the best place to apply the dissolve because it
2370  // depends on the global position of each tile's
2371  // pixels. Apparently it's the only mode which can apply to a
2372  // single layer.
2373 
2374  if (layer.mode == DISSOLVE_MODE) {
2375  if (!random_table_initialized) {
2376  initializeRandomTable();
2377  random_table_initialized = true;
2378  }
2379  if (layer.type == RGBA_GIMAGE) {
2380  dissolveRGBPixels(layer.image_tiles[j][i], x, y);
2381  }
2382 
2383  else if (layer.type == GRAYA_GIMAGE) {
2384  dissolveAlphaPixels(layer.alpha_tiles[j][i], x, y);
2385  }
2386  }
2387 
2388  // Shortcut for common case
2389  if (merge == mergeRGBToRGB && layer.apply_mask != 1 && layer.mode == NORMAL_MODE) {
2390  QPainter painter(&image);
2391  painter.setOpacity(layer.opacity / 255.0);
2392  painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
2393  painter.drawImage(x + layer.x_offset, y + layer.y_offset, layer.image_tiles[j][i]);
2394  continue;
2395  }
2396 
2397  for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
2398  for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
2399  int m = x + k + layer.x_offset;
2400  int n = y + l + layer.y_offset;
2401 
2402  if (m < 0 || m >= image.width() || n < 0 || n >= image.height()) {
2403  continue;
2404  }
2405 
2406  (*merge)(layer, i, j, k, l, image, m, n);
2407  }
2408  }
2409  }
2410  }
2411 }
2412 
2413 /*!
2414  * Merge an RGB pixel from the layer to the RGB image. Straight-forward.
2415  * The only thing this has to take account of is the opacity of the
2416  * layer. Evidently, the GIMP exporter itself does not actually do this.
2417  * \param layer source layer.
2418  * \param i x tile index.
2419  * \param j y tile index.
2420  * \param k x pixel index of tile i,j.
2421  * \param l y pixel index of tile i,j.
2422  * \param image destination image.
2423  * \param m x pixel of destination image.
2424  * \param n y pixel of destination image.
2425  */
2426 void XCFImageFormat::mergeRGBToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
2427 {
2428  QRgb src = layer.image_tiles[j][i].pixel(k, l);
2429  QRgb dst = image.pixel(m, n);
2430 
2431  uchar src_r = qRed(src);
2432  uchar src_g = qGreen(src);
2433  uchar src_b = qBlue(src);
2434  uchar src_a = qAlpha(src);
2435 
2436  uchar dst_r = qRed(dst);
2437  uchar dst_g = qGreen(dst);
2438  uchar dst_b = qBlue(dst);
2439  uchar dst_a = qAlpha(dst);
2440 
2441  if (!src_a) {
2442  return; // nothing to merge
2443  }
2444 
2445  switch (layer.mode) {
2446  case GIMP_LAYER_MODE_NORMAL:
2447  case GIMP_LAYER_MODE_NORMAL_LEGACY:
2448  break;
2449  case GIMP_LAYER_MODE_MULTIPLY:
2450  case GIMP_LAYER_MODE_MULTIPLY_LEGACY:
2451  src_r = INT_MULT(src_r, dst_r);
2452  src_g = INT_MULT(src_g, dst_g);
2453  src_b = INT_MULT(src_b, dst_b);
2454  src_a = qMin(src_a, dst_a);
2455  break;
2456  case GIMP_LAYER_MODE_DIVIDE:
2457  case GIMP_LAYER_MODE_DIVIDE_LEGACY:
2458  src_r = qMin((dst_r * 256) / (1 + src_r), 255);
2459  src_g = qMin((dst_g * 256) / (1 + src_g), 255);
2460  src_b = qMin((dst_b * 256) / (1 + src_b), 255);
2461  src_a = qMin(src_a, dst_a);
2462  break;
2463  case GIMP_LAYER_MODE_SCREEN:
2464  case GIMP_LAYER_MODE_SCREEN_LEGACY:
2465  src_r = 255 - INT_MULT(255 - dst_r, 255 - src_r);
2466  src_g = 255 - INT_MULT(255 - dst_g, 255 - src_g);
2467  src_b = 255 - INT_MULT(255 - dst_b, 255 - src_b);
2468  src_a = qMin(src_a, dst_a);
2469  break;
2470  case GIMP_LAYER_MODE_OVERLAY:
2471  case GIMP_LAYER_MODE_OVERLAY_LEGACY:
2472  src_r = INT_MULT(dst_r, dst_r + INT_MULT(2 * src_r, 255 - dst_r));
2473  src_g = INT_MULT(dst_g, dst_g + INT_MULT(2 * src_g, 255 - dst_g));
2474  src_b = INT_MULT(dst_b, dst_b + INT_MULT(2 * src_b, 255 - dst_b));
2475  src_a = qMin(src_a, dst_a);
2476  break;
2477  case GIMP_LAYER_MODE_DIFFERENCE:
2478  case GIMP_LAYER_MODE_DIFFERENCE_LEGACY:
2479  src_r = dst_r > src_r ? dst_r - src_r : src_r - dst_r;
2480  src_g = dst_g > src_g ? dst_g - src_g : src_g - dst_g;
2481  src_b = dst_b > src_b ? dst_b - src_b : src_b - dst_b;
2482  src_a = qMin(src_a, dst_a);
2483  break;
2484  case GIMP_LAYER_MODE_ADDITION:
2485  case GIMP_LAYER_MODE_ADDITION_LEGACY:
2486  src_r = add_lut(dst_r, src_r);
2487  src_g = add_lut(dst_g, src_g);
2488  src_b = add_lut(dst_b, src_b);
2489  src_a = qMin(src_a, dst_a);
2490  break;
2491  case GIMP_LAYER_MODE_SUBTRACT:
2492  case GIMP_LAYER_MODE_SUBTRACT_LEGACY:
2493  src_r = dst_r > src_r ? dst_r - src_r : 0;
2494  src_g = dst_g > src_g ? dst_g - src_g : 0;
2495  src_b = dst_b > src_b ? dst_b - src_b : 0;
2496  src_a = qMin(src_a, dst_a);
2497  break;
2498  case GIMP_LAYER_MODE_DARKEN_ONLY:
2499  case GIMP_LAYER_MODE_DARKEN_ONLY_LEGACY:
2500  src_r = dst_r < src_r ? dst_r : src_r;
2501  src_g = dst_g < src_g ? dst_g : src_g;
2502  src_b = dst_b < src_b ? dst_b : src_b;
2503  src_a = qMin(src_a, dst_a);
2504  break;
2505  case GIMP_LAYER_MODE_LIGHTEN_ONLY:
2506  case GIMP_LAYER_MODE_LIGHTEN_ONLY_LEGACY:
2507  src_r = dst_r < src_r ? src_r : dst_r;
2508  src_g = dst_g < src_g ? src_g : dst_g;
2509  src_b = dst_b < src_b ? src_b : dst_b;
2510  src_a = qMin(src_a, dst_a);
2511  break;
2512  case GIMP_LAYER_MODE_HSV_HUE_LEGACY: {
2513  uchar new_r = dst_r;
2514  uchar new_g = dst_g;
2515  uchar new_b = dst_b;
2516 
2517  RGBTOHSV(src_r, src_g, src_b);
2518  RGBTOHSV(new_r, new_g, new_b);
2519 
2520  new_r = src_r;
2521 
2522  HSVTORGB(new_r, new_g, new_b);
2523 
2524  src_r = new_r;
2525  src_g = new_g;
2526  src_b = new_b;
2527  src_a = qMin(src_a, dst_a);
2528  } break;
2529  case GIMP_LAYER_MODE_HSV_SATURATION_LEGACY: {
2530  uchar new_r = dst_r;
2531  uchar new_g = dst_g;
2532  uchar new_b = dst_b;
2533 
2534  RGBTOHSV(src_r, src_g, src_b);
2535  RGBTOHSV(new_r, new_g, new_b);
2536 
2537  new_g = src_g;
2538 
2539  HSVTORGB(new_r, new_g, new_b);
2540 
2541  src_r = new_r;
2542  src_g = new_g;
2543  src_b = new_b;
2544  src_a = qMin(src_a, dst_a);
2545  } break;
2546  case GIMP_LAYER_MODE_HSV_VALUE_LEGACY: {
2547  uchar new_r = dst_r;
2548  uchar new_g = dst_g;
2549  uchar new_b = dst_b;
2550 
2551  RGBTOHSV(src_r, src_g, src_b);
2552  RGBTOHSV(new_r, new_g, new_b);
2553 
2554  new_b = src_b;
2555 
2556  HSVTORGB(new_r, new_g, new_b);
2557 
2558  src_r = new_r;
2559  src_g = new_g;
2560  src_b = new_b;
2561  src_a = qMin(src_a, dst_a);
2562  } break;
2563  case GIMP_LAYER_MODE_HSL_COLOR_LEGACY: {
2564  uchar new_r = dst_r;
2565  uchar new_g = dst_g;
2566  uchar new_b = dst_b;
2567 
2568  RGBTOHLS(src_r, src_g, src_b);
2569  RGBTOHLS(new_r, new_g, new_b);
2570 
2571  new_r = src_r;
2572  new_b = src_b;
2573 
2574  HLSTORGB(new_r, new_g, new_b);
2575 
2576  src_r = new_r;
2577  src_g = new_g;
2578  src_b = new_b;
2579  src_a = qMin(src_a, dst_a);
2580  } break;
2581  case GIMP_LAYER_MODE_DODGE_LEGACY: {
2582  uint tmp;
2583 
2584  tmp = dst_r << 8;
2585  tmp /= 256 - src_r;
2586  src_r = (uchar)qMin(tmp, 255u);
2587 
2588  tmp = dst_g << 8;
2589  tmp /= 256 - src_g;
2590  src_g = (uchar)qMin(tmp, 255u);
2591 
2592  tmp = dst_b << 8;
2593  tmp /= 256 - src_b;
2594  src_b = (uchar)qMin(tmp, 255u);
2595 
2596  src_a = qMin(src_a, dst_a);
2597  } break;
2598  case GIMP_LAYER_MODE_BURN_LEGACY: {
2599  uint tmp;
2600 
2601  tmp = (255 - dst_r) << 8;
2602  tmp /= src_r + 1;
2603  src_r = (uchar)qMin(tmp, 255u);
2604  src_r = 255 - src_r;
2605 
2606  tmp = (255 - dst_g) << 8;
2607  tmp /= src_g + 1;
2608  src_g = (uchar)qMin(tmp, 255u);
2609  src_g = 255 - src_g;
2610 
2611  tmp = (255 - dst_b) << 8;
2612  tmp /= src_b + 1;
2613  src_b = (uchar)qMin(tmp, 255u);
2614  src_b = 255 - src_b;
2615 
2616  src_a = qMin(src_a, dst_a);
2617  } break;
2618  case GIMP_LAYER_MODE_HARDLIGHT_LEGACY: {
2619  uint tmp;
2620  if (src_r > 128) {
2621  tmp = ((int)255 - dst_r) * ((int)255 - ((src_r - 128) << 1));
2622  src_r = (uchar)qMin(255 - (tmp >> 8), 255u);
2623  } else {
2624  tmp = (int)dst_r * ((int)src_r << 1);
2625  src_r = (uchar)qMin(tmp >> 8, 255u);
2626  }
2627 
2628  if (src_g > 128) {
2629  tmp = ((int)255 - dst_g) * ((int)255 - ((src_g - 128) << 1));
2630  src_g = (uchar)qMin(255 - (tmp >> 8), 255u);
2631  } else {
2632  tmp = (int)dst_g * ((int)src_g << 1);
2633  src_g = (uchar)qMin(tmp >> 8, 255u);
2634  }
2635 
2636  if (src_b > 128) {
2637  tmp = ((int)255 - dst_b) * ((int)255 - ((src_b - 128) << 1));
2638  src_b = (uchar)qMin(255 - (tmp >> 8), 255u);
2639  } else {
2640  tmp = (int)dst_b * ((int)src_b << 1);
2641  src_b = (uchar)qMin(tmp >> 8, 255u);
2642  }
2643  src_a = qMin(src_a, dst_a);
2644  } break;
2645  case GIMP_LAYER_MODE_SOFTLIGHT_LEGACY: {
2646  uint tmpS;
2647  uint tmpM;
2648 
2649  tmpM = INT_MULT(dst_r, src_r);
2650  tmpS = 255 - INT_MULT((255 - dst_r), (255 - src_r));
2651  src_r = INT_MULT((255 - dst_r), tmpM) + INT_MULT(dst_r, tmpS);
2652 
2653  tmpM = INT_MULT(dst_g, src_g);
2654  tmpS = 255 - INT_MULT((255 - dst_g), (255 - src_g));
2655  src_g = INT_MULT((255 - dst_g), tmpM) + INT_MULT(dst_g, tmpS);
2656 
2657  tmpM = INT_MULT(dst_b, src_b);
2658  tmpS = 255 - INT_MULT((255 - dst_b), (255 - src_b));
2659  src_b = INT_MULT((255 - dst_b), tmpM) + INT_MULT(dst_b, tmpS);
2660 
2661  src_a = qMin(src_a, dst_a);
2662  } break;
2663  case GIMP_LAYER_MODE_GRAIN_EXTRACT_LEGACY: {
2664  int tmp;
2665 
2666  tmp = dst_r - src_r + 128;
2667  tmp = qMin(tmp, 255);
2668  tmp = qMax(tmp, 0);
2669  src_r = (uchar)tmp;
2670 
2671  tmp = dst_g - src_g + 128;
2672  tmp = qMin(tmp, 255);
2673  tmp = qMax(tmp, 0);
2674  src_g = (uchar)tmp;
2675 
2676  tmp = dst_b - src_b + 128;
2677  tmp = qMin(tmp, 255);
2678  tmp = qMax(tmp, 0);
2679  src_b = (uchar)tmp;
2680 
2681  src_a = qMin(src_a, dst_a);
2682  } break;
2683  case GIMP_LAYER_MODE_GRAIN_MERGE_LEGACY: {
2684  int tmp;
2685 
2686  tmp = dst_r + src_r - 128;
2687  tmp = qMin(tmp, 255);
2688  tmp = qMax(tmp, 0);
2689  src_r = (uchar)tmp;
2690 
2691  tmp = dst_g + src_g - 128;
2692  tmp = qMin(tmp, 255);
2693  tmp = qMax(tmp, 0);
2694  src_g = (uchar)tmp;
2695 
2696  tmp = dst_b + src_b - 128;
2697  tmp = qMin(tmp, 255);
2698  tmp = qMax(tmp, 0);
2699  src_b = (uchar)tmp;
2700 
2701  src_a = qMin(src_a, dst_a);
2702  } break;
2703  default:
2704  break;
2705  }
2706 
2707  src_a = INT_MULT(src_a, layer.opacity);
2708 
2709  // Apply the mask (if any)
2710 
2711  if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
2712  src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
2713  }
2714 
2715  uchar new_r;
2716  uchar new_g;
2717  uchar new_b;
2718  uchar new_a;
2719  new_a = dst_a + INT_MULT(OPAQUE_OPACITY - dst_a, src_a);
2720 
2721  const float src_ratio = new_a == 0 ? 1.0 : (float)src_a / new_a;
2722  float dst_ratio = 1.0 - src_ratio;
2723 
2724  new_r = (uchar)(src_ratio * src_r + dst_ratio * dst_r + EPSILON);
2725  new_g = (uchar)(src_ratio * src_g + dst_ratio * dst_g + EPSILON);
2726  new_b = (uchar)(src_ratio * src_b + dst_ratio * dst_b + EPSILON);
2727 
2728  if (!modeAffectsSourceAlpha(layer.mode)) {
2729  new_a = dst_a;
2730  }
2731 
2732  image.setPixel(m, n, qRgba(new_r, new_g, new_b, new_a));
2733 }
2734 
2735 /*!
2736  * Merge a Gray pixel from the layer to the Gray image. Straight-forward.
2737  * \param layer source layer.
2738  * \param i x tile index.
2739  * \param j y tile index.
2740  * \param k x pixel index of tile i,j.
2741  * \param l y pixel index of tile i,j.
2742  * \param image destination image.
2743  * \param m x pixel of destination image.
2744  * \param n y pixel of destination image.
2745  */
2746 void XCFImageFormat::mergeGrayToGray(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
2747 {
2748  int src = layer.image_tiles[j][i].pixelIndex(k, l);
2749  image.setPixel(m, n, src);
2750 }
2751 
2752 /*!
2753  * Merge a GrayA pixel from the layer to the Gray image. Straight-forward.
2754  * \param layer source layer.
2755  * \param i x tile index.
2756  * \param j y tile index.
2757  * \param k x pixel index of tile i,j.
2758  * \param l y pixel index of tile i,j.
2759  * \param image destination image.
2760  * \param m x pixel of destination image.
2761  * \param n y pixel of destination image.
2762  */
2763 void XCFImageFormat::mergeGrayAToGray(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
2764 {
2765  int src = qGray(layer.image_tiles[j][i].pixel(k, l));
2766  int dst = image.pixelIndex(m, n);
2767 
2768  uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
2769 
2770  if (!src_a) {
2771  return; // nothing to merge
2772  }
2773 
2774  switch (layer.mode) {
2775  case MULTIPLY_MODE: {
2776  src = INT_MULT(src, dst);
2777  } break;
2778  case DIVIDE_MODE: {
2779  src = qMin((dst * 256) / (1 + src), 255);
2780  } break;
2781  case SCREEN_MODE: {
2782  src = 255 - INT_MULT(255 - dst, 255 - src);
2783  } break;
2784  case OVERLAY_MODE: {
2785  src = INT_MULT(dst, dst + INT_MULT(2 * src, 255 - dst));
2786  } break;
2787  case DIFFERENCE_MODE: {
2788  src = dst > src ? dst - src : src - dst;
2789  } break;
2790  case ADDITION_MODE: {
2791  src = add_lut(dst, src);
2792  } break;
2793  case SUBTRACT_MODE: {
2794  src = dst > src ? dst - src : 0;
2795  } break;
2796  case DARKEN_ONLY_MODE: {
2797  src = dst < src ? dst : src;
2798  } break;
2799  case LIGHTEN_ONLY_MODE: {
2800  src = dst < src ? src : dst;
2801  } break;
2802  case DODGE_MODE: {
2803  uint tmp = dst << 8;
2804  tmp /= 256 - src;
2805  src = (uchar)qMin(tmp, 255u);
2806  } break;
2807  case BURN_MODE: {
2808  uint tmp = (255 - dst) << 8;
2809  tmp /= src + 1;
2810  src = (uchar)qMin(tmp, 255u);
2811  src = 255 - src;
2812  } break;
2813  case HARDLIGHT_MODE: {
2814  uint tmp;
2815  if (src > 128) {
2816  tmp = ((int)255 - dst) * ((int)255 - ((src - 128) << 1));
2817  src = (uchar)qMin(255 - (tmp >> 8), 255u);
2818  } else {
2819  tmp = (int)dst * ((int)src << 1);
2820  src = (uchar)qMin(tmp >> 8, 255u);
2821  }
2822  } break;
2823  case SOFTLIGHT_MODE: {
2824  uint tmpS;
2825  uint tmpM;
2826 
2827  tmpM = INT_MULT(dst, src);
2828  tmpS = 255 - INT_MULT((255 - dst), (255 - src));
2829  src = INT_MULT((255 - dst), tmpM) + INT_MULT(dst, tmpS);
2830 
2831  } break;
2832  case GRAIN_EXTRACT_MODE: {
2833  int tmp;
2834 
2835  tmp = dst - src + 128;
2836  tmp = qMin(tmp, 255);
2837  tmp = qMax(tmp, 0);
2838 
2839  src = (uchar)tmp;
2840  } break;
2841  case GRAIN_MERGE_MODE: {
2842  int tmp;
2843 
2844  tmp = dst + src - 128;
2845  tmp = qMin(tmp, 255);
2846  tmp = qMax(tmp, 0);
2847 
2848  src = (uchar)tmp;
2849  } break;
2850  }
2851 
2852  src_a = INT_MULT(src_a, layer.opacity);
2853 
2854  // Apply the mask (if any)
2855 
2856  if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
2857  src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
2858  }
2859 
2860  uchar new_a = OPAQUE_OPACITY;
2861 
2862  const float src_ratio = new_a == 0 ? 1.0 : (float)src_a / new_a;
2863  float dst_ratio = 1.0 - src_ratio;
2864 
2865  uchar new_g = (uchar)(src_ratio * src + dst_ratio * dst + EPSILON);
2866 
2867  image.setPixel(m, n, new_g);
2868 }
2869 
2870 /*!
2871  * Merge a Gray pixel from the layer to an RGB image. Straight-forward.
2872  * The only thing this has to take account of is the opacity of the
2873  * layer. Evidently, the GIMP exporter itself does not actually do this.
2874  * \param layer source layer.
2875  * \param i x tile index.
2876  * \param j y tile index.
2877  * \param k x pixel index of tile i,j.
2878  * \param l y pixel index of tile i,j.
2879  * \param image destination image.
2880  * \param m x pixel of destination image.
2881  * \param n y pixel of destination image.
2882  */
2883 void XCFImageFormat::mergeGrayToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
2884 {
2885  QRgb src = layer.image_tiles[j][i].pixel(k, l);
2886  uchar src_a = layer.opacity;
2887  image.setPixel(m, n, qRgba(src, src_a));
2888 }
2889 
2890 /*!
2891  * Merge a GrayA pixel from the layer to an RGB image. Straight-forward.
2892  * The only thing this has to take account of is the opacity of the
2893  * layer. Evidently, the GIMP exporter itself does not actually do this.
2894  * \param layer source layer.
2895  * \param i x tile index.
2896  * \param j y tile index.
2897  * \param k x pixel index of tile i,j.
2898  * \param l y pixel index of tile i,j.
2899  * \param image destination image.
2900  * \param m x pixel of destination image.
2901  * \param n y pixel of destination image.
2902  */
2903 void XCFImageFormat::mergeGrayAToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
2904 {
2905  int src = qGray(layer.image_tiles[j][i].pixel(k, l));
2906  int dst = qGray(image.pixel(m, n));
2907 
2908  uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
2909  uchar dst_a = qAlpha(image.pixel(m, n));
2910 
2911  if (!src_a) {
2912  return; // nothing to merge
2913  }
2914 
2915  switch (layer.mode) {
2916  case MULTIPLY_MODE: {
2917  src = INT_MULT(src, dst);
2918  src_a = qMin(src_a, dst_a);
2919  } break;
2920  case DIVIDE_MODE: {
2921  src = qMin((dst * 256) / (1 + src), 255);
2922  src_a = qMin(src_a, dst_a);
2923  } break;
2924  case SCREEN_MODE: {
2925  src = 255 - INT_MULT(255 - dst, 255 - src);
2926  src_a = qMin(src_a, dst_a);
2927  } break;
2928  case OVERLAY_MODE: {
2929  src = INT_MULT(dst, dst + INT_MULT(2 * src, 255 - dst));
2930  src_a = qMin(src_a, dst_a);
2931  } break;
2932  case DIFFERENCE_MODE: {
2933  src = dst > src ? dst - src : src - dst;
2934  src_a = qMin(src_a, dst_a);
2935  } break;
2936  case ADDITION_MODE: {
2937  src = add_lut(dst, src);
2938  src_a = qMin(src_a, dst_a);
2939  } break;
2940  case SUBTRACT_MODE: {
2941  src = dst > src ? dst - src : 0;
2942  src_a = qMin(src_a, dst_a);
2943  } break;
2944  case DARKEN_ONLY_MODE: {
2945  src = dst < src ? dst : src;
2946  src_a = qMin(src_a, dst_a);
2947  } break;
2948  case LIGHTEN_ONLY_MODE: {
2949  src = dst < src ? src : dst;
2950  src_a = qMin(src_a, dst_a);
2951  } break;
2952  case DODGE_MODE: {
2953  uint tmp = dst << 8;
2954  tmp /= 256 - src;
2955  src = (uchar)qMin(tmp, 255u);
2956  src_a = qMin(src_a, dst_a);
2957  } break;
2958  case BURN_MODE: {
2959  uint tmp = (255 - dst) << 8;
2960  tmp /= src + 1;
2961  src = (uchar)qMin(tmp, 255u);
2962  src = 255 - src;
2963  src_a = qMin(src_a, dst_a);
2964  } break;
2965  case HARDLIGHT_MODE: {
2966  uint tmp;
2967  if (src > 128) {
2968  tmp = ((int)255 - dst) * ((int)255 - ((src - 128) << 1));
2969  src = (uchar)qMin(255 - (tmp >> 8), 255u);
2970  } else {
2971  tmp = (int)dst * ((int)src << 1);
2972  src = (uchar)qMin(tmp >> 8, 255u);
2973  }
2974  src_a = qMin(src_a, dst_a);
2975  } break;
2976  case SOFTLIGHT_MODE: {
2977  uint tmpS;
2978  uint tmpM;
2979 
2980  tmpM = INT_MULT(dst, src);
2981  tmpS = 255 - INT_MULT((255 - dst), (255 - src));
2982  src = INT_MULT((255 - dst), tmpM) + INT_MULT(dst, tmpS);
2983 
2984  src_a = qMin(src_a, dst_a);
2985  } break;
2986  case GRAIN_EXTRACT_MODE: {
2987  int tmp;
2988 
2989  tmp = dst - src + 128;
2990  tmp = qMin(tmp, 255);
2991  tmp = qMax(tmp, 0);
2992 
2993  src = (uchar)tmp;
2994  src_a = qMin(src_a, dst_a);
2995  } break;
2996  case GRAIN_MERGE_MODE: {
2997  int tmp;
2998 
2999  tmp = dst + src - 128;
3000  tmp = qMin(tmp, 255);
3001  tmp = qMax(tmp, 0);
3002 
3003  src = (uchar)tmp;
3004  src_a = qMin(src_a, dst_a);
3005  } break;
3006  }
3007 
3008  src_a = INT_MULT(src_a, layer.opacity);
3009 
3010  // Apply the mask (if any)
3011  if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
3012  src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
3013  }
3014 
3015  uchar new_a = dst_a + INT_MULT(OPAQUE_OPACITY - dst_a, src_a);
3016 
3017  const float src_ratio = new_a == 0 ? 1.0 : (float)src_a / new_a;
3018  float dst_ratio = 1.0 - src_ratio;
3019 
3020  uchar new_g = (uchar)(src_ratio * src + dst_ratio * dst + EPSILON);
3021 
3022  if (!modeAffectsSourceAlpha(layer.mode)) {
3023  new_a = dst_a;
3024  }
3025 
3026  image.setPixel(m, n, qRgba(new_g, new_g, new_g, new_a));
3027 }
3028 
3029 /*!
3030  * Merge an Indexed pixel from the layer to the Indexed image. Straight-forward.
3031  * \param layer source layer.
3032  * \param i x tile index.
3033  * \param j y tile index.
3034  * \param k x pixel index of tile i,j.
3035  * \param l y pixel index of tile i,j.
3036  * \param image destination image.
3037  * \param m x pixel of destination image.
3038  * \param n y pixel of destination image.
3039  */
3040 void XCFImageFormat::mergeIndexedToIndexed(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
3041 {
3042  int src = layer.image_tiles[j][i].pixelIndex(k, l);
3043  image.setPixel(m, n, src);
3044 }
3045 
3046 /*!
3047  * Merge an IndexedA pixel from the layer to the Indexed image. Straight-forward.
3048  * \param layer source layer.
3049  * \param i x tile index.
3050  * \param j y tile index.
3051  * \param k x pixel index of tile i,j.
3052  * \param l y pixel index of tile i,j.
3053  * \param image destination image.
3054  * \param m x pixel of destination image.
3055  * \param n y pixel of destination image.
3056  */
3057 void XCFImageFormat::mergeIndexedAToIndexed(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
3058 {
3059  uchar src = layer.image_tiles[j][i].pixelIndex(k, l);
3060  uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
3061  src_a = INT_MULT(src_a, layer.opacity);
3062 
3063  if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
3064  src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
3065  }
3066 
3067  if (src_a > 127) {
3068  src++;
3069  image.setPixel(m, n, src);
3070  }
3071 }
3072 
3073 /*!
3074  * Merge an IndexedA pixel from the layer to an RGB image. Straight-forward.
3075  * The only thing this has to take account of is the opacity of the
3076  * layer. Evidently, the GIMP exporter itself does not actually do this.
3077  * \param layer source layer.
3078  * \param i x tile index.
3079  * \param j y tile index.
3080  * \param k x pixel index of tile i,j.
3081  * \param l y pixel index of tile i,j.
3082  * \param image destination image.
3083  * \param m x pixel of destination image.
3084  * \param n y pixel of destination image.
3085  */
3086 void XCFImageFormat::mergeIndexedAToRGB(const Layer &layer, uint i, uint j, int k, int l, QImage &image, int m, int n)
3087 {
3088  QRgb src = layer.image_tiles[j][i].pixel(k, l);
3089  uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
3090  src_a = INT_MULT(src_a, layer.opacity);
3091 
3092  // Apply the mask (if any)
3093  if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j && layer.mask_tiles[j].size() > (int)i) {
3094  src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
3095  }
3096 
3097  // This is what appears in the GIMP window
3098  if (src_a <= 127) {
3099  src_a = 0;
3100  } else {
3101  src_a = OPAQUE_OPACITY;
3102  }
3103 
3104  image.setPixel(m, n, qRgba(src, src_a));
3105 }
3106 
3107 /*!
3108  * Dissolving pixels: pick a random number between 0 and 255. If the pixel's
3109  * alpha is less than that, make it transparent.
3110  * \param image the image tile to dissolve.
3111  * \param x the global x position of the tile.
3112  * \param y the global y position of the tile.
3113  */
3114 void XCFImageFormat::dissolveRGBPixels(QImage &image, int x, int y)
3115 {
3116  // The apparently spurious rand() calls are to wind the random
3117  // numbers up to the same point for each tile.
3118 
3119  for (int l = 0; l < image.height(); l++) {
3120  unsigned int next = randomTable.values[(l + y) % RANDOM_TABLE_SIZE];
3121 
3122  for (int k = 0; k < x; k++) {
3123  RandomTable::rand_r(&next);
3124  }
3125 
3126  for (int k = 0; k < image.width(); k++) {
3127  int rand_val = RandomTable::rand_r(&next) & 0xff;
3128  QRgb pixel = image.pixel(k, l);
3129 
3130  if (rand_val > qAlpha(pixel)) {
3131  image.setPixel(k, l, qRgba(pixel, 0));
3132  }
3133  }
3134  }
3135 }
3136 
3137 /*!
3138  * Dissolving pixels: pick a random number between 0 and 255. If the pixel's
3139  * alpha is less than that, make it transparent. This routine works for
3140  * the GRAYA and INDEXEDA image types where the pixel alpha's are stored
3141  * separately from the pixel themselves.
3142  * \param image the alpha tile to dissolve.
3143  * \param x the global x position of the tile.
3144  * \param y the global y position of the tile.
3145  */
3146 void XCFImageFormat::dissolveAlphaPixels(QImage &image, int x, int y)
3147 {
3148  // The apparently spurious rand() calls are to wind the random
3149  // numbers up to the same point for each tile.
3150 
3151  for (int l = 0; l < image.height(); l++) {
3152  unsigned int next = randomTable.values[(l + y) % RANDOM_TABLE_SIZE];
3153 
3154  for (int k = 0; k < x; k++) {
3155  RandomTable::rand_r(&next);
3156  }
3157 
3158  for (int k = 0; k < image.width(); k++) {
3159  int rand_val = RandomTable::rand_r(&next) & 0xff;
3160  uchar alpha = image.pixelIndex(k, l);
3161 
3162  if (rand_val > alpha) {
3163  image.setPixel(k, l, 0);
3164  }
3165  }
3166  }
3167 }
3168 
3169 ///////////////////////////////////////////////////////////////////////////////
3170 
3171 XCFHandler::XCFHandler()
3172 {
3173 }
3174 
3175 bool XCFHandler::canRead() const
3176 {
3177  if (canRead(device())) {
3178  setFormat("xcf");
3179  return true;
3180  }
3181  return false;
3182 }
3183 
3184 bool XCFHandler::read(QImage *image)
3185 {
3186  XCFImageFormat xcfif;
3187  return xcfif.readXCF(device(), image);
3188 }
3189 
3190 bool XCFHandler::write(const QImage &)
3191 {
3192  return false;
3193 }
3194 
3195 bool XCFHandler::canRead(QIODevice *device)
3196 {
3197  if (!device) {
3198  qCDebug(XCFPLUGIN) << "XCFHandler::canRead() called with no device";
3199  return false;
3200  }
3201 
3202  qint64 oldPos = device->pos();
3203 
3204  char head[8];
3205  qint64 readBytes = device->read(head, sizeof(head));
3206  if (readBytes != sizeof(head)) {
3207  if (device->isSequential()) {
3208  while (readBytes > 0) {
3209  device->ungetChar(head[readBytes-- - 1]);
3210  }
3211  } else {
3212  device->seek(oldPos);
3213  }
3214  return false;
3215  }
3216 
3217  if (device->isSequential()) {
3218  while (readBytes > 0) {
3219  device->ungetChar(head[readBytes-- - 1]);
3220  }
3221  } else {
3222  device->seek(oldPos);
3223  }
3224 
3225  return qstrncmp(head, "gimp xcf", 8) == 0;
3226 }
3227 
3228 QImageIOPlugin::Capabilities XCFPlugin::capabilities(QIODevice *device, const QByteArray &format) const
3229 {
3230  if (format == "xcf") {
3231  return Capabilities(CanRead);
3232  }
3233  if (!format.isEmpty()) {
3234  return {};
3235  }
3236  if (!device->isOpen()) {
3237  return {};
3238  }
3239 
3240  Capabilities cap;
3241  if (device->isReadable() && XCFHandler::canRead(device)) {
3242  cap |= CanRead;
3243  }
3244  return cap;
3245 }
3246 
3247 QImageIOHandler *XCFPlugin::create(QIODevice *device, const QByteArray &format) const
3248 {
3249  QImageIOHandler *handler = new XCFHandler;
3250  handler->setDevice(device);
3251  handler->setFormat(format);
3252  return handler;
3253 }
3254 
3255 // Just so I can get enum values printed
3256 #include "xcf.moc"
void setDotsPerMeterX(int x)
void setDotsPerMeterY(int y)
virtual bool atEnd() const const
virtual bool seek(qint64 pos)
void push(const T &t)
void setPixel(int x, int y, uint index_or_rgb)
int colorCount() const const
bool isEmpty() const const
void setColorCount(int colorCount)
MESSAGECORE_EXPORT KMime::Content * next(KMime::Content *node, bool allowChildren=true)
bool isNull() const const
bool isReadable() const const
const QLatin1String name
virtual bool isSequential() const const
int readRawData(char *s, int len)
virtual qint64 pos() const const
QVector< V > values(const QMultiHash< K, V > &c)
KIOCORE_EXPORT CopyJob * copy(const QUrl &src, const QUrl &dest, JobFlags flags=DefaultFlags)
QRgb pixel(int x, int y) const const
PartitionTable::TableType type
QString fromUtf8(const char *str, int size)
void fill(uint pixelValue)
int width() const const
void setDevice(QIODevice *device)
qint64 read(char *data, qint64 maxSize)
bool isOpen() const const
CompositionMode_Source
int bytesPerLine() const const
bool isEmpty() const const
void setColorTable(const QVector< QRgb > colors)
char * data()
uchar * bits()
typedef Capabilities
void setFormat(const QByteArray &format)
int height() const const
int pixelIndex(int x, int y) const const
QIODevice * device() const const
int version() const const
int size() const const
int size() const const
QVariant merge(const QVariant &lhs, const QVariant &rhs)
void ungetChar(char c)
int skipRawData(int len)
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Thu Dec 2 2021 22:45:39 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.