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 if (!copy) {
01182 return;
01183 }
01184
01185
01186
01187 for (uint j = 0; j < layer.nrows; j++) {
01188 uint y = j * TILE_HEIGHT;
01189
01190 for (uint i = 0; i < layer.ncols; i++) {
01191 uint x = i * TILE_WIDTH;
01192
01193
01194
01195
01196
01197
01198 if (layer.mode == DISSOLVE_MODE) {
01199 if (layer.type == RGBA_GIMAGE)
01200 dissolveRGBPixels(layer.image_tiles[j][i], x, y);
01201
01202 else if (layer.type == GRAYA_GIMAGE)
01203 dissolveAlphaPixels(layer.alpha_tiles[j][i], x, y);
01204 }
01205
01206 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
01207 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
01208
01209 int m = x + k + layer.x_offset;
01210 int n = y + l + layer.y_offset;
01211
01212 if (m < 0 || m >= image.width() || n < 0 || n >= image.height())
01213 continue;
01214
01215 (*copy)(layer, i, j, k, l, image, m, n);
01216 }
01217 }
01218 }
01219 }
01220 }
01221
01222
01236 void XCFImageFormat::copyRGBToRGB(Layer& layer, uint i, uint j, int k, int l,
01237 QImage& image, int m, int n)
01238 {
01239 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01240 uchar src_a = layer.opacity;
01241
01242 if (layer.type == RGBA_GIMAGE)
01243 src_a = INT_MULT(src_a, qAlpha(src));
01244
01245
01246
01247 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
01248 layer.mask_tiles[j].size() > (int)i)
01249 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01250
01251 image.setPixel(m, n, qRgba(src, src_a));
01252 }
01253
01254
01266 void XCFImageFormat::copyGrayToGray(Layer& layer, uint i, uint j, int k, int l,
01267 QImage& image, int m, int n)
01268 {
01269 int src = layer.image_tiles[j][i].pixelIndex(k, l);
01270 image.setPixel(m, n, src);
01271 }
01272
01273
01287 void XCFImageFormat::copyGrayToRGB(Layer& layer, uint i, uint j, int k, int l,
01288 QImage& image, int m, int n)
01289 {
01290 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01291 uchar src_a = layer.opacity;
01292 image.setPixel(m, n, qRgba(src, src_a));
01293 }
01294
01295
01309 void XCFImageFormat::copyGrayAToRGB(Layer& layer, uint i, uint j, int k, int l,
01310 QImage& image, int m, int n)
01311 {
01312 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01313 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
01314 src_a = INT_MULT(src_a, layer.opacity);
01315
01316
01317
01318 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
01319 layer.mask_tiles[j].size() > (int)i)
01320 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01321
01322 image.setPixel(m, n, qRgba(src, src_a));
01323 }
01324
01325
01337 void XCFImageFormat::copyIndexedToIndexed(Layer& layer, uint i, uint j, int k, int l,
01338 QImage& image, int m, int n)
01339 {
01340 int src = layer.image_tiles[j][i].pixelIndex(k, l);
01341 image.setPixel(m, n, src);
01342 }
01343
01344
01356 void XCFImageFormat::copyIndexedAToIndexed(Layer& layer, uint i, uint j, int k, int l,
01357 QImage& image, int m, int n)
01358 {
01359 uchar src = layer.image_tiles[j][i].pixelIndex(k, l);
01360 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
01361 src_a = INT_MULT(src_a, layer.opacity);
01362
01363 if (layer.apply_mask == 1 &&
01364 layer.mask_tiles.size() > (int)j &&
01365 layer.mask_tiles[j].size() > (int)i)
01366 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01367
01368 if (src_a > 127)
01369 src++;
01370 else
01371 src = 0;
01372
01373 image.setPixel(m, n, src);
01374 }
01375
01376
01390 void XCFImageFormat::copyIndexedAToRGB(Layer& layer, uint i, uint j, int k, int l,
01391 QImage& image, int m, int n)
01392 {
01393 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01394 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
01395 src_a = INT_MULT(src_a, layer.opacity);
01396
01397
01398 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
01399 layer.mask_tiles[j].size() > (int)i)
01400 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01401
01402
01403 if (src_a <= 127)
01404 src_a = 0;
01405 else
01406 src_a = OPAQUE_OPACITY;
01407
01408 image.setPixel(m, n, qRgba(src, src_a));
01409 }
01410
01411
01416 void XCFImageFormat::mergeLayerIntoImage(XCFImage& xcf_image)
01417 {
01418 Layer& layer(xcf_image.layer);
01419 QImage& image(xcf_image.image);
01420
01421 PixelMergeOperation merge = 0;
01422
01423 if (!layer.opacity) return;
01424
01425 switch (layer.type) {
01426 case RGB_GIMAGE:
01427 case RGBA_GIMAGE:
01428 merge = mergeRGBToRGB;
01429 break;
01430 case GRAY_GIMAGE:
01431 if (layer.opacity == OPAQUE_OPACITY)
01432 merge = mergeGrayToGray;
01433 else
01434 merge = mergeGrayToRGB;
01435 break;
01436 case GRAYA_GIMAGE:
01437 if (xcf_image.image.depth() <= 8)
01438 merge = mergeGrayAToGray;
01439 else
01440 merge = mergeGrayAToRGB;
01441 break;
01442 case INDEXED_GIMAGE:
01443 merge = mergeIndexedToIndexed;
01444 break;
01445 case INDEXEDA_GIMAGE:
01446 if (xcf_image.image.depth() <= 8)
01447 merge = mergeIndexedAToIndexed;
01448 else
01449 merge = mergeIndexedAToRGB;
01450 }
01451
01452 if (!merge) {
01453 return;
01454 }
01455
01456 for (uint j = 0; j < layer.nrows; j++) {
01457 uint y = j * TILE_HEIGHT;
01458
01459 for (uint i = 0; i < layer.ncols; i++) {
01460 uint x = i * TILE_WIDTH;
01461
01462
01463
01464
01465
01466
01467 if (layer.mode == DISSOLVE_MODE) {
01468 if (layer.type == RGBA_GIMAGE)
01469 dissolveRGBPixels(layer.image_tiles[j][i], x, y);
01470
01471 else if (layer.type == GRAYA_GIMAGE)
01472 dissolveAlphaPixels(layer.alpha_tiles[j][i], x, y);
01473 }
01474
01475 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
01476 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
01477
01478 int m = x + k + layer.x_offset;
01479 int n = y + l + layer.y_offset;
01480
01481 if (m < 0 || m >= image.width() || n < 0 || n >= image.height())
01482 continue;
01483
01484 (*merge)(layer, i, j, k, l, image, m, n);
01485 }
01486 }
01487 }
01488 }
01489 }
01490
01491
01505 void XCFImageFormat::mergeRGBToRGB(Layer& layer, uint i, uint j, int k, int l,
01506 QImage& image, int m, int n)
01507 {
01508 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01509 QRgb dst = image.pixel(m, n);
01510
01511 uchar src_r = qRed(src);
01512 uchar src_g = qGreen(src);
01513 uchar src_b = qBlue(src);
01514 uchar src_a = qAlpha(src);
01515
01516 uchar dst_r = qRed(dst);
01517 uchar dst_g = qGreen(dst);
01518 uchar dst_b = qBlue(dst);
01519 uchar dst_a = qAlpha(dst);
01520
01521 if (!src_a) return;
01522
01523 switch (layer.mode) {
01524 case MULTIPLY_MODE: {
01525 src_r = INT_MULT(src_r, dst_r);
01526 src_g = INT_MULT(src_g, dst_g);
01527 src_b = INT_MULT(src_b, dst_b);
01528 src_a = qMin(src_a, dst_a);
01529 }
01530 break;
01531 case DIVIDE_MODE: {
01532 src_r = qMin((dst_r * 256) / (1 + src_r), 255);
01533 src_g = qMin((dst_g * 256) / (1 + src_g), 255);
01534 src_b = qMin((dst_b * 256) / (1 + src_b), 255);
01535 src_a = qMin(src_a, dst_a);
01536 }
01537 break;
01538 case SCREEN_MODE: {
01539 src_r = 255 - INT_MULT(255 - dst_r, 255 - src_r);
01540 src_g = 255 - INT_MULT(255 - dst_g, 255 - src_g);
01541 src_b = 255 - INT_MULT(255 - dst_b, 255 - src_b);
01542 src_a = qMin(src_a, dst_a);
01543 }
01544 break;
01545 case OVERLAY_MODE: {
01546 src_r = INT_MULT(dst_r, dst_r + INT_MULT(2 * src_r, 255 - dst_r));
01547 src_g = INT_MULT(dst_g, dst_g + INT_MULT(2 * src_g, 255 - dst_g));
01548 src_b = INT_MULT(dst_b, dst_b + INT_MULT(2 * src_b, 255 - dst_b));
01549 src_a = qMin(src_a, dst_a);
01550 }
01551 break;
01552 case DIFFERENCE_MODE: {
01553 src_r = dst_r > src_r ? dst_r - src_r : src_r - dst_r;
01554 src_g = dst_g > src_g ? dst_g - src_g : src_g - dst_g;
01555 src_b = dst_b > src_b ? dst_b - src_b : src_b - dst_b;
01556 src_a = qMin(src_a, dst_a);
01557 }
01558 break;
01559 case ADDITION_MODE: {
01560 src_r = add_lut(dst_r,src_r);
01561 src_g = add_lut(dst_g,src_g);
01562 src_b = add_lut(dst_b,src_b);
01563 src_a = qMin(src_a, dst_a);
01564 }
01565 break;
01566 case SUBTRACT_MODE: {
01567 src_r = dst_r > src_r ? dst_r - src_r : 0;
01568 src_g = dst_g > src_g ? dst_g - src_g : 0;
01569 src_b = dst_b > src_b ? dst_b - src_b : 0;
01570 src_a = qMin(src_a, dst_a);
01571 }
01572 break;
01573 case DARKEN_ONLY_MODE: {
01574 src_r = dst_r < src_r ? dst_r : src_r;
01575 src_g = dst_g < src_g ? dst_g : src_g;
01576 src_b = dst_b < src_b ? dst_b : src_b;
01577 src_a = qMin( src_a, dst_a );
01578 }
01579 break;
01580 case LIGHTEN_ONLY_MODE: {
01581 src_r = dst_r < src_r ? src_r : dst_r;
01582 src_g = dst_g < src_g ? src_g : dst_g;
01583 src_b = dst_b < src_b ? src_b : dst_b;
01584 src_a = qMin(src_a, dst_a);
01585 }
01586 break;
01587 case HUE_MODE: {
01588 uchar new_r = dst_r;
01589 uchar new_g = dst_g;
01590 uchar new_b = dst_b;
01591
01592 RGBTOHSV(src_r, src_g, src_b);
01593 RGBTOHSV(new_r, new_g, new_b);
01594
01595 new_r = src_r;
01596
01597 HSVTORGB(new_r, new_g, new_b);
01598
01599 src_r = new_r;
01600 src_g = new_g;
01601 src_b = new_b;
01602 src_a = qMin( src_a, dst_a );
01603 }
01604 break;
01605 case SATURATION_MODE: {
01606 uchar new_r = dst_r;
01607 uchar new_g = dst_g;
01608 uchar new_b = dst_b;
01609
01610 RGBTOHSV(src_r, src_g, src_b);
01611 RGBTOHSV(new_r, new_g, new_b);
01612
01613 new_g = src_g;
01614
01615 HSVTORGB(new_r, new_g, new_b);
01616
01617 src_r = new_r;
01618 src_g = new_g;
01619 src_b = new_b;
01620 src_a = qMin(src_a, dst_a);
01621 }
01622 break;
01623 case VALUE_MODE: {
01624 uchar new_r = dst_r;
01625 uchar new_g = dst_g;
01626 uchar new_b = dst_b;
01627
01628 RGBTOHSV(src_r, src_g, src_b);
01629 RGBTOHSV(new_r, new_g, new_b);
01630
01631 new_b = src_b;
01632
01633 HSVTORGB(new_r, new_g, new_b);
01634
01635 src_r = new_r;
01636 src_g = new_g;
01637 src_b = new_b;
01638 src_a = qMin(src_a, dst_a);
01639 }
01640 break;
01641 case COLOR_MODE: {
01642 uchar new_r = dst_r;
01643 uchar new_g = dst_g;
01644 uchar new_b = dst_b;
01645
01646 RGBTOHLS(src_r, src_g, src_b);
01647 RGBTOHLS(new_r, new_g, new_b);
01648
01649 new_r = src_r;
01650 new_b = src_b;
01651
01652 HLSTORGB(new_r, new_g, new_b);
01653
01654 src_r = new_r;
01655 src_g = new_g;
01656 src_b = new_b;
01657 src_a = qMin(src_a, dst_a);
01658 }
01659 break;
01660 case DODGE_MODE: {
01661 uint tmp;
01662
01663 tmp = dst_r << 8;
01664 tmp /= 256 - src_r;
01665 src_r = (uchar) qMin(tmp, 255u);
01666
01667 tmp = dst_g << 8;
01668 tmp /= 256 - src_g;
01669 src_g = (uchar) qMin(tmp, 255u);
01670
01671 tmp = dst_b << 8;
01672 tmp /= 256 - src_b;
01673 src_b = (uchar) qMin(tmp, 255u);
01674
01675 src_a = qMin(src_a, dst_a);
01676 }
01677 break;
01678 case BURN_MODE: {
01679 uint tmp;
01680
01681 tmp = (255 - dst_r) << 8;
01682 tmp /= src_r + 1;
01683 src_r = (uchar) qMin(tmp, 255u);
01684 src_r = 255 - src_r;
01685
01686 tmp = (255 - dst_g) << 8;
01687 tmp /= src_g + 1;
01688 src_g = (uchar) qMin(tmp, 255u);
01689 src_g = 255 - src_g;
01690
01691 tmp = (255 - dst_b) << 8;
01692 tmp /= src_b + 1;
01693 src_b = (uchar) qMin(tmp, 255u);
01694 src_b = 255 - src_b;
01695
01696 src_a = qMin(src_a, dst_a);
01697 }
01698 break;
01699 case HARDLIGHT_MODE: {
01700 uint tmp;
01701 if (src_r > 128) {
01702 tmp = ((int)255-dst_r) * ((int) 255 - ((src_r-128) << 1));
01703 src_r = (uchar) qMin(255 - (tmp >> 8), 255u);
01704 } else {
01705 tmp = (int) dst_r * ((int) src_r << 1);
01706 src_r = (uchar) qMin(tmp >> 8, 255u);
01707 }
01708
01709 if (src_g > 128) {
01710 tmp = ((int)255-dst_g) * ((int) 255 - ((src_g-128) << 1));
01711 src_g = (uchar) qMin(255 - (tmp >> 8), 255u);
01712 } else {
01713 tmp = (int) dst_g * ((int) src_g << 1);
01714 src_g = (uchar) qMin(tmp >> 8, 255u);
01715 }
01716
01717 if (src_b > 128) {
01718 tmp = ((int)255-dst_b) * ((int) 255 - ((src_b-128) << 1));
01719 src_b = (uchar) qMin(255 - (tmp >> 8), 255u);
01720 } else {
01721 tmp = (int) dst_b * ((int) src_b << 1);
01722 src_b = (uchar) qMin(tmp >> 8, 255u);
01723 }
01724 src_a = qMin(src_a, dst_a);
01725 }
01726 break;
01727 case SOFTLIGHT_MODE: {
01728 uint tmpS, tmpM;
01729
01730 tmpM = INT_MULT(dst_r, src_r);
01731 tmpS = 255 - INT_MULT((255 - dst_r), (255-src_r));
01732 src_r = INT_MULT((255 - dst_r), tmpM)
01733 + INT_MULT(dst_r, tmpS);
01734
01735 tmpM = INT_MULT(dst_g, src_g);
01736 tmpS = 255 - INT_MULT((255 - dst_g), (255-src_g));
01737 src_g = INT_MULT((255 - dst_g), tmpM)
01738 + INT_MULT(dst_g, tmpS);
01739
01740 tmpM = INT_MULT(dst_b, src_b);
01741 tmpS = 255 - INT_MULT((255 - dst_b), (255-src_b));
01742 src_b = INT_MULT((255 - dst_b), tmpM)
01743 + INT_MULT(dst_b, tmpS);
01744
01745 src_a = qMin(src_a, dst_a);
01746 }
01747 break;
01748 case GRAIN_EXTRACT_MODE: {
01749 int tmp;
01750
01751 tmp = dst_r - src_r + 128;
01752 tmp = qMin(tmp, 255);
01753 tmp = qMax(tmp, 0);
01754 src_r = (uchar) tmp;
01755
01756 tmp = dst_g - src_g + 128;
01757 tmp = qMin(tmp, 255);
01758 tmp = qMax(tmp, 0);
01759 src_g = (uchar) tmp;
01760
01761 tmp = dst_b - src_b + 128;
01762 tmp = qMin(tmp, 255);
01763 tmp = qMax(tmp, 0);
01764 src_b = (uchar) tmp;
01765
01766 src_a = qMin(src_a, dst_a);
01767 }
01768 break;
01769 case GRAIN_MERGE_MODE: {
01770 int tmp;
01771
01772 tmp = dst_r + src_r - 128;
01773 tmp = qMin(tmp, 255);
01774 tmp = qMax(tmp, 0);
01775 src_r = (uchar) tmp;
01776
01777 tmp = dst_g + src_g - 128;
01778 tmp = qMin(tmp, 255);
01779 tmp = qMax(tmp, 0);
01780 src_g = (uchar) tmp;
01781
01782 tmp = dst_b + src_b - 128;
01783 tmp = qMin(tmp, 255);
01784 tmp = qMax(tmp, 0);
01785 src_b = (uchar) tmp;
01786
01787 src_a = qMin(src_a, dst_a);
01788 }
01789 break;
01790 }
01791
01792 src_a = INT_MULT(src_a, layer.opacity);
01793
01794
01795
01796 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
01797 layer.mask_tiles[j].size() > (int)i)
01798 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01799
01800 uchar new_r, new_g, new_b, new_a;
01801 new_a = dst_a + INT_MULT(OPAQUE_OPACITY - dst_a, src_a);
01802
01803 float src_ratio = (float)src_a / new_a;
01804 float dst_ratio = 1.0 - src_ratio;
01805
01806 new_r = (uchar)(src_ratio * src_r + dst_ratio * dst_r + EPSILON);
01807 new_g = (uchar)(src_ratio * src_g + dst_ratio * dst_g + EPSILON);
01808 new_b = (uchar)(src_ratio * src_b + dst_ratio * dst_b + EPSILON);
01809
01810 if (!layer_modes[layer.mode].affect_alpha)
01811 new_a = dst_a;
01812
01813 image.setPixel(m, n, qRgba(new_r, new_g, new_b, new_a));
01814 }
01815
01816
01828 void XCFImageFormat::mergeGrayToGray(Layer& layer, uint i, uint j, int k, int l,
01829 QImage& image, int m, int n)
01830 {
01831 int src = layer.image_tiles[j][i].pixelIndex(k, l);
01832 image.setPixel(m, n, src);
01833 }
01834
01835
01847 void XCFImageFormat::mergeGrayAToGray(Layer& layer, uint i, uint j, int k, int l,
01848 QImage& image, int m, int n)
01849 {
01850 int src = qGray(layer.image_tiles[j][i].pixel(k, l));
01851 int dst = image.pixelIndex(m, n);
01852
01853 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
01854
01855 if (!src_a) return;
01856
01857 switch (layer.mode) {
01858 case MULTIPLY_MODE: {
01859 src = INT_MULT( src, dst );
01860 }
01861 break;
01862 case DIVIDE_MODE: {
01863 src = qMin((dst * 256) / (1 + src), 255);
01864 }
01865 break;
01866 case SCREEN_MODE: {
01867 src = 255 - INT_MULT(255 - dst, 255 - src);
01868 }
01869 break;
01870 case OVERLAY_MODE: {
01871 src = INT_MULT(dst, dst + INT_MULT(2 * src, 255 - dst));
01872 }
01873 break;
01874 case DIFFERENCE_MODE: {
01875 src = dst > src ? dst - src : src - dst;
01876 }
01877 break;
01878 case ADDITION_MODE: {
01879 src = add_lut(dst,src);
01880 }
01881 break;
01882 case SUBTRACT_MODE: {
01883 src = dst > src ? dst - src : 0;
01884 }
01885 break;
01886 case DARKEN_ONLY_MODE: {
01887 src = dst < src ? dst : src;
01888 }
01889 break;
01890 case LIGHTEN_ONLY_MODE: {
01891 src = dst < src ? src : dst;
01892 }
01893 break;
01894 case DODGE_MODE: {
01895 uint tmp = dst << 8;
01896 tmp /= 256 - src;
01897 src = (uchar) qMin(tmp, 255u);
01898 }
01899 break;
01900 case BURN_MODE: {
01901 uint tmp = (255-dst) << 8;
01902 tmp /= src + 1;
01903 src = (uchar) qMin(tmp, 255u);
01904 src = 255 - src;
01905 }
01906 break;
01907 case HARDLIGHT_MODE: {
01908 uint tmp;
01909 if (src > 128) {
01910 tmp = ((int)255-dst) * ((int) 255 - ((src-128) << 1));
01911 src = (uchar) qMin(255 - (tmp >> 8), 255u);
01912 } else {
01913 tmp = (int) dst * ((int) src << 1);
01914 src = (uchar) qMin(tmp >> 8, 255u);
01915 }
01916 }
01917 break;
01918 case SOFTLIGHT_MODE: {
01919 uint tmpS, tmpM;
01920
01921 tmpM = INT_MULT(dst, src);
01922 tmpS = 255 - INT_MULT((255-dst), (255-src));
01923 src = INT_MULT((255 - dst), tmpM)
01924 + INT_MULT(dst, tmpS);
01925
01926 }
01927 break;
01928 case GRAIN_EXTRACT_MODE: {
01929 int tmp;
01930
01931 tmp = dst - src + 128;
01932 tmp = qMin(tmp, 255);
01933 tmp = qMax(tmp, 0);
01934
01935 src = (uchar) tmp;
01936 }
01937 break;
01938 case GRAIN_MERGE_MODE: {
01939 int tmp;
01940
01941 tmp = dst + src - 128;
01942 tmp = qMin(tmp, 255);
01943 tmp = qMax(tmp, 0);
01944
01945 src = (uchar) tmp;
01946 }
01947 break;
01948 }
01949
01950 src_a = INT_MULT(src_a, layer.opacity);
01951
01952
01953
01954 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
01955 layer.mask_tiles[j].size() > (int)i)
01956 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01957
01958 uchar new_a = OPAQUE_OPACITY;
01959
01960 float src_ratio = (float)src_a / new_a;
01961 float dst_ratio = 1.0 - src_ratio;
01962
01963 uchar new_g = (uchar)(src_ratio * src + dst_ratio * dst + EPSILON);
01964
01965 image.setPixel(m, n, new_g);
01966 }
01967
01968
01982 void XCFImageFormat::mergeGrayToRGB(Layer& layer, uint i, uint j, int k, int l,
01983 QImage& image, int m, int n)
01984 {
01985 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01986 uchar src_a = layer.opacity;
01987 image.setPixel(m, n, qRgba(src, src_a));
01988 }
01989
01990
02004 void XCFImageFormat::mergeGrayAToRGB(Layer& layer, uint i, uint j, int k, int l,
02005 QImage& image, int m, int n)
02006 {
02007 int src = qGray(layer.image_tiles[j][i].pixel(k, l));
02008 int dst = qGray(image.pixel(m, n));
02009
02010 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
02011 uchar dst_a = qAlpha(image.pixel(m, n));
02012
02013 if (!src_a) return;
02014
02015 switch (layer.mode) {
02016 case MULTIPLY_MODE: {
02017 src = INT_MULT(src, dst);
02018 src_a = qMin(src_a, dst_a);
02019 }
02020 break;
02021 case DIVIDE_MODE: {
02022 src = qMin((dst * 256) / (1 + src), 255);
02023 src_a = qMin(src_a, dst_a);
02024 }
02025 break;
02026 case SCREEN_MODE: {
02027 src = 255 - INT_MULT(255 - dst, 255 - src);
02028 src_a = qMin(src_a, dst_a);
02029 }
02030 break;
02031 case OVERLAY_MODE: {
02032 src = INT_MULT( dst, dst + INT_MULT(2 * src, 255 - dst));
02033 src_a = qMin(src_a, dst_a);
02034 }
02035 break;
02036 case DIFFERENCE_MODE: {
02037 src = dst > src ? dst - src : src - dst;
02038 src_a = qMin(src_a, dst_a);
02039 }
02040 break;
02041 case ADDITION_MODE: {
02042 src = add_lut(dst,src);
02043 src_a = qMin(src_a, dst_a);
02044 }
02045 break;
02046 case SUBTRACT_MODE: {
02047 src = dst > src ? dst - src : 0;
02048 src_a = qMin(src_a, dst_a);
02049 }
02050 break;
02051 case DARKEN_ONLY_MODE: {
02052 src = dst < src ? dst : src;
02053 src_a = qMin(src_a, dst_a);
02054 }
02055 break;
02056 case LIGHTEN_ONLY_MODE: {
02057 src = dst < src ? src : dst;
02058 src_a = qMin(src_a, dst_a);
02059 }
02060 break;
02061 case DODGE_MODE: {
02062 uint tmp = dst << 8;
02063 tmp /= 256 - src;
02064 src = (uchar) qMin(tmp, 255u);
02065 src_a = qMin(src_a, dst_a);
02066 }
02067 break;
02068 case BURN_MODE: {
02069 uint tmp = (255-dst) << 8;
02070 tmp /= src + 1;
02071 src = (uchar) qMin(tmp, 255u);
02072 src = 255 - src;
02073 src_a = qMin(src_a, dst_a);
02074 }
02075 break;
02076 case HARDLIGHT_MODE: {
02077 uint tmp;
02078 if (src > 128) {
02079 tmp = ((int)255-dst) * ((int) 255 - ((src-128) << 1));
02080 src = (uchar) qMin(255 - (tmp >> 8), 255u);
02081 } else {
02082 tmp = (int) dst * ((int) src << 1);
02083 src = (uchar) qMin(tmp >> 8, 255u);
02084 }
02085 src_a = qMin(src_a, dst_a);
02086 }
02087 break;
02088 case SOFTLIGHT_MODE: {
02089 uint tmpS, tmpM;
02090
02091 tmpM = INT_MULT(dst, src);
02092 tmpS = 255 - INT_MULT((255 - dst), (255-src));
02093 src = INT_MULT((255 - dst), tmpM)
02094 + INT_MULT(dst, tmpS);
02095
02096 src_a = qMin(src_a, dst_a);
02097 }
02098 break;
02099 case GRAIN_EXTRACT_MODE: {
02100 int tmp;
02101
02102 tmp = dst - src + 128;
02103 tmp = qMin(tmp, 255);
02104 tmp = qMax(tmp, 0);
02105
02106 src = (uchar) tmp;
02107 src_a = qMin(src_a, dst_a);
02108 }
02109 break;
02110 case GRAIN_MERGE_MODE: {
02111 int tmp;
02112
02113 tmp = dst + src - 128;
02114 tmp = qMin(tmp, 255);
02115 tmp = qMax(tmp, 0);
02116
02117 src = (uchar) tmp;
02118 src_a = qMin(src_a, dst_a);
02119 }
02120 break;
02121 }
02122
02123 src_a = INT_MULT(src_a, layer.opacity);
02124
02125
02126 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
02127 layer.mask_tiles[j].size() > (int)i)
02128 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
02129
02130 uchar new_a = dst_a + INT_MULT(OPAQUE_OPACITY - dst_a, src_a);
02131
02132 float src_ratio = (float)src_a / new_a;
02133 float dst_ratio = 1.0 - src_ratio;
02134
02135 uchar new_g = (uchar)(src_ratio * src + dst_ratio * dst + EPSILON);
02136
02137 if (!layer_modes[layer.mode].affect_alpha)
02138 new_a = dst_a;
02139
02140 image.setPixel(m, n, qRgba(new_g, new_g, new_g, new_a));
02141 }
02142
02143
02155 void XCFImageFormat::mergeIndexedToIndexed(Layer& layer, uint i, uint j, int k, int l,
02156 QImage& image, int m, int n)
02157 {
02158 int src = layer.image_tiles[j][i].pixelIndex(k, l);
02159 image.setPixel(m, n, src);
02160 }
02161
02162
02174 void XCFImageFormat::mergeIndexedAToIndexed(Layer& layer, uint i, uint j, int k, int l,
02175 QImage& image, int m, int n)
02176 {
02177 uchar src = layer.image_tiles[j][i].pixelIndex(k, l);
02178 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
02179 src_a = INT_MULT( src_a, layer.opacity );
02180
02181 if ( layer.apply_mask == 1 &&
02182 layer.mask_tiles.size() > (int)j &&
02183 layer.mask_tiles[j].size() > (int)i)
02184 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
02185
02186 if (src_a > 127) {
02187 src++;
02188 image.setPixel(m, n, src);
02189 }
02190 }
02191
02192
02206 void XCFImageFormat::mergeIndexedAToRGB(Layer& layer, uint i, uint j, int k, int l,
02207 QImage& image, int m, int n)
02208 {
02209 QRgb src = layer.image_tiles[j][i].pixel(k, l);
02210 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
02211 src_a = INT_MULT(src_a, layer.opacity);
02212
02213
02214 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
02215 layer.mask_tiles[j].size() > (int)i)
02216 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
02217
02218
02219 if (src_a <= 127)
02220 src_a = 0;
02221 else
02222 src_a = OPAQUE_OPACITY;
02223
02224 image.setPixel(m, n, qRgba(src, src_a));
02225 }
02226
02227
02235 void XCFImageFormat::dissolveRGBPixels ( QImage& image, int x, int y )
02236 {
02237
02238
02239
02240 for (int l = 0; l < image.height(); l++) {
02241 srand(random_table[( l + y ) % RANDOM_TABLE_SIZE]);
02242
02243 for (int k = 0; k < x; k++)
02244 rand();
02245
02246 for (int k = 0; k < image.width(); k++) {
02247 int rand_val = rand() & 0xff;
02248 QRgb pixel = image.pixel(k, l);
02249
02250 if (rand_val > qAlpha(pixel)) {
02251 image.setPixel(k, l, qRgba(pixel, 0));
02252 }
02253 }
02254 }
02255 }
02256
02257
02267 void XCFImageFormat::dissolveAlphaPixels ( QImage& image, int x, int y )
02268 {
02269
02270
02271
02272 for (int l = 0; l < image.height(); l++) {
02273 srand( random_table[(l + y) % RANDOM_TABLE_SIZE]);
02274
02275 for (int k = 0; k < x; k++)
02276 rand();
02277
02278 for (int k = 0; k < image.width(); k++) {
02279 int rand_val = rand() & 0xff;
02280 uchar alpha = image.pixelIndex(k, l);
02281
02282 if (rand_val > alpha) {
02283 image.setPixel(k, l, 0);
02284 }
02285 }
02286 }
02287 }
02288
02289
02291
02292 XCFHandler::XCFHandler()
02293 {
02294 }
02295
02296 bool XCFHandler::canRead() const
02297 {
02298 if (canRead(device())) {
02299 setFormat("xcf");
02300 return true;
02301 }
02302 return false;
02303 }
02304
02305 bool XCFHandler::read(QImage *image)
02306 {
02307 XCFImageFormat xcfif;
02308 return xcfif.readXCF(device(), image);
02309 }
02310
02311 bool XCFHandler::write(const QImage &)
02312 {
02313 return false;
02314 }
02315
02316 QByteArray XCFHandler::name() const
02317 {
02318 return "xcf";
02319 }
02320
02321 bool XCFHandler::canRead(QIODevice *device)
02322 {
02323 if (!device) {
02324 qWarning("DDSHandler::canRead() called with no device");
02325 return false;
02326 }
02327
02328 qint64 oldPos = device->pos();
02329
02330 char head[8];
02331 qint64 readBytes = device->read(head, sizeof(head));
02332 if (readBytes != sizeof(head)) {
02333 if (device->isSequential()) {
02334 while (readBytes > 0)
02335 device->ungetChar(head[readBytes-- - 1]);
02336 } else {
02337 device->seek(oldPos);
02338 }
02339 return false;
02340 }
02341
02342 if (device->isSequential()) {
02343 while (readBytes > 0)
02344 device->ungetChar(head[readBytes-- - 1]);
02345 } else {
02346 device->seek(oldPos);
02347 }
02348
02349 return qstrncmp(head, "gimp xcf", 8) == 0;
02350 }
02351
02352
02353 class XCFPlugin : public QImageIOPlugin
02354 {
02355 public:
02356 QStringList keys() const;
02357 Capabilities capabilities(QIODevice *device, const QByteArray &format) const;
02358 QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const;
02359 };
02360
02361 QStringList XCFPlugin::keys() const
02362 {
02363 return QStringList() << "xcf" << "XCF";
02364 }
02365
02366 QImageIOPlugin::Capabilities XCFPlugin::capabilities(QIODevice *device, const QByteArray &format) const
02367 {
02368 if (format == "xcf" || format == "XCF")
02369 return Capabilities(CanRead);
02370 if (!format.isEmpty())
02371 return 0;
02372 if (!device->isOpen())
02373 return 0;
02374
02375 Capabilities cap;
02376 if (device->isReadable() && XCFHandler::canRead(device))
02377 cap |= CanRead;
02378 return cap;
02379 }
02380
02381 QImageIOHandler *XCFPlugin::create(QIODevice *device, const QByteArray &format) const
02382 {
02383 QImageIOHandler *handler = new XCFHandler;
02384 handler->setDevice(device);
02385 handler->setFormat(format);
02386 return handler;
02387 }
02388
02389 Q_EXPORT_STATIC_PLUGIN(XCFPlugin)
02390 Q_EXPORT_PLUGIN2(xcf,XCFPlugin)