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 quint32 ncolors;
00280 xcf_io >> ncolors;
00281
00282 if(size > 65535 || size < 4)
00283 return false;
00284
00285 size = 3 * ncolors + 4;
00286 data = new char[size];
00287
00288
00289 data[0] = 0;
00290 data[1] = 0;
00291 data[2] = ncolors >> 8;
00292 data[3] = ncolors & 255;
00293
00294
00295 xcf_io.readRawData(data + 4, size - 4);
00296 } else if (type == PROP_USER_UNIT) {
00297
00298 float factor;
00299 qint32 digits;
00300
00301 xcf_io >> size >> factor >> digits;
00302
00303 for (int i = 0; i < 5; i++) {
00304 char* unit_strings;
00305
00306 xcf_io >> unit_strings;
00307
00308 delete[] unit_strings;
00309
00310 if (xcf_io.device()->atEnd()) {
00311 kDebug(399) << "XCF: read failure on property " << type;
00312 return false;
00313 }
00314 }
00315
00316 size = 0;
00317 } else {
00318 xcf_io >> size;
00319 if(size >256000)
00320 return false;
00321 data = new char[size];
00322 xcf_io.readRawData(data, size);
00323 }
00324
00325 if (size != 0 && data)
00326 bytes = QByteArray(data,size);
00327
00328 delete [] data;
00329
00330 return true;
00331 }
00332
00333
00342 bool XCFImageFormat::loadLayer(QDataStream& xcf_io, XCFImage& xcf_image)
00343 {
00344 Layer& layer(xcf_image.layer);
00345 delete[] layer.name;
00346
00347 xcf_io >> layer.width >> layer.height >> layer.type >> layer.name;
00348
00349 if (!loadLayerProperties(xcf_io, layer))
00350 return false;
00351 #if 0
00352 cout << "layer: \"" << layer.name << "\", size: " << layer.width << " x "
00353 << layer.height << ", type: " << layer.type << ", mode: " << layer.mode
00354 << ", opacity: " << layer.opacity << ", visible: " << layer.visible
00355 << ", offset: " << layer.x_offset << ", " << layer.y_offset << endl;
00356 #endif
00357
00358
00359
00360
00361 if (layer.visible == 0)
00362 return true;
00363
00364
00365
00366 xcf_io >> layer.hierarchy_offset >> layer.mask_offset;
00367
00368
00369
00370
00371 if( !composeTiles(xcf_image))
00372 return false;
00373 xcf_io.device()->seek(layer.hierarchy_offset);
00374
00375
00376
00377
00378
00379 layer.assignBytes = assignImageBytes;
00380
00381 if (!loadHierarchy(xcf_io, layer))
00382 return false;
00383
00384 if (layer.mask_offset != 0) {
00385 xcf_io.device()->seek(layer.mask_offset);
00386
00387 if (!loadMask(xcf_io, layer))
00388 return false;
00389 }
00390
00391
00392
00393
00394
00395 if (!xcf_image.initialized) {
00396 if( !initializeImage(xcf_image))
00397 return false;
00398 copyLayerToImage(xcf_image);
00399 xcf_image.initialized = true;
00400 } else
00401 mergeLayerIntoImage(xcf_image);
00402
00403 return true;
00404 }
00405
00406
00414 bool XCFImageFormat::loadLayerProperties(QDataStream& xcf_io, Layer& layer)
00415 {
00416 while (true) {
00417 PropType type;
00418 QByteArray bytes;
00419
00420 if (!loadProperty(xcf_io, type, bytes)) {
00421 kDebug(399) << "XCF: error loading layer properties";
00422 return false;
00423 }
00424
00425 QDataStream property(bytes);
00426
00427 switch (type) {
00428 case PROP_END:
00429 return true;
00430
00431 case PROP_ACTIVE_LAYER:
00432 layer.active = true;
00433 break;
00434
00435 case PROP_OPACITY:
00436 property >> layer.opacity;
00437 break;
00438
00439 case PROP_VISIBLE:
00440 property >> layer.visible;
00441 break;
00442
00443 case PROP_LINKED:
00444 property >> layer.linked;
00445 break;
00446
00447 case PROP_PRESERVE_TRANSPARENCY:
00448 property >> layer.preserve_transparency;
00449 break;
00450
00451 case PROP_APPLY_MASK:
00452 property >> layer.apply_mask;
00453 break;
00454
00455 case PROP_EDIT_MASK:
00456 property >> layer.edit_mask;
00457 break;
00458
00459 case PROP_SHOW_MASK:
00460 property >> layer.show_mask;
00461 break;
00462
00463 case PROP_OFFSETS:
00464 property >> layer.x_offset >> layer.y_offset;
00465 break;
00466
00467 case PROP_MODE:
00468 property >> layer.mode;
00469 break;
00470
00471 case PROP_TATTOO:
00472 property >> layer.tattoo;
00473 break;
00474
00475 default:
00476 kDebug(399) << "XCF: unimplemented layer property " << type
00477 << ", size " << bytes.size() << endl;
00478 }
00479 }
00480 }
00481
00482
00488 bool XCFImageFormat::composeTiles(XCFImage& xcf_image)
00489 {
00490 Layer& layer(xcf_image.layer);
00491
00492 layer.nrows = (layer.height + TILE_HEIGHT - 1) / TILE_HEIGHT;
00493 layer.ncols = (layer.width + TILE_WIDTH - 1) / TILE_WIDTH;
00494
00495 layer.image_tiles.resize(layer.nrows);
00496
00497 if (layer.type == GRAYA_GIMAGE || layer.type == INDEXEDA_GIMAGE)
00498 layer.alpha_tiles.resize(layer.nrows);
00499
00500 if (layer.mask_offset != 0)
00501 layer.mask_tiles.resize(layer.nrows);
00502
00503 for (uint j = 0; j < layer.nrows; j++) {
00504 layer.image_tiles[j].resize(layer.ncols);
00505
00506 if (layer.type == GRAYA_GIMAGE || layer.type == INDEXEDA_GIMAGE)
00507 layer.alpha_tiles[j].resize(layer.ncols);
00508
00509 if (layer.mask_offset != 0)
00510 layer.mask_tiles[j].resize(layer.ncols);
00511 }
00512
00513 for (uint j = 0; j < layer.nrows; j++) {
00514 for (uint i = 0; i < layer.ncols; i++) {
00515
00516 uint tile_width = (i + 1) * TILE_WIDTH <= layer.width
00517 ? TILE_WIDTH : layer.width - i * TILE_WIDTH;
00518
00519 uint tile_height = (j + 1) * TILE_HEIGHT <= layer.height
00520 ? TILE_HEIGHT : layer.height - j * TILE_HEIGHT;
00521
00522
00523
00524
00525 switch (layer.type) {
00526 case RGB_GIMAGE:
00527 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_RGB32);
00528 layer.image_tiles[j][i].setNumColors(0);
00529 if( layer.image_tiles[j][i].isNull())
00530 return false;
00531 break;
00532
00533 case RGBA_GIMAGE:
00534 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_ARGB32);
00535 layer.image_tiles[j][i].setNumColors(0);
00536 if( layer.image_tiles[j][i].isNull())
00537 return false;
00538 break;
00539
00540 case GRAY_GIMAGE:
00541 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
00542 layer.image_tiles[j][i].setNumColors(256);
00543 if( layer.image_tiles[j][i].isNull())
00544 return false;
00545 setGrayPalette(layer.image_tiles[j][i]);
00546 break;
00547
00548 case GRAYA_GIMAGE:
00549 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
00550 layer.image_tiles[j][i].setNumColors(256);
00551 if( layer.image_tiles[j][i].isNull())
00552 return false;
00553 setGrayPalette(layer.image_tiles[j][i]);
00554
00555 layer.alpha_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
00556 layer.alpha_tiles[j][i].setNumColors(256);
00557 if( layer.alpha_tiles[j][i].isNull())
00558 return false;
00559 setGrayPalette(layer.alpha_tiles[j][i]);
00560 break;
00561
00562 case INDEXED_GIMAGE:
00563 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
00564 layer.image_tiles[j][i].setNumColors(xcf_image.num_colors);
00565 if( layer.image_tiles[j][i].isNull())
00566 return false;
00567 setPalette(xcf_image, layer.image_tiles[j][i]);
00568 break;
00569
00570 case INDEXEDA_GIMAGE:
00571 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
00572 layer.image_tiles[j][i].setNumColors(xcf_image.num_colors);
00573 if( layer.image_tiles[j][i].isNull())
00574 return false;
00575 setPalette(xcf_image, layer.image_tiles[j][i]);
00576
00577 layer.alpha_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
00578 layer.alpha_tiles[j][i].setNumColors(256);
00579 if( layer.alpha_tiles[j][i].isNull())
00580 return false;
00581 setGrayPalette(layer.alpha_tiles[j][i]);
00582 }
00583
00584 if (layer.mask_offset != 0) {
00585 layer.mask_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
00586 layer.mask_tiles[j][i].setNumColors(256);
00587 if( layer.mask_tiles[j][i].isNull())
00588 return false;
00589 setGrayPalette(layer.mask_tiles[j][i]);
00590 }
00591 }
00592 }
00593 return true;
00594 }
00595
00596
00603 void XCFImageFormat::setGrayPalette(QImage& image)
00604 {
00605 for (int i = 0; i < 256; i++)
00606 image.setColor(i, qRgb(i, i, i));
00607 }
00608
00609
00615 void XCFImageFormat::setPalette(XCFImage& xcf_image, QImage& image)
00616 {
00617 for (int i = 0; i < xcf_image.num_colors; i++)
00618 image.setColor(i, xcf_image.palette[i]);
00619 }
00620
00621
00629 void XCFImageFormat::assignImageBytes(Layer& layer, uint i, uint j)
00630 {
00631 uchar* tile = layer.tile;
00632
00633 switch (layer.type) {
00634 case RGB_GIMAGE:
00635 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
00636 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
00637 layer.image_tiles[j][i].setPixel(k, l,
00638 qRgb(tile[0], tile[1], tile[2]));
00639 tile += sizeof(QRgb);
00640 }
00641 }
00642 break;
00643
00644 case RGBA_GIMAGE:
00645 for ( int l = 0; l < layer.image_tiles[j][i].height(); l++ ) {
00646 for ( int k = 0; k < layer.image_tiles[j][i].width(); k++ ) {
00647 layer.image_tiles[j][i].setPixel(k, l,
00648 qRgba(tile[0], tile[1], tile[2], tile[3]));
00649 tile += sizeof(QRgb);
00650 }
00651 }
00652 break;
00653
00654 case GRAY_GIMAGE:
00655 case INDEXED_GIMAGE:
00656 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
00657 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
00658 layer.image_tiles[j][i].setPixel(k, l, tile[0]);
00659 tile += sizeof(QRgb);
00660 }
00661 }
00662 break;
00663
00664 case GRAYA_GIMAGE:
00665 case INDEXEDA_GIMAGE:
00666 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
00667 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
00668
00669
00670
00671
00672
00673 if (tile[0] < layer.image_tiles[j][i].numColors())
00674 layer.image_tiles[j][i].setPixel(k, l, tile[0]);
00675
00676 layer.alpha_tiles[j][i].setPixel(k, l, tile[1]);
00677 tile += sizeof(QRgb);
00678 }
00679 }
00680 break;
00681 }
00682 }
00683
00684
00693 bool XCFImageFormat::loadHierarchy(QDataStream& xcf_io, Layer& layer)
00694 {
00695 qint32 width;
00696 qint32 height;
00697 qint32 bpp;
00698 quint32 offset;
00699
00700 xcf_io >> width >> height >> bpp >> offset;
00701
00702
00703
00704
00705
00706 quint32 junk;
00707 do {
00708 xcf_io >> junk;
00709
00710 if (xcf_io.device()->atEnd()) {
00711 kDebug(399) << "XCF: read failure on layer " << layer.name << " level offsets";
00712 return false;
00713 }
00714 } while (junk != 0);
00715
00716 qint64 saved_pos = xcf_io.device()->pos();
00717
00718 xcf_io.device()->seek(offset);
00719 if (!loadLevel(xcf_io, layer, bpp))
00720 return false;
00721
00722 xcf_io.device()->seek(saved_pos);
00723 return true;
00724 }
00725
00726
00735 bool XCFImageFormat::loadLevel(QDataStream& xcf_io, Layer& layer, qint32 bpp)
00736 {
00737 qint32 width;
00738 qint32 height;
00739 quint32 offset;
00740
00741 xcf_io >> width >> height >> offset;
00742
00743 if (offset == 0)
00744 return true;
00745
00746 for (uint j = 0; j < layer.nrows; j++) {
00747 for (uint i = 0; i < layer.ncols; i++) {
00748
00749 if (offset == 0) {
00750 kDebug(399) << "XCF: incorrect number of tiles in layer " << layer.name;
00751 return false;
00752 }
00753
00754 qint64 saved_pos = xcf_io.device()->pos();
00755 quint32 offset2;
00756 xcf_io >> offset2;
00757
00758
00759
00760 if (offset2 == 0)
00761 offset2 = offset + (uint)(TILE_WIDTH * TILE_HEIGHT * 4 * 1.5);
00762
00763 xcf_io.device()->seek(offset);
00764 int size = layer.image_tiles[j][i].width() * layer.image_tiles[j][i].height();
00765
00766 if (!loadTileRLE(xcf_io, layer.tile, size, offset2 - offset, bpp))
00767 return false;
00768
00769
00770
00771
00772
00773 layer.assignBytes(layer, i, j);
00774
00775 xcf_io.device()->seek(saved_pos);
00776 xcf_io >> offset;
00777 }
00778 }
00779
00780 return true;
00781 }
00782
00783
00790 bool XCFImageFormat::loadMask(QDataStream& xcf_io, Layer& layer)
00791 {
00792 qint32 width;
00793 qint32 height;
00794 char* name;
00795
00796 xcf_io >> width >> height >> name;
00797
00798 delete name;
00799
00800 if (!loadChannelProperties(xcf_io, layer))
00801 return false;
00802
00803 quint32 hierarchy_offset;
00804 xcf_io >> hierarchy_offset;
00805
00806 xcf_io.device()->seek(hierarchy_offset);
00807 layer.assignBytes = assignMaskBytes;
00808
00809 if (!loadHierarchy(xcf_io, layer))
00810 return false;
00811
00812 return true;
00813 }
00814
00815
00839 bool XCFImageFormat::loadTileRLE(QDataStream& xcf_io, uchar* tile, int image_size,
00840 int data_length, qint32 bpp)
00841 {
00842 uchar* data;
00843
00844 uchar* xcfdata;
00845 uchar* xcfodata;
00846 uchar* xcfdatalimit;
00847
00848 xcfdata = xcfodata = new uchar[data_length];
00849
00850 xcf_io.readRawData((char*)xcfdata, data_length);
00851
00852 if (!xcf_io.device()->isOpen()) {
00853 delete[] xcfodata;
00854 kDebug(399) << "XCF: read failure on tile";
00855 return false;
00856 }
00857
00858 xcfdatalimit = &xcfodata[data_length - 1];
00859
00860 for (int i = 0; i < bpp; ++i) {
00861
00862 data = tile + i;
00863
00864 int count = 0;
00865 int size = image_size;
00866
00867 while (size > 0) {
00868 if (xcfdata > xcfdatalimit)
00869 goto bogus_rle;
00870
00871 uchar val = *xcfdata++;
00872 uint length = val;
00873
00874 if (length >= 128) {
00875 length = 255 - (length - 1);
00876 if (length == 128) {
00877 if (xcfdata >= xcfdatalimit)
00878 goto bogus_rle;
00879
00880 length = (*xcfdata << 8) + xcfdata[1];
00881
00882 xcfdata += 2;
00883 }
00884
00885 count += length;
00886 size -= length;
00887
00888 if (size < 0)
00889 goto bogus_rle;
00890
00891 if (&xcfdata[length - 1] > xcfdatalimit)
00892 goto bogus_rle;
00893
00894 while (length-- > 0) {
00895 *data = *xcfdata++;
00896 data += sizeof(QRgb);
00897 }
00898 } else {
00899 length += 1;
00900 if (length == 128) {
00901 if (xcfdata >= xcfdatalimit)
00902 goto bogus_rle;
00903
00904 length = (*xcfdata << 8) + xcfdata[1];
00905 xcfdata += 2;
00906 }
00907
00908 count += length;
00909 size -= length;
00910
00911 if (size < 0)
00912 goto bogus_rle;
00913
00914 if (xcfdata > xcfdatalimit)
00915 goto bogus_rle;
00916
00917 val = *xcfdata++;
00918
00919 while (length-- > 0) {
00920 *data = val;
00921 data += sizeof(QRgb);
00922 }
00923 }
00924 }
00925 }
00926
00927 delete[] xcfodata;
00928 return true;
00929
00930 bogus_rle:
00931
00932 kDebug(399) << "The run length encoding could not be decoded properly";
00933 delete[] xcfodata;
00934 return false;
00935 }
00936
00937
00945 bool XCFImageFormat::loadChannelProperties(QDataStream& xcf_io, Layer& layer)
00946 {
00947 while (true) {
00948 PropType type;
00949 QByteArray bytes;
00950
00951 if (!loadProperty(xcf_io, type, bytes)) {
00952 kDebug(399) << "XCF: error loading channel properties";
00953 return false;
00954 }
00955
00956 QDataStream property(bytes);
00957
00958 switch (type) {
00959 case PROP_END:
00960 return true;
00961
00962 case PROP_OPACITY:
00963 property >> layer.mask_channel.opacity;
00964 break;
00965
00966 case PROP_VISIBLE:
00967 property >> layer.mask_channel.visible;
00968 break;
00969
00970 case PROP_SHOW_MASKED:
00971 property >> layer.mask_channel.show_masked;
00972 break;
00973
00974 case PROP_COLOR:
00975 property >> layer.mask_channel.red >> layer.mask_channel.green
00976 >> layer.mask_channel.blue;
00977 break;
00978
00979 case PROP_TATTOO:
00980 property >> layer.mask_channel.tattoo;
00981 break;
00982
00983 default:
00984 kDebug(399) << "XCF: unimplemented channel property " << type
00985 << ", size " << bytes.size() << endl;
00986 }
00987 }
00988 }
00989
00990
00997 void XCFImageFormat::assignMaskBytes(Layer& layer, uint i, uint j)
00998 {
00999 uchar* tile = layer.tile;
01000
01001 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
01002 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
01003 layer.mask_tiles[j][i].setPixel(k, l, tile[0]);
01004 tile += sizeof(QRgb);
01005 }
01006 }
01007 }
01008
01009
01038 bool XCFImageFormat::initializeImage(XCFImage& xcf_image)
01039 {
01040
01041 Layer& layer(xcf_image.layer);
01042 QImage& image(xcf_image.image);
01043
01044 switch (layer.type) {
01045 case RGB_GIMAGE:
01046 if (layer.opacity == OPAQUE_OPACITY) {
01047 image = QImage( xcf_image.width, xcf_image.height, QImage::Format_RGB32);
01048 if( image.isNull())
01049 return false;
01050 image.fill(qRgb(255, 255, 255));
01051 break;
01052 }
01053
01054 case RGBA_GIMAGE:
01055 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_ARGB32);
01056 if( image.isNull())
01057 return false;
01058 image.fill(qRgba(255, 255, 255, 0));
01059 break;
01060
01061 case GRAY_GIMAGE:
01062 if (layer.opacity == OPAQUE_OPACITY) {
01063 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_Indexed8);
01064 image.setNumColors(256);
01065 if( image.isNull())
01066 return false;
01067 setGrayPalette(image);
01068 image.fill(255);
01069 break;
01070 }
01071
01072 case GRAYA_GIMAGE:
01073 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_ARGB32);
01074 if( image.isNull())
01075 return false;
01076 image.fill(qRgba(255, 255, 255, 0));
01077 break;
01078
01079 case INDEXED_GIMAGE:
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092 if (xcf_image.num_colors <= 2) {
01093 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_MonoLSB);
01094 image.setNumColors(xcf_image.num_colors);
01095 if( image.isNull())
01096 return false;
01097 image.fill(0);
01098 setPalette(xcf_image, image);
01099 } else if (xcf_image.num_colors <= 256) {
01100 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_Indexed8);
01101 image.setNumColors(xcf_image.num_colors);
01102 if( image.isNull())
01103 return false;
01104 image.fill(0);
01105 setPalette(xcf_image, image);
01106 }
01107 break;
01108
01109 case INDEXEDA_GIMAGE:
01110 if (xcf_image.num_colors == 1) {
01111
01112 xcf_image.num_colors++;
01113 xcf_image.palette.resize(xcf_image.num_colors);
01114 xcf_image.palette[1] = xcf_image.palette[0];
01115 xcf_image.palette[0] = qRgba(255, 255, 255, 0);
01116
01117 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_MonoLSB);
01118 image.setNumColors(xcf_image.num_colors);
01119 if( image.isNull())
01120 return false;
01121 image.fill(0);
01122 setPalette(xcf_image, image);
01123 } else if (xcf_image.num_colors < 256) {
01124
01125 xcf_image.num_colors++;
01126 xcf_image.palette.resize(xcf_image.num_colors);
01127 for (int c = xcf_image.num_colors - 1; c >= 1; c--)
01128 xcf_image.palette[c] = xcf_image.palette[c - 1];
01129
01130 xcf_image.palette[0] = qRgba(255, 255, 255, 0);
01131 image = QImage( xcf_image.width, xcf_image.height, QImage::Format_Indexed8);
01132 image.setNumColors(xcf_image.num_colors);
01133 if( image.isNull())
01134 return false;
01135 image.fill(0);
01136 setPalette(xcf_image, image);
01137 } else {
01138
01139
01140
01141 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_ARGB32);
01142 if( image.isNull())
01143 return false;
01144 image.fill(qRgba(255, 255, 255, 0));
01145 }
01146 break;
01147 }
01148
01149 image.setDotsPerMeterX((int)(xcf_image.x_resolution * INCHESPERMETER));
01150 image.setDotsPerMeterY((int)(xcf_image.y_resolution * INCHESPERMETER));
01151 return true;
01152 }
01153
01154
01160 void XCFImageFormat::copyLayerToImage(XCFImage& xcf_image)
01161 {
01162 Layer& layer(xcf_image.layer);
01163 QImage& image(xcf_image.image);
01164 PixelCopyOperation copy = 0;
01165
01166 switch (layer.type) {
01167 case RGB_GIMAGE:
01168 case RGBA_GIMAGE:
01169 copy = copyRGBToRGB;
01170 break;
01171 case GRAY_GIMAGE:
01172 if (layer.opacity == OPAQUE_OPACITY)
01173 copy = copyGrayToGray;
01174 else
01175 copy = copyGrayToRGB;
01176 break;
01177 case GRAYA_GIMAGE:
01178 copy = copyGrayAToRGB;
01179 break;
01180 case INDEXED_GIMAGE:
01181 copy = copyIndexedToIndexed;
01182 break;
01183 case INDEXEDA_GIMAGE:
01184 if (xcf_image.image.depth() <= 8)
01185 copy = copyIndexedAToIndexed;
01186 else
01187 copy = copyIndexedAToRGB;
01188 }
01189
01190 if (!copy) {
01191 return;
01192 }
01193
01194
01195
01196 for (uint j = 0; j < layer.nrows; j++) {
01197 uint y = j * TILE_HEIGHT;
01198
01199 for (uint i = 0; i < layer.ncols; i++) {
01200 uint x = i * TILE_WIDTH;
01201
01202
01203
01204
01205
01206
01207 if (layer.mode == DISSOLVE_MODE) {
01208 if (layer.type == RGBA_GIMAGE)
01209 dissolveRGBPixels(layer.image_tiles[j][i], x, y);
01210
01211 else if (layer.type == GRAYA_GIMAGE)
01212 dissolveAlphaPixels(layer.alpha_tiles[j][i], x, y);
01213 }
01214
01215 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
01216 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
01217
01218 int m = x + k + layer.x_offset;
01219 int n = y + l + layer.y_offset;
01220
01221 if (m < 0 || m >= image.width() || n < 0 || n >= image.height())
01222 continue;
01223
01224 (*copy)(layer, i, j, k, l, image, m, n);
01225 }
01226 }
01227 }
01228 }
01229 }
01230
01231
01245 void XCFImageFormat::copyRGBToRGB(Layer& layer, uint i, uint j, int k, int l,
01246 QImage& image, int m, int n)
01247 {
01248 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01249 uchar src_a = layer.opacity;
01250
01251 if (layer.type == RGBA_GIMAGE)
01252 src_a = INT_MULT(src_a, qAlpha(src));
01253
01254
01255
01256 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
01257 layer.mask_tiles[j].size() > (int)i)
01258 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01259
01260 image.setPixel(m, n, qRgba(src, src_a));
01261 }
01262
01263
01275 void XCFImageFormat::copyGrayToGray(Layer& layer, uint i, uint j, int k, int l,
01276 QImage& image, int m, int n)
01277 {
01278 int src = layer.image_tiles[j][i].pixelIndex(k, l);
01279 image.setPixel(m, n, src);
01280 }
01281
01282
01296 void XCFImageFormat::copyGrayToRGB(Layer& layer, uint i, uint j, int k, int l,
01297 QImage& image, int m, int n)
01298 {
01299 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01300 uchar src_a = layer.opacity;
01301 image.setPixel(m, n, qRgba(src, src_a));
01302 }
01303
01304
01318 void XCFImageFormat::copyGrayAToRGB(Layer& layer, uint i, uint j, int k, int l,
01319 QImage& image, int m, int n)
01320 {
01321 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01322 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
01323 src_a = INT_MULT(src_a, layer.opacity);
01324
01325
01326
01327 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
01328 layer.mask_tiles[j].size() > (int)i)
01329 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01330
01331 image.setPixel(m, n, qRgba(src, src_a));
01332 }
01333
01334
01346 void XCFImageFormat::copyIndexedToIndexed(Layer& layer, uint i, uint j, int k, int l,
01347 QImage& image, int m, int n)
01348 {
01349 int src = layer.image_tiles[j][i].pixelIndex(k, l);
01350 image.setPixel(m, n, src);
01351 }
01352
01353
01365 void XCFImageFormat::copyIndexedAToIndexed(Layer& layer, uint i, uint j, int k, int l,
01366 QImage& image, int m, int n)
01367 {
01368 uchar src = layer.image_tiles[j][i].pixelIndex(k, l);
01369 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
01370 src_a = INT_MULT(src_a, layer.opacity);
01371
01372 if (layer.apply_mask == 1 &&
01373 layer.mask_tiles.size() > (int)j &&
01374 layer.mask_tiles[j].size() > (int)i)
01375 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01376
01377 if (src_a > 127)
01378 src++;
01379 else
01380 src = 0;
01381
01382 image.setPixel(m, n, src);
01383 }
01384
01385
01399 void XCFImageFormat::copyIndexedAToRGB(Layer& layer, uint i, uint j, int k, int l,
01400 QImage& image, int m, int n)
01401 {
01402 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01403 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
01404 src_a = INT_MULT(src_a, layer.opacity);
01405
01406
01407 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
01408 layer.mask_tiles[j].size() > (int)i)
01409 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01410
01411
01412 if (src_a <= 127)
01413 src_a = 0;
01414 else
01415 src_a = OPAQUE_OPACITY;
01416
01417 image.setPixel(m, n, qRgba(src, src_a));
01418 }
01419
01420
01425 void XCFImageFormat::mergeLayerIntoImage(XCFImage& xcf_image)
01426 {
01427 Layer& layer(xcf_image.layer);
01428 QImage& image(xcf_image.image);
01429
01430 PixelMergeOperation merge = 0;
01431
01432 if (!layer.opacity) return;
01433
01434 switch (layer.type) {
01435 case RGB_GIMAGE:
01436 case RGBA_GIMAGE:
01437 merge = mergeRGBToRGB;
01438 break;
01439 case GRAY_GIMAGE:
01440 if (layer.opacity == OPAQUE_OPACITY)
01441 merge = mergeGrayToGray;
01442 else
01443 merge = mergeGrayToRGB;
01444 break;
01445 case GRAYA_GIMAGE:
01446 if (xcf_image.image.depth() <= 8)
01447 merge = mergeGrayAToGray;
01448 else
01449 merge = mergeGrayAToRGB;
01450 break;
01451 case INDEXED_GIMAGE:
01452 merge = mergeIndexedToIndexed;
01453 break;
01454 case INDEXEDA_GIMAGE:
01455 if (xcf_image.image.depth() <= 8)
01456 merge = mergeIndexedAToIndexed;
01457 else
01458 merge = mergeIndexedAToRGB;
01459 }
01460
01461 if (!merge) {
01462 return;
01463 }
01464
01465 for (uint j = 0; j < layer.nrows; j++) {
01466 uint y = j * TILE_HEIGHT;
01467
01468 for (uint i = 0; i < layer.ncols; i++) {
01469 uint x = i * TILE_WIDTH;
01470
01471
01472
01473
01474
01475
01476 if (layer.mode == DISSOLVE_MODE) {
01477 if (layer.type == RGBA_GIMAGE)
01478 dissolveRGBPixels(layer.image_tiles[j][i], x, y);
01479
01480 else if (layer.type == GRAYA_GIMAGE)
01481 dissolveAlphaPixels(layer.alpha_tiles[j][i], x, y);
01482 }
01483
01484 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
01485 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
01486
01487 int m = x + k + layer.x_offset;
01488 int n = y + l + layer.y_offset;
01489
01490 if (m < 0 || m >= image.width() || n < 0 || n >= image.height())
01491 continue;
01492
01493 (*merge)(layer, i, j, k, l, image, m, n);
01494 }
01495 }
01496 }
01497 }
01498 }
01499
01500
01514 void XCFImageFormat::mergeRGBToRGB(Layer& layer, uint i, uint j, int k, int l,
01515 QImage& image, int m, int n)
01516 {
01517 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01518 QRgb dst = image.pixel(m, n);
01519
01520 uchar src_r = qRed(src);
01521 uchar src_g = qGreen(src);
01522 uchar src_b = qBlue(src);
01523 uchar src_a = qAlpha(src);
01524
01525 uchar dst_r = qRed(dst);
01526 uchar dst_g = qGreen(dst);
01527 uchar dst_b = qBlue(dst);
01528 uchar dst_a = qAlpha(dst);
01529
01530 if (!src_a) return;
01531
01532 switch (layer.mode) {
01533 case MULTIPLY_MODE: {
01534 src_r = INT_MULT(src_r, dst_r);
01535 src_g = INT_MULT(src_g, dst_g);
01536 src_b = INT_MULT(src_b, dst_b);
01537 src_a = qMin(src_a, dst_a);
01538 }
01539 break;
01540 case DIVIDE_MODE: {
01541 src_r = qMin((dst_r * 256) / (1 + src_r), 255);
01542 src_g = qMin((dst_g * 256) / (1 + src_g), 255);
01543 src_b = qMin((dst_b * 256) / (1 + src_b), 255);
01544 src_a = qMin(src_a, dst_a);
01545 }
01546 break;
01547 case SCREEN_MODE: {
01548 src_r = 255 - INT_MULT(255 - dst_r, 255 - src_r);
01549 src_g = 255 - INT_MULT(255 - dst_g, 255 - src_g);
01550 src_b = 255 - INT_MULT(255 - dst_b, 255 - src_b);
01551 src_a = qMin(src_a, dst_a);
01552 }
01553 break;
01554 case OVERLAY_MODE: {
01555 src_r = INT_MULT(dst_r, dst_r + INT_MULT(2 * src_r, 255 - dst_r));
01556 src_g = INT_MULT(dst_g, dst_g + INT_MULT(2 * src_g, 255 - dst_g));
01557 src_b = INT_MULT(dst_b, dst_b + INT_MULT(2 * src_b, 255 - dst_b));
01558 src_a = qMin(src_a, dst_a);
01559 }
01560 break;
01561 case DIFFERENCE_MODE: {
01562 src_r = dst_r > src_r ? dst_r - src_r : src_r - dst_r;
01563 src_g = dst_g > src_g ? dst_g - src_g : src_g - dst_g;
01564 src_b = dst_b > src_b ? dst_b - src_b : src_b - dst_b;
01565 src_a = qMin(src_a, dst_a);
01566 }
01567 break;
01568 case ADDITION_MODE: {
01569 src_r = add_lut(dst_r,src_r);
01570 src_g = add_lut(dst_g,src_g);
01571 src_b = add_lut(dst_b,src_b);
01572 src_a = qMin(src_a, dst_a);
01573 }
01574 break;
01575 case SUBTRACT_MODE: {
01576 src_r = dst_r > src_r ? dst_r - src_r : 0;
01577 src_g = dst_g > src_g ? dst_g - src_g : 0;
01578 src_b = dst_b > src_b ? dst_b - src_b : 0;
01579 src_a = qMin(src_a, dst_a);
01580 }
01581 break;
01582 case DARKEN_ONLY_MODE: {
01583 src_r = dst_r < src_r ? dst_r : src_r;
01584 src_g = dst_g < src_g ? dst_g : src_g;
01585 src_b = dst_b < src_b ? dst_b : src_b;
01586 src_a = qMin( src_a, dst_a );
01587 }
01588 break;
01589 case LIGHTEN_ONLY_MODE: {
01590 src_r = dst_r < src_r ? src_r : dst_r;
01591 src_g = dst_g < src_g ? src_g : dst_g;
01592 src_b = dst_b < src_b ? src_b : dst_b;
01593 src_a = qMin(src_a, dst_a);
01594 }
01595 break;
01596 case HUE_MODE: {
01597 uchar new_r = dst_r;
01598 uchar new_g = dst_g;
01599 uchar new_b = dst_b;
01600
01601 RGBTOHSV(src_r, src_g, src_b);
01602 RGBTOHSV(new_r, new_g, new_b);
01603
01604 new_r = src_r;
01605
01606 HSVTORGB(new_r, new_g, new_b);
01607
01608 src_r = new_r;
01609 src_g = new_g;
01610 src_b = new_b;
01611 src_a = qMin( src_a, dst_a );
01612 }
01613 break;
01614 case SATURATION_MODE: {
01615 uchar new_r = dst_r;
01616 uchar new_g = dst_g;
01617 uchar new_b = dst_b;
01618
01619 RGBTOHSV(src_r, src_g, src_b);
01620 RGBTOHSV(new_r, new_g, new_b);
01621
01622 new_g = src_g;
01623
01624 HSVTORGB(new_r, new_g, new_b);
01625
01626 src_r = new_r;
01627 src_g = new_g;
01628 src_b = new_b;
01629 src_a = qMin(src_a, dst_a);
01630 }
01631 break;
01632 case VALUE_MODE: {
01633 uchar new_r = dst_r;
01634 uchar new_g = dst_g;
01635 uchar new_b = dst_b;
01636
01637 RGBTOHSV(src_r, src_g, src_b);
01638 RGBTOHSV(new_r, new_g, new_b);
01639
01640 new_b = src_b;
01641
01642 HSVTORGB(new_r, new_g, new_b);
01643
01644 src_r = new_r;
01645 src_g = new_g;
01646 src_b = new_b;
01647 src_a = qMin(src_a, dst_a);
01648 }
01649 break;
01650 case COLOR_MODE: {
01651 uchar new_r = dst_r;
01652 uchar new_g = dst_g;
01653 uchar new_b = dst_b;
01654
01655 RGBTOHLS(src_r, src_g, src_b);
01656 RGBTOHLS(new_r, new_g, new_b);
01657
01658 new_r = src_r;
01659 new_b = src_b;
01660
01661 HLSTORGB(new_r, new_g, new_b);
01662
01663 src_r = new_r;
01664 src_g = new_g;
01665 src_b = new_b;
01666 src_a = qMin(src_a, dst_a);
01667 }
01668 break;
01669 case DODGE_MODE: {
01670 uint tmp;
01671
01672 tmp = dst_r << 8;
01673 tmp /= 256 - src_r;
01674 src_r = (uchar) qMin(tmp, 255u);
01675
01676 tmp = dst_g << 8;
01677 tmp /= 256 - src_g;
01678 src_g = (uchar) qMin(tmp, 255u);
01679
01680 tmp = dst_b << 8;
01681 tmp /= 256 - src_b;
01682 src_b = (uchar) qMin(tmp, 255u);
01683
01684 src_a = qMin(src_a, dst_a);
01685 }
01686 break;
01687 case BURN_MODE: {
01688 uint tmp;
01689
01690 tmp = (255 - dst_r) << 8;
01691 tmp /= src_r + 1;
01692 src_r = (uchar) qMin(tmp, 255u);
01693 src_r = 255 - src_r;
01694
01695 tmp = (255 - dst_g) << 8;
01696 tmp /= src_g + 1;
01697 src_g = (uchar) qMin(tmp, 255u);
01698 src_g = 255 - src_g;
01699
01700 tmp = (255 - dst_b) << 8;
01701 tmp /= src_b + 1;
01702 src_b = (uchar) qMin(tmp, 255u);
01703 src_b = 255 - src_b;
01704
01705 src_a = qMin(src_a, dst_a);
01706 }
01707 break;
01708 case HARDLIGHT_MODE: {
01709 uint tmp;
01710 if (src_r > 128) {
01711 tmp = ((int)255-dst_r) * ((int) 255 - ((src_r-128) << 1));
01712 src_r = (uchar) qMin(255 - (tmp >> 8), 255u);
01713 } else {
01714 tmp = (int) dst_r * ((int) src_r << 1);
01715 src_r = (uchar) qMin(tmp >> 8, 255u);
01716 }
01717
01718 if (src_g > 128) {
01719 tmp = ((int)255-dst_g) * ((int) 255 - ((src_g-128) << 1));
01720 src_g = (uchar) qMin(255 - (tmp >> 8), 255u);
01721 } else {
01722 tmp = (int) dst_g * ((int) src_g << 1);
01723 src_g = (uchar) qMin(tmp >> 8, 255u);
01724 }
01725
01726 if (src_b > 128) {
01727 tmp = ((int)255-dst_b) * ((int) 255 - ((src_b-128) << 1));
01728 src_b = (uchar) qMin(255 - (tmp >> 8), 255u);
01729 } else {
01730 tmp = (int) dst_b * ((int) src_b << 1);
01731 src_b = (uchar) qMin(tmp >> 8, 255u);
01732 }
01733 src_a = qMin(src_a, dst_a);
01734 }
01735 break;
01736 case SOFTLIGHT_MODE: {
01737 uint tmpS, tmpM;
01738
01739 tmpM = INT_MULT(dst_r, src_r);
01740 tmpS = 255 - INT_MULT((255 - dst_r), (255-src_r));
01741 src_r = INT_MULT((255 - dst_r), tmpM)
01742 + INT_MULT(dst_r, tmpS);
01743
01744 tmpM = INT_MULT(dst_g, src_g);
01745 tmpS = 255 - INT_MULT((255 - dst_g), (255-src_g));
01746 src_g = INT_MULT((255 - dst_g), tmpM)
01747 + INT_MULT(dst_g, tmpS);
01748
01749 tmpM = INT_MULT(dst_b, src_b);
01750 tmpS = 255 - INT_MULT((255 - dst_b), (255-src_b));
01751 src_b = INT_MULT((255 - dst_b), tmpM)
01752 + INT_MULT(dst_b, tmpS);
01753
01754 src_a = qMin(src_a, dst_a);
01755 }
01756 break;
01757 case GRAIN_EXTRACT_MODE: {
01758 int tmp;
01759
01760 tmp = dst_r - src_r + 128;
01761 tmp = qMin(tmp, 255);
01762 tmp = qMax(tmp, 0);
01763 src_r = (uchar) tmp;
01764
01765 tmp = dst_g - src_g + 128;
01766 tmp = qMin(tmp, 255);
01767 tmp = qMax(tmp, 0);
01768 src_g = (uchar) tmp;
01769
01770 tmp = dst_b - src_b + 128;
01771 tmp = qMin(tmp, 255);
01772 tmp = qMax(tmp, 0);
01773 src_b = (uchar) tmp;
01774
01775 src_a = qMin(src_a, dst_a);
01776 }
01777 break;
01778 case GRAIN_MERGE_MODE: {
01779 int tmp;
01780
01781 tmp = dst_r + src_r - 128;
01782 tmp = qMin(tmp, 255);
01783 tmp = qMax(tmp, 0);
01784 src_r = (uchar) tmp;
01785
01786 tmp = dst_g + src_g - 128;
01787 tmp = qMin(tmp, 255);
01788 tmp = qMax(tmp, 0);
01789 src_g = (uchar) tmp;
01790
01791 tmp = dst_b + src_b - 128;
01792 tmp = qMin(tmp, 255);
01793 tmp = qMax(tmp, 0);
01794 src_b = (uchar) tmp;
01795
01796 src_a = qMin(src_a, dst_a);
01797 }
01798 break;
01799 }
01800
01801 src_a = INT_MULT(src_a, layer.opacity);
01802
01803
01804
01805 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
01806 layer.mask_tiles[j].size() > (int)i)
01807 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01808
01809 uchar new_r, new_g, new_b, new_a;
01810 new_a = dst_a + INT_MULT(OPAQUE_OPACITY - dst_a, src_a);
01811
01812 float src_ratio = (float)src_a / new_a;
01813 float dst_ratio = 1.0 - src_ratio;
01814
01815 new_r = (uchar)(src_ratio * src_r + dst_ratio * dst_r + EPSILON);
01816 new_g = (uchar)(src_ratio * src_g + dst_ratio * dst_g + EPSILON);
01817 new_b = (uchar)(src_ratio * src_b + dst_ratio * dst_b + EPSILON);
01818
01819 if (!layer_modes[layer.mode].affect_alpha)
01820 new_a = dst_a;
01821
01822 image.setPixel(m, n, qRgba(new_r, new_g, new_b, new_a));
01823 }
01824
01825
01837 void XCFImageFormat::mergeGrayToGray(Layer& layer, uint i, uint j, int k, int l,
01838 QImage& image, int m, int n)
01839 {
01840 int src = layer.image_tiles[j][i].pixelIndex(k, l);
01841 image.setPixel(m, n, src);
01842 }
01843
01844
01856 void XCFImageFormat::mergeGrayAToGray(Layer& layer, uint i, uint j, int k, int l,
01857 QImage& image, int m, int n)
01858 {
01859 int src = qGray(layer.image_tiles[j][i].pixel(k, l));
01860 int dst = image.pixelIndex(m, n);
01861
01862 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
01863
01864 if (!src_a) return;
01865
01866 switch (layer.mode) {
01867 case MULTIPLY_MODE: {
01868 src = INT_MULT( src, dst );
01869 }
01870 break;
01871 case DIVIDE_MODE: {
01872 src = qMin((dst * 256) / (1 + src), 255);
01873 }
01874 break;
01875 case SCREEN_MODE: {
01876 src = 255 - INT_MULT(255 - dst, 255 - src);
01877 }
01878 break;
01879 case OVERLAY_MODE: {
01880 src = INT_MULT(dst, dst + INT_MULT(2 * src, 255 - dst));
01881 }
01882 break;
01883 case DIFFERENCE_MODE: {
01884 src = dst > src ? dst - src : src - dst;
01885 }
01886 break;
01887 case ADDITION_MODE: {
01888 src = add_lut(dst,src);
01889 }
01890 break;
01891 case SUBTRACT_MODE: {
01892 src = dst > src ? dst - src : 0;
01893 }
01894 break;
01895 case DARKEN_ONLY_MODE: {
01896 src = dst < src ? dst : src;
01897 }
01898 break;
01899 case LIGHTEN_ONLY_MODE: {
01900 src = dst < src ? src : dst;
01901 }
01902 break;
01903 case DODGE_MODE: {
01904 uint tmp = dst << 8;
01905 tmp /= 256 - src;
01906 src = (uchar) qMin(tmp, 255u);
01907 }
01908 break;
01909 case BURN_MODE: {
01910 uint tmp = (255-dst) << 8;
01911 tmp /= src + 1;
01912 src = (uchar) qMin(tmp, 255u);
01913 src = 255 - src;
01914 }
01915 break;
01916 case HARDLIGHT_MODE: {
01917 uint tmp;
01918 if (src > 128) {
01919 tmp = ((int)255-dst) * ((int) 255 - ((src-128) << 1));
01920 src = (uchar) qMin(255 - (tmp >> 8), 255u);
01921 } else {
01922 tmp = (int) dst * ((int) src << 1);
01923 src = (uchar) qMin(tmp >> 8, 255u);
01924 }
01925 }
01926 break;
01927 case SOFTLIGHT_MODE: {
01928 uint tmpS, tmpM;
01929
01930 tmpM = INT_MULT(dst, src);
01931 tmpS = 255 - INT_MULT((255-dst), (255-src));
01932 src = INT_MULT((255 - dst), tmpM)
01933 + INT_MULT(dst, tmpS);
01934
01935 }
01936 break;
01937 case GRAIN_EXTRACT_MODE: {
01938 int tmp;
01939
01940 tmp = dst - src + 128;
01941 tmp = qMin(tmp, 255);
01942 tmp = qMax(tmp, 0);
01943
01944 src = (uchar) tmp;
01945 }
01946 break;
01947 case GRAIN_MERGE_MODE: {
01948 int tmp;
01949
01950 tmp = dst + src - 128;
01951 tmp = qMin(tmp, 255);
01952 tmp = qMax(tmp, 0);
01953
01954 src = (uchar) tmp;
01955 }
01956 break;
01957 }
01958
01959 src_a = INT_MULT(src_a, layer.opacity);
01960
01961
01962
01963 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
01964 layer.mask_tiles[j].size() > (int)i)
01965 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01966
01967 uchar new_a = OPAQUE_OPACITY;
01968
01969 float src_ratio = (float)src_a / new_a;
01970 float dst_ratio = 1.0 - src_ratio;
01971
01972 uchar new_g = (uchar)(src_ratio * src + dst_ratio * dst + EPSILON);
01973
01974 image.setPixel(m, n, new_g);
01975 }
01976
01977
01991 void XCFImageFormat::mergeGrayToRGB(Layer& layer, uint i, uint j, int k, int l,
01992 QImage& image, int m, int n)
01993 {
01994 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01995 uchar src_a = layer.opacity;
01996 image.setPixel(m, n, qRgba(src, src_a));
01997 }
01998
01999
02013 void XCFImageFormat::mergeGrayAToRGB(Layer& layer, uint i, uint j, int k, int l,
02014 QImage& image, int m, int n)
02015 {
02016 int src = qGray(layer.image_tiles[j][i].pixel(k, l));
02017 int dst = qGray(image.pixel(m, n));
02018
02019 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
02020 uchar dst_a = qAlpha(image.pixel(m, n));
02021
02022 if (!src_a) return;
02023
02024 switch (layer.mode) {
02025 case MULTIPLY_MODE: {
02026 src = INT_MULT(src, dst);
02027 src_a = qMin(src_a, dst_a);
02028 }
02029 break;
02030 case DIVIDE_MODE: {
02031 src = qMin((dst * 256) / (1 + src), 255);
02032 src_a = qMin(src_a, dst_a);
02033 }
02034 break;
02035 case SCREEN_MODE: {
02036 src = 255 - INT_MULT(255 - dst, 255 - src);
02037 src_a = qMin(src_a, dst_a);
02038 }
02039 break;
02040 case OVERLAY_MODE: {
02041 src = INT_MULT( dst, dst + INT_MULT(2 * src, 255 - dst));
02042 src_a = qMin(src_a, dst_a);
02043 }
02044 break;
02045 case DIFFERENCE_MODE: {
02046 src = dst > src ? dst - src : src - dst;
02047 src_a = qMin(src_a, dst_a);
02048 }
02049 break;
02050 case ADDITION_MODE: {
02051 src = add_lut(dst,src);
02052 src_a = qMin(src_a, dst_a);
02053 }
02054 break;
02055 case SUBTRACT_MODE: {
02056 src = dst > src ? dst - src : 0;
02057 src_a = qMin(src_a, dst_a);
02058 }
02059 break;
02060 case DARKEN_ONLY_MODE: {
02061 src = dst < src ? dst : src;
02062 src_a = qMin(src_a, dst_a);
02063 }
02064 break;
02065 case LIGHTEN_ONLY_MODE: {
02066 src = dst < src ? src : dst;
02067 src_a = qMin(src_a, dst_a);
02068 }
02069 break;
02070 case DODGE_MODE: {
02071 uint tmp = dst << 8;
02072 tmp /= 256 - src;
02073 src = (uchar) qMin(tmp, 255u);
02074 src_a = qMin(src_a, dst_a);
02075 }
02076 break;
02077 case BURN_MODE: {
02078 uint tmp = (255-dst) << 8;
02079 tmp /= src + 1;
02080 src = (uchar) qMin(tmp, 255u);
02081 src = 255 - src;
02082 src_a = qMin(src_a, dst_a);
02083 }
02084 break;
02085 case HARDLIGHT_MODE: {
02086 uint tmp;
02087 if (src > 128) {
02088 tmp = ((int)255-dst) * ((int) 255 - ((src-128) << 1));
02089 src = (uchar) qMin(255 - (tmp >> 8), 255u);
02090 } else {
02091 tmp = (int) dst * ((int) src << 1);
02092 src = (uchar) qMin(tmp >> 8, 255u);
02093 }
02094 src_a = qMin(src_a, dst_a);
02095 }
02096 break;
02097 case SOFTLIGHT_MODE: {
02098 uint tmpS, tmpM;
02099
02100 tmpM = INT_MULT(dst, src);
02101 tmpS = 255 - INT_MULT((255 - dst), (255-src));
02102 src = INT_MULT((255 - dst), tmpM)
02103 + INT_MULT(dst, tmpS);
02104
02105 src_a = qMin(src_a, dst_a);
02106 }
02107 break;
02108 case GRAIN_EXTRACT_MODE: {
02109 int tmp;
02110
02111 tmp = dst - src + 128;
02112 tmp = qMin(tmp, 255);
02113 tmp = qMax(tmp, 0);
02114
02115 src = (uchar) tmp;
02116 src_a = qMin(src_a, dst_a);
02117 }
02118 break;
02119 case GRAIN_MERGE_MODE: {
02120 int tmp;
02121
02122 tmp = dst + src - 128;
02123 tmp = qMin(tmp, 255);
02124 tmp = qMax(tmp, 0);
02125
02126 src = (uchar) tmp;
02127 src_a = qMin(src_a, dst_a);
02128 }
02129 break;
02130 }
02131
02132 src_a = INT_MULT(src_a, layer.opacity);
02133
02134
02135 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
02136 layer.mask_tiles[j].size() > (int)i)
02137 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
02138
02139 uchar new_a = dst_a + INT_MULT(OPAQUE_OPACITY - dst_a, src_a);
02140
02141 float src_ratio = (float)src_a / new_a;
02142 float dst_ratio = 1.0 - src_ratio;
02143
02144 uchar new_g = (uchar)(src_ratio * src + dst_ratio * dst + EPSILON);
02145
02146 if (!layer_modes[layer.mode].affect_alpha)
02147 new_a = dst_a;
02148
02149 image.setPixel(m, n, qRgba(new_g, new_g, new_g, new_a));
02150 }
02151
02152
02164 void XCFImageFormat::mergeIndexedToIndexed(Layer& layer, uint i, uint j, int k, int l,
02165 QImage& image, int m, int n)
02166 {
02167 int src = layer.image_tiles[j][i].pixelIndex(k, l);
02168 image.setPixel(m, n, src);
02169 }
02170
02171
02183 void XCFImageFormat::mergeIndexedAToIndexed(Layer& layer, uint i, uint j, int k, int l,
02184 QImage& image, int m, int n)
02185 {
02186 uchar src = layer.image_tiles[j][i].pixelIndex(k, l);
02187 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
02188 src_a = INT_MULT( src_a, layer.opacity );
02189
02190 if ( layer.apply_mask == 1 &&
02191 layer.mask_tiles.size() > (int)j &&
02192 layer.mask_tiles[j].size() > (int)i)
02193 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
02194
02195 if (src_a > 127) {
02196 src++;
02197 image.setPixel(m, n, src);
02198 }
02199 }
02200
02201
02215 void XCFImageFormat::mergeIndexedAToRGB(Layer& layer, uint i, uint j, int k, int l,
02216 QImage& image, int m, int n)
02217 {
02218 QRgb src = layer.image_tiles[j][i].pixel(k, l);
02219 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
02220 src_a = INT_MULT(src_a, layer.opacity);
02221
02222
02223 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
02224 layer.mask_tiles[j].size() > (int)i)
02225 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
02226
02227
02228 if (src_a <= 127)
02229 src_a = 0;
02230 else
02231 src_a = OPAQUE_OPACITY;
02232
02233 image.setPixel(m, n, qRgba(src, src_a));
02234 }
02235
02236
02244 void XCFImageFormat::dissolveRGBPixels ( QImage& image, int x, int y )
02245 {
02246
02247
02248
02249 for (int l = 0; l < image.height(); l++) {
02250 srand(random_table[( l + y ) % RANDOM_TABLE_SIZE]);
02251
02252 for (int k = 0; k < x; k++)
02253 rand();
02254
02255 for (int k = 0; k < image.width(); k++) {
02256 int rand_val = rand() & 0xff;
02257 QRgb pixel = image.pixel(k, l);
02258
02259 if (rand_val > qAlpha(pixel)) {
02260 image.setPixel(k, l, qRgba(pixel, 0));
02261 }
02262 }
02263 }
02264 }
02265
02266
02276 void XCFImageFormat::dissolveAlphaPixels ( QImage& image, int x, int y )
02277 {
02278
02279
02280
02281 for (int l = 0; l < image.height(); l++) {
02282 srand( random_table[(l + y) % RANDOM_TABLE_SIZE]);
02283
02284 for (int k = 0; k < x; k++)
02285 rand();
02286
02287 for (int k = 0; k < image.width(); k++) {
02288 int rand_val = rand() & 0xff;
02289 uchar alpha = image.pixelIndex(k, l);
02290
02291 if (rand_val > alpha) {
02292 image.setPixel(k, l, 0);
02293 }
02294 }
02295 }
02296 }
02297
02298
02300
02301 XCFHandler::XCFHandler()
02302 {
02303 }
02304
02305 bool XCFHandler::canRead() const
02306 {
02307 if (canRead(device())) {
02308 setFormat("xcf");
02309 return true;
02310 }
02311 return false;
02312 }
02313
02314 bool XCFHandler::read(QImage *image)
02315 {
02316 XCFImageFormat xcfif;
02317 return xcfif.readXCF(device(), image);
02318 }
02319
02320 bool XCFHandler::write(const QImage &)
02321 {
02322 return false;
02323 }
02324
02325 QByteArray XCFHandler::name() const
02326 {
02327 return "xcf";
02328 }
02329
02330 bool XCFHandler::canRead(QIODevice *device)
02331 {
02332 if (!device) {
02333 qWarning("DDSHandler::canRead() called with no device");
02334 return false;
02335 }
02336
02337 qint64 oldPos = device->pos();
02338
02339 char head[8];
02340 qint64 readBytes = device->read(head, sizeof(head));
02341 if (readBytes != sizeof(head)) {
02342 if (device->isSequential()) {
02343 while (readBytes > 0)
02344 device->ungetChar(head[readBytes-- - 1]);
02345 } else {
02346 device->seek(oldPos);
02347 }
02348 return false;
02349 }
02350
02351 if (device->isSequential()) {
02352 while (readBytes > 0)
02353 device->ungetChar(head[readBytes-- - 1]);
02354 } else {
02355 device->seek(oldPos);
02356 }
02357
02358 return qstrncmp(head, "gimp xcf", 8) == 0;
02359 }
02360
02361
02362 class XCFPlugin : public QImageIOPlugin
02363 {
02364 public:
02365 QStringList keys() const;
02366 Capabilities capabilities(QIODevice *device, const QByteArray &format) const;
02367 QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const;
02368 };
02369
02370 QStringList XCFPlugin::keys() const
02371 {
02372 return QStringList() << "xcf" << "XCF";
02373 }
02374
02375 QImageIOPlugin::Capabilities XCFPlugin::capabilities(QIODevice *device, const QByteArray &format) const
02376 {
02377 if (format == "xcf" || format == "XCF")
02378 return Capabilities(CanRead);
02379 if (!format.isEmpty())
02380 return 0;
02381 if (!device->isOpen())
02382 return 0;
02383
02384 Capabilities cap;
02385 if (device->isReadable() && XCFHandler::canRead(device))
02386 cap |= CanRead;
02387 return cap;
02388 }
02389
02390 QImageIOHandler *XCFPlugin::create(QIODevice *device, const QByteArray &format) const
02391 {
02392 QImageIOHandler *handler = new XCFHandler;
02393 handler->setDevice(device);
02394 handler->setFormat(format);
02395 return handler;
02396 }
02397
02398 Q_EXPORT_STATIC_PLUGIN(XCFPlugin)
02399 Q_EXPORT_PLUGIN2(xcf,XCFPlugin)