some more win32'fication to fix non-ascii filename handling
[kdelibs.git] / kimgio / xcf.cpp
blob3ca6718b6a76ad246d6d6eef3b8b5133c8d2efdd
1 /*
2 * qxcfi.cpp: A Qt 3 plug-in for reading GIMP XCF image files
3 * Copyright (C) 2001 lignum Computing, Inc. <allen@lignumcomputing.com>
4 * Copyright (C) 2004 Melchior FRANZ <mfranz@kde.org>
6 * This plug-in is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "xcf.h"
24 #include <stdlib.h>
25 #include <QtGui/QImage>
26 #include <QtCore/QIODevice>
27 #include <QtCore/QStack>
28 #include <QtCore/QVector>
30 #include <kdebug.h>
33 int XCFImageFormat::random_table[RANDOM_TABLE_SIZE];
35 //int XCFImageFormat::add_lut[256][256];
38 const XCFImageFormat::LayerModes XCFImageFormat::layer_modes[] = {
39 {true}, // NORMAL_MODE
40 {true}, // DISSOLVE_MODE
41 {true}, // BEHIND_MODE
42 {false}, // MULTIPLY_MODE
43 {false}, // SCREEN_MODE
44 {false}, // OVERLAY_MODE
45 {false}, // DIFFERENCE_MODE
46 {false}, // ADDITION_MODE
47 {false}, // SUBTRACT_MODE
48 {false}, // DARKEN_ONLY_MODE
49 {false}, // LIGHTEN_ONLY_MODE
50 {false}, // HUE_MODE
51 {false}, // SATURATION_MODE
52 {false}, // COLOR_MODE
53 {false}, // VALUE_MODE
54 {false}, // DIVIDE_MODE
55 {false}, // DODGE_MODE
56 {false}, // BURN_MODE
57 {false}, // HARDLIGHT_MODE
58 {false}, // SOFTLIGHT_MODE
59 {false}, // GRAIN_EXTRACT_MODE
60 {false}, // GRAIN_MERGE_MODE
64 //! Change a QRgb value's alpha only.
65 inline QRgb qRgba ( const QRgb& rgb, int a )
67 return ((a & 0xff) << 24 | (rgb & RGB_MASK));
71 /*!
72 * The constructor for the XCF image loader. This initializes the
73 * tables used in the layer merging routines.
75 XCFImageFormat::XCFImageFormat()
77 // From GIMP "paint_funcs.c" v1.2
78 srand(RANDOM_SEED);
80 for (int i = 0; i < RANDOM_TABLE_SIZE; i++)
81 random_table[i] = rand();
83 for (int i = 0; i < RANDOM_TABLE_SIZE; i++) {
84 int tmp;
85 int swap = i + rand() % (RANDOM_TABLE_SIZE - i);
86 tmp = random_table[i];
87 random_table[i] = random_table[swap];
88 random_table[swap] = tmp;
91 // for (int j = 0; j < 256; j++) {
92 // for (int k = 0; k < 256; k++) {
93 // int tmp_sum = j + k;
94 // if (tmp_sum > 255)
95 // tmp_sum = 255;
96 // add_lut[j][k] = tmp_sum;
97 // }
98 // }
101 inline
102 int XCFImageFormat::add_lut( int a, int b ) {
103 return qMin( a + b, 255 );
106 bool XCFImageFormat::readXCF(QIODevice *device, QImage *outImage)
108 XCFImage xcf_image;
109 QDataStream xcf_io(device);
111 char tag[14];;
113 if (xcf_io.readRawData(tag, sizeof(tag)) != sizeof(tag)) {
114 kDebug(399) << "XCF: read failure on header tag";
115 return false;
118 xcf_io >> xcf_image.width >> xcf_image.height >> xcf_image.type;
120 kDebug() << tag << " " << xcf_image.width << " " << xcf_image.height << " " << xcf_image.type;
121 if (!loadImageProperties(xcf_io, xcf_image))
122 return false;
124 // The layers appear to be stored in top-to-bottom order. This is
125 // the reverse of how a merged image must be computed. So, the layer
126 // offsets are pushed onto a LIFO stack (thus, we don't have to load
127 // all the data of all layers before beginning to construct the
128 // merged image).
130 QStack<qint32> layer_offsets;
132 while (true) {
133 qint32 layer_offset;
135 xcf_io >> layer_offset;
137 if (layer_offset == 0)
138 break;
140 layer_offsets.push(layer_offset);
143 xcf_image.num_layers = layer_offsets.size();
145 if (layer_offsets.size() == 0) {
146 kDebug(399) << "XCF: no layers!";
147 return false;
150 // Load each layer and add it to the image
151 while (!layer_offsets.isEmpty()) {
152 qint32 layer_offset = layer_offsets.pop();
154 xcf_io.device()->seek(layer_offset);
156 if (!loadLayer(xcf_io, xcf_image))
157 return false;
160 if (!xcf_image.initialized) {
161 kDebug(399) << "XCF: no visible layers!";
162 return false;
165 *outImage = xcf_image.image;
166 return true;
171 * An XCF file can contain an arbitrary number of properties associated
172 * with the image (and layer and mask).
173 * \param xcf_io the data stream connected to the XCF image
174 * \param xcf_image XCF image data.
175 * \return true if there were no I/O errors.
177 bool XCFImageFormat::loadImageProperties(QDataStream& xcf_io, XCFImage& xcf_image)
179 while (true) {
180 PropType type;
181 QByteArray bytes;
183 if (!loadProperty(xcf_io, type, bytes)) {
184 kDebug(399) << "XCF: error loading global image properties";
185 return false;
188 QDataStream property(bytes);
190 switch (type) {
191 case PROP_END:
192 return true;
194 case PROP_COMPRESSION:
195 property >> xcf_image.compression;
196 break;
198 case PROP_RESOLUTION:
199 property >> xcf_image.x_resolution >> xcf_image.y_resolution;
200 break;
202 case PROP_TATTOO:
203 property >> xcf_image.tattoo;
204 break;
206 case PROP_PARASITES:
207 while (!property.atEnd()) {
208 char* tag;
209 quint32 size;
211 property.readBytes(tag, size);
213 quint32 flags;
214 char* data=0;
215 property >> flags >> data;
217 if (tag && strncmp(tag, "gimp-comment", strlen("gimp-comment")) == 0)
218 xcf_image.image.setText("Comment", 0, data);
220 delete[] tag;
221 delete[] data;
223 break;
225 case PROP_UNIT:
226 property >> xcf_image.unit;
227 break;
229 case PROP_PATHS: // This property is ignored.
230 break;
232 case PROP_USER_UNIT: // This property is ignored.
233 break;
235 case PROP_COLORMAP:
236 property >> xcf_image.num_colors;
237 if(xcf_image.num_colors < 0 || xcf_image.num_colors > 65535)
238 return false;
240 xcf_image.palette.reserve(xcf_image.num_colors);
242 for (int i = 0; i < xcf_image.num_colors; i++) {
243 uchar r, g, b;
244 property >> r >> g >> b;
245 xcf_image.palette.push_back( qRgb(r,g,b) );
247 break;
249 default:
250 kDebug(399) << "XCF: unimplemented image property" << type
251 << ", size " << bytes.size() << endl;
258 * Read a single property from the image file. The property type is returned
259 * in type and the data is returned in bytes.
260 * \param xcf the image file data stream.
261 * \param type returns with the property type.
262 * \param bytes returns with the property data.
263 * \return true if there were no IO errors. */
264 bool XCFImageFormat::loadProperty(QDataStream& xcf_io, PropType& type, QByteArray& bytes)
266 quint32 foo;
267 xcf_io >> foo;
268 type=PropType(foo); // TODO urks
270 char* data = 0;
271 quint32 size;
273 // The colormap property size is not the correct number of bytes:
274 // The GIMP source xcf.c has size = 4 + ncolors, but it should be
275 // 4 + 3 * ncolors
277 if (type == PROP_COLORMAP) {
278 xcf_io >> size;
280 if(size > 65535 || size < 4)
281 return false;
283 size = 3 * (size - 4) + 4;
284 data = new char[size];
286 xcf_io.readRawData(data, size);
287 } else if (type == PROP_USER_UNIT) {
288 // The USER UNIT property size is not correct. I'm not sure why, though.
289 float factor;
290 qint32 digits;
292 xcf_io >> size >> factor >> digits;
294 for (int i = 0; i < 5; i++) {
295 char* unit_strings;
297 xcf_io >> unit_strings;
299 delete[] unit_strings;
301 if (xcf_io.device()->atEnd()) {
302 kDebug(399) << "XCF: read failure on property " << type;
303 return false;
307 size = 0;
308 } else {
309 xcf_io >> size;
310 if(size >256000)
311 return false;
312 data = new char[size];
313 xcf_io.readRawData(data, size);
316 if (size != 0 && data)
317 bytes = QByteArray(data,size);
319 delete [] data;
321 return true;
326 * Load a layer from the XCF file. The data stream must be positioned at
327 * the beginning of the layer data.
328 * \param xcf_io the image file data stream.
329 * \param xcf_image contains the layer and the color table
330 * (if the image is indexed).
331 * \return true if there were no I/O errors.
333 bool XCFImageFormat::loadLayer(QDataStream& xcf_io, XCFImage& xcf_image)
335 Layer& layer(xcf_image.layer);
336 delete[] layer.name;
338 xcf_io >> layer.width >> layer.height >> layer.type >> layer.name;
340 if (!loadLayerProperties(xcf_io, layer))
341 return false;
342 #if 0
343 cout << "layer: \"" << layer.name << "\", size: " << layer.width << " x "
344 << layer.height << ", type: " << layer.type << ", mode: " << layer.mode
345 << ", opacity: " << layer.opacity << ", visible: " << layer.visible
346 << ", offset: " << layer.x_offset << ", " << layer.y_offset << endl;
347 #endif
348 // Skip reading the rest of it if it is not visible. Typically, when
349 // you export an image from the The GIMP it flattens (or merges) only
350 // the visible layers into the output image.
352 if (layer.visible == 0)
353 return true;
355 // If there are any more layers, merge them into the final QImage.
357 xcf_io >> layer.hierarchy_offset >> layer.mask_offset;
359 // Allocate the individual tile QImages based on the size and type
360 // of this layer.
362 if( !composeTiles(xcf_image))
363 return false;
364 xcf_io.device()->seek(layer.hierarchy_offset);
366 // As tiles are loaded, they are copied into the layers tiles by
367 // this routine. (loadMask(), below, uses a slightly different
368 // version of assignBytes().)
370 layer.assignBytes = assignImageBytes;
372 if (!loadHierarchy(xcf_io, layer))
373 return false;
375 if (layer.mask_offset != 0) {
376 xcf_io.device()->seek(layer.mask_offset);
378 if (!loadMask(xcf_io, layer))
379 return false;
382 // Now we should have enough information to initialize the final
383 // QImage. The first visible layer determines the attributes
384 // of the QImage.
386 if (!xcf_image.initialized) {
387 if( !initializeImage(xcf_image))
388 return false;
389 copyLayerToImage(xcf_image);
390 xcf_image.initialized = true;
391 } else
392 mergeLayerIntoImage(xcf_image);
394 return true;
399 * An XCF file can contain an arbitrary number of properties associated
400 * with a layer.
401 * \param xcf_io the data stream connected to the XCF image.
402 * \param layer layer to collect the properties.
403 * \return true if there were no I/O errors.
405 bool XCFImageFormat::loadLayerProperties(QDataStream& xcf_io, Layer& layer)
407 while (true) {
408 PropType type;
409 QByteArray bytes;
411 if (!loadProperty(xcf_io, type, bytes)) {
412 kDebug(399) << "XCF: error loading layer properties";
413 return false;
416 QDataStream property(bytes);
418 switch (type) {
419 case PROP_END:
420 return true;
422 case PROP_ACTIVE_LAYER:
423 layer.active = true;
424 break;
426 case PROP_OPACITY:
427 property >> layer.opacity;
428 break;
430 case PROP_VISIBLE:
431 property >> layer.visible;
432 break;
434 case PROP_LINKED:
435 property >> layer.linked;
436 break;
438 case PROP_PRESERVE_TRANSPARENCY:
439 property >> layer.preserve_transparency;
440 break;
442 case PROP_APPLY_MASK:
443 property >> layer.apply_mask;
444 break;
446 case PROP_EDIT_MASK:
447 property >> layer.edit_mask;
448 break;
450 case PROP_SHOW_MASK:
451 property >> layer.show_mask;
452 break;
454 case PROP_OFFSETS:
455 property >> layer.x_offset >> layer.y_offset;
456 break;
458 case PROP_MODE:
459 property >> layer.mode;
460 break;
462 case PROP_TATTOO:
463 property >> layer.tattoo;
464 break;
466 default:
467 kDebug(399) << "XCF: unimplemented layer property " << type
468 << ", size " << bytes.size() << endl;
475 * Compute the number of tiles in the current layer and allocate
476 * QImage structures for each of them.
477 * \param xcf_image contains the current layer.
479 bool XCFImageFormat::composeTiles(XCFImage& xcf_image)
481 Layer& layer(xcf_image.layer);
483 layer.nrows = (layer.height + TILE_HEIGHT - 1) / TILE_HEIGHT;
484 layer.ncols = (layer.width + TILE_WIDTH - 1) / TILE_WIDTH;
486 layer.image_tiles.resize(layer.nrows);
488 if (layer.type == GRAYA_GIMAGE || layer.type == INDEXEDA_GIMAGE)
489 layer.alpha_tiles.resize(layer.nrows);
491 if (layer.mask_offset != 0)
492 layer.mask_tiles.resize(layer.nrows);
494 for (uint j = 0; j < layer.nrows; j++) {
495 layer.image_tiles[j].resize(layer.ncols);
497 if (layer.type == GRAYA_GIMAGE || layer.type == INDEXEDA_GIMAGE)
498 layer.alpha_tiles[j].resize(layer.ncols);
500 if (layer.mask_offset != 0)
501 layer.mask_tiles[j].resize(layer.ncols);
504 for (uint j = 0; j < layer.nrows; j++) {
505 for (uint i = 0; i < layer.ncols; i++) {
507 uint tile_width = (i + 1) * TILE_WIDTH <= layer.width
508 ? TILE_WIDTH : layer.width - i * TILE_WIDTH;
510 uint tile_height = (j + 1) * TILE_HEIGHT <= layer.height
511 ? TILE_HEIGHT : layer.height - j * TILE_HEIGHT;
513 // Try to create the most appropriate QImage (each GIMP layer
514 // type is treated slightly differently)
516 switch (layer.type) {
517 case RGB_GIMAGE:
518 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_RGB32);
519 layer.image_tiles[j][i].setNumColors(0);
520 if( layer.image_tiles[j][i].isNull())
521 return false;
522 break;
524 case RGBA_GIMAGE:
525 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_ARGB32);
526 layer.image_tiles[j][i].setNumColors(0);
527 if( layer.image_tiles[j][i].isNull())
528 return false;
529 break;
531 case GRAY_GIMAGE:
532 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
533 layer.image_tiles[j][i].setNumColors(256);
534 if( layer.image_tiles[j][i].isNull())
535 return false;
536 setGrayPalette(layer.image_tiles[j][i]);
537 break;
539 case GRAYA_GIMAGE:
540 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
541 layer.image_tiles[j][i].setNumColors(256);
542 if( layer.image_tiles[j][i].isNull())
543 return false;
544 setGrayPalette(layer.image_tiles[j][i]);
546 layer.alpha_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
547 layer.alpha_tiles[j][i].setNumColors(256);
548 if( layer.alpha_tiles[j][i].isNull())
549 return false;
550 setGrayPalette(layer.alpha_tiles[j][i]);
551 break;
553 case INDEXED_GIMAGE:
554 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
555 layer.image_tiles[j][i].setNumColors(xcf_image.num_colors);
556 if( layer.image_tiles[j][i].isNull())
557 return false;
558 setPalette(xcf_image, layer.image_tiles[j][i]);
559 break;
561 case INDEXEDA_GIMAGE:
562 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
563 layer.image_tiles[j][i].setNumColors(xcf_image.num_colors);
564 if( layer.image_tiles[j][i].isNull())
565 return false;
566 setPalette(xcf_image, layer.image_tiles[j][i]);
568 layer.alpha_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
569 layer.alpha_tiles[j][i].setNumColors(256);
570 if( layer.alpha_tiles[j][i].isNull())
571 return false;
572 setGrayPalette(layer.alpha_tiles[j][i]);
575 if (layer.mask_offset != 0) {
576 layer.mask_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
577 layer.mask_tiles[j][i].setNumColors(256);
578 if( layer.mask_tiles[j][i].isNull())
579 return false;
580 setGrayPalette(layer.mask_tiles[j][i]);
584 return true;
589 * Apply a grayscale palette to the QImage. Note that Qt does not distinguish
590 * between grayscale and indexed images. A grayscale image is just
591 * an indexed image with a 256-color, grayscale palette.
592 * \param image image to set to a grayscale palette.
594 void XCFImageFormat::setGrayPalette(QImage& image)
596 for (int i = 0; i < 256; i++)
597 image.setColor(i, qRgb(i, i, i));
602 * Copy the indexed palette from the XCF image into the QImage.
603 * \param xcf_image XCF image containing the palette read from the data stream.
604 * \param image image to apply the palette to.
606 void XCFImageFormat::setPalette(XCFImage& xcf_image, QImage& image)
608 for (int i = 0; i < xcf_image.num_colors; i++)
609 image.setColor(i, xcf_image.palette[i]);
614 * Copy the bytes from the tile buffer into the image tile QImage, taking into
615 * account all the myriad different modes.
616 * \param layer layer containing the tile buffer and the image tile matrix.
617 * \param i column index of current tile.
618 * \param j row index of current tile.
620 void XCFImageFormat::assignImageBytes(Layer& layer, uint i, uint j)
622 uchar* tile = layer.tile;
624 switch (layer.type) {
625 case RGB_GIMAGE:
626 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
627 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
628 layer.image_tiles[j][i].setPixel(k, l,
629 qRgb(tile[0], tile[1], tile[2]));
630 tile += sizeof(QRgb);
633 break;
635 case RGBA_GIMAGE:
636 for ( int l = 0; l < layer.image_tiles[j][i].height(); l++ ) {
637 for ( int k = 0; k < layer.image_tiles[j][i].width(); k++ ) {
638 layer.image_tiles[j][i].setPixel(k, l,
639 qRgba(tile[0], tile[1], tile[2], tile[3]));
640 tile += sizeof(QRgb);
643 break;
645 case GRAY_GIMAGE:
646 case INDEXED_GIMAGE:
647 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
648 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
649 layer.image_tiles[j][i].setPixel(k, l, tile[0]);
650 tile += sizeof(QRgb);
653 break;
655 case GRAYA_GIMAGE:
656 case INDEXEDA_GIMAGE:
657 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
658 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
660 // The "if" here should not be necessary, but apparently there
661 // are some cases where the image can contain larger indices
662 // than there are colors in the palette. (A bug in The GIMP?)
664 if (tile[0] < layer.image_tiles[j][i].numColors())
665 layer.image_tiles[j][i].setPixel(k, l, tile[0]);
667 layer.alpha_tiles[j][i].setPixel(k, l, tile[1]);
668 tile += sizeof(QRgb);
671 break;
677 * The GIMP stores images in a "mipmap"-like hierarchy. As far as the QImage
678 * is concerned, however, only the top level (i.e., the full resolution image)
679 * is used.
680 * \param xcf_io the data stream connected to the XCF image.
681 * \param layer the layer to collect the image.
682 * \return true if there were no I/O errors.
684 bool XCFImageFormat::loadHierarchy(QDataStream& xcf_io, Layer& layer)
686 qint32 width;
687 qint32 height;
688 qint32 bpp;
689 quint32 offset;
691 xcf_io >> width >> height >> bpp >> offset;
693 // GIMP stores images in a "mipmap"-like format (multiple levels of
694 // increasingly lower resolution). Only the top level is used here,
695 // however.
697 quint32 junk;
698 do {
699 xcf_io >> junk;
701 if (xcf_io.device()->atEnd()) {
702 kDebug(399) << "XCF: read failure on layer " << layer.name << " level offsets";
703 return false;
705 } while (junk != 0);
707 qint64 saved_pos = xcf_io.device()->pos();
709 xcf_io.device()->seek(offset);
710 if (!loadLevel(xcf_io, layer, bpp))
711 return false;
713 xcf_io.device()->seek(saved_pos);
714 return true;
719 * Load one level of the image hierarchy (but only the top level is ever used).
720 * \param xcf_io the data stream connected to the XCF image.
721 * \param layer the layer to collect the image.
722 * \param bpp the number of bytes in a pixel.
723 * \return true if there were no I/O errors.
724 * \sa loadTileRLE().
726 bool XCFImageFormat::loadLevel(QDataStream& xcf_io, Layer& layer, qint32 bpp)
728 qint32 width;
729 qint32 height;
730 quint32 offset;
732 xcf_io >> width >> height >> offset;
734 if (offset == 0)
735 return true;
737 for (uint j = 0; j < layer.nrows; j++) {
738 for (uint i = 0; i < layer.ncols; i++) {
740 if (offset == 0) {
741 kDebug(399) << "XCF: incorrect number of tiles in layer " << layer.name;
742 return false;
745 qint64 saved_pos = xcf_io.device()->pos();
746 quint32 offset2;
747 xcf_io >> offset2;
749 // Evidently, RLE can occasionally expand a tile instead of compressing it!
751 if (offset2 == 0)
752 offset2 = offset + (uint)(TILE_WIDTH * TILE_HEIGHT * 4 * 1.5);
754 xcf_io.device()->seek(offset);
755 int size = layer.image_tiles[j][i].width() * layer.image_tiles[j][i].height();
757 if (!loadTileRLE(xcf_io, layer.tile, size, offset2 - offset, bpp))
758 return false;
760 // The bytes in the layer tile are juggled differently depending on
761 // the target QImage. The caller has set layer.assignBytes to the
762 // appropriate routine.
764 layer.assignBytes(layer, i, j);
766 xcf_io.device()->seek(saved_pos);
767 xcf_io >> offset;
771 return true;
776 * A layer can have a one channel image which is used as a mask.
777 * \param xcf_io the data stream connected to the XCF image.
778 * \param layer the layer to collect the mask image.
779 * \return true if there were no I/O errors.
781 bool XCFImageFormat::loadMask(QDataStream& xcf_io, Layer& layer)
783 qint32 width;
784 qint32 height;
785 char* name;
787 xcf_io >> width >> height >> name;
789 delete name;
791 if (!loadChannelProperties(xcf_io, layer))
792 return false;
794 quint32 hierarchy_offset;
795 xcf_io >> hierarchy_offset;
797 xcf_io.device()->seek(hierarchy_offset);
798 layer.assignBytes = assignMaskBytes;
800 if (!loadHierarchy(xcf_io, layer))
801 return false;
803 return true;
808 * This is the routine for which all the other code is simply
809 * infrastructure. Read the image bytes out of the file and
810 * store them in the tile buffer. This is passed a full 32-bit deep
811 * buffer, even if bpp is smaller. The caller can figure out what to
812 * do with the bytes.
814 * The tile is stored in "channels", i.e. the red component of all
815 * pixels, then the green component of all pixels, then blue then
816 * alpha, or, for indexed images, the color indices of all pixels then
817 * the alpha of all pixels.
819 * The data is compressed with "run length encoding". Some simple data
820 * integrity checks are made.
822 * \param xcf_io the data stream connected to the XCF image.
823 * \param tile the buffer to expand the RLE into.
824 * \param image_size number of bytes expected to be in the image tile.
825 * \param data_length number of bytes expected in the RLE.
826 * \param bpp number of bytes per pixel.
827 * \return true if there were no I/O errors and no obvious corruption of
828 * the RLE data.
830 bool XCFImageFormat::loadTileRLE(QDataStream& xcf_io, uchar* tile, int image_size,
831 int data_length, qint32 bpp)
833 uchar* data;
835 uchar* xcfdata;
836 uchar* xcfodata;
837 uchar* xcfdatalimit;
839 xcfdata = xcfodata = new uchar[data_length];
841 xcf_io.readRawData((char*)xcfdata, data_length);
843 if (!xcf_io.device()->isOpen()) {
844 delete[] xcfodata;
845 kDebug(399) << "XCF: read failure on tile";
846 return false;
849 xcfdatalimit = &xcfodata[data_length - 1];
851 for (int i = 0; i < bpp; ++i) {
853 data = tile + i;
855 int count = 0;
856 int size = image_size;
858 while (size > 0) {
859 if (xcfdata > xcfdatalimit)
860 goto bogus_rle;
862 uchar val = *xcfdata++;
863 uint length = val;
865 if (length >= 128) {
866 length = 255 - (length - 1);
867 if (length == 128) {
868 if (xcfdata >= xcfdatalimit)
869 goto bogus_rle;
871 length = (*xcfdata << 8) + xcfdata[1];
873 xcfdata += 2;
876 count += length;
877 size -= length;
879 if (size < 0)
880 goto bogus_rle;
882 if (&xcfdata[length - 1] > xcfdatalimit)
883 goto bogus_rle;
885 while (length-- > 0) {
886 *data = *xcfdata++;
887 data += sizeof(QRgb);
889 } else {
890 length += 1;
891 if (length == 128) {
892 if (xcfdata >= xcfdatalimit)
893 goto bogus_rle;
895 length = (*xcfdata << 8) + xcfdata[1];
896 xcfdata += 2;
899 count += length;
900 size -= length;
902 if (size < 0)
903 goto bogus_rle;
905 if (xcfdata > xcfdatalimit)
906 goto bogus_rle;
908 val = *xcfdata++;
910 while (length-- > 0) {
911 *data = val;
912 data += sizeof(QRgb);
918 delete[] xcfodata;
919 return true;
921 bogus_rle:
923 kDebug(399) << "The run length encoding could not be decoded properly";
924 delete[] xcfodata;
925 return false;
930 * An XCF file can contain an arbitrary number of properties associated
931 * with a channel. Note that this routine only reads mask channel properties.
932 * \param xcf_io the data stream connected to the XCF image.
933 * \param layer layer containing the mask channel to collect the properties.
934 * \return true if there were no I/O errors.
936 bool XCFImageFormat::loadChannelProperties(QDataStream& xcf_io, Layer& layer)
938 while (true) {
939 PropType type;
940 QByteArray bytes;
942 if (!loadProperty(xcf_io, type, bytes)) {
943 kDebug(399) << "XCF: error loading channel properties";
944 return false;
947 QDataStream property(bytes);
949 switch (type) {
950 case PROP_END:
951 return true;
953 case PROP_OPACITY:
954 property >> layer.mask_channel.opacity;
955 break;
957 case PROP_VISIBLE:
958 property >> layer.mask_channel.visible;
959 break;
961 case PROP_SHOW_MASKED:
962 property >> layer.mask_channel.show_masked;
963 break;
965 case PROP_COLOR:
966 property >> layer.mask_channel.red >> layer.mask_channel.green
967 >> layer.mask_channel.blue;
968 break;
970 case PROP_TATTOO:
971 property >> layer.mask_channel.tattoo;
972 break;
974 default:
975 kDebug(399) << "XCF: unimplemented channel property " << type
976 << ", size " << bytes.size() << endl;
983 * Copy the bytes from the tile buffer into the mask tile QImage.
984 * \param layer layer containing the tile buffer and the mask tile matrix.
985 * \param i column index of current tile.
986 * \param j row index of current tile.
988 void XCFImageFormat::assignMaskBytes(Layer& layer, uint i, uint j)
990 uchar* tile = layer.tile;
992 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
993 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
994 layer.mask_tiles[j][i].setPixel(k, l, tile[0]);
995 tile += sizeof(QRgb);
1002 * Construct the QImage which will eventually be returned to the QImage
1003 * loader.
1005 * There are a couple of situations which require that the QImage is not
1006 * exactly the same as The GIMP's representation. The full table is:
1007 * \verbatim
1008 * Grayscale opaque : 8 bpp indexed
1009 * Grayscale translucent : 32 bpp + alpha
1010 * Indexed opaque : 1 bpp if num_colors <= 2
1011 * : 8 bpp indexed otherwise
1012 * Indexed translucent : 8 bpp indexed + alpha if num_colors < 256
1013 * : 32 bpp + alpha otherwise
1014 * RGB opaque : 32 bpp
1015 * RGBA translucent : 32 bpp + alpha
1016 * \endverbatim
1017 * Whether the image is translucent or not is determined by the bottom layer's
1018 * alpha channel. However, even if the bottom layer lacks an alpha channel,
1019 * it can still have an opacity < 1. In this case, the QImage is promoted
1020 * to 32-bit. (Note this is different from the output from the GIMP image
1021 * exporter, which seems to ignore this attribute.)
1023 * Independently, higher layers can be translucent, but the background of
1024 * the image will not show through if the bottom layer is opaque.
1026 * For indexed images, translucency is an all or nothing effect.
1027 * \param xcf_image contains image info and bottom-most layer.
1029 bool XCFImageFormat::initializeImage(XCFImage& xcf_image)
1031 // (Aliases to make the code look a little better.)
1032 Layer& layer(xcf_image.layer);
1033 QImage& image(xcf_image.image);
1035 switch (layer.type) {
1036 case RGB_GIMAGE:
1037 if (layer.opacity == OPAQUE_OPACITY) {
1038 image = QImage( xcf_image.width, xcf_image.height, QImage::Format_RGB32);
1039 if( image.isNull())
1040 return false;
1041 image.fill(qRgb(255, 255, 255));
1042 break;
1043 } // else, fall through to 32-bit representation
1045 case RGBA_GIMAGE:
1046 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_ARGB32);
1047 if( image.isNull())
1048 return false;
1049 image.fill(qRgba(255, 255, 255, 0));
1050 break;
1052 case GRAY_GIMAGE:
1053 if (layer.opacity == OPAQUE_OPACITY) {
1054 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_Indexed8);
1055 image.setNumColors(256);
1056 if( image.isNull())
1057 return false;
1058 setGrayPalette(image);
1059 image.fill(255);
1060 break;
1061 } // else, fall through to 32-bit representation
1063 case GRAYA_GIMAGE:
1064 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_ARGB32);
1065 if( image.isNull())
1066 return false;
1067 image.fill(qRgba(255, 255, 255, 0));
1068 break;
1070 case INDEXED_GIMAGE:
1071 // As noted in the table above, there are quite a few combinations
1072 // which are possible with indexed images, depending on the
1073 // presence of transparency (note: not translucency, which is not
1074 // supported by The GIMP for indexed images) and the number of
1075 // individual colors.
1077 // Note: Qt treats a bitmap with a Black and White color palette
1078 // as a mask, so only the "on" bits are drawn, regardless of the
1079 // order color table entries. Otherwise (i.e., at least one of the
1080 // color table entries is not black or white), it obeys the one-
1081 // or two-color palette. Have to ask about this...
1083 if (xcf_image.num_colors <= 2) {
1084 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_MonoLSB);
1085 image.setNumColors(xcf_image.num_colors);
1086 if( image.isNull())
1087 return false;
1088 image.fill(0);
1089 setPalette(xcf_image, image);
1090 } else if (xcf_image.num_colors <= 256) {
1091 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_Indexed8);
1092 image.setNumColors(xcf_image.num_colors);
1093 if( image.isNull())
1094 return false;
1095 image.fill(0);
1096 setPalette(xcf_image, image);
1098 break;
1100 case INDEXEDA_GIMAGE:
1101 if (xcf_image.num_colors == 1) {
1102 // Plenty(!) of room to add a transparent color
1103 xcf_image.num_colors++;
1104 xcf_image.palette.resize(xcf_image.num_colors);
1105 xcf_image.palette[1] = xcf_image.palette[0];
1106 xcf_image.palette[0] = qRgba(255, 255, 255, 0);
1108 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_MonoLSB);
1109 image.setNumColors(xcf_image.num_colors);
1110 if( image.isNull())
1111 return false;
1112 image.fill(0);
1113 setPalette(xcf_image, image);
1114 } else if (xcf_image.num_colors < 256) {
1115 // Plenty of room to add a transparent color
1116 xcf_image.num_colors++;
1117 xcf_image.palette.resize(xcf_image.num_colors);
1118 for (int c = xcf_image.num_colors - 1; c >= 1; c--)
1119 xcf_image.palette[c] = xcf_image.palette[c - 1];
1121 xcf_image.palette[0] = qRgba(255, 255, 255, 0);
1122 image = QImage( xcf_image.width, xcf_image.height, QImage::Format_Indexed8);
1123 image.setNumColors(xcf_image.num_colors);
1124 if( image.isNull())
1125 return false;
1126 image.fill(0);
1127 setPalette(xcf_image, image);
1128 } else {
1129 // No room for a transparent color, so this has to be promoted to
1130 // true color. (There is no equivalent PNG representation output
1131 // from The GIMP as of v1.2.)
1132 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_ARGB32);
1133 if( image.isNull())
1134 return false;
1135 image.fill(qRgba(255, 255, 255, 0));
1137 break;
1140 image.setDotsPerMeterX((int)(xcf_image.x_resolution * INCHESPERMETER));
1141 image.setDotsPerMeterY((int)(xcf_image.y_resolution * INCHESPERMETER));
1142 return true;
1147 * Copy a layer into an image, taking account of the manifold modes. The
1148 * contents of the image are replaced.
1149 * \param xcf_image contains the layer and image to be replaced.
1151 void XCFImageFormat::copyLayerToImage(XCFImage& xcf_image)
1153 Layer& layer(xcf_image.layer);
1154 QImage& image(xcf_image.image);
1155 PixelCopyOperation copy = 0;
1157 switch (layer.type) {
1158 case RGB_GIMAGE:
1159 case RGBA_GIMAGE:
1160 copy = copyRGBToRGB;
1161 break;
1162 case GRAY_GIMAGE:
1163 if (layer.opacity == OPAQUE_OPACITY)
1164 copy = copyGrayToGray;
1165 else
1166 copy = copyGrayToRGB;
1167 break;
1168 case GRAYA_GIMAGE:
1169 copy = copyGrayAToRGB;
1170 break;
1171 case INDEXED_GIMAGE:
1172 copy = copyIndexedToIndexed;
1173 break;
1174 case INDEXEDA_GIMAGE:
1175 if (xcf_image.image.depth() <= 8)
1176 copy = copyIndexedAToIndexed;
1177 else
1178 copy = copyIndexedAToRGB;
1181 if (!copy) {
1182 return;
1185 // For each tile...
1187 for (uint j = 0; j < layer.nrows; j++) {
1188 uint y = j * TILE_HEIGHT;
1190 for (uint i = 0; i < layer.ncols; i++) {
1191 uint x = i * TILE_WIDTH;
1193 // This seems the best place to apply the dissolve because it
1194 // depends on the global position of each tile's
1195 // pixels. Apparently it's the only mode which can apply to a
1196 // single layer.
1198 if (layer.mode == DISSOLVE_MODE) {
1199 if (layer.type == RGBA_GIMAGE)
1200 dissolveRGBPixels(layer.image_tiles[j][i], x, y);
1202 else if (layer.type == GRAYA_GIMAGE)
1203 dissolveAlphaPixels(layer.alpha_tiles[j][i], x, y);
1206 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
1207 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
1209 int m = x + k + layer.x_offset;
1210 int n = y + l + layer.y_offset;
1212 if (m < 0 || m >= image.width() || n < 0 || n >= image.height())
1213 continue;
1215 (*copy)(layer, i, j, k, l, image, m, n);
1224 * Copy an RGB pixel from the layer to the RGB image. Straight-forward.
1225 * The only thing this has to take account of is the opacity of the
1226 * layer. Evidently, the GIMP exporter itself does not actually do this.
1227 * \param layer source layer.
1228 * \param i x tile index.
1229 * \param j y tile index.
1230 * \param k x pixel index of tile i,j.
1231 * \param l y pixel index of tile i,j.
1232 * \param image destination image.
1233 * \param m x pixel of destination image.
1234 * \param n y pixel of destination image.
1236 void XCFImageFormat::copyRGBToRGB(Layer& layer, uint i, uint j, int k, int l,
1237 QImage& image, int m, int n)
1239 QRgb src = layer.image_tiles[j][i].pixel(k, l);
1240 uchar src_a = layer.opacity;
1242 if (layer.type == RGBA_GIMAGE)
1243 src_a = INT_MULT(src_a, qAlpha(src));
1245 // Apply the mask (if any)
1247 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
1248 layer.mask_tiles[j].size() > (int)i)
1249 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
1251 image.setPixel(m, n, qRgba(src, src_a));
1256 * Copy a Gray pixel from the layer to the Gray image. Straight-forward.
1257 * \param layer source layer.
1258 * \param i x tile index.
1259 * \param j y tile index.
1260 * \param k x pixel index of tile i,j.
1261 * \param l y pixel index of tile i,j.
1262 * \param image destination image.
1263 * \param m x pixel of destination image.
1264 * \param n y pixel of destination image.
1266 void XCFImageFormat::copyGrayToGray(Layer& layer, uint i, uint j, int k, int l,
1267 QImage& image, int m, int n)
1269 int src = layer.image_tiles[j][i].pixelIndex(k, l);
1270 image.setPixel(m, n, src);
1275 * Copy a Gray pixel from the layer to an RGB image. Straight-forward.
1276 * The only thing this has to take account of is the opacity of the
1277 * layer. Evidently, the GIMP exporter itself does not actually do this.
1278 * \param layer source layer.
1279 * \param i x tile index.
1280 * \param j y tile index.
1281 * \param k x pixel index of tile i,j.
1282 * \param l y pixel index of tile i,j.
1283 * \param image destination image.
1284 * \param m x pixel of destination image.
1285 * \param n y pixel of destination image.
1287 void XCFImageFormat::copyGrayToRGB(Layer& layer, uint i, uint j, int k, int l,
1288 QImage& image, int m, int n)
1290 QRgb src = layer.image_tiles[j][i].pixel(k, l);
1291 uchar src_a = layer.opacity;
1292 image.setPixel(m, n, qRgba(src, src_a));
1297 * Copy a GrayA pixel from the layer to an RGB image. Straight-forward.
1298 * The only thing this has to take account of is the opacity of the
1299 * layer. Evidently, the GIMP exporter itself does not actually do this.
1300 * \param layer source layer.
1301 * \param i x tile index.
1302 * \param j y tile index.
1303 * \param k x pixel index of tile i,j.
1304 * \param l y pixel index of tile i,j.
1305 * \param image destination image.
1306 * \param m x pixel of destination image.
1307 * \param n y pixel of destination image.
1309 void XCFImageFormat::copyGrayAToRGB(Layer& layer, uint i, uint j, int k, int l,
1310 QImage& image, int m, int n)
1312 QRgb src = layer.image_tiles[j][i].pixel(k, l);
1313 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
1314 src_a = INT_MULT(src_a, layer.opacity);
1316 // Apply the mask (if any)
1318 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
1319 layer.mask_tiles[j].size() > (int)i)
1320 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
1322 image.setPixel(m, n, qRgba(src, src_a));
1327 * Copy an Indexed pixel from the layer to the Indexed image. Straight-forward.
1328 * \param layer source layer.
1329 * \param i x tile index.
1330 * \param j y tile index.
1331 * \param k x pixel index of tile i,j.
1332 * \param l y pixel index of tile i,j.
1333 * \param image destination image.
1334 * \param m x pixel of destination image.
1335 * \param n y pixel of destination image.
1337 void XCFImageFormat::copyIndexedToIndexed(Layer& layer, uint i, uint j, int k, int l,
1338 QImage& image, int m, int n)
1340 int src = layer.image_tiles[j][i].pixelIndex(k, l);
1341 image.setPixel(m, n, src);
1346 * Copy an IndexedA pixel from the layer to the Indexed image. Straight-forward.
1347 * \param layer source layer.
1348 * \param i x tile index.
1349 * \param j y tile index.
1350 * \param k x pixel index of tile i,j.
1351 * \param l y pixel index of tile i,j.
1352 * \param image destination image.
1353 * \param m x pixel of destination image.
1354 * \param n y pixel of destination image.
1356 void XCFImageFormat::copyIndexedAToIndexed(Layer& layer, uint i, uint j, int k, int l,
1357 QImage& image, int m, int n)
1359 uchar src = layer.image_tiles[j][i].pixelIndex(k, l);
1360 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
1361 src_a = INT_MULT(src_a, layer.opacity);
1363 if (layer.apply_mask == 1 &&
1364 layer.mask_tiles.size() > (int)j &&
1365 layer.mask_tiles[j].size() > (int)i)
1366 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
1368 if (src_a > 127)
1369 src++;
1370 else
1371 src = 0;
1373 image.setPixel(m, n, src);
1378 * Copy an IndexedA pixel from the layer to an RGB image. Straight-forward.
1379 * The only thing this has to take account of is the opacity of the
1380 * layer. Evidently, the GIMP exporter itself does not actually do this.
1381 * \param layer source layer.
1382 * \param i x tile index.
1383 * \param j y tile index.
1384 * \param k x pixel index of tile i,j.
1385 * \param l y pixel index of tile i,j.
1386 * \param image destination image.
1387 * \param m x pixel of destination image.
1388 * \param n y pixel of destination image.
1390 void XCFImageFormat::copyIndexedAToRGB(Layer& layer, uint i, uint j, int k, int l,
1391 QImage& image, int m, int n)
1393 QRgb src = layer.image_tiles[j][i].pixel(k, l);
1394 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
1395 src_a = INT_MULT(src_a, layer.opacity);
1397 // Apply the mask (if any)
1398 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
1399 layer.mask_tiles[j].size() > (int)i)
1400 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
1402 // This is what appears in the GIMP window
1403 if (src_a <= 127)
1404 src_a = 0;
1405 else
1406 src_a = OPAQUE_OPACITY;
1408 image.setPixel(m, n, qRgba(src, src_a));
1413 * Merge a layer into an image, taking account of the manifold modes.
1414 * \param xcf_image contains the layer and image to merge.
1416 void XCFImageFormat::mergeLayerIntoImage(XCFImage& xcf_image)
1418 Layer& layer(xcf_image.layer);
1419 QImage& image(xcf_image.image);
1421 PixelMergeOperation merge = 0;
1423 if (!layer.opacity) return; // don't bother doing anything
1425 switch (layer.type) {
1426 case RGB_GIMAGE:
1427 case RGBA_GIMAGE:
1428 merge = mergeRGBToRGB;
1429 break;
1430 case GRAY_GIMAGE:
1431 if (layer.opacity == OPAQUE_OPACITY)
1432 merge = mergeGrayToGray;
1433 else
1434 merge = mergeGrayToRGB;
1435 break;
1436 case GRAYA_GIMAGE:
1437 if (xcf_image.image.depth() <= 8)
1438 merge = mergeGrayAToGray;
1439 else
1440 merge = mergeGrayAToRGB;
1441 break;
1442 case INDEXED_GIMAGE:
1443 merge = mergeIndexedToIndexed;
1444 break;
1445 case INDEXEDA_GIMAGE:
1446 if (xcf_image.image.depth() <= 8)
1447 merge = mergeIndexedAToIndexed;
1448 else
1449 merge = mergeIndexedAToRGB;
1452 if (!merge) {
1453 return;
1456 for (uint j = 0; j < layer.nrows; j++) {
1457 uint y = j * TILE_HEIGHT;
1459 for (uint i = 0; i < layer.ncols; i++) {
1460 uint x = i * TILE_WIDTH;
1462 // This seems the best place to apply the dissolve because it
1463 // depends on the global position of each tile's
1464 // pixels. Apparently it's the only mode which can apply to a
1465 // single layer.
1467 if (layer.mode == DISSOLVE_MODE) {
1468 if (layer.type == RGBA_GIMAGE)
1469 dissolveRGBPixels(layer.image_tiles[j][i], x, y);
1471 else if (layer.type == GRAYA_GIMAGE)
1472 dissolveAlphaPixels(layer.alpha_tiles[j][i], x, y);
1475 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
1476 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
1478 int m = x + k + layer.x_offset;
1479 int n = y + l + layer.y_offset;
1481 if (m < 0 || m >= image.width() || n < 0 || n >= image.height())
1482 continue;
1484 (*merge)(layer, i, j, k, l, image, m, n);
1493 * Merge an RGB pixel from the layer to the RGB image. Straight-forward.
1494 * The only thing this has to take account of is the opacity of the
1495 * layer. Evidently, the GIMP exporter itself does not actually do this.
1496 * \param layer source layer.
1497 * \param i x tile index.
1498 * \param j y tile index.
1499 * \param k x pixel index of tile i,j.
1500 * \param l y pixel index of tile i,j.
1501 * \param image destination image.
1502 * \param m x pixel of destination image.
1503 * \param n y pixel of destination image.
1505 void XCFImageFormat::mergeRGBToRGB(Layer& layer, uint i, uint j, int k, int l,
1506 QImage& image, int m, int n)
1508 QRgb src = layer.image_tiles[j][i].pixel(k, l);
1509 QRgb dst = image.pixel(m, n);
1511 uchar src_r = qRed(src);
1512 uchar src_g = qGreen(src);
1513 uchar src_b = qBlue(src);
1514 uchar src_a = qAlpha(src);
1516 uchar dst_r = qRed(dst);
1517 uchar dst_g = qGreen(dst);
1518 uchar dst_b = qBlue(dst);
1519 uchar dst_a = qAlpha(dst);
1521 if (!src_a) return; // nothing to merge
1523 switch (layer.mode) {
1524 case MULTIPLY_MODE: {
1525 src_r = INT_MULT(src_r, dst_r);
1526 src_g = INT_MULT(src_g, dst_g);
1527 src_b = INT_MULT(src_b, dst_b);
1528 src_a = qMin(src_a, dst_a);
1530 break;
1531 case DIVIDE_MODE: {
1532 src_r = qMin((dst_r * 256) / (1 + src_r), 255);
1533 src_g = qMin((dst_g * 256) / (1 + src_g), 255);
1534 src_b = qMin((dst_b * 256) / (1 + src_b), 255);
1535 src_a = qMin(src_a, dst_a);
1537 break;
1538 case SCREEN_MODE: {
1539 src_r = 255 - INT_MULT(255 - dst_r, 255 - src_r);
1540 src_g = 255 - INT_MULT(255 - dst_g, 255 - src_g);
1541 src_b = 255 - INT_MULT(255 - dst_b, 255 - src_b);
1542 src_a = qMin(src_a, dst_a);
1544 break;
1545 case OVERLAY_MODE: {
1546 src_r = INT_MULT(dst_r, dst_r + INT_MULT(2 * src_r, 255 - dst_r));
1547 src_g = INT_MULT(dst_g, dst_g + INT_MULT(2 * src_g, 255 - dst_g));
1548 src_b = INT_MULT(dst_b, dst_b + INT_MULT(2 * src_b, 255 - dst_b));
1549 src_a = qMin(src_a, dst_a);
1551 break;
1552 case DIFFERENCE_MODE: {
1553 src_r = dst_r > src_r ? dst_r - src_r : src_r - dst_r;
1554 src_g = dst_g > src_g ? dst_g - src_g : src_g - dst_g;
1555 src_b = dst_b > src_b ? dst_b - src_b : src_b - dst_b;
1556 src_a = qMin(src_a, dst_a);
1558 break;
1559 case ADDITION_MODE: {
1560 src_r = add_lut(dst_r,src_r);
1561 src_g = add_lut(dst_g,src_g);
1562 src_b = add_lut(dst_b,src_b);
1563 src_a = qMin(src_a, dst_a);
1565 break;
1566 case SUBTRACT_MODE: {
1567 src_r = dst_r > src_r ? dst_r - src_r : 0;
1568 src_g = dst_g > src_g ? dst_g - src_g : 0;
1569 src_b = dst_b > src_b ? dst_b - src_b : 0;
1570 src_a = qMin(src_a, dst_a);
1572 break;
1573 case DARKEN_ONLY_MODE: {
1574 src_r = dst_r < src_r ? dst_r : src_r;
1575 src_g = dst_g < src_g ? dst_g : src_g;
1576 src_b = dst_b < src_b ? dst_b : src_b;
1577 src_a = qMin( src_a, dst_a );
1579 break;
1580 case LIGHTEN_ONLY_MODE: {
1581 src_r = dst_r < src_r ? src_r : dst_r;
1582 src_g = dst_g < src_g ? src_g : dst_g;
1583 src_b = dst_b < src_b ? src_b : dst_b;
1584 src_a = qMin(src_a, dst_a);
1586 break;
1587 case HUE_MODE: {
1588 uchar new_r = dst_r;
1589 uchar new_g = dst_g;
1590 uchar new_b = dst_b;
1592 RGBTOHSV(src_r, src_g, src_b);
1593 RGBTOHSV(new_r, new_g, new_b);
1595 new_r = src_r;
1597 HSVTORGB(new_r, new_g, new_b);
1599 src_r = new_r;
1600 src_g = new_g;
1601 src_b = new_b;
1602 src_a = qMin( src_a, dst_a );
1604 break;
1605 case SATURATION_MODE: {
1606 uchar new_r = dst_r;
1607 uchar new_g = dst_g;
1608 uchar new_b = dst_b;
1610 RGBTOHSV(src_r, src_g, src_b);
1611 RGBTOHSV(new_r, new_g, new_b);
1613 new_g = src_g;
1615 HSVTORGB(new_r, new_g, new_b);
1617 src_r = new_r;
1618 src_g = new_g;
1619 src_b = new_b;
1620 src_a = qMin(src_a, dst_a);
1622 break;
1623 case VALUE_MODE: {
1624 uchar new_r = dst_r;
1625 uchar new_g = dst_g;
1626 uchar new_b = dst_b;
1628 RGBTOHSV(src_r, src_g, src_b);
1629 RGBTOHSV(new_r, new_g, new_b);
1631 new_b = src_b;
1633 HSVTORGB(new_r, new_g, new_b);
1635 src_r = new_r;
1636 src_g = new_g;
1637 src_b = new_b;
1638 src_a = qMin(src_a, dst_a);
1640 break;
1641 case COLOR_MODE: {
1642 uchar new_r = dst_r;
1643 uchar new_g = dst_g;
1644 uchar new_b = dst_b;
1646 RGBTOHLS(src_r, src_g, src_b);
1647 RGBTOHLS(new_r, new_g, new_b);
1649 new_r = src_r;
1650 new_b = src_b;
1652 HLSTORGB(new_r, new_g, new_b);
1654 src_r = new_r;
1655 src_g = new_g;
1656 src_b = new_b;
1657 src_a = qMin(src_a, dst_a);
1659 break;
1660 case DODGE_MODE: {
1661 uint tmp;
1663 tmp = dst_r << 8;
1664 tmp /= 256 - src_r;
1665 src_r = (uchar) qMin(tmp, 255u);
1667 tmp = dst_g << 8;
1668 tmp /= 256 - src_g;
1669 src_g = (uchar) qMin(tmp, 255u);
1671 tmp = dst_b << 8;
1672 tmp /= 256 - src_b;
1673 src_b = (uchar) qMin(tmp, 255u);
1675 src_a = qMin(src_a, dst_a);
1677 break;
1678 case BURN_MODE: {
1679 uint tmp;
1681 tmp = (255 - dst_r) << 8;
1682 tmp /= src_r + 1;
1683 src_r = (uchar) qMin(tmp, 255u);
1684 src_r = 255 - src_r;
1686 tmp = (255 - dst_g) << 8;
1687 tmp /= src_g + 1;
1688 src_g = (uchar) qMin(tmp, 255u);
1689 src_g = 255 - src_g;
1691 tmp = (255 - dst_b) << 8;
1692 tmp /= src_b + 1;
1693 src_b = (uchar) qMin(tmp, 255u);
1694 src_b = 255 - src_b;
1696 src_a = qMin(src_a, dst_a);
1698 break;
1699 case HARDLIGHT_MODE: {
1700 uint tmp;
1701 if (src_r > 128) {
1702 tmp = ((int)255-dst_r) * ((int) 255 - ((src_r-128) << 1));
1703 src_r = (uchar) qMin(255 - (tmp >> 8), 255u);
1704 } else {
1705 tmp = (int) dst_r * ((int) src_r << 1);
1706 src_r = (uchar) qMin(tmp >> 8, 255u);
1709 if (src_g > 128) {
1710 tmp = ((int)255-dst_g) * ((int) 255 - ((src_g-128) << 1));
1711 src_g = (uchar) qMin(255 - (tmp >> 8), 255u);
1712 } else {
1713 tmp = (int) dst_g * ((int) src_g << 1);
1714 src_g = (uchar) qMin(tmp >> 8, 255u);
1717 if (src_b > 128) {
1718 tmp = ((int)255-dst_b) * ((int) 255 - ((src_b-128) << 1));
1719 src_b = (uchar) qMin(255 - (tmp >> 8), 255u);
1720 } else {
1721 tmp = (int) dst_b * ((int) src_b << 1);
1722 src_b = (uchar) qMin(tmp >> 8, 255u);
1724 src_a = qMin(src_a, dst_a);
1726 break;
1727 case SOFTLIGHT_MODE: {
1728 uint tmpS, tmpM;
1730 tmpM = INT_MULT(dst_r, src_r);
1731 tmpS = 255 - INT_MULT((255 - dst_r), (255-src_r));
1732 src_r = INT_MULT((255 - dst_r), tmpM)
1733 + INT_MULT(dst_r, tmpS);
1735 tmpM = INT_MULT(dst_g, src_g);
1736 tmpS = 255 - INT_MULT((255 - dst_g), (255-src_g));
1737 src_g = INT_MULT((255 - dst_g), tmpM)
1738 + INT_MULT(dst_g, tmpS);
1740 tmpM = INT_MULT(dst_b, src_b);
1741 tmpS = 255 - INT_MULT((255 - dst_b), (255-src_b));
1742 src_b = INT_MULT((255 - dst_b), tmpM)
1743 + INT_MULT(dst_b, tmpS);
1745 src_a = qMin(src_a, dst_a);
1747 break;
1748 case GRAIN_EXTRACT_MODE: {
1749 int tmp;
1751 tmp = dst_r - src_r + 128;
1752 tmp = qMin(tmp, 255);
1753 tmp = qMax(tmp, 0);
1754 src_r = (uchar) tmp;
1756 tmp = dst_g - src_g + 128;
1757 tmp = qMin(tmp, 255);
1758 tmp = qMax(tmp, 0);
1759 src_g = (uchar) tmp;
1761 tmp = dst_b - src_b + 128;
1762 tmp = qMin(tmp, 255);
1763 tmp = qMax(tmp, 0);
1764 src_b = (uchar) tmp;
1766 src_a = qMin(src_a, dst_a);
1768 break;
1769 case GRAIN_MERGE_MODE: {
1770 int tmp;
1772 tmp = dst_r + src_r - 128;
1773 tmp = qMin(tmp, 255);
1774 tmp = qMax(tmp, 0);
1775 src_r = (uchar) tmp;
1777 tmp = dst_g + src_g - 128;
1778 tmp = qMin(tmp, 255);
1779 tmp = qMax(tmp, 0);
1780 src_g = (uchar) tmp;
1782 tmp = dst_b + src_b - 128;
1783 tmp = qMin(tmp, 255);
1784 tmp = qMax(tmp, 0);
1785 src_b = (uchar) tmp;
1787 src_a = qMin(src_a, dst_a);
1789 break;
1792 src_a = INT_MULT(src_a, layer.opacity);
1794 // Apply the mask (if any)
1796 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
1797 layer.mask_tiles[j].size() > (int)i)
1798 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
1800 uchar new_r, new_g, new_b, new_a;
1801 new_a = dst_a + INT_MULT(OPAQUE_OPACITY - dst_a, src_a);
1803 float src_ratio = (float)src_a / new_a;
1804 float dst_ratio = 1.0 - src_ratio;
1806 new_r = (uchar)(src_ratio * src_r + dst_ratio * dst_r + EPSILON);
1807 new_g = (uchar)(src_ratio * src_g + dst_ratio * dst_g + EPSILON);
1808 new_b = (uchar)(src_ratio * src_b + dst_ratio * dst_b + EPSILON);
1810 if (!layer_modes[layer.mode].affect_alpha)
1811 new_a = dst_a;
1813 image.setPixel(m, n, qRgba(new_r, new_g, new_b, new_a));
1818 * Merge a Gray pixel from the layer to the Gray image. Straight-forward.
1819 * \param layer source layer.
1820 * \param i x tile index.
1821 * \param j y tile index.
1822 * \param k x pixel index of tile i,j.
1823 * \param l y pixel index of tile i,j.
1824 * \param image destination image.
1825 * \param m x pixel of destination image.
1826 * \param n y pixel of destination image.
1828 void XCFImageFormat::mergeGrayToGray(Layer& layer, uint i, uint j, int k, int l,
1829 QImage& image, int m, int n)
1831 int src = layer.image_tiles[j][i].pixelIndex(k, l);
1832 image.setPixel(m, n, src);
1837 * Merge a GrayA pixel from the layer to the Gray image. Straight-forward.
1838 * \param layer source layer.
1839 * \param i x tile index.
1840 * \param j y tile index.
1841 * \param k x pixel index of tile i,j.
1842 * \param l y pixel index of tile i,j.
1843 * \param image destination image.
1844 * \param m x pixel of destination image.
1845 * \param n y pixel of destination image.
1847 void XCFImageFormat::mergeGrayAToGray(Layer& layer, uint i, uint j, int k, int l,
1848 QImage& image, int m, int n)
1850 int src = qGray(layer.image_tiles[j][i].pixel(k, l));
1851 int dst = image.pixelIndex(m, n);
1853 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
1855 if (!src_a) return; // nothing to merge
1857 switch (layer.mode) {
1858 case MULTIPLY_MODE: {
1859 src = INT_MULT( src, dst );
1861 break;
1862 case DIVIDE_MODE: {
1863 src = qMin((dst * 256) / (1 + src), 255);
1865 break;
1866 case SCREEN_MODE: {
1867 src = 255 - INT_MULT(255 - dst, 255 - src);
1869 break;
1870 case OVERLAY_MODE: {
1871 src = INT_MULT(dst, dst + INT_MULT(2 * src, 255 - dst));
1873 break;
1874 case DIFFERENCE_MODE: {
1875 src = dst > src ? dst - src : src - dst;
1877 break;
1878 case ADDITION_MODE: {
1879 src = add_lut(dst,src);
1881 break;
1882 case SUBTRACT_MODE: {
1883 src = dst > src ? dst - src : 0;
1885 break;
1886 case DARKEN_ONLY_MODE: {
1887 src = dst < src ? dst : src;
1889 break;
1890 case LIGHTEN_ONLY_MODE: {
1891 src = dst < src ? src : dst;
1893 break;
1894 case DODGE_MODE: {
1895 uint tmp = dst << 8;
1896 tmp /= 256 - src;
1897 src = (uchar) qMin(tmp, 255u);
1899 break;
1900 case BURN_MODE: {
1901 uint tmp = (255-dst) << 8;
1902 tmp /= src + 1;
1903 src = (uchar) qMin(tmp, 255u);
1904 src = 255 - src;
1906 break;
1907 case HARDLIGHT_MODE: {
1908 uint tmp;
1909 if (src > 128) {
1910 tmp = ((int)255-dst) * ((int) 255 - ((src-128) << 1));
1911 src = (uchar) qMin(255 - (tmp >> 8), 255u);
1912 } else {
1913 tmp = (int) dst * ((int) src << 1);
1914 src = (uchar) qMin(tmp >> 8, 255u);
1917 break;
1918 case SOFTLIGHT_MODE: {
1919 uint tmpS, tmpM;
1921 tmpM = INT_MULT(dst, src);
1922 tmpS = 255 - INT_MULT((255-dst), (255-src));
1923 src = INT_MULT((255 - dst), tmpM)
1924 + INT_MULT(dst, tmpS);
1927 break;
1928 case GRAIN_EXTRACT_MODE: {
1929 int tmp;
1931 tmp = dst - src + 128;
1932 tmp = qMin(tmp, 255);
1933 tmp = qMax(tmp, 0);
1935 src = (uchar) tmp;
1937 break;
1938 case GRAIN_MERGE_MODE: {
1939 int tmp;
1941 tmp = dst + src - 128;
1942 tmp = qMin(tmp, 255);
1943 tmp = qMax(tmp, 0);
1945 src = (uchar) tmp;
1947 break;
1950 src_a = INT_MULT(src_a, layer.opacity);
1952 // Apply the mask (if any)
1954 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
1955 layer.mask_tiles[j].size() > (int)i)
1956 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
1958 uchar new_a = OPAQUE_OPACITY;
1960 float src_ratio = (float)src_a / new_a;
1961 float dst_ratio = 1.0 - src_ratio;
1963 uchar new_g = (uchar)(src_ratio * src + dst_ratio * dst + EPSILON);
1965 image.setPixel(m, n, new_g);
1970 * Merge a Gray pixel from the layer to an RGB image. Straight-forward.
1971 * The only thing this has to take account of is the opacity of the
1972 * layer. Evidently, the GIMP exporter itself does not actually do this.
1973 * \param layer source layer.
1974 * \param i x tile index.
1975 * \param j y tile index.
1976 * \param k x pixel index of tile i,j.
1977 * \param l y pixel index of tile i,j.
1978 * \param image destination image.
1979 * \param m x pixel of destination image.
1980 * \param n y pixel of destination image.
1982 void XCFImageFormat::mergeGrayToRGB(Layer& layer, uint i, uint j, int k, int l,
1983 QImage& image, int m, int n)
1985 QRgb src = layer.image_tiles[j][i].pixel(k, l);
1986 uchar src_a = layer.opacity;
1987 image.setPixel(m, n, qRgba(src, src_a));
1992 * Merge a GrayA pixel from the layer to an RGB image. Straight-forward.
1993 * The only thing this has to take account of is the opacity of the
1994 * layer. Evidently, the GIMP exporter itself does not actually do this.
1995 * \param layer source layer.
1996 * \param i x tile index.
1997 * \param j y tile index.
1998 * \param k x pixel index of tile i,j.
1999 * \param l y pixel index of tile i,j.
2000 * \param image destination image.
2001 * \param m x pixel of destination image.
2002 * \param n y pixel of destination image.
2004 void XCFImageFormat::mergeGrayAToRGB(Layer& layer, uint i, uint j, int k, int l,
2005 QImage& image, int m, int n)
2007 int src = qGray(layer.image_tiles[j][i].pixel(k, l));
2008 int dst = qGray(image.pixel(m, n));
2010 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
2011 uchar dst_a = qAlpha(image.pixel(m, n));
2013 if (!src_a) return; // nothing to merge
2015 switch (layer.mode) {
2016 case MULTIPLY_MODE: {
2017 src = INT_MULT(src, dst);
2018 src_a = qMin(src_a, dst_a);
2020 break;
2021 case DIVIDE_MODE: {
2022 src = qMin((dst * 256) / (1 + src), 255);
2023 src_a = qMin(src_a, dst_a);
2025 break;
2026 case SCREEN_MODE: {
2027 src = 255 - INT_MULT(255 - dst, 255 - src);
2028 src_a = qMin(src_a, dst_a);
2030 break;
2031 case OVERLAY_MODE: {
2032 src = INT_MULT( dst, dst + INT_MULT(2 * src, 255 - dst));
2033 src_a = qMin(src_a, dst_a);
2035 break;
2036 case DIFFERENCE_MODE: {
2037 src = dst > src ? dst - src : src - dst;
2038 src_a = qMin(src_a, dst_a);
2040 break;
2041 case ADDITION_MODE: {
2042 src = add_lut(dst,src);
2043 src_a = qMin(src_a, dst_a);
2045 break;
2046 case SUBTRACT_MODE: {
2047 src = dst > src ? dst - src : 0;
2048 src_a = qMin(src_a, dst_a);
2050 break;
2051 case DARKEN_ONLY_MODE: {
2052 src = dst < src ? dst : src;
2053 src_a = qMin(src_a, dst_a);
2055 break;
2056 case LIGHTEN_ONLY_MODE: {
2057 src = dst < src ? src : dst;
2058 src_a = qMin(src_a, dst_a);
2060 break;
2061 case DODGE_MODE: {
2062 uint tmp = dst << 8;
2063 tmp /= 256 - src;
2064 src = (uchar) qMin(tmp, 255u);
2065 src_a = qMin(src_a, dst_a);
2067 break;
2068 case BURN_MODE: {
2069 uint tmp = (255-dst) << 8;
2070 tmp /= src + 1;
2071 src = (uchar) qMin(tmp, 255u);
2072 src = 255 - src;
2073 src_a = qMin(src_a, dst_a);
2075 break;
2076 case HARDLIGHT_MODE: {
2077 uint tmp;
2078 if (src > 128) {
2079 tmp = ((int)255-dst) * ((int) 255 - ((src-128) << 1));
2080 src = (uchar) qMin(255 - (tmp >> 8), 255u);
2081 } else {
2082 tmp = (int) dst * ((int) src << 1);
2083 src = (uchar) qMin(tmp >> 8, 255u);
2085 src_a = qMin(src_a, dst_a);
2087 break;
2088 case SOFTLIGHT_MODE: {
2089 uint tmpS, tmpM;
2091 tmpM = INT_MULT(dst, src);
2092 tmpS = 255 - INT_MULT((255 - dst), (255-src));
2093 src = INT_MULT((255 - dst), tmpM)
2094 + INT_MULT(dst, tmpS);
2096 src_a = qMin(src_a, dst_a);
2098 break;
2099 case GRAIN_EXTRACT_MODE: {
2100 int tmp;
2102 tmp = dst - src + 128;
2103 tmp = qMin(tmp, 255);
2104 tmp = qMax(tmp, 0);
2106 src = (uchar) tmp;
2107 src_a = qMin(src_a, dst_a);
2109 break;
2110 case GRAIN_MERGE_MODE: {
2111 int tmp;
2113 tmp = dst + src - 128;
2114 tmp = qMin(tmp, 255);
2115 tmp = qMax(tmp, 0);
2117 src = (uchar) tmp;
2118 src_a = qMin(src_a, dst_a);
2120 break;
2123 src_a = INT_MULT(src_a, layer.opacity);
2125 // Apply the mask (if any)
2126 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
2127 layer.mask_tiles[j].size() > (int)i)
2128 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
2130 uchar new_a = dst_a + INT_MULT(OPAQUE_OPACITY - dst_a, src_a);
2132 float src_ratio = (float)src_a / new_a;
2133 float dst_ratio = 1.0 - src_ratio;
2135 uchar new_g = (uchar)(src_ratio * src + dst_ratio * dst + EPSILON);
2137 if (!layer_modes[layer.mode].affect_alpha)
2138 new_a = dst_a;
2140 image.setPixel(m, n, qRgba(new_g, new_g, new_g, new_a));
2145 * Merge an Indexed pixel from the layer to the Indexed image. Straight-forward.
2146 * \param layer source layer.
2147 * \param i x tile index.
2148 * \param j y tile index.
2149 * \param k x pixel index of tile i,j.
2150 * \param l y pixel index of tile i,j.
2151 * \param image destination image.
2152 * \param m x pixel of destination image.
2153 * \param n y pixel of destination image.
2155 void XCFImageFormat::mergeIndexedToIndexed(Layer& layer, uint i, uint j, int k, int l,
2156 QImage& image, int m, int n)
2158 int src = layer.image_tiles[j][i].pixelIndex(k, l);
2159 image.setPixel(m, n, src);
2164 * Merge an IndexedA pixel from the layer to the Indexed image. Straight-forward.
2165 * \param layer source layer.
2166 * \param i x tile index.
2167 * \param j y tile index.
2168 * \param k x pixel index of tile i,j.
2169 * \param l y pixel index of tile i,j.
2170 * \param image destination image.
2171 * \param m x pixel of destination image.
2172 * \param n y pixel of destination image.
2174 void XCFImageFormat::mergeIndexedAToIndexed(Layer& layer, uint i, uint j, int k, int l,
2175 QImage& image, int m, int n)
2177 uchar src = layer.image_tiles[j][i].pixelIndex(k, l);
2178 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
2179 src_a = INT_MULT( src_a, layer.opacity );
2181 if ( layer.apply_mask == 1 &&
2182 layer.mask_tiles.size() > (int)j &&
2183 layer.mask_tiles[j].size() > (int)i)
2184 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
2186 if (src_a > 127) {
2187 src++;
2188 image.setPixel(m, n, src);
2194 * Merge an IndexedA pixel from the layer to an RGB image. Straight-forward.
2195 * The only thing this has to take account of is the opacity of the
2196 * layer. Evidently, the GIMP exporter itself does not actually do this.
2197 * \param layer source layer.
2198 * \param i x tile index.
2199 * \param j y tile index.
2200 * \param k x pixel index of tile i,j.
2201 * \param l y pixel index of tile i,j.
2202 * \param image destination image.
2203 * \param m x pixel of destination image.
2204 * \param n y pixel of destination image.
2206 void XCFImageFormat::mergeIndexedAToRGB(Layer& layer, uint i, uint j, int k, int l,
2207 QImage& image, int m, int n)
2209 QRgb src = layer.image_tiles[j][i].pixel(k, l);
2210 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
2211 src_a = INT_MULT(src_a, layer.opacity);
2213 // Apply the mask (if any)
2214 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
2215 layer.mask_tiles[j].size() > (int)i)
2216 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
2218 // This is what appears in the GIMP window
2219 if (src_a <= 127)
2220 src_a = 0;
2221 else
2222 src_a = OPAQUE_OPACITY;
2224 image.setPixel(m, n, qRgba(src, src_a));
2229 * Dissolving pixels: pick a random number between 0 and 255. If the pixel's
2230 * alpha is less than that, make it transparent.
2231 * \param image the image tile to dissolve.
2232 * \param x the global x position of the tile.
2233 * \param y the global y position of the tile.
2235 void XCFImageFormat::dissolveRGBPixels ( QImage& image, int x, int y )
2237 // The apparently spurious rand() calls are to wind the random
2238 // numbers up to the same point for each tile.
2240 for (int l = 0; l < image.height(); l++) {
2241 srand(random_table[( l + y ) % RANDOM_TABLE_SIZE]);
2243 for (int k = 0; k < x; k++)
2244 rand();
2246 for (int k = 0; k < image.width(); k++) {
2247 int rand_val = rand() & 0xff;
2248 QRgb pixel = image.pixel(k, l);
2250 if (rand_val > qAlpha(pixel)) {
2251 image.setPixel(k, l, qRgba(pixel, 0));
2259 * Dissolving pixels: pick a random number between 0 and 255. If the pixel's
2260 * alpha is less than that, make it transparent. This routine works for
2261 * the GRAYA and INDEXEDA image types where the pixel alpha's are stored
2262 * separately from the pixel themselves.
2263 * \param image the alpha tile to dissolve.
2264 * \param x the global x position of the tile.
2265 * \param y the global y position of the tile.
2267 void XCFImageFormat::dissolveAlphaPixels ( QImage& image, int x, int y )
2269 // The apparently spurious rand() calls are to wind the random
2270 // numbers up to the same point for each tile.
2272 for (int l = 0; l < image.height(); l++) {
2273 srand( random_table[(l + y) % RANDOM_TABLE_SIZE]);
2275 for (int k = 0; k < x; k++)
2276 rand();
2278 for (int k = 0; k < image.width(); k++) {
2279 int rand_val = rand() & 0xff;
2280 uchar alpha = image.pixelIndex(k, l);
2282 if (rand_val > alpha) {
2283 image.setPixel(k, l, 0);
2290 ///////////////////////////////////////////////////////////////////////////////
2292 XCFHandler::XCFHandler()
2296 bool XCFHandler::canRead() const
2298 if (canRead(device())) {
2299 setFormat("xcf");
2300 return true;
2302 return false;
2305 bool XCFHandler::read(QImage *image)
2307 XCFImageFormat xcfif;
2308 return xcfif.readXCF(device(), image);
2311 bool XCFHandler::write(const QImage &)
2313 return false;
2316 QByteArray XCFHandler::name() const
2318 return "xcf";
2321 bool XCFHandler::canRead(QIODevice *device)
2323 if (!device) {
2324 qWarning("DDSHandler::canRead() called with no device");
2325 return false;
2328 qint64 oldPos = device->pos();
2330 char head[8];
2331 qint64 readBytes = device->read(head, sizeof(head));
2332 if (readBytes != sizeof(head)) {
2333 if (device->isSequential()) {
2334 while (readBytes > 0)
2335 device->ungetChar(head[readBytes-- - 1]);
2336 } else {
2337 device->seek(oldPos);
2339 return false;
2342 if (device->isSequential()) {
2343 while (readBytes > 0)
2344 device->ungetChar(head[readBytes-- - 1]);
2345 } else {
2346 device->seek(oldPos);
2349 return qstrncmp(head, "gimp xcf", 8) == 0;
2353 class XCFPlugin : public QImageIOPlugin
2355 public:
2356 QStringList keys() const;
2357 Capabilities capabilities(QIODevice *device, const QByteArray &format) const;
2358 QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const;
2361 QStringList XCFPlugin::keys() const
2363 return QStringList() << "xcf" << "XCF";
2366 QImageIOPlugin::Capabilities XCFPlugin::capabilities(QIODevice *device, const QByteArray &format) const
2368 if (format == "xcf" || format == "XCF")
2369 return Capabilities(CanRead);
2370 if (!format.isEmpty())
2371 return 0;
2372 if (!device->isOpen())
2373 return 0;
2375 Capabilities cap;
2376 if (device->isReadable() && XCFHandler::canRead(device))
2377 cap |= CanRead;
2378 return cap;
2381 QImageIOHandler *XCFPlugin::create(QIODevice *device, const QByteArray &format) const
2383 QImageIOHandler *handler = new XCFHandler;
2384 handler->setDevice(device);
2385 handler->setFormat(format);
2386 return handler;
2389 Q_EXPORT_STATIC_PLUGIN(XCFPlugin)
2390 Q_EXPORT_PLUGIN2(xcf,XCFPlugin)