00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "xcf.h"
00023
00024 #include <stdlib.h>
00025 #include <QtGui/QImage>
00026 #include <QtCore/QIODevice>
00027 #include <QtCore/QStack>
00028 #include <QtCore/QVector>
00029
00030 #include <kdebug.h>
00031
00032
00033 int XCFImageFormat::random_table[RANDOM_TABLE_SIZE];
00034
00035
00036
00037
00038 const XCFImageFormat::LayerModes XCFImageFormat::layer_modes[] = {
00039 {true},
00040 {true},
00041 {true},
00042 {false},
00043 {false},
00044 {false},
00045 {false},
00046 {false},
00047 {false},
00048 {false},
00049 {false},
00050 {false},
00051 {false},
00052 {false},
00053 {false},
00054 {false},
00055 {false},
00056 {false},
00057 {false},
00058 {false},
00059 {false},
00060 {false},
00061 };
00062
00063
00065 inline QRgb qRgba ( const QRgb& rgb, int a )
00066 {
00067 return ((a & 0xff) << 24 | (rgb & RGB_MASK));
00068 }
00069
00070
00075 XCFImageFormat::XCFImageFormat()
00076 {
00077
00078 srand(RANDOM_SEED);
00079
00080 for (int i = 0; i < RANDOM_TABLE_SIZE; i++)
00081 random_table[i] = rand();
00082
00083 for (int i = 0; i < RANDOM_TABLE_SIZE; i++) {
00084 int tmp;
00085 int swap = i + rand() % (RANDOM_TABLE_SIZE - i);
00086 tmp = random_table[i];
00087 random_table[i] = random_table[swap];
00088 random_table[swap] = tmp;
00089 }
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 }
00100
00101 inline
00102 int XCFImageFormat::add_lut( int a, int b ) {
00103 return qMin( a + b, 255 );
00104 }
00105
00106 bool XCFImageFormat::readXCF(QIODevice *device, QImage *outImage)
00107 {
00108 XCFImage xcf_image;
00109 QDataStream xcf_io(device);
00110
00111 char tag[14];;
00112
00113 if (xcf_io.readRawData(tag, sizeof(tag)) != sizeof(tag)) {
00114 kDebug(399) << "XCF: read failure on header tag";
00115 return false;
00116 }
00117
00118 xcf_io >> xcf_image.width >> xcf_image.height >> xcf_image.type;
00119
00120 kDebug() << tag << " " << xcf_image.width << " " << xcf_image.height << " " << xcf_image.type;
00121 if (!loadImageProperties(xcf_io, xcf_image))
00122 return false;
00123
00124
00125
00126
00127
00128
00129
00130 QStack<qint32> layer_offsets;
00131
00132 while (true) {
00133 qint32 layer_offset;
00134
00135 xcf_io >> layer_offset;
00136
00137 if (layer_offset == 0)
00138 break;
00139
00140 layer_offsets.push(layer_offset);
00141 }
00142
00143 xcf_image.num_layers = layer_offsets.size();
00144
00145 if (layer_offsets.size() == 0) {
00146 kDebug(399) << "XCF: no layers!";
00147 return false;
00148 }
00149
00150
00151 while (!layer_offsets.isEmpty()) {
00152 qint32 layer_offset = layer_offsets.pop();
00153
00154 xcf_io.device()->seek(layer_offset);
00155
00156 if (!loadLayer(xcf_io, xcf_image))
00157 return false;
00158 }
00159
00160 if (!xcf_image.initialized) {
00161 kDebug(399) << "XCF: no visible layers!";
00162 return false;
00163 }
00164
00165 *outImage = xcf_image.image;
00166 return true;
00167 }
00168
00169
00177 bool XCFImageFormat::loadImageProperties(QDataStream& xcf_io, XCFImage& xcf_image)
00178 {
00179 while (true) {
00180 PropType type;
00181 QByteArray bytes;
00182
00183 if (!loadProperty(xcf_io, type, bytes)) {
00184 kDebug(399) << "XCF: error loading global image properties";
00185 return false;
00186 }
00187
00188 QDataStream property(bytes);
00189
00190 switch (type) {
00191 case PROP_END:
00192 return true;
00193
00194 case PROP_COMPRESSION:
00195 property >> xcf_image.compression;
00196 break;
00197
00198 case PROP_RESOLUTION:
00199 property >> xcf_image.x_resolution >> xcf_image.y_resolution;
00200 break;
00201
00202 case PROP_TATTOO:
00203 property >> xcf_image.tattoo;
00204 break;
00205
00206 case PROP_PARASITES:
00207 while (!property.atEnd()) {
00208 char* tag;
00209 quint32 size;
00210
00211 property.readBytes(tag, size);
00212
00213 quint32 flags;
00214 char* data=0;
00215 property >> flags >> data;
00216
00217 if (tag && strncmp(tag, "gimp-comment", strlen("gimp-comment")) == 0)
00218 xcf_image.image.setText("Comment", 0, data);
00219
00220 delete[] tag;
00221 delete[] data;
00222 }
00223 break;
00224
00225 case PROP_UNIT:
00226 property >> xcf_image.unit;
00227 break;
00228
00229 case PROP_PATHS:
00230 break;
00231
00232 case PROP_USER_UNIT:
00233 break;
00234
00235 case PROP_COLORMAP:
00236 property >> xcf_image.num_colors;
00237 if(xcf_image.num_colors < 0 || xcf_image.num_colors > 65535)
00238 return false;
00239
00240 xcf_image.palette.reserve(xcf_image.num_colors);
00241
00242 for (int i = 0; i < xcf_image.num_colors; i++) {
00243 uchar r, g, b;
00244 property >> r >> g >> b;
00245 xcf_image.palette.push_back( qRgb(r,g,b) );
00246 }
00247 break;
00248
00249 default:
00250 kDebug(399) << "XCF: unimplemented image property" << type
00251 << ", size " << bytes.size() << endl;
00252 }
00253 }
00254 }
00255
00256
00264 bool XCFImageFormat::loadProperty(QDataStream& xcf_io, PropType& type, QByteArray& bytes)
00265 {
00266 quint32 foo;
00267 xcf_io >> foo;
00268 type=PropType(foo);
00269
00270 char* data = 0;
00271 quint32 size;
00272
00273
00274
00275
00276
00277 if (type == PROP_COLORMAP) {
00278 xcf_io >> size;
00279
00280 if(size > 65535 || size < 4)
00281 return false;
00282
00283 size = 3 * (size - 4) + 4;
00284 data = new char[size];
00285
00286 xcf_io.readRawData(data, size);
00287 } else if (type == PROP_USER_UNIT) {
00288
00289 float factor;
00290 qint32 digits;
00291
00292 xcf_io >> size >> factor >> digits;
00293
00294 for (int i = 0; i < 5; i++) {
00295 char* unit_strings;
00296
00297 xcf_io >> unit_strings;
00298
00299 delete[] unit_strings;
00300
00301 if (xcf_io.device()->atEnd()) {
00302 kDebug(399) << "XCF: read failure on property " << type;
00303 return false;
00304 }
00305 }
00306
00307 size = 0;
00308 } else {
00309 xcf_io >> size;
00310 if(size >256000)
00311 return false;
00312 data = new char[size];
00313 xcf_io.readRawData(data, size);
00314 }
00315
00316 if (size != 0 && data)
00317 bytes = QByteArray(data,size);
00318
00319 delete [] data;
00320
00321 return true;
00322 }
00323
00324
00333 bool XCFImageFormat::loadLayer(QDataStream& xcf_io, XCFImage& xcf_image)
00334 {
00335 Layer& layer(xcf_image.layer);
00336 delete[] layer.name;
00337
00338 xcf_io >> layer.width >> layer.height >> layer.type >> layer.name;
00339
00340 if (!loadLayerProperties(xcf_io, layer))
00341 return false;
00342 #if 0
00343 cout << "layer: \"" << layer.name << "\", size: " << layer.width << " x "
00344 << layer.height << ", type: " << layer.type << ", mode: " << layer.mode
00345 << ", opacity: " << layer.opacity << ", visible: " << layer.visible
00346 << ", offset: " << layer.x_offset << ", " << layer.y_offset << endl;
00347 #endif
00348
00349
00350
00351
00352 if (layer.visible == 0)
00353 return true;
00354
00355
00356
00357 xcf_io >> layer.hierarchy_offset >> layer.mask_offset;
00358
00359
00360
00361
00362 if( !composeTiles(xcf_image))
00363 return false;
00364 xcf_io.device()->seek(layer.hierarchy_offset);
00365
00366
00367
00368
00369
00370 layer.assignBytes = assignImageBytes;
00371
00372 if (!loadHierarchy(xcf_io, layer))
00373 return false;
00374
00375 if (layer.mask_offset != 0) {
00376 xcf_io.device()->seek(layer.mask_offset);
00377
00378 if (!loadMask(xcf_io, layer))
00379 return false;
00380 }
00381
00382
00383
00384
00385
00386 if (!xcf_image.initialized) {
00387 if( !initializeImage(xcf_image))
00388 return false;
00389 copyLayerToImage(xcf_image);
00390 xcf_image.initialized = true;
00391 } else
00392 mergeLayerIntoImage(xcf_image);
00393
00394 return true;
00395 }
00396
00397
00405 bool XCFImageFormat::loadLayerProperties(QDataStream& xcf_io, Layer& layer)
00406 {
00407 while (true) {
00408 PropType type;
00409 QByteArray bytes;
00410
00411 if (!loadProperty(xcf_io, type, bytes)) {
00412 kDebug(399) << "XCF: error loading layer properties";
00413 return false;
00414 }
00415
00416 QDataStream property(bytes);
00417
00418 switch (type) {
00419 case PROP_END:
00420 return true;
00421
00422 case PROP_ACTIVE_LAYER:
00423 layer.active = true;
00424 break;
00425
00426 case PROP_OPACITY:
00427 property >> layer.opacity;
00428 break;
00429
00430 case PROP_VISIBLE:
00431 property >> layer.visible;
00432 break;
00433
00434 case PROP_LINKED:
00435 property >> layer.linked;
00436 break;
00437
00438 case PROP_PRESERVE_TRANSPARENCY:
00439 property >> layer.preserve_transparency;
00440 break;
00441
00442 case PROP_APPLY_MASK:
00443 property >> layer.apply_mask;
00444 break;
00445
00446 case PROP_EDIT_MASK:
00447 property >> layer.edit_mask;
00448 break;
00449
00450 case PROP_SHOW_MASK:
00451 property >> layer.show_mask;
00452 break;
00453
00454 case PROP_OFFSETS:
00455 property >> layer.x_offset >> layer.y_offset;
00456 break;
00457
00458 case PROP_MODE:
00459 property >> layer.mode;
00460 break;
00461
00462 case PROP_TATTOO:
00463 property >> layer.tattoo;
00464 break;
00465
00466 default:
00467 kDebug(399) << "XCF: unimplemented layer property " << type
00468 << ", size " << bytes.size() << endl;
00469 }
00470 }
00471 }
00472
00473
00479 bool XCFImageFormat::composeTiles(XCFImage& xcf_image)
00480 {
00481 Layer& layer(xcf_image.layer);
00482
00483 layer.nrows = (layer.height + TILE_HEIGHT - 1) / TILE_HEIGHT;
00484 layer.ncols = (layer.width + TILE_WIDTH - 1) / TILE_WIDTH;
00485
00486 layer.image_tiles.resize(layer.nrows);
00487
00488 if (layer.type == GRAYA_GIMAGE || layer.type == INDEXEDA_GIMAGE)
00489 layer.alpha_tiles.resize(layer.nrows);
00490
00491 if (layer.mask_offset != 0)
00492 layer.mask_tiles.resize(layer.nrows);
00493
00494 for (uint j = 0; j < layer.nrows; j++) {
00495 layer.image_tiles[j].resize(layer.ncols);
00496
00497 if (layer.type == GRAYA_GIMAGE || layer.type == INDEXEDA_GIMAGE)
00498 layer.alpha_tiles[j].resize(layer.ncols);
00499
00500 if (layer.mask_offset != 0)
00501 layer.mask_tiles[j].resize(layer.ncols);
00502 }
00503
00504 for (uint j = 0; j < layer.nrows; j++) {
00505 for (uint i = 0; i < layer.ncols; i++) {
00506
00507 uint tile_width = (i + 1) * TILE_WIDTH <= layer.width
00508 ? TILE_WIDTH : layer.width - i * TILE_WIDTH;
00509
00510 uint tile_height = (j + 1) * TILE_HEIGHT <= layer.height
00511 ? TILE_HEIGHT : layer.height - j * TILE_HEIGHT;
00512
00513
00514
00515
00516 switch (layer.type) {
00517 case RGB_GIMAGE:
00518 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_RGB32);
00519 layer.image_tiles[j][i].setNumColors(0);
00520 if( layer.image_tiles[j][i].isNull())
00521 return false;
00522 break;
00523
00524 case RGBA_GIMAGE:
00525 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_ARGB32);
00526 layer.image_tiles[j][i].setNumColors(0);
00527 if( layer.image_tiles[j][i].isNull())
00528 return false;
00529 break;
00530
00531 case GRAY_GIMAGE:
00532 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
00533 layer.image_tiles[j][i].setNumColors(256);
00534 if( layer.image_tiles[j][i].isNull())
00535 return false;
00536 setGrayPalette(layer.image_tiles[j][i]);
00537 break;
00538
00539 case GRAYA_GIMAGE:
00540 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
00541 layer.image_tiles[j][i].setNumColors(256);
00542 if( layer.image_tiles[j][i].isNull())
00543 return false;
00544 setGrayPalette(layer.image_tiles[j][i]);
00545
00546 layer.alpha_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
00547 layer.alpha_tiles[j][i].setNumColors(256);
00548 if( layer.alpha_tiles[j][i].isNull())
00549 return false;
00550 setGrayPalette(layer.alpha_tiles[j][i]);
00551 break;
00552
00553 case INDEXED_GIMAGE:
00554 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
00555 layer.image_tiles[j][i].setNumColors(xcf_image.num_colors);
00556 if( layer.image_tiles[j][i].isNull())
00557 return false;
00558 setPalette(xcf_image, layer.image_tiles[j][i]);
00559 break;
00560
00561 case INDEXEDA_GIMAGE:
00562 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
00563 layer.image_tiles[j][i].setNumColors(xcf_image.num_colors);
00564 if( layer.image_tiles[j][i].isNull())
00565 return false;
00566 setPalette(xcf_image, layer.image_tiles[j][i]);
00567
00568 layer.alpha_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
00569 layer.alpha_tiles[j][i].setNumColors(256);
00570 if( layer.alpha_tiles[j][i].isNull())
00571 return false;
00572 setGrayPalette(layer.alpha_tiles[j][i]);
00573 }
00574
00575 if (layer.mask_offset != 0) {
00576 layer.mask_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
00577 layer.mask_tiles[j][i].setNumColors(256);
00578 if( layer.mask_tiles[j][i].isNull())
00579 return false;
00580 setGrayPalette(layer.mask_tiles[j][i]);
00581 }
00582 }
00583 }
00584 return true;
00585 }
00586
00587
00594 void XCFImageFormat::setGrayPalette(QImage& image)
00595 {
00596 for (int i = 0; i < 256; i++)
00597 image.setColor(i, qRgb(i, i, i));
00598 }
00599
00600
00606 void XCFImageFormat::setPalette(XCFImage& xcf_image, QImage& image)
00607 {
00608 for (int i = 0; i < xcf_image.num_colors; i++)
00609 image.setColor(i, xcf_image.palette[i]);
00610 }
00611
00612
00620 void XCFImageFormat::assignImageBytes(Layer& layer, uint i, uint j)
00621 {
00622 uchar* tile = layer.tile;
00623
00624 switch (layer.type) {
00625 case RGB_GIMAGE:
00626 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
00627 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
00628 layer.image_tiles[j][i].setPixel(k, l,
00629 qRgb(tile[0], tile[1], tile[2]));
00630 tile += sizeof(QRgb);
00631 }
00632 }
00633 break;
00634
00635 case RGBA_GIMAGE:
00636 for ( int l = 0; l < layer.image_tiles[j][i].height(); l++ ) {
00637 for ( int k = 0; k < layer.image_tiles[j][i].width(); k++ ) {
00638 layer.image_tiles[j][i].setPixel(k, l,
00639 qRgba(tile[0], tile[1], tile[2], tile[3]));
00640 tile += sizeof(QRgb);
00641 }
00642 }
00643 break;
00644
00645 case GRAY_GIMAGE:
00646 case INDEXED_GIMAGE:
00647 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
00648 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
00649 layer.image_tiles[j][i].setPixel(k, l, tile[0]);
00650 tile += sizeof(QRgb);
00651 }
00652 }
00653 break;
00654
00655 case GRAYA_GIMAGE:
00656 case INDEXEDA_GIMAGE:
00657 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
00658 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
00659
00660
00661
00662
00663
00664 if (tile[0] < layer.image_tiles[j][i].numColors())
00665 layer.image_tiles[j][i].setPixel(k, l, tile[0]);
00666
00667 layer.alpha_tiles[j][i].setPixel(k, l, tile[1]);
00668 tile += sizeof(QRgb);
00669 }
00670 }
00671 break;
00672 }
00673 }
00674
00675
00684 bool XCFImageFormat::loadHierarchy(QDataStream& xcf_io, Layer& layer)
00685 {
00686 qint32 width;
00687 qint32 height;
00688 qint32 bpp;
00689 quint32 offset;
00690
00691 xcf_io >> width >> height >> bpp >> offset;
00692
00693
00694
00695
00696
00697 quint32 junk;
00698 do {
00699 xcf_io >> junk;
00700
00701 if (xcf_io.device()->atEnd()) {
00702 kDebug(399) << "XCF: read failure on layer " << layer.name << " level offsets";
00703 return false;
00704 }
00705 } while (junk != 0);
00706
00707 qint64 saved_pos = xcf_io.device()->pos();
00708
00709 xcf_io.device()->seek(offset);
00710 if (!loadLevel(xcf_io, layer, bpp))
00711 return false;
00712
00713 xcf_io.device()->seek(saved_pos);
00714 return true;
00715 }
00716
00717
00726 bool XCFImageFormat::loadLevel(QDataStream& xcf_io, Layer& layer, qint32 bpp)
00727 {
00728 qint32 width;
00729 qint32 height;
00730 quint32 offset;
00731
00732 xcf_io >> width >> height >> offset;
00733
00734 if (offset == 0)
00735 return true;
00736
00737 for (uint j = 0; j < layer.nrows; j++) {
00738 for (uint i = 0; i < layer.ncols; i++) {
00739
00740 if (offset == 0) {
00741 kDebug(399) << "XCF: incorrect number of tiles in layer " << layer.name;
00742 return false;
00743 }
00744
00745 qint64 saved_pos = xcf_io.device()->pos();
00746 quint32 offset2;
00747 xcf_io >> offset2;
00748
00749
00750
00751 if (offset2 == 0)
00752 offset2 = offset + (uint)(TILE_WIDTH * TILE_HEIGHT * 4 * 1.5);
00753
00754 xcf_io.device()->seek(offset);
00755 int size = layer.image_tiles[j][i].width() * layer.image_tiles[j][i].height();
00756
00757 if (!loadTileRLE(xcf_io, layer.tile, size, offset2 - offset, bpp))
00758 return false;
00759
00760
00761
00762
00763
00764 layer.assignBytes(layer, i, j);
00765
00766 xcf_io.device()->seek(saved_pos);
00767 xcf_io >> offset;
00768 }
00769 }
00770
00771 return true;
00772 }
00773
00774
00781 bool XCFImageFormat::loadMask(QDataStream& xcf_io, Layer& layer)
00782 {
00783 qint32 width;
00784 qint32 height;
00785 char* name;
00786
00787 xcf_io >> width >> height >> name;
00788
00789 delete name;
00790
00791 if (!loadChannelProperties(xcf_io, layer))
00792 return false;
00793
00794 quint32 hierarchy_offset;
00795 xcf_io >> hierarchy_offset;
00796
00797 xcf_io.device()->seek(hierarchy_offset);
00798 layer.assignBytes = assignMaskBytes;
00799
00800 if (!loadHierarchy(xcf_io, layer))
00801 return false;
00802
00803 return true;
00804 }
00805
00806
00830 bool XCFImageFormat::loadTileRLE(QDataStream& xcf_io, uchar* tile, int image_size,
00831 int data_length, qint32 bpp)
00832 {
00833 uchar* data;
00834
00835 uchar* xcfdata;
00836 uchar* xcfodata;
00837 uchar* xcfdatalimit;
00838
00839 xcfdata = xcfodata = new uchar[data_length];
00840
00841 xcf_io.readRawData((char*)xcfdata, data_length);
00842
00843 if (!xcf_io.device()->isOpen()) {
00844 delete[] xcfodata;
00845 kDebug(399) << "XCF: read failure on tile";
00846 return false;
00847 }
00848
00849 xcfdatalimit = &xcfodata[data_length - 1];
00850
00851 for (int i = 0; i < bpp; ++i) {
00852
00853 data = tile + i;
00854
00855 int count = 0;
00856 int size = image_size;
00857
00858 while (size > 0) {
00859 if (xcfdata > xcfdatalimit)
00860 goto bogus_rle;
00861
00862 uchar val = *xcfdata++;
00863 uint length = val;
00864
00865 if (length >= 128) {
00866 length = 255 - (length - 1);
00867 if (length == 128) {
00868 if (xcfdata >= xcfdatalimit)
00869 goto bogus_rle;
00870
00871 length = (*xcfdata << 8) + xcfdata[1];
00872
00873 xcfdata += 2;
00874 }
00875
00876 count += length;
00877 size -= length;
00878
00879 if (size < 0)
00880 goto bogus_rle;
00881
00882 if (&xcfdata[length - 1] > xcfdatalimit)
00883 goto bogus_rle;
00884
00885 while (length-- > 0) {
00886 *data = *xcfdata++;
00887 data += sizeof(QRgb);
00888 }
00889 } else {
00890 length += 1;
00891 if (length == 128) {
00892 if (xcfdata >= xcfdatalimit)
00893 goto bogus_rle;
00894
00895 length = (*xcfdata << 8) + xcfdata[1];
00896 xcfdata += 2;
00897 }
00898
00899 count += length;
00900 size -= length;
00901
00902 if (size < 0)
00903 goto bogus_rle;
00904
00905 if (xcfdata > xcfdatalimit)
00906 goto bogus_rle;
00907
00908 val = *xcfdata++;
00909
00910 while (length-- > 0) {
00911 *data = val;
00912 data += sizeof(QRgb);
00913 }
00914 }
00915 }
00916 }
00917
00918 delete[] xcfodata;
00919 return true;
00920
00921 bogus_rle:
00922
00923 kDebug(399) << "The run length encoding could not be decoded properly";
00924 delete[] xcfodata;
00925 return false;
00926 }
00927
00928
00936 bool XCFImageFormat::loadChannelProperties(QDataStream& xcf_io, Layer& layer)
00937 {
00938 while (true) {
00939 PropType type;
00940 QByteArray bytes;
00941
00942 if (!loadProperty(xcf_io, type, bytes)) {
00943 kDebug(399) << "XCF: error loading channel properties";
00944 return false;
00945 }
00946
00947 QDataStream property(bytes);
00948
00949 switch (type) {
00950 case PROP_END:
00951 return true;
00952
00953 case PROP_OPACITY:
00954 property >> layer.mask_channel.opacity;
00955 break;
00956
00957 case PROP_VISIBLE:
00958 property >> layer.mask_channel.visible;
00959 break;
00960
00961 case PROP_SHOW_MASKED:
00962 property >> layer.mask_channel.show_masked;
00963 break;
00964
00965 case PROP_COLOR:
00966 property >> layer.mask_channel.red >> layer.mask_channel.green
00967 >> layer.mask_channel.blue;
00968 break;
00969
00970 case PROP_TATTOO:
00971 property >> layer.mask_channel.tattoo;
00972 break;
00973
00974 default:
00975 kDebug(399) << "XCF: unimplemented channel property " << type
00976 << ", size " << bytes.size() << endl;
00977 }
00978 }
00979 }
00980
00981
00988 void XCFImageFormat::assignMaskBytes(Layer& layer, uint i, uint j)
00989 {
00990 uchar* tile = layer.tile;
00991
00992 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
00993 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
00994 layer.mask_tiles[j][i].setPixel(k, l, tile[0]);
00995 tile += sizeof(QRgb);
00996 }
00997 }
00998 }
00999
01000
01029 bool XCFImageFormat::initializeImage(XCFImage& xcf_image)
01030 {
01031
01032 Layer& layer(xcf_image.layer);
01033 QImage& image(xcf_image.image);
01034
01035 switch (layer.type) {
01036 case RGB_GIMAGE:
01037 if (layer.opacity == OPAQUE_OPACITY) {
01038 image = QImage( xcf_image.width, xcf_image.height, QImage::Format_RGB32);
01039 if( image.isNull())
01040 return false;
01041 image.fill(qRgb(255, 255, 255));
01042 break;
01043 }
01044
01045 case RGBA_GIMAGE:
01046 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_ARGB32);
01047 if( image.isNull())
01048 return false;
01049 image.fill(qRgba(255, 255, 255, 0));
01050 break;
01051
01052 case GRAY_GIMAGE:
01053 if (layer.opacity == OPAQUE_OPACITY) {
01054 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_Indexed8);
01055 image.setNumColors(256);
01056 if( image.isNull())
01057 return false;
01058 setGrayPalette(image);
01059 image.fill(255);
01060 break;
01061 }
01062
01063 case GRAYA_GIMAGE:
01064 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_ARGB32);
01065 if( image.isNull())
01066 return false;
01067 image.fill(qRgba(255, 255, 255, 0));
01068 break;
01069
01070 case INDEXED_GIMAGE:
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083 if (xcf_image.num_colors <= 2) {
01084 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_MonoLSB);
01085 image.setNumColors(xcf_image.num_colors);
01086 if( image.isNull())
01087 return false;
01088 image.fill(0);
01089 setPalette(xcf_image, image);
01090 } else if (xcf_image.num_colors <= 256) {
01091 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_Indexed8);
01092 image.setNumColors(xcf_image.num_colors);
01093 if( image.isNull())
01094 return false;
01095 image.fill(0);
01096 setPalette(xcf_image, image);
01097 }
01098 break;
01099
01100 case INDEXEDA_GIMAGE:
01101 if (xcf_image.num_colors == 1) {
01102
01103 xcf_image.num_colors++;
01104 xcf_image.palette.resize(xcf_image.num_colors);
01105 xcf_image.palette[1] = xcf_image.palette[0];
01106 xcf_image.palette[0] = qRgba(255, 255, 255, 0);
01107
01108 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_MonoLSB);
01109 image.setNumColors(xcf_image.num_colors);
01110 if( image.isNull())
01111 return false;
01112 image.fill(0);
01113 setPalette(xcf_image, image);
01114 } else if (xcf_image.num_colors < 256) {
01115
01116 xcf_image.num_colors++;
01117 xcf_image.palette.resize(xcf_image.num_colors);
01118 for (int c = xcf_image.num_colors - 1; c >= 1; c--)
01119 xcf_image.palette[c] = xcf_image.palette[c - 1];
01120
01121 xcf_image.palette[0] = qRgba(255, 255, 255, 0);
01122 image = QImage( xcf_image.width, xcf_image.height, QImage::Format_Indexed8);
01123 image.setNumColors(xcf_image.num_colors);
01124 if( image.isNull())
01125 return false;
01126 image.fill(0);
01127 setPalette(xcf_image, image);
01128 } else {
01129
01130
01131
01132 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_ARGB32);
01133 if( image.isNull())
01134 return false;
01135 image.fill(qRgba(255, 255, 255, 0));
01136 }
01137 break;
01138 }
01139
01140 image.setDotsPerMeterX((int)(xcf_image.x_resolution * INCHESPERMETER));
01141 image.setDotsPerMeterY((int)(xcf_image.y_resolution * INCHESPERMETER));
01142 return true;
01143 }
01144
01145
01151 void XCFImageFormat::copyLayerToImage(XCFImage& xcf_image)
01152 {
01153 Layer& layer(xcf_image.layer);
01154 QImage& image(xcf_image.image);
01155 PixelCopyOperation copy = 0;
01156
01157 switch (layer.type) {
01158 case RGB_GIMAGE:
01159 case RGBA_GIMAGE:
01160 copy = copyRGBToRGB;
01161 break;
01162 case GRAY_GIMAGE:
01163 if (layer.opacity == OPAQUE_OPACITY)
01164 copy = copyGrayToGray;
01165 else
01166 copy = copyGrayToRGB;
01167 break;
01168 case GRAYA_GIMAGE:
01169 copy = copyGrayAToRGB;
01170 break;
01171 case INDEXED_GIMAGE:
01172 copy = copyIndexedToIndexed;
01173 break;
01174 case INDEXEDA_GIMAGE:
01175 if (xcf_image.image.depth() <= 8)
01176 copy = copyIndexedAToIndexed;
01177 else
01178 copy = copyIndexedAToRGB;
01179 }
01180
01181
01182
01183 for (uint j = 0; j < layer.nrows; j++) {
01184 uint y = j * TILE_HEIGHT;
01185
01186 for (uint i = 0; i < layer.ncols; i++) {
01187 uint x = i * TILE_WIDTH;
01188
01189
01190
01191
01192
01193
01194 if (layer.mode == DISSOLVE_MODE) {
01195 if (layer.type == RGBA_GIMAGE)
01196 dissolveRGBPixels(layer.image_tiles[j][i], x, y);
01197
01198 else if (layer.type == GRAYA_GIMAGE)
01199 dissolveAlphaPixels(layer.alpha_tiles[j][i], x, y);
01200 }
01201
01202 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
01203 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
01204
01205 int m = x + k + layer.x_offset;
01206 int n = y + l + layer.y_offset;
01207
01208 if (m < 0 || m >= image.width() || n < 0 || n >= image.height())
01209 continue;
01210
01211 (*copy)(layer, i, j, k, l, image, m, n);
01212 }
01213 }
01214 }
01215 }
01216 }
01217
01218
01232 void XCFImageFormat::copyRGBToRGB(Layer& layer, uint i, uint j, int k, int l,
01233 QImage& image, int m, int n)
01234 {
01235 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01236 uchar src_a = layer.opacity;
01237
01238 if (layer.type == RGBA_GIMAGE)
01239 src_a = INT_MULT(src_a, qAlpha(src));
01240
01241
01242
01243 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
01244 layer.mask_tiles[j].size() > (int)i)
01245 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01246
01247 image.setPixel(m, n, qRgba(src, src_a));
01248 }
01249
01250
01262 void XCFImageFormat::copyGrayToGray(Layer& layer, uint i, uint j, int k, int l,
01263 QImage& image, int m, int n)
01264 {
01265 int src = layer.image_tiles[j][i].pixelIndex(k, l);
01266 image.setPixel(m, n, src);
01267 }
01268
01269
01283 void XCFImageFormat::copyGrayToRGB(Layer& layer, uint i, uint j, int k, int l,
01284 QImage& image, int m, int n)
01285 {
01286 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01287 uchar src_a = layer.opacity;
01288 image.setPixel(m, n, qRgba(src, src_a));
01289 }
01290
01291
01305 void XCFImageFormat::copyGrayAToRGB(Layer& layer, uint i, uint j, int k, int l,
01306 QImage& image, int m, int n)
01307 {
01308 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01309 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
01310 src_a = INT_MULT(src_a, layer.opacity);
01311
01312
01313
01314 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
01315 layer.mask_tiles[j].size() > (int)i)
01316 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01317
01318 image.setPixel(m, n, qRgba(src, src_a));
01319 }
01320
01321
01333 void XCFImageFormat::copyIndexedToIndexed(Layer& layer, uint i, uint j, int k, int l,
01334 QImage& image, int m, int n)
01335 {
01336 int src = layer.image_tiles[j][i].pixelIndex(k, l);
01337 image.setPixel(m, n, src);
01338 }
01339
01340
01352 void XCFImageFormat::copyIndexedAToIndexed(Layer& layer, uint i, uint j, int k, int l,
01353 QImage& image, int m, int n)
01354 {
01355 uchar src = layer.image_tiles[j][i].pixelIndex(k, l);
01356 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
01357 src_a = INT_MULT(src_a, layer.opacity);
01358
01359 if (layer.apply_mask == 1 &&
01360 layer.mask_tiles.size() > (int)j &&
01361 layer.mask_tiles[j].size() > (int)i)
01362 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01363
01364 if (src_a > 127)
01365 src++;
01366 else
01367 src = 0;
01368
01369 image.setPixel(m, n, src);
01370 }
01371
01372
01386 void XCFImageFormat::copyIndexedAToRGB(Layer& layer, uint i, uint j, int k, int l,
01387 QImage& image, int m, int n)
01388 {
01389 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01390 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
01391 src_a = INT_MULT(src_a, layer.opacity);
01392
01393
01394 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
01395 layer.mask_tiles[j].size() > (int)i)
01396 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01397
01398
01399 if (src_a <= 127)
01400 src_a = 0;
01401 else
01402 src_a = OPAQUE_OPACITY;
01403
01404 image.setPixel(m, n, qRgba(src, src_a));
01405 }
01406
01407
01412 void XCFImageFormat::mergeLayerIntoImage(XCFImage& xcf_image)
01413 {
01414 Layer& layer(xcf_image.layer);
01415 QImage& image(xcf_image.image);
01416
01417 PixelMergeOperation merge = 0;
01418
01419 if (!layer.opacity) return;
01420
01421 switch (layer.type) {
01422 case RGB_GIMAGE:
01423 case RGBA_GIMAGE:
01424 merge = mergeRGBToRGB;
01425 break;
01426 case GRAY_GIMAGE:
01427 if (layer.opacity == OPAQUE_OPACITY)
01428 merge = mergeGrayToGray;
01429 else
01430 merge = mergeGrayToRGB;
01431 break;
01432 case GRAYA_GIMAGE:
01433 if (xcf_image.image.depth() <= 8)
01434 merge = mergeGrayAToGray;
01435 else
01436 merge = mergeGrayAToRGB;
01437 break;
01438 case INDEXED_GIMAGE:
01439 merge = mergeIndexedToIndexed;
01440 break;
01441 case INDEXEDA_GIMAGE:
01442 if (xcf_image.image.depth() <= 8)
01443 merge = mergeIndexedAToIndexed;
01444 else
01445 merge = mergeIndexedAToRGB;
01446 }
01447
01448 for (uint j = 0; j < layer.nrows; j++) {
01449 uint y = j * TILE_HEIGHT;
01450
01451 for (uint i = 0; i < layer.ncols; i++) {
01452 uint x = i * TILE_WIDTH;
01453
01454
01455
01456
01457
01458
01459 if (layer.mode == DISSOLVE_MODE) {
01460 if (layer.type == RGBA_GIMAGE)
01461 dissolveRGBPixels(layer.image_tiles[j][i], x, y);
01462
01463 else if (layer.type == GRAYA_GIMAGE)
01464 dissolveAlphaPixels(layer.alpha_tiles[j][i], x, y);
01465 }
01466
01467 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
01468 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
01469
01470 int m = x + k + layer.x_offset;
01471 int n = y + l + layer.y_offset;
01472
01473 if (m < 0 || m >= image.width() || n < 0 || n >= image.height())
01474 continue;
01475
01476 (*merge)(layer, i, j, k, l, image, m, n);
01477 }
01478 }
01479 }
01480 }
01481 }
01482
01483
01497 void XCFImageFormat::mergeRGBToRGB(Layer& layer, uint i, uint j, int k, int l,
01498 QImage& image, int m, int n)
01499 {
01500 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01501 QRgb dst = image.pixel(m, n);
01502
01503 uchar src_r = qRed(src);
01504 uchar src_g = qGreen(src);
01505 uchar src_b = qBlue(src);
01506 uchar src_a = qAlpha(src);
01507
01508 uchar dst_r = qRed(dst);
01509 uchar dst_g = qGreen(dst);
01510 uchar dst_b = qBlue(dst);
01511 uchar dst_a = qAlpha(dst);
01512
01513 if (!src_a) return;
01514
01515 switch (layer.mode) {
01516 case MULTIPLY_MODE: {
01517 src_r = INT_MULT(src_r, dst_r);
01518 src_g = INT_MULT(src_g, dst_g);
01519 src_b = INT_MULT(src_b, dst_b);
01520 src_a = qMin(src_a, dst_a);
01521 }
01522 break;
01523 case DIVIDE_MODE: {
01524 src_r = qMin((dst_r * 256) / (1 + src_r), 255);
01525 src_g = qMin((dst_g * 256) / (1 + src_g), 255);
01526 src_b = qMin((dst_b * 256) / (1 + src_b), 255);
01527 src_a = qMin(src_a, dst_a);
01528 }
01529 break;
01530 case SCREEN_MODE: {
01531 src_r = 255 - INT_MULT(255 - dst_r, 255 - src_r);
01532 src_g = 255 - INT_MULT(255 - dst_g, 255 - src_g);
01533 src_b = 255 - INT_MULT(255 - dst_b, 255 - src_b);
01534 src_a = qMin(src_a, dst_a);
01535 }
01536 break;
01537 case OVERLAY_MODE: {
01538 src_r = INT_MULT(dst_r, dst_r + INT_MULT(2 * src_r, 255 - dst_r));
01539 src_g = INT_MULT(dst_g, dst_g + INT_MULT(2 * src_g, 255 - dst_g));
01540 src_b = INT_MULT(dst_b, dst_b + INT_MULT(2 * src_b, 255 - dst_b));
01541 src_a = qMin(src_a, dst_a);
01542 }
01543 break;
01544 case DIFFERENCE_MODE: {
01545 src_r = dst_r > src_r ? dst_r - src_r : src_r - dst_r;
01546 src_g = dst_g > src_g ? dst_g - src_g : src_g - dst_g;
01547 src_b = dst_b > src_b ? dst_b - src_b : src_b - dst_b;
01548 src_a = qMin(src_a, dst_a);
01549 }
01550 break;
01551 case ADDITION_MODE: {
01552 src_r = add_lut(dst_r,src_r);
01553 src_g = add_lut(dst_g,src_g);
01554 src_b = add_lut(dst_b,src_b);
01555 src_a = qMin(src_a, dst_a);
01556 }
01557 break;
01558 case SUBTRACT_MODE: {
01559 src_r = dst_r > src_r ? dst_r - src_r : 0;
01560 src_g = dst_g > src_g ? dst_g - src_g : 0;
01561 src_b = dst_b > src_b ? dst_b - src_b : 0;
01562 src_a = qMin(src_a, dst_a);
01563 }
01564 break;
01565 case DARKEN_ONLY_MODE: {
01566 src_r = dst_r < src_r ? dst_r : src_r;
01567 src_g = dst_g < src_g ? dst_g : src_g;
01568 src_b = dst_b < src_b ? dst_b : src_b;
01569 src_a = qMin( src_a, dst_a );
01570 }
01571 break;
01572 case LIGHTEN_ONLY_MODE: {
01573 src_r = dst_r < src_r ? src_r : dst_r;
01574 src_g = dst_g < src_g ? src_g : dst_g;
01575 src_b = dst_b < src_b ? src_b : dst_b;
01576 src_a = qMin(src_a, dst_a);
01577 }
01578 break;
01579 case HUE_MODE: {
01580 uchar new_r = dst_r;
01581 uchar new_g = dst_g;
01582 uchar new_b = dst_b;
01583
01584 RGBTOHSV(src_r, src_g, src_b);
01585 RGBTOHSV(new_r, new_g, new_b);
01586
01587 new_r = src_r;
01588
01589 HSVTORGB(new_r, new_g, new_b);
01590
01591 src_r = new_r;
01592 src_g = new_g;
01593 src_b = new_b;
01594 src_a = qMin( src_a, dst_a );
01595 }
01596 break;
01597 case SATURATION_MODE: {
01598 uchar new_r = dst_r;
01599 uchar new_g = dst_g;
01600 uchar new_b = dst_b;
01601
01602 RGBTOHSV(src_r, src_g, src_b);
01603 RGBTOHSV(new_r, new_g, new_b);
01604
01605 new_g = src_g;
01606
01607 HSVTORGB(new_r, new_g, new_b);
01608
01609 src_r = new_r;
01610 src_g = new_g;
01611 src_b = new_b;
01612 src_a = qMin(src_a, dst_a);
01613 }
01614 break;
01615 case VALUE_MODE: {
01616 uchar new_r = dst_r;
01617 uchar new_g = dst_g;
01618 uchar new_b = dst_b;
01619
01620 RGBTOHSV(src_r, src_g, src_b);
01621 RGBTOHSV(new_r, new_g, new_b);
01622
01623 new_b = src_b;
01624
01625 HSVTORGB(new_r, new_g, new_b);
01626
01627 src_r = new_r;
01628 src_g = new_g;
01629 src_b = new_b;
01630 src_a = qMin(src_a, dst_a);
01631 }
01632 break;
01633 case COLOR_MODE: {
01634 uchar new_r = dst_r;
01635 uchar new_g = dst_g;
01636 uchar new_b = dst_b;
01637
01638 RGBTOHLS(src_r, src_g, src_b);
01639 RGBTOHLS(new_r, new_g, new_b);
01640
01641 new_r = src_r;
01642 new_b = src_b;
01643
01644 HLSTORGB(new_r, new_g, new_b);
01645
01646 src_r = new_r;
01647 src_g = new_g;
01648 src_b = new_b;
01649 src_a = qMin(src_a, dst_a);
01650 }
01651 break;
01652 case DODGE_MODE: {
01653 uint tmp;
01654
01655 tmp = dst_r << 8;
01656 tmp /= 256 - src_r;
01657 src_r = (uchar) qMin(tmp, 255u);
01658
01659 tmp = dst_g << 8;
01660 tmp /= 256 - src_g;
01661 src_g = (uchar) qMin(tmp, 255u);
01662
01663 tmp = dst_b << 8;
01664 tmp /= 256 - src_b;
01665 src_b = (uchar) qMin(tmp, 255u);
01666
01667 src_a = qMin(src_a, dst_a);
01668 }
01669 break;
01670 case BURN_MODE: {
01671 uint tmp;
01672
01673 tmp = (255 - dst_r) << 8;
01674 tmp /= src_r + 1;
01675 src_r = (uchar) qMin(tmp, 255u);
01676 src_r = 255 - src_r;
01677
01678 tmp = (255 - dst_g) << 8;
01679 tmp /= src_g + 1;
01680 src_g = (uchar) qMin(tmp, 255u);
01681 src_g = 255 - src_g;
01682
01683 tmp = (255 - dst_b) << 8;
01684 tmp /= src_b + 1;
01685 src_b = (uchar) qMin(tmp, 255u);
01686 src_b = 255 - src_b;
01687
01688 src_a = qMin(src_a, dst_a);
01689 }
01690 break;
01691 case HARDLIGHT_MODE: {
01692 uint tmp;
01693 if (src_r > 128) {
01694 tmp = ((int)255-dst_r) * ((int) 255 - ((src_r-128) << 1));
01695 src_r = (uchar) qMin(255 - (tmp >> 8), 255u);
01696 } else {
01697 tmp = (int) dst_r * ((int) src_r << 1);
01698 src_r = (uchar) qMin(tmp >> 8, 255u);
01699 }
01700
01701 if (src_g > 128) {
01702 tmp = ((int)255-dst_g) * ((int) 255 - ((src_g-128) << 1));
01703 src_g = (uchar) qMin(255 - (tmp >> 8), 255u);
01704 } else {
01705 tmp = (int) dst_g * ((int) src_g << 1);
01706 src_g = (uchar) qMin(tmp >> 8, 255u);
01707 }
01708
01709 if (src_b > 128) {
01710 tmp = ((int)255-dst_b) * ((int) 255 - ((src_b-128) << 1));
01711 src_b = (uchar) qMin(255 - (tmp >> 8), 255u);
01712 } else {
01713 tmp = (int) dst_b * ((int) src_b << 1);
01714 src_b = (uchar) qMin(tmp >> 8, 255u);
01715 }
01716 src_a = qMin(src_a, dst_a);
01717 }
01718 break;
01719 case SOFTLIGHT_MODE: {
01720 uint tmpS, tmpM;
01721
01722 tmpM = INT_MULT(dst_r, src_r);
01723 tmpS = 255 - INT_MULT((255 - dst_r), (255-src_r));
01724 src_r = INT_MULT((255 - dst_r), tmpM)
01725 + INT_MULT(dst_r, tmpS);
01726
01727 tmpM = INT_MULT(dst_g, src_g);
01728 tmpS = 255 - INT_MULT((255 - dst_g), (255-src_g));
01729 src_g = INT_MULT((255 - dst_g), tmpM)
01730 + INT_MULT(dst_g, tmpS);
01731
01732 tmpM = INT_MULT(dst_b, src_b);
01733 tmpS = 255 - INT_MULT((255 - dst_b), (255-src_b));
01734 src_b = INT_MULT((255 - dst_b), tmpM)
01735 + INT_MULT(dst_b, tmpS);
01736
01737 src_a = qMin(src_a, dst_a);
01738 }
01739 break;
01740 case GRAIN_EXTRACT_MODE: {
01741 int tmp;
01742
01743 tmp = dst_r - src_r + 128;
01744 tmp = qMin(tmp, 255);
01745 tmp = qMax(tmp, 0);
01746 src_r = (uchar) tmp;
01747
01748 tmp = dst_g - src_g + 128;
01749 tmp = qMin(tmp, 255);
01750 tmp = qMax(tmp, 0);
01751 src_g = (uchar) tmp;
01752
01753 tmp = dst_b - src_b + 128;
01754 tmp = qMin(tmp, 255);
01755 tmp = qMax(tmp, 0);
01756 src_b = (uchar) tmp;
01757
01758 src_a = qMin(src_a, dst_a);
01759 }
01760 break;
01761 case GRAIN_MERGE_MODE: {
01762 int tmp;
01763
01764 tmp = dst_r + src_r - 128;
01765 tmp = qMin(tmp, 255);
01766 tmp = qMax(tmp, 0);
01767 src_r = (uchar) tmp;
01768
01769 tmp = dst_g + src_g - 128;
01770 tmp = qMin(tmp, 255);
01771 tmp = qMax(tmp, 0);
01772 src_g = (uchar) tmp;
01773
01774 tmp = dst_b + src_b - 128;
01775 tmp = qMin(tmp, 255);
01776 tmp = qMax(tmp, 0);
01777 src_b = (uchar) tmp;
01778
01779 src_a = qMin(src_a, dst_a);
01780 }
01781 break;
01782 }
01783
01784 src_a = INT_MULT(src_a, layer.opacity);
01785
01786
01787
01788 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
01789 layer.mask_tiles[j].size() > (int)i)
01790 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01791
01792 uchar new_r, new_g, new_b, new_a;
01793 new_a = dst_a + INT_MULT(OPAQUE_OPACITY - dst_a, src_a);
01794
01795 float src_ratio = (float)src_a / new_a;
01796 float dst_ratio = 1.0 - src_ratio;
01797
01798 new_r = (uchar)(src_ratio * src_r + dst_ratio * dst_r + EPSILON);
01799 new_g = (uchar)(src_ratio * src_g + dst_ratio * dst_g + EPSILON);
01800 new_b = (uchar)(src_ratio * src_b + dst_ratio * dst_b + EPSILON);
01801
01802 if (!layer_modes[layer.mode].affect_alpha)
01803 new_a = dst_a;
01804
01805 image.setPixel(m, n, qRgba(new_r, new_g, new_b, new_a));
01806 }
01807
01808
01820 void XCFImageFormat::mergeGrayToGray(Layer& layer, uint i, uint j, int k, int l,
01821 QImage& image, int m, int n)
01822 {
01823 int src = layer.image_tiles[j][i].pixelIndex(k, l);
01824 image.setPixel(m, n, src);
01825 }
01826
01827
01839 void XCFImageFormat::mergeGrayAToGray(Layer& layer, uint i, uint j, int k, int l,
01840 QImage& image, int m, int n)
01841 {
01842 int src = qGray(layer.image_tiles[j][i].pixel(k, l));
01843 int dst = image.pixelIndex(m, n);
01844
01845 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
01846
01847 if (!src_a) return;
01848
01849 switch (layer.mode) {
01850 case MULTIPLY_MODE: {
01851 src = INT_MULT( src, dst );
01852 }
01853 break;
01854 case DIVIDE_MODE: {
01855 src = qMin((dst * 256) / (1 + src), 255);
01856 }
01857 break;
01858 case SCREEN_MODE: {
01859 src = 255 - INT_MULT(255 - dst, 255 - src);
01860 }
01861 break;
01862 case OVERLAY_MODE: {
01863 src = INT_MULT(dst, dst + INT_MULT(2 * src, 255 - dst));
01864 }
01865 break;
01866 case DIFFERENCE_MODE: {
01867 src = dst > src ? dst - src : src - dst;
01868 }
01869 break;
01870 case ADDITION_MODE: {
01871 src = add_lut(dst,src);
01872 }
01873 break;
01874 case SUBTRACT_MODE: {
01875 src = dst > src ? dst - src : 0;
01876 }
01877 break;
01878 case DARKEN_ONLY_MODE: {
01879 src = dst < src ? dst : src;
01880 }
01881 break;
01882 case LIGHTEN_ONLY_MODE: {
01883 src = dst < src ? src : dst;
01884 }
01885 break;
01886 case DODGE_MODE: {
01887 uint tmp = dst << 8;
01888 tmp /= 256 - src;
01889 src = (uchar) qMin(tmp, 255u);
01890 }
01891 break;
01892 case BURN_MODE: {
01893 uint tmp = (255-dst) << 8;
01894 tmp /= src + 1;
01895 src = (uchar) qMin(tmp, 255u);
01896 src = 255 - src;
01897 }
01898 break;
01899 case HARDLIGHT_MODE: {
01900 uint tmp;
01901 if (src > 128) {
01902 tmp = ((int)255-dst) * ((int) 255 - ((src-128) << 1));
01903 src = (uchar) qMin(255 - (tmp >> 8), 255u);
01904 } else {
01905 tmp = (int) dst * ((int) src << 1);
01906 src = (uchar) qMin(tmp >> 8, 255u);
01907 }
01908 }
01909 break;
01910 case SOFTLIGHT_MODE: {
01911 uint tmpS, tmpM;
01912
01913 tmpM = INT_MULT(dst, src);
01914 tmpS = 255 - INT_MULT((255-dst), (255-src));
01915 src = INT_MULT((255 - dst), tmpM)
01916 + INT_MULT(dst, tmpS);
01917
01918 }
01919 break;
01920 case GRAIN_EXTRACT_MODE: {
01921 int tmp;
01922
01923 tmp = dst - src + 128;
01924 tmp = qMin(tmp, 255);
01925 tmp = qMax(tmp, 0);
01926
01927 src = (uchar) tmp;
01928 }
01929 break;
01930 case GRAIN_MERGE_MODE: {
01931 int tmp;
01932
01933 tmp = dst + src - 128;
01934 tmp = qMin(tmp, 255);
01935 tmp = qMax(tmp, 0);
01936
01937 src = (uchar) tmp;
01938 }
01939 break;
01940 }
01941
01942 src_a = INT_MULT(src_a, layer.opacity);
01943
01944
01945
01946 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
01947 layer.mask_tiles[j].size() > (int)i)
01948 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01949
01950 uchar new_a = OPAQUE_OPACITY;
01951
01952 float src_ratio = (float)src_a / new_a;
01953 float dst_ratio = 1.0 - src_ratio;
01954
01955 uchar new_g = (uchar)(src_ratio * src + dst_ratio * dst + EPSILON);
01956
01957 image.setPixel(m, n, new_g);
01958 }
01959
01960
01974 void XCFImageFormat::mergeGrayToRGB(Layer& layer, uint i, uint j, int k, int l,
01975 QImage& image, int m, int n)
01976 {
01977 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01978 uchar src_a = layer.opacity;
01979 image.setPixel(m, n, qRgba(src, src_a));
01980 }
01981
01982
01996 void XCFImageFormat::mergeGrayAToRGB(Layer& layer, uint i, uint j, int k, int l,
01997 QImage& image, int m, int n)
01998 {
01999 int src = qGray(layer.image_tiles[j][i].pixel(k, l));
02000 int dst = qGray(image.pixel(m, n));
02001
02002 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
02003 uchar dst_a = qAlpha(image.pixel(m, n));
02004
02005 if (!src_a) return;
02006
02007 switch (layer.mode) {
02008 case MULTIPLY_MODE: {
02009 src = INT_MULT(src, dst);
02010 src_a = qMin(src_a, dst_a);
02011 }
02012 break;
02013 case DIVIDE_MODE: {
02014 src = qMin((dst * 256) / (1 + src), 255);
02015 src_a = qMin(src_a, dst_a);
02016 }
02017 break;
02018 case SCREEN_MODE: {
02019 src = 255 - INT_MULT(255 - dst, 255 - src);
02020 src_a = qMin(src_a, dst_a);
02021 }
02022 break;
02023 case OVERLAY_MODE: {
02024 src = INT_MULT( dst, dst + INT_MULT(2 * src, 255 - dst));
02025 src_a = qMin(src_a, dst_a);
02026 }
02027 break;
02028 case DIFFERENCE_MODE: {
02029 src = dst > src ? dst - src : src - dst;
02030 src_a = qMin(src_a, dst_a);
02031 }
02032 break;
02033 case ADDITION_MODE: {
02034 src = add_lut(dst,src);
02035 src_a = qMin(src_a, dst_a);
02036 }
02037 break;
02038 case SUBTRACT_MODE: {
02039 src = dst > src ? dst - src : 0;
02040 src_a = qMin(src_a, dst_a);
02041 }
02042 break;
02043 case DARKEN_ONLY_MODE: {
02044 src = dst < src ? dst : src;
02045 src_a = qMin(src_a, dst_a);
02046 }
02047 break;
02048 case LIGHTEN_ONLY_MODE: {
02049 src = dst < src ? src : dst;
02050 src_a = qMin(src_a, dst_a);
02051 }
02052 break;
02053 case DODGE_MODE: {
02054 uint tmp = dst << 8;
02055 tmp /= 256 - src;
02056 src = (uchar) qMin(tmp, 255u);
02057 src_a = qMin(src_a, dst_a);
02058 }
02059 break;
02060 case BURN_MODE: {
02061 uint tmp = (255-dst) << 8;
02062 tmp /= src + 1;
02063 src = (uchar) qMin(tmp, 255u);
02064 src = 255 - src;
02065 src_a = qMin(src_a, dst_a);
02066 }
02067 break;
02068 case HARDLIGHT_MODE: {
02069 uint tmp;
02070 if (src > 128) {
02071 tmp = ((int)255-dst) * ((int) 255 - ((src-128) << 1));
02072 src = (uchar) qMin(255 - (tmp >> 8), 255u);
02073 } else {
02074 tmp = (int) dst * ((int) src << 1);
02075 src = (uchar) qMin(tmp >> 8, 255u);
02076 }
02077 src_a = qMin(src_a, dst_a);
02078 }
02079 break;
02080 case SOFTLIGHT_MODE: {
02081 uint tmpS, tmpM;
02082
02083 tmpM = INT_MULT(dst, src);
02084 tmpS = 255 - INT_MULT((255 - dst), (255-src));
02085 src = INT_MULT((255 - dst), tmpM)
02086 + INT_MULT(dst, tmpS);
02087
02088 src_a = qMin(src_a, dst_a);
02089 }
02090 break;
02091 case GRAIN_EXTRACT_MODE: {
02092 int tmp;
02093
02094 tmp = dst - src + 128;
02095 tmp = qMin(tmp, 255);
02096 tmp = qMax(tmp, 0);
02097
02098 src = (uchar) tmp;
02099 src_a = qMin(src_a, dst_a);
02100 }
02101 break;
02102 case GRAIN_MERGE_MODE: {
02103 int tmp;
02104
02105 tmp = dst + src - 128;
02106 tmp = qMin(tmp, 255);
02107 tmp = qMax(tmp, 0);
02108
02109 src = (uchar) tmp;
02110 src_a = qMin(src_a, dst_a);
02111 }
02112 break;
02113 }
02114
02115 src_a = INT_MULT(src_a, layer.opacity);
02116
02117
02118 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
02119 layer.mask_tiles[j].size() > (int)i)
02120 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
02121
02122 uchar new_a = dst_a + INT_MULT(OPAQUE_OPACITY - dst_a, src_a);
02123
02124 float src_ratio = (float)src_a / new_a;
02125 float dst_ratio = 1.0 - src_ratio;
02126
02127 uchar new_g = (uchar)(src_ratio * src + dst_ratio * dst + EPSILON);
02128
02129 if (!layer_modes[layer.mode].affect_alpha)
02130 new_a = dst_a;
02131
02132 image.setPixel(m, n, qRgba(new_g, new_g, new_g, new_a));
02133 }
02134
02135
02147 void XCFImageFormat::mergeIndexedToIndexed(Layer& layer, uint i, uint j, int k, int l,
02148 QImage& image, int m, int n)
02149 {
02150 int src = layer.image_tiles[j][i].pixelIndex(k, l);
02151 image.setPixel(m, n, src);
02152 }
02153
02154
02166 void XCFImageFormat::mergeIndexedAToIndexed(Layer& layer, uint i, uint j, int k, int l,
02167 QImage& image, int m, int n)
02168 {
02169 uchar src = layer.image_tiles[j][i].pixelIndex(k, l);
02170 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
02171 src_a = INT_MULT( src_a, layer.opacity );
02172
02173 if ( layer.apply_mask == 1 &&
02174 layer.mask_tiles.size() > (int)j &&
02175 layer.mask_tiles[j].size() > (int)i)
02176 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
02177
02178 if (src_a > 127) {
02179 src++;
02180 image.setPixel(m, n, src);
02181 }
02182 }
02183
02184
02198 void XCFImageFormat::mergeIndexedAToRGB(Layer& layer, uint i, uint j, int k, int l,
02199 QImage& image, int m, int n)
02200 {
02201 QRgb src = layer.image_tiles[j][i].pixel(k, l);
02202 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
02203 src_a = INT_MULT(src_a, layer.opacity);
02204
02205
02206 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
02207 layer.mask_tiles[j].size() > (int)i)
02208 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
02209
02210
02211 if (src_a <= 127)
02212 src_a = 0;
02213 else
02214 src_a = OPAQUE_OPACITY;
02215
02216 image.setPixel(m, n, qRgba(src, src_a));
02217 }
02218
02219
02227 void XCFImageFormat::dissolveRGBPixels ( QImage& image, int x, int y )
02228 {
02229
02230
02231
02232 for (int l = 0; l < image.height(); l++) {
02233 srand(random_table[( l + y ) % RANDOM_TABLE_SIZE]);
02234
02235 for (int k = 0; k < x; k++)
02236 rand();
02237
02238 for (int k = 0; k < image.width(); k++) {
02239 int rand_val = rand() & 0xff;
02240 QRgb pixel = image.pixel(k, l);
02241
02242 if (rand_val > qAlpha(pixel)) {
02243 image.setPixel(k, l, qRgba(pixel, 0));
02244 }
02245 }
02246 }
02247 }
02248
02249
02259 void XCFImageFormat::dissolveAlphaPixels ( QImage& image, int x, int y )
02260 {
02261
02262
02263
02264 for (int l = 0; l < image.height(); l++) {
02265 srand( random_table[(l + y) % RANDOM_TABLE_SIZE]);
02266
02267 for (int k = 0; k < x; k++)
02268 rand();
02269
02270 for (int k = 0; k < image.width(); k++) {
02271 int rand_val = rand() & 0xff;
02272 uchar alpha = image.pixelIndex(k, l);
02273
02274 if (rand_val > alpha) {
02275 image.setPixel(k, l, 0);
02276 }
02277 }
02278 }
02279 }
02280
02281
02283
02284 XCFHandler::XCFHandler()
02285 {
02286 }
02287
02288 bool XCFHandler::canRead() const
02289 {
02290 if (canRead(device())) {
02291 setFormat("xcf");
02292 return true;
02293 }
02294 return false;
02295 }
02296
02297 bool XCFHandler::read(QImage *image)
02298 {
02299 XCFImageFormat xcfif;
02300 return xcfif.readXCF(device(), image);
02301 }
02302
02303 bool XCFHandler::write(const QImage &)
02304 {
02305 return false;
02306 }
02307
02308 QByteArray XCFHandler::name() const
02309 {
02310 return "xcf";
02311 }
02312
02313 bool XCFHandler::canRead(QIODevice *device)
02314 {
02315 if (!device) {
02316 qWarning("DDSHandler::canRead() called with no device");
02317 return false;
02318 }
02319
02320 qint64 oldPos = device->pos();
02321
02322 char head[8];
02323 qint64 readBytes = device->read(head, sizeof(head));
02324 if (readBytes != sizeof(head)) {
02325 if (device->isSequential()) {
02326 while (readBytes > 0)
02327 device->ungetChar(head[readBytes-- - 1]);
02328 } else {
02329 device->seek(oldPos);
02330 }
02331 return false;
02332 }
02333
02334 if (device->isSequential()) {
02335 while (readBytes > 0)
02336 device->ungetChar(head[readBytes-- - 1]);
02337 } else {
02338 device->seek(oldPos);
02339 }
02340
02341 return qstrncmp(head, "gimp xcf", 8) == 0;
02342 }
02343
02344
02345 class XCFPlugin : public QImageIOPlugin
02346 {
02347 public:
02348 QStringList keys() const;
02349 Capabilities capabilities(QIODevice *device, const QByteArray &format) const;
02350 QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const;
02351 };
02352
02353 QStringList XCFPlugin::keys() const
02354 {
02355 return QStringList() << "xcf" << "XCF";
02356 }
02357
02358 QImageIOPlugin::Capabilities XCFPlugin::capabilities(QIODevice *device, const QByteArray &format) const
02359 {
02360 if (format == "xcf" || format == "XCF")
02361 return Capabilities(CanRead);
02362 if (!format.isEmpty())
02363 return 0;
02364 if (!device->isOpen())
02365 return 0;
02366
02367 Capabilities cap;
02368 if (device->isReadable() && XCFHandler::canRead(device))
02369 cap |= CanRead;
02370 return cap;
02371 }
02372
02373 QImageIOHandler *XCFPlugin::create(QIODevice *device, const QByteArray &format) const
02374 {
02375 QImageIOHandler *handler = new XCFHandler;
02376 handler->setDevice(device);
02377 handler->setFormat(format);
02378 return handler;
02379 }
02380
02381 Q_EXPORT_STATIC_PLUGIN(XCFPlugin)
02382 Q_EXPORT_PLUGIN2(xcf,XCFPlugin)