00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <stdlib.h>
00023 #include <qimage.h>
00024 #include <qiodevice.h>
00025 #include <qvaluestack.h>
00026 #include <qvaluevector.h>
00027
00028 #include <kdebug.h>
00029 #include "xcf.h"
00030
00031
00033
00034
00035 KDE_EXPORT void kimgio_xcf_read(QImageIO *io)
00036 {
00037 XCFImageFormat xcfif;
00038 xcfif.readXCF(io);
00039 }
00040
00041
00042 KDE_EXPORT void kimgio_xcf_write(QImageIO *io)
00043 {
00044 kdDebug(399) << "XCF: write support not implemented" << endl;
00045 io->setStatus(-1);
00046 }
00047
00049
00050
00051
00052 int XCFImageFormat::random_table[RANDOM_TABLE_SIZE];
00053
00054
00055
00056
00057 const XCFImageFormat::LayerModes XCFImageFormat::layer_modes[] = {
00058 {true},
00059 {true},
00060 {true},
00061 {false},
00062 {false},
00063 {false},
00064 {false},
00065 {false},
00066 {false},
00067 {false},
00068 {false},
00069 {false},
00070 {false},
00071 {false},
00072 {false},
00073 {false},
00074 {true},
00075 {true},
00076 {true},
00077 };
00078
00079
00081 inline QRgb qRgba ( QRgb rgb, int a )
00082 {
00083 return ((a & 0xff) << 24 | (rgb & RGB_MASK));
00084 }
00085
00086
00091 XCFImageFormat::XCFImageFormat()
00092 {
00093
00094 srand(RANDOM_SEED);
00095
00096 for (int i = 0; i < RANDOM_TABLE_SIZE; i++)
00097 random_table[i] = rand();
00098
00099 for (int i = 0; i < RANDOM_TABLE_SIZE; i++) {
00100 int tmp;
00101 int swap = i + rand() % (RANDOM_TABLE_SIZE - i);
00102 tmp = random_table[i];
00103 random_table[i] = random_table[swap];
00104 random_table[swap] = tmp;
00105 }
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 }
00116
00117 inline
00118 int XCFImageFormat::add_lut( int a, int b ) {
00119 return QMIN( a + b, 255 );
00120 }
00121
00122 void XCFImageFormat::readXCF(QImageIO *io)
00123 {
00124 XCFImage xcf_image;
00125 QDataStream xcf_io(io->ioDevice());
00126
00127 char tag[14];
00128 xcf_io.readRawBytes(tag, sizeof(tag));
00129
00130 if (xcf_io.device()->status() != IO_Ok) {
00131 kdDebug(399) << "XCF: read failure on header tag" << endl;
00132 return;
00133 }
00134
00135 xcf_io >> xcf_image.width >> xcf_image.height >> xcf_image.type;
00136
00137 if (xcf_io.device()->status() != IO_Ok) {
00138 kdDebug(399) << "XCF: read failure on image info" << endl;
00139 return;
00140 }
00141
00142 kdDebug() << tag << " " << xcf_image.width << " " << xcf_image.height << " " << xcf_image.type << endl;
00143 if (!loadImageProperties(xcf_io, xcf_image))
00144 return;
00145
00146
00147
00148
00149
00150
00151
00152 QValueStack<Q_INT32> layer_offsets;
00153
00154 while (true) {
00155 Q_INT32 layer_offset;
00156
00157 xcf_io >> layer_offset;
00158
00159 if (xcf_io.device()->status() != IO_Ok) {
00160 kdDebug(399) << "XCF: read failure on layer offsets" << endl;
00161 return;
00162 }
00163
00164 if (layer_offset == 0)
00165 break;
00166
00167 layer_offsets.push(layer_offset);
00168 }
00169
00170 xcf_image.num_layers = layer_offsets.size();
00171
00172 if (layer_offsets.size() == 0) {
00173 kdDebug(399) << "XCF: no layers!" << endl;
00174 return;
00175 }
00176
00177
00178 while (!layer_offsets.isEmpty()) {
00179 Q_INT32 layer_offset = layer_offsets.pop();
00180
00181 xcf_io.device()->at(layer_offset);
00182
00183 if (!loadLayer(xcf_io, xcf_image))
00184 return;
00185 }
00186
00187 if (!xcf_image.initialized) {
00188 kdDebug(399) << "XCF: no visible layers!" << endl;
00189 return;
00190 }
00191
00192 io->setImage(xcf_image.image);
00193 io->setStatus(0);
00194 }
00195
00196
00204 bool XCFImageFormat::loadImageProperties(QDataStream& xcf_io, XCFImage& xcf_image)
00205 {
00206 while (true) {
00207 PropType type;
00208 QByteArray bytes;
00209
00210 if (!loadProperty(xcf_io, type, bytes)) {
00211 kdDebug(399) << "XCF: error loading global image properties" << endl;
00212 return false;
00213 }
00214
00215 QDataStream property(bytes, IO_ReadOnly);
00216
00217 switch (type) {
00218 case PROP_END:
00219 return true;
00220
00221 case PROP_COMPRESSION:
00222 property >> xcf_image.compression;
00223 break;
00224
00225 case PROP_RESOLUTION:
00226 property >> xcf_image.x_resolution >> xcf_image.y_resolution;
00227 break;
00228
00229 case PROP_TATTOO:
00230 property >> xcf_image.tattoo;
00231 break;
00232
00233 case PROP_PARASITES:
00234 while (!property.atEnd()) {
00235 char* tag;
00236 Q_UINT32 size;
00237
00238 property.readBytes(tag, size);
00239
00240 Q_UINT32 flags;
00241 char* data=0;
00242 property >> flags >> data;
00243
00244 if (tag && strncmp(tag, "gimp-comment", strlen("gimp-comment")) == 0)
00245 xcf_image.image.setText("Comment", 0, data);
00246
00247 delete[] tag;
00248 delete[] data;
00249 }
00250 break;
00251
00252 case PROP_UNIT:
00253 property >> xcf_image.unit;
00254 break;
00255
00256 case PROP_PATHS:
00257 break;
00258
00259 case PROP_USER_UNIT:
00260 break;
00261
00262 case PROP_COLORMAP:
00263 property >> xcf_image.num_colors;
00264 if(xcf_image.num_colors < 0 || xcf_image.num_colors > 65535)
00265 return false;
00266
00267 xcf_image.palette.reserve(xcf_image.num_colors);
00268
00269 for (int i = 0; i < xcf_image.num_colors; i++) {
00270 uchar r, g, b;
00271 property >> r >> g >> b;
00272 xcf_image.palette.push_back( qRgb(r,g,b) );
00273 }
00274 break;
00275
00276 default:
00277 kdDebug(399) << "XCF: unimplemented image property" << type
00278 << ", size " << bytes.size() << endl;
00279 }
00280 }
00281 }
00282
00283
00291 bool XCFImageFormat::loadProperty(QDataStream& xcf_io, PropType& type, QByteArray& bytes)
00292 {
00293 Q_UINT32 foo;
00294 xcf_io >> foo;
00295 type=PropType(foo);
00296
00297 if (xcf_io.device()->status() != IO_Ok) {
00298 kdDebug(399) << "XCF: read failure on property type" << type << endl;
00299 return false;
00300 }
00301
00302 char* data;
00303 Q_UINT32 size;
00304
00305
00306
00307
00308
00309 if (type == PROP_COLORMAP) {
00310 xcf_io >> size;
00311
00312 if (xcf_io.device()->status() != IO_Ok) {
00313 kdDebug(399) << "XCF: read failure on property " << type << " size" << endl;
00314 return false;
00315 }
00316
00317 if(size > 65535 || size < 4)
00318 return false;
00319
00320 size = 3 * (size - 4) + 4;
00321 data = new char[size];
00322
00323 xcf_io.readRawBytes(data, size);
00324 } else if (type == PROP_USER_UNIT) {
00325
00326 float factor;
00327 Q_INT32 digits;
00328 char* unit_strings;
00329
00330 xcf_io >> size >> factor >> digits;
00331
00332 if (xcf_io.device()->status() != IO_Ok) {
00333 kdDebug(399) << "XCF: read failure on property " << type << endl;
00334 return false;
00335 }
00336
00337 for (int i = 0; i < 5; i++) {
00338 xcf_io >> unit_strings;
00339
00340 if (xcf_io.device()->status() != IO_Ok) {
00341 kdDebug(399) << "XCF: read failure on property " << type << endl;
00342 return false;
00343 }
00344
00345 delete[] unit_strings;
00346 }
00347
00348 size = 0;
00349 } else {
00350 xcf_io >> size;
00351 if(size >256000)
00352 return false;
00353 data = new char[size];
00354 xcf_io.readRawBytes(data, size);
00355 }
00356
00357 if (xcf_io.device()->status() != IO_Ok) {
00358 kdDebug(399) << "XCF: read failure on property " << type << " data, size " << size << endl;
00359 return false;
00360 }
00361
00362 if (size != 0 && data) {
00363 bytes.assign(data,size);
00364 }
00365
00366 return true;
00367 }
00368
00369
00378 bool XCFImageFormat::loadLayer(QDataStream& xcf_io, XCFImage& xcf_image)
00379 {
00380 Layer& layer(xcf_image.layer);
00381 delete[] layer.name;
00382
00383 xcf_io >> layer.width >> layer.height >> layer.type >> layer.name;
00384
00385 if (xcf_io.device()->status() != IO_Ok) {
00386 kdDebug(399) << "XCF: read failure on layer" << endl;
00387 return false;
00388 }
00389
00390 if (!loadLayerProperties(xcf_io, layer))
00391 return false;
00392 #if 0
00393 cout << "layer: \"" << layer.name << "\", size: " << layer.width << " x "
00394 << layer.height << ", type: " << layer.type << ", mode: " << layer.mode
00395 << ", opacity: " << layer.opacity << ", visible: " << layer.visible
00396 << ", offset: " << layer.x_offset << ", " << layer.y_offset << endl;
00397 #endif
00398
00399
00400
00401
00402 if (layer.visible == 0)
00403 return true;
00404
00405
00406
00407 xcf_io >> layer.hierarchy_offset >> layer.mask_offset;
00408 if (xcf_io.device()->status() != IO_Ok) {
00409 kdDebug(399) << "XCF: read failure on layer image offsets" << endl;
00410 return false;
00411 }
00412
00413
00414
00415
00416 if( !composeTiles(xcf_image))
00417 return false;
00418 xcf_io.device()->at(layer.hierarchy_offset);
00419
00420
00421
00422
00423
00424 layer.assignBytes = assignImageBytes;
00425
00426 if (!loadHierarchy(xcf_io, layer))
00427 return false;
00428
00429 if (layer.mask_offset != 0) {
00430 xcf_io.device()->at(layer.mask_offset);
00431
00432 if (!loadMask(xcf_io, layer))
00433 return false;
00434 }
00435
00436
00437
00438
00439
00440 if (!xcf_image.initialized) {
00441 if( !initializeImage(xcf_image))
00442 return false;
00443 copyLayerToImage(xcf_image);
00444 xcf_image.initialized = true;
00445 } else
00446 mergeLayerIntoImage(xcf_image);
00447
00448 return true;
00449 }
00450
00451
00459 bool XCFImageFormat::loadLayerProperties(QDataStream& xcf_io, Layer& layer)
00460 {
00461 while (true) {
00462 PropType type;
00463 QByteArray bytes;
00464
00465 if (!loadProperty(xcf_io, type, bytes)) {
00466 kdDebug(399) << "XCF: error loading layer properties" << endl;
00467 return false;
00468 }
00469
00470 QDataStream property(bytes, IO_ReadOnly);
00471
00472 switch (type) {
00473 case PROP_END:
00474 return true;
00475
00476 case PROP_ACTIVE_LAYER:
00477 layer.active = true;
00478 break;
00479
00480 case PROP_OPACITY:
00481 property >> layer.opacity;
00482 break;
00483
00484 case PROP_VISIBLE:
00485 property >> layer.visible;
00486 break;
00487
00488 case PROP_LINKED:
00489 property >> layer.linked;
00490 break;
00491
00492 case PROP_PRESERVE_TRANSPARENCY:
00493 property >> layer.preserve_transparency;
00494 break;
00495
00496 case PROP_APPLY_MASK:
00497 property >> layer.apply_mask;
00498 break;
00499
00500 case PROP_EDIT_MASK:
00501 property >> layer.edit_mask;
00502 break;
00503
00504 case PROP_SHOW_MASK:
00505 property >> layer.show_mask;
00506 break;
00507
00508 case PROP_OFFSETS:
00509 property >> layer.x_offset >> layer.y_offset;
00510 break;
00511
00512 case PROP_MODE:
00513 property >> layer.mode;
00514 break;
00515
00516 case PROP_TATTOO:
00517 property >> layer.tattoo;
00518 break;
00519
00520 default:
00521 kdDebug(399) << "XCF: unimplemented layer property " << type
00522 << ", size " << bytes.size() << endl;
00523 }
00524 }
00525 }
00526
00527
00533 bool XCFImageFormat::composeTiles(XCFImage& xcf_image)
00534 {
00535 Layer& layer(xcf_image.layer);
00536
00537 layer.nrows = (layer.height + TILE_HEIGHT - 1) / TILE_HEIGHT;
00538 layer.ncols = (layer.width + TILE_WIDTH - 1) / TILE_WIDTH;
00539
00540 layer.image_tiles.resize(layer.nrows);
00541
00542 if (layer.type == GRAYA_GIMAGE || layer.type == INDEXEDA_GIMAGE)
00543 layer.alpha_tiles.resize(layer.nrows);
00544
00545 if (layer.mask_offset != 0)
00546 layer.mask_tiles.resize(layer.nrows);
00547
00548 for (uint j = 0; j < layer.nrows; j++) {
00549 layer.image_tiles[j].resize(layer.ncols);
00550
00551 if (layer.type == GRAYA_GIMAGE || layer.type == INDEXEDA_GIMAGE)
00552 layer.alpha_tiles[j].resize(layer.ncols);
00553
00554 if (layer.mask_offset != 0)
00555 layer.mask_tiles[j].resize(layer.ncols);
00556 }
00557
00558 for (uint j = 0; j < layer.nrows; j++) {
00559 for (uint i = 0; i < layer.ncols; i++) {
00560
00561 uint tile_width = (i + 1) * TILE_WIDTH <= layer.width
00562 ? TILE_WIDTH : layer.width - i * TILE_WIDTH;
00563
00564 uint tile_height = (j + 1) * TILE_HEIGHT <= layer.height
00565 ? TILE_HEIGHT : layer.height - j * TILE_HEIGHT;
00566
00567
00568
00569
00570 switch (layer.type) {
00571 case RGB_GIMAGE:
00572 layer.image_tiles[j][i] = QImage(tile_width, tile_height, 32, 0);
00573 if( layer.image_tiles[j][i].isNull())
00574 return false;
00575 layer.image_tiles[j][i].setAlphaBuffer(false);
00576 break;
00577
00578 case RGBA_GIMAGE:
00579 layer.image_tiles[j][i] = QImage(tile_width, tile_height, 32, 0);
00580 if( layer.image_tiles[j][i].isNull())
00581 return false;
00582 layer.image_tiles[j][i].setAlphaBuffer(true);
00583 break;
00584
00585 case GRAY_GIMAGE:
00586 layer.image_tiles[j][i] = QImage(tile_width, tile_height, 8, 256);
00587 if( layer.image_tiles[j][i].isNull())
00588 return false;
00589 setGrayPalette(layer.image_tiles[j][i]);
00590 break;
00591
00592 case GRAYA_GIMAGE:
00593 layer.image_tiles[j][i] = QImage(tile_width, tile_height, 8, 256);
00594 if( layer.image_tiles[j][i].isNull())
00595 return false;
00596 setGrayPalette(layer.image_tiles[j][i]);
00597
00598 layer.alpha_tiles[j][i] = QImage( tile_width, tile_height, 8, 256);
00599 if( layer.alpha_tiles[j][i].isNull())
00600 return false;
00601 setGrayPalette(layer.alpha_tiles[j][i]);
00602 break;
00603
00604 case INDEXED_GIMAGE:
00605 layer.image_tiles[j][i] = QImage(tile_width, tile_height, 8,
00606 xcf_image.num_colors);
00607 if( layer.image_tiles[j][i].isNull())
00608 return false;
00609 setPalette(xcf_image, layer.image_tiles[j][i]);
00610 break;
00611
00612 case INDEXEDA_GIMAGE:
00613 layer.image_tiles[j][i] = QImage(tile_width, tile_height,8,
00614 xcf_image.num_colors);
00615 if( layer.image_tiles[j][i].isNull())
00616 return false;
00617 setPalette(xcf_image, layer.image_tiles[j][i]);
00618
00619 layer.alpha_tiles[j][i] = QImage(tile_width, tile_height, 8, 256);
00620 if( layer.alpha_tiles[j][i].isNull())
00621 return false;
00622 setGrayPalette(layer.alpha_tiles[j][i]);
00623 }
00624
00625 if (layer.mask_offset != 0) {
00626 layer.mask_tiles[j][i] = QImage(tile_width, tile_height, 8, 256);
00627 if( layer.mask_tiles[j][i].isNull())
00628 return false;
00629 setGrayPalette(layer.mask_tiles[j][i]);
00630 }
00631 }
00632 }
00633 return true;
00634 }
00635
00636
00643 void XCFImageFormat::setGrayPalette(QImage& image)
00644 {
00645 for (int i = 0; i < 256; i++)
00646 image.setColor(i, qRgb(i, i, i));
00647 }
00648
00649
00655 void XCFImageFormat::setPalette(XCFImage& xcf_image, QImage& image)
00656 {
00657 for (int i = 0; i < xcf_image.num_colors; i++)
00658 image.setColor(i, xcf_image.palette[i]);
00659 }
00660
00661
00669 void XCFImageFormat::assignImageBytes(Layer& layer, uint i, uint j)
00670 {
00671 uchar* tile = layer.tile;
00672
00673 switch (layer.type) {
00674 case RGB_GIMAGE:
00675 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
00676 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
00677 layer.image_tiles[j][i].setPixel(k, l,
00678 qRgb(tile[0], tile[1], tile[2]));
00679 tile += sizeof(QRgb);
00680 }
00681 }
00682 break;
00683
00684 case RGBA_GIMAGE:
00685 for ( int l = 0; l < layer.image_tiles[j][i].height(); l++ ) {
00686 for ( int k = 0; k < layer.image_tiles[j][i].width(); k++ ) {
00687 layer.image_tiles[j][i].setPixel(k, l,
00688 qRgba(tile[0], tile[1], tile[2], tile[3]));
00689 tile += sizeof(QRgb);
00690 }
00691 }
00692 break;
00693
00694 case GRAY_GIMAGE:
00695 case INDEXED_GIMAGE:
00696 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
00697 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
00698 layer.image_tiles[j][i].setPixel(k, l, tile[0]);
00699 tile += sizeof(QRgb);
00700 }
00701 }
00702 break;
00703
00704 case GRAYA_GIMAGE:
00705 case INDEXEDA_GIMAGE:
00706 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
00707 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
00708
00709
00710
00711
00712
00713 if (tile[0] < layer.image_tiles[j][i].numColors())
00714 layer.image_tiles[j][i].setPixel(k, l, tile[0]);
00715
00716 layer.alpha_tiles[j][i].setPixel(k, l, tile[1]);
00717 tile += sizeof(QRgb);
00718 }
00719 }
00720 break;
00721 }
00722 }
00723
00724
00733 bool XCFImageFormat::loadHierarchy(QDataStream& xcf_io, Layer& layer)
00734 {
00735 Q_INT32 width;
00736 Q_INT32 height;
00737 Q_INT32 bpp;
00738 Q_UINT32 offset;
00739
00740 xcf_io >> width >> height >> bpp >> offset;
00741
00742 if (xcf_io.device()->status() != IO_Ok) {
00743 kdDebug(399) << "XCF: read failure on layer " << layer.name << " image header" << endl;
00744 return false;
00745 }
00746
00747
00748
00749
00750
00751 Q_UINT32 junk;
00752 do {
00753 xcf_io >> junk;
00754
00755 if (xcf_io.device()->status() != IO_Ok) {
00756 kdDebug(399) << "XCF: read failure on layer " << layer.name << " level offsets" << endl;
00757 return false;
00758 }
00759 } while (junk != 0);
00760
00761 QIODevice::Offset saved_pos = xcf_io.device()->at();
00762
00763 xcf_io.device()->at(offset);
00764 if (!loadLevel(xcf_io, layer, bpp))
00765 return false;
00766
00767 xcf_io.device()->at(saved_pos);
00768 return true;
00769 }
00770
00771
00780 bool XCFImageFormat::loadLevel(QDataStream& xcf_io, Layer& layer, Q_INT32 bpp)
00781 {
00782 Q_INT32 width;
00783 Q_INT32 height;
00784 Q_UINT32 offset;
00785
00786 xcf_io >> width >> height >> offset;
00787
00788 if (xcf_io.device()->status() != IO_Ok) {
00789 kdDebug(399) << "XCF: read failure on layer " << layer.name << " level info" << endl;
00790 return false;
00791 }
00792
00793 if (offset == 0)
00794 return true;
00795
00796 for (uint j = 0; j < layer.nrows; j++) {
00797 for (uint i = 0; i < layer.ncols; i++) {
00798
00799 if (offset == 0) {
00800 kdDebug(399) << "XCF: incorrect number of tiles in layer " << layer.name << endl;
00801 return false;
00802 }
00803
00804 QIODevice::Offset saved_pos = xcf_io.device()->at();
00805 Q_UINT32 offset2;
00806 xcf_io >> offset2;
00807
00808 if (xcf_io.device()->status() != IO_Ok) {
00809 kdDebug(399) << "XCF: read failure on layer " << layer.name << " level offset look-ahead" << endl;
00810 return false;
00811 }
00812
00813
00814
00815 if (offset2 == 0)
00816 offset2 = offset + (uint)(TILE_WIDTH * TILE_HEIGHT * 4 * 1.5);
00817
00818 xcf_io.device()->at(offset);
00819 int size = layer.image_tiles[j][i].width() * layer.image_tiles[j][i].height();
00820
00821 if (!loadTileRLE(xcf_io, layer.tile, size, offset2 - offset, bpp))
00822 return false;
00823
00824
00825
00826
00827
00828 layer.assignBytes(layer, i, j);
00829
00830 xcf_io.device()->at(saved_pos);
00831 xcf_io >> offset;
00832
00833 if (xcf_io.device()->status() != IO_Ok) {
00834 kdDebug(399) << "XCF: read failure on layer " << layer.name << " level offset" << endl;
00835 return false;
00836 }
00837 }
00838 }
00839
00840 return true;
00841 }
00842
00843
00850 bool XCFImageFormat::loadMask(QDataStream& xcf_io, Layer& layer)
00851 {
00852 Q_INT32 width;
00853 Q_INT32 height;
00854 char* name;
00855
00856 xcf_io >> width >> height >> name;
00857
00858 if (xcf_io.device()->status() != IO_Ok) {
00859 kdDebug(399) << "XCF: read failure on mask info" << endl;
00860 return false;
00861 }
00862
00863 delete name;
00864
00865 if (!loadChannelProperties(xcf_io, layer))
00866 return false;
00867
00868 Q_UINT32 hierarchy_offset;
00869 xcf_io >> hierarchy_offset;
00870
00871 if (xcf_io.device()->status() != IO_Ok) {
00872 kdDebug(399) << "XCF: read failure on mask image offset" << endl;
00873 return false;
00874 }
00875
00876 xcf_io.device()->at(hierarchy_offset);
00877 layer.assignBytes = assignMaskBytes;
00878
00879 if (!loadHierarchy(xcf_io, layer))
00880 return false;
00881
00882 return true;
00883 }
00884
00885
00909 bool XCFImageFormat::loadTileRLE(QDataStream& xcf_io, uchar* tile, int image_size,
00910 int data_length, Q_INT32 bpp)
00911 {
00912 uchar* data;
00913
00914 uchar* xcfdata;
00915 uchar* xcfodata;
00916 uchar* xcfdatalimit;
00917
00918 xcfdata = xcfodata = new uchar[data_length];
00919
00920 xcf_io.readRawBytes((char*)xcfdata, data_length);
00921
00922 if (xcf_io.device()->status() != IO_Ok) {
00923 delete[] xcfodata;
00924 kdDebug(399) << "XCF: read failure on tile" << endl;
00925 return false;
00926 }
00927
00928 xcfdatalimit = &xcfodata[data_length - 1];
00929
00930 for (int i = 0; i < bpp; ++i) {
00931
00932 data = tile + i;
00933
00934 int count = 0;
00935 int size = image_size;
00936
00937 while (size > 0) {
00938 if (xcfdata > xcfdatalimit)
00939 goto bogus_rle;
00940
00941 uchar val = *xcfdata++;
00942 uint length = val;
00943
00944 if (length >= 128) {
00945 length = 255 - (length - 1);
00946 if (length == 128) {
00947 if (xcfdata >= xcfdatalimit)
00948 goto bogus_rle;
00949
00950 length = (*xcfdata << 8) + xcfdata[1];
00951
00952 xcfdata += 2;
00953 }
00954
00955 count += length;
00956 size -= length;
00957
00958 if (size < 0)
00959 goto bogus_rle;
00960
00961 if (&xcfdata[length - 1] > xcfdatalimit)
00962 goto bogus_rle;
00963
00964 while (length-- > 0) {
00965 *data = *xcfdata++;
00966 data += sizeof(QRgb);
00967 }
00968 } else {
00969 length += 1;
00970 if (length == 128) {
00971 if (xcfdata >= xcfdatalimit)
00972 goto bogus_rle;
00973
00974 length = (*xcfdata << 8) + xcfdata[1];
00975 xcfdata += 2;
00976 }
00977
00978 count += length;
00979 size -= length;
00980
00981 if (size < 0)
00982 goto bogus_rle;
00983
00984 if (xcfdata > xcfdatalimit)
00985 goto bogus_rle;
00986
00987 val = *xcfdata++;
00988
00989 while (length-- > 0) {
00990 *data = val;
00991 data += sizeof(QRgb);
00992 }
00993 }
00994 }
00995 }
00996
00997 delete[] xcfodata;
00998 return true;
00999
01000 bogus_rle:
01001
01002 kdDebug(399) << "The run length encoding could not be decoded properly" << endl;
01003 delete[] xcfodata;
01004 return false;
01005 }
01006
01007
01015 bool XCFImageFormat::loadChannelProperties(QDataStream& xcf_io, Layer& layer)
01016 {
01017 while (true) {
01018 PropType type;
01019 QByteArray bytes;
01020
01021 if (!loadProperty(xcf_io, type, bytes)) {
01022 kdDebug(399) << "XCF: error loading channel properties" << endl;
01023 return false;
01024 }
01025
01026 QDataStream property(bytes, IO_ReadOnly);
01027
01028 switch (type) {
01029 case PROP_END:
01030 return true;
01031
01032 case PROP_OPACITY:
01033 property >> layer.mask_channel.opacity;
01034 break;
01035
01036 case PROP_VISIBLE:
01037 property >> layer.mask_channel.visible;
01038 break;
01039
01040 case PROP_SHOW_MASKED:
01041 property >> layer.mask_channel.show_masked;
01042 break;
01043
01044 case PROP_COLOR:
01045 property >> layer.mask_channel.red >> layer.mask_channel.green
01046 >> layer.mask_channel.blue;
01047 break;
01048
01049 case PROP_TATTOO:
01050 property >> layer.mask_channel.tattoo;
01051 break;
01052
01053 default:
01054 kdDebug(399) << "XCF: unimplemented channel property " << type
01055 << ", size " << bytes.size() << endl;
01056 }
01057 }
01058 }
01059
01060
01067 void XCFImageFormat::assignMaskBytes(Layer& layer, uint i, uint j)
01068 {
01069 uchar* tile = layer.tile;
01070
01071 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
01072 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
01073 layer.mask_tiles[j][i].setPixel(k, l, tile[0]);
01074 tile += sizeof(QRgb);
01075 }
01076 }
01077 }
01078
01079
01108 bool XCFImageFormat::initializeImage(XCFImage& xcf_image)
01109 {
01110
01111 Layer& layer(xcf_image.layer);
01112 QImage& image(xcf_image.image);
01113
01114 switch (layer.type) {
01115 case RGB_GIMAGE:
01116 if (layer.opacity == OPAQUE_OPACITY) {
01117 image.create( xcf_image.width, xcf_image.height, 32);
01118 if( image.isNull())
01119 return false;
01120 image.fill(qRgb(255, 255, 255));
01121 break;
01122 }
01123
01124 case RGBA_GIMAGE:
01125 image.create(xcf_image.width, xcf_image.height, 32);
01126 if( image.isNull())
01127 return false;
01128 image.fill(qRgba(255, 255, 255, 0));
01129
01130
01131 image.setAlphaBuffer(true);
01132 break;
01133
01134 case GRAY_GIMAGE:
01135 if (layer.opacity == OPAQUE_OPACITY) {
01136 image.create(xcf_image.width, xcf_image.height, 8, 256);
01137 if( image.isNull())
01138 return false;
01139 setGrayPalette(image);
01140 image.fill(255);
01141 break;
01142 }
01143
01144 case GRAYA_GIMAGE:
01145 image.create(xcf_image.width, xcf_image.height, 32);
01146 if( image.isNull())
01147 return false;
01148 image.fill(qRgba(255, 255, 255, 0));
01149 image.setAlphaBuffer(true);
01150 break;
01151
01152 case INDEXED_GIMAGE:
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165 if (xcf_image.num_colors <= 2) {
01166 image.create(xcf_image.width, xcf_image.height,
01167 1, xcf_image.num_colors,
01168 QImage::LittleEndian);
01169 if( image.isNull())
01170 return false;
01171 image.fill(0);
01172 setPalette(xcf_image, image);
01173 } else if (xcf_image.num_colors <= 256) {
01174 image.create(xcf_image.width, xcf_image.height,
01175 8, xcf_image.num_colors,
01176 QImage::LittleEndian);
01177 if( image.isNull())
01178 return false;
01179 image.fill(0);
01180 setPalette(xcf_image, image);
01181 }
01182 break;
01183
01184 case INDEXEDA_GIMAGE:
01185 if (xcf_image.num_colors == 1) {
01186
01187 xcf_image.num_colors++;
01188 xcf_image.palette.resize(xcf_image.num_colors);
01189 xcf_image.palette[1] = xcf_image.palette[0];
01190 xcf_image.palette[0] = qRgba(255, 255, 255, 0);
01191
01192 image.create(xcf_image.width, xcf_image.height,
01193 1, xcf_image.num_colors,
01194 QImage::LittleEndian);
01195 if( image.isNull())
01196 return false;
01197 image.fill(0);
01198 setPalette(xcf_image, image);
01199 image.setAlphaBuffer(true);
01200 } else if (xcf_image.num_colors < 256) {
01201
01202 xcf_image.num_colors++;
01203 xcf_image.palette.resize(xcf_image.num_colors);
01204 for (int c = xcf_image.num_colors - 1; c >= 1; c--)
01205 xcf_image.palette[c] = xcf_image.palette[c - 1];
01206
01207 xcf_image.palette[0] = qRgba(255, 255, 255, 0);
01208 image.create( xcf_image.width, xcf_image.height,
01209 8, xcf_image.num_colors);
01210 if( image.isNull())
01211 return false;
01212 image.fill(0);
01213 setPalette(xcf_image, image);
01214 image.setAlphaBuffer(true);
01215 } else {
01216
01217
01218
01219 image.create(xcf_image.width, xcf_image.height, 32);
01220 if( image.isNull())
01221 return false;
01222 image.fill(qRgba(255, 255, 255, 0));
01223 image.setAlphaBuffer(true);
01224 }
01225 break;
01226 }
01227
01228 image.setDotsPerMeterX((int)(xcf_image.x_resolution * INCHESPERMETER));
01229 image.setDotsPerMeterY((int)(xcf_image.y_resolution * INCHESPERMETER));
01230 return true;
01231 }
01232
01233
01239 void XCFImageFormat::copyLayerToImage(XCFImage& xcf_image)
01240 {
01241 Layer& layer(xcf_image.layer);
01242 QImage& image(xcf_image.image);
01243 PixelCopyOperation copy = 0;
01244
01245 switch (layer.type) {
01246 case RGB_GIMAGE:
01247 case RGBA_GIMAGE:
01248 copy = copyRGBToRGB;
01249 break;
01250 case GRAY_GIMAGE:
01251 if (layer.opacity == OPAQUE_OPACITY)
01252 copy = copyGrayToGray;
01253 else
01254 copy = copyGrayToRGB;
01255 break;
01256 case GRAYA_GIMAGE:
01257 copy = copyGrayAToRGB;
01258 break;
01259 case INDEXED_GIMAGE:
01260 copy = copyIndexedToIndexed;
01261 break;
01262 case INDEXEDA_GIMAGE:
01263 if (xcf_image.image.depth() <= 8)
01264 copy = copyIndexedAToIndexed;
01265 else
01266 copy = copyIndexedAToRGB;
01267 }
01268
01269
01270
01271 for (uint j = 0; j < layer.nrows; j++) {
01272 uint y = j * TILE_HEIGHT;
01273
01274 for (uint i = 0; i < layer.ncols; i++) {
01275 uint x = i * TILE_WIDTH;
01276
01277
01278
01279
01280
01281
01282 if (layer.mode == DISSOLVE_MODE) {
01283 if (layer.type == RGBA_GIMAGE)
01284 dissolveRGBPixels(layer.image_tiles[j][i], x, y);
01285
01286 else if (layer.type == GRAYA_GIMAGE)
01287 dissolveAlphaPixels(layer.alpha_tiles[j][i], x, y);
01288 }
01289
01290 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
01291 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
01292
01293 int m = x + k + layer.x_offset;
01294 int n = y + l + layer.y_offset;
01295
01296 if (m < 0 || m >= image.width() || n < 0 || n >= image.height())
01297 continue;
01298
01299 (*copy)(layer, i, j, k, l, image, m, n);
01300 }
01301 }
01302 }
01303 }
01304 }
01305
01306
01320 void XCFImageFormat::copyRGBToRGB(Layer& layer, uint i, uint j, int k, int l,
01321 QImage& image, int m, int n)
01322 {
01323 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01324 uchar src_a = layer.opacity;
01325
01326 if (layer.type == RGBA_GIMAGE)
01327 src_a = INT_MULT(src_a, qAlpha(src));
01328
01329
01330
01331 if (layer.apply_mask == 1 && layer.mask_tiles.size() > j &&
01332 layer.mask_tiles[j].size() > i)
01333 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01334
01335 image.setPixel(m, n, qRgba(src, src_a));
01336 }
01337
01338
01350 void XCFImageFormat::copyGrayToGray(Layer& layer, uint i, uint j, int k, int l,
01351 QImage& image, int m, int n)
01352 {
01353 int src = layer.image_tiles[j][i].pixelIndex(k, l);
01354 image.setPixel(m, n, src);
01355 }
01356
01357
01371 void XCFImageFormat::copyGrayToRGB(Layer& layer, uint i, uint j, int k, int l,
01372 QImage& image, int m, int n)
01373 {
01374 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01375 uchar src_a = layer.opacity;
01376 image.setPixel(m, n, qRgba(src, src_a));
01377 }
01378
01379
01393 void XCFImageFormat::copyGrayAToRGB(Layer& layer, uint i, uint j, int k, int l,
01394 QImage& image, int m, int n)
01395 {
01396 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01397 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
01398 src_a = INT_MULT(src_a, layer.opacity);
01399
01400
01401
01402 if (layer.apply_mask == 1 && layer.mask_tiles.size() > j &&
01403 layer.mask_tiles[j].size() > i)
01404 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01405
01406 image.setPixel(m, n, qRgba(src, src_a));
01407 }
01408
01409
01421 void XCFImageFormat::copyIndexedToIndexed(Layer& layer, uint i, uint j, int k, int l,
01422 QImage& image, int m, int n)
01423 {
01424 int src = layer.image_tiles[j][i].pixelIndex(k, l);
01425 image.setPixel(m, n, src);
01426 }
01427
01428
01440 void XCFImageFormat::copyIndexedAToIndexed(Layer& layer, uint i, uint j, int k, int l,
01441 QImage& image, int m, int n)
01442 {
01443 uchar src = layer.image_tiles[j][i].pixelIndex(k, l);
01444 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
01445 src_a = INT_MULT(src_a, layer.opacity);
01446
01447 if (layer.apply_mask == 1 &&
01448 layer.mask_tiles.size() > j &&
01449 layer.mask_tiles[j].size() > i)
01450 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01451
01452 if (src_a > 127)
01453 src++;
01454 else
01455 src = 0;
01456
01457 image.setPixel(m, n, src);
01458 }
01459
01460
01474 void XCFImageFormat::copyIndexedAToRGB(Layer& layer, uint i, uint j, int k, int l,
01475 QImage& image, int m, int n)
01476 {
01477 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01478 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
01479 src_a = INT_MULT(src_a, layer.opacity);
01480
01481
01482 if (layer.apply_mask == 1 && layer.mask_tiles.size() > j &&
01483 layer.mask_tiles[j].size() > i)
01484 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01485
01486
01487 if (src_a <= 127)
01488 src_a = 0;
01489 else
01490 src_a = OPAQUE_OPACITY;
01491
01492 image.setPixel(m, n, qRgba(src, src_a));
01493 }
01494
01495
01500 void XCFImageFormat::mergeLayerIntoImage(XCFImage& xcf_image)
01501 {
01502 Layer& layer(xcf_image.layer);
01503 QImage& image(xcf_image.image);
01504
01505 PixelMergeOperation merge = 0;
01506
01507 switch (layer.type) {
01508 case RGB_GIMAGE:
01509 case RGBA_GIMAGE:
01510 merge = mergeRGBToRGB;
01511 break;
01512 case GRAY_GIMAGE:
01513 if (layer.opacity == OPAQUE_OPACITY)
01514 merge = mergeGrayToGray;
01515 else
01516 merge = mergeGrayToRGB;
01517 break;
01518 case GRAYA_GIMAGE:
01519 if (xcf_image.image.depth() <= 8)
01520 merge = mergeGrayAToGray;
01521 else
01522 merge = mergeGrayAToRGB;
01523 break;
01524 case INDEXED_GIMAGE:
01525 merge = mergeIndexedToIndexed;
01526 break;
01527 case INDEXEDA_GIMAGE:
01528 if (xcf_image.image.depth() <= 8)
01529 merge = mergeIndexedAToIndexed;
01530 else
01531 merge = mergeIndexedAToRGB;
01532 }
01533
01534 for (uint j = 0; j < layer.nrows; j++) {
01535 uint y = j * TILE_HEIGHT;
01536
01537 for (uint i = 0; i < layer.ncols; i++) {
01538 uint x = i * TILE_WIDTH;
01539
01540
01541
01542
01543
01544
01545 if (layer.mode == DISSOLVE_MODE) {
01546 if (layer.type == RGBA_GIMAGE)
01547 dissolveRGBPixels(layer.image_tiles[j][i], x, y);
01548
01549 else if (layer.type == GRAYA_GIMAGE)
01550 dissolveAlphaPixels(layer.alpha_tiles[j][i], x, y);
01551 }
01552
01553 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
01554 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
01555
01556 int m = x + k + layer.x_offset;
01557 int n = y + l + layer.y_offset;
01558
01559 if (m < 0 || m >= image.width() || n < 0 || n >= image.height())
01560 continue;
01561
01562 (*merge)(layer, i, j, k, l, image, m, n);
01563 }
01564 }
01565 }
01566 }
01567 }
01568
01569
01583 void XCFImageFormat::mergeRGBToRGB(Layer& layer, uint i, uint j, int k, int l,
01584 QImage& image, int m, int n)
01585 {
01586 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01587 QRgb dst = image.pixel(m, n);
01588
01589 uchar src_r = qRed(src);
01590 uchar src_g = qGreen(src);
01591 uchar src_b = qBlue(src);
01592 uchar src_a = qAlpha(src);
01593
01594 uchar dst_r = qRed(dst);
01595 uchar dst_g = qGreen(dst);
01596 uchar dst_b = qBlue(dst);
01597 uchar dst_a = qAlpha(dst);
01598
01599 switch (layer.mode) {
01600 case MULTIPLY_MODE: {
01601 src_r = INT_MULT(src_r, dst_r);
01602 src_g = INT_MULT(src_g, dst_g);
01603 src_b = INT_MULT(src_b, dst_b);
01604 src_a = KMIN(src_a, dst_a);
01605 }
01606 break;
01607 case DIVIDE_MODE: {
01608 src_r = KMIN((dst_r * 256) / (1 + src_r), 255);
01609 src_g = KMIN((dst_g * 256) / (1 + src_g), 255);
01610 src_b = KMIN((dst_b * 256) / (1 + src_b), 255);
01611 src_a = KMIN(src_a, dst_a);
01612 }
01613 break;
01614 case SCREEN_MODE: {
01615 src_r = 255 - INT_MULT(255 - dst_r, 255 - src_r);
01616 src_g = 255 - INT_MULT(255 - dst_g, 255 - src_g);
01617 src_b = 255 - INT_MULT(255 - dst_b, 255 - src_b);
01618 src_a = KMIN(src_a, dst_a);
01619 }
01620 break;
01621 case OVERLAY_MODE: {
01622 src_r = INT_MULT(dst_r, dst_r + INT_MULT(2 * src_r, 255 - dst_r));
01623 src_g = INT_MULT(dst_g, dst_g + INT_MULT(2 * src_g, 255 - dst_g));
01624 src_b = INT_MULT(dst_b, dst_b + INT_MULT(2 * src_b, 255 - dst_b));
01625 src_a = KMIN(src_a, dst_a);
01626 }
01627 break;
01628 case DIFFERENCE_MODE: {
01629 src_r = dst_r > src_r ? dst_r - src_r : src_r - dst_r;
01630 src_g = dst_g > src_g ? dst_g - src_g : src_g - dst_g;
01631 src_b = dst_b > src_b ? dst_b - src_b : src_b - dst_b;
01632 src_a = KMIN(src_a, dst_a);
01633 }
01634 break;
01635 case ADDITION_MODE: {
01636 src_r = add_lut(dst_r,src_r);
01637 src_g = add_lut(dst_g,src_g);
01638 src_b = add_lut(dst_b,src_b);
01639 src_a = KMIN(src_a, dst_a);
01640 }
01641 break;
01642 case SUBTRACT_MODE: {
01643 src_r = dst_r > src_r ? dst_r - src_r : 0;
01644 src_g = dst_g > src_g ? dst_g - src_g : 0;
01645 src_b = dst_b > src_b ? dst_b - src_b : 0;
01646 src_a = KMIN(src_a, dst_a);
01647 }
01648 break;
01649 case DARKEN_ONLY_MODE: {
01650 src_r = dst_r < src_r ? dst_r : src_r;
01651 src_g = dst_g < src_g ? dst_g : src_g;
01652 src_b = dst_b < src_b ? dst_b : src_b;
01653 src_a = KMIN( src_a, dst_a );
01654 }
01655 break;
01656 case LIGHTEN_ONLY_MODE: {
01657 src_r = dst_r < src_r ? src_r : dst_r;
01658 src_g = dst_g < src_g ? src_g : dst_g;
01659 src_b = dst_b < src_b ? src_b : dst_b;
01660 src_a = KMIN(src_a, dst_a);
01661 }
01662 break;
01663 case HUE_MODE: {
01664 uchar new_r = dst_r;
01665 uchar new_g = dst_g;
01666 uchar new_b = dst_b;
01667
01668 RGBTOHSV(src_r, src_g, src_b);
01669 RGBTOHSV(new_r, new_g, new_b);
01670
01671 new_r = src_r;
01672
01673 HSVTORGB(new_r, new_g, new_b);
01674
01675 src_r = new_r;
01676 src_g = new_g;
01677 src_b = new_b;
01678 src_a = KMIN( src_a, dst_a );
01679 }
01680 break;
01681 case SATURATION_MODE: {
01682 uchar new_r = dst_r;
01683 uchar new_g = dst_g;
01684 uchar new_b = dst_b;
01685
01686 RGBTOHSV(src_r, src_g, src_b);
01687 RGBTOHSV(new_r, new_g, new_b);
01688
01689 new_g = src_g;
01690
01691 HSVTORGB(new_r, new_g, new_b);
01692
01693 src_r = new_r;
01694 src_g = new_g;
01695 src_b = new_b;
01696 src_a = KMIN(src_a, dst_a);
01697 }
01698 break;
01699 case VALUE_MODE: {
01700 uchar new_r = dst_r;
01701 uchar new_g = dst_g;
01702 uchar new_b = dst_b;
01703
01704 RGBTOHSV(src_r, src_g, src_b);
01705 RGBTOHSV(new_r, new_g, new_b);
01706
01707 new_b = src_b;
01708
01709 HSVTORGB(new_r, new_g, new_b);
01710
01711 src_r = new_r;
01712 src_g = new_g;
01713 src_b = new_b;
01714 src_a = KMIN(src_a, dst_a);
01715 }
01716 break;
01717 case COLOR_MODE: {
01718 uchar new_r = dst_r;
01719 uchar new_g = dst_g;
01720 uchar new_b = dst_b;
01721
01722 RGBTOHLS(src_r, src_g, src_b);
01723 RGBTOHLS(new_r, new_g, new_b);
01724
01725 new_r = src_r;
01726 new_b = src_b;
01727
01728 HLSTORGB(new_r, new_g, new_b);
01729
01730 src_r = new_r;
01731 src_g = new_g;
01732 src_b = new_b;
01733 src_a = KMIN(src_a, dst_a);
01734 }
01735 break;
01736 }
01737
01738 src_a = INT_MULT(src_a, layer.opacity);
01739
01740
01741
01742 if (layer.apply_mask == 1 && layer.mask_tiles.size() > j &&
01743 layer.mask_tiles[j].size() > i)
01744 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01745
01746 uchar new_r, new_g, new_b, new_a;
01747 new_a = dst_a + INT_MULT(OPAQUE_OPACITY - dst_a, src_a);
01748
01749 float src_ratio = (float)src_a / new_a;
01750 float dst_ratio = 1.0 - src_ratio;
01751
01752 new_r = (uchar)(src_ratio * src_r + dst_ratio * dst_r + EPSILON);
01753 new_g = (uchar)(src_ratio * src_g + dst_ratio * dst_g + EPSILON);
01754 new_b = (uchar)(src_ratio * src_b + dst_ratio * dst_b + EPSILON);
01755
01756 if (!layer_modes[layer.mode].affect_alpha)
01757 new_a = dst_a;
01758
01759 image.setPixel(m, n, qRgba(new_r, new_g, new_b, new_a));
01760 }
01761
01762
01774 void XCFImageFormat::mergeGrayToGray(Layer& layer, uint i, uint j, int k, int l,
01775 QImage& image, int m, int n)
01776 {
01777 int src = layer.image_tiles[j][i].pixelIndex(k, l);
01778 image.setPixel(m, n, src);
01779 }
01780
01781
01793 void XCFImageFormat::mergeGrayAToGray(Layer& layer, uint i, uint j, int k, int l,
01794 QImage& image, int m, int n)
01795 {
01796 int src = qGray(layer.image_tiles[j][i].pixel(k, l));
01797 int dst = image.pixelIndex(m, n);
01798
01799 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
01800
01801 switch (layer.mode) {
01802 case MULTIPLY_MODE: {
01803 src = INT_MULT( src, dst );
01804 }
01805 break;
01806 case DIVIDE_MODE: {
01807 src = KMIN((dst * 256) / (1 + src), 255);
01808 }
01809 break;
01810 case SCREEN_MODE: {
01811 src = 255 - INT_MULT(255 - dst, 255 - src);
01812 }
01813 break;
01814 case OVERLAY_MODE: {
01815 src = INT_MULT(dst, dst + INT_MULT(2 * src, 255 - dst));
01816 }
01817 break;
01818 case DIFFERENCE_MODE: {
01819 src = dst > src ? dst - src : src - dst;
01820 }
01821 break;
01822 case ADDITION_MODE: {
01823 src = add_lut(dst,src);
01824 }
01825 break;
01826 case SUBTRACT_MODE: {
01827 src = dst > src ? dst - src : 0;
01828 }
01829 break;
01830 case DARKEN_ONLY_MODE: {
01831 src = dst < src ? dst : src;
01832 }
01833 break;
01834 case LIGHTEN_ONLY_MODE: {
01835 src = dst < src ? src : dst;
01836 }
01837 break;
01838 }
01839
01840 src_a = INT_MULT(src_a, layer.opacity);
01841
01842
01843
01844 if (layer.apply_mask == 1 && layer.mask_tiles.size() > j &&
01845 layer.mask_tiles[j].size() > i)
01846 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01847
01848 uchar new_a = OPAQUE_OPACITY;
01849
01850 float src_ratio = (float)src_a / new_a;
01851 float dst_ratio = 1.0 - src_ratio;
01852
01853 uchar new_g = (uchar)(src_ratio * src + dst_ratio * dst + EPSILON);
01854
01855 image.setPixel(m, n, new_g);
01856 }
01857
01858
01872 void XCFImageFormat::mergeGrayToRGB(Layer& layer, uint i, uint j, int k, int l,
01873 QImage& image, int m, int n)
01874 {
01875 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01876 uchar src_a = layer.opacity;
01877 image.setPixel(m, n, qRgba(src, src_a));
01878 }
01879
01880
01894 void XCFImageFormat::mergeGrayAToRGB(Layer& layer, uint i, uint j, int k, int l,
01895 QImage& image, int m, int n)
01896 {
01897 int src = qGray(layer.image_tiles[j][i].pixel(k, l));
01898 int dst = qGray(image.pixel(m, n));
01899
01900 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
01901 uchar dst_a = qAlpha(image.pixel(m, n));
01902
01903 switch (layer.mode) {
01904 case MULTIPLY_MODE: {
01905 src = INT_MULT(src, dst);
01906 src_a = KMIN(src_a, dst_a);
01907 }
01908 break;
01909 case DIVIDE_MODE: {
01910 src = KMIN((dst * 256) / (1 + src), 255);
01911 src_a = KMIN(src_a, dst_a);
01912 }
01913 break;
01914 case SCREEN_MODE: {
01915 src = 255 - INT_MULT(255 - dst, 255 - src);
01916 src_a = KMIN(src_a, dst_a);
01917 }
01918 break;
01919 case OVERLAY_MODE: {
01920 src = INT_MULT( dst, dst + INT_MULT(2 * src, 255 - dst));
01921 src_a = KMIN(src_a, dst_a);
01922 }
01923 break;
01924 case DIFFERENCE_MODE: {
01925 src = dst > src ? dst - src : src - dst;
01926 src_a = KMIN(src_a, dst_a);
01927 }
01928 break;
01929 case ADDITION_MODE: {
01930 src = add_lut(dst,src);
01931 src_a = KMIN(src_a, dst_a);
01932 }
01933 break;
01934 case SUBTRACT_MODE: {
01935 src = dst > src ? dst - src : 0;
01936 src_a = KMIN(src_a, dst_a);
01937 }
01938 break;
01939 case DARKEN_ONLY_MODE: {
01940 src = dst < src ? dst : src;
01941 src_a = KMIN(src_a, dst_a);
01942 }
01943 break;
01944 case LIGHTEN_ONLY_MODE: {
01945 src = dst < src ? src : dst;
01946 src_a = KMIN(src_a, dst_a);
01947 }
01948 break;
01949 }
01950
01951 src_a = INT_MULT(src_a, layer.opacity);
01952
01953
01954 if (layer.apply_mask == 1 && layer.mask_tiles.size() > j &&
01955 layer.mask_tiles[j].size() > i)
01956 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01957
01958 uchar new_a = dst_a + INT_MULT(OPAQUE_OPACITY - dst_a, src_a);
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 if (!layer_modes[layer.mode].affect_alpha)
01966 new_a = dst_a;
01967
01968 image.setPixel(m, n, qRgba(new_g, new_g, new_g, new_a));
01969 }
01970
01971
01983 void XCFImageFormat::mergeIndexedToIndexed(Layer& layer, uint i, uint j, int k, int l,
01984 QImage& image, int m, int n)
01985 {
01986 int src = layer.image_tiles[j][i].pixelIndex(k, l);
01987 image.setPixel(m, n, src);
01988 }
01989
01990
02002 void XCFImageFormat::mergeIndexedAToIndexed(Layer& layer, uint i, uint j, int k, int l,
02003 QImage& image, int m, int n)
02004 {
02005 uchar src = layer.image_tiles[j][i].pixelIndex(k, l);
02006 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
02007 src_a = INT_MULT( src_a, layer.opacity );
02008
02009 if ( layer.apply_mask == 1 &&
02010 layer.mask_tiles.size() > j &&
02011 layer.mask_tiles[j].size() > i)
02012 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
02013
02014 if (src_a > 127) {
02015 src++;
02016 image.setPixel(m, n, src);
02017 }
02018 }
02019
02020
02034 void XCFImageFormat::mergeIndexedAToRGB(Layer& layer, uint i, uint j, int k, int l,
02035 QImage& image, int m, int n)
02036 {
02037 QRgb src = layer.image_tiles[j][i].pixel(k, l);
02038 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
02039 src_a = INT_MULT(src_a, layer.opacity);
02040
02041
02042 if (layer.apply_mask == 1 && layer.mask_tiles.size() > j &&
02043 layer.mask_tiles[j].size() > i)
02044 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
02045
02046
02047 if (src_a <= 127)
02048 src_a = 0;
02049 else
02050 src_a = OPAQUE_OPACITY;
02051
02052 image.setPixel(m, n, qRgba(src, src_a));
02053 }
02054
02055
02063 void XCFImageFormat::dissolveRGBPixels ( QImage& image, int x, int y )
02064 {
02065
02066
02067
02068 for (int l = 0; l < image.height(); l++) {
02069 srand(random_table[( l + y ) % RANDOM_TABLE_SIZE]);
02070
02071 for (int k = 0; k < x; k++)
02072 rand();
02073
02074 for (int k = 0; k < image.width(); k++) {
02075 int rand_val = rand() & 0xff;
02076 QRgb pixel = image.pixel(k, l);
02077
02078 if (rand_val > qAlpha(pixel)) {
02079 image.setPixel(k, l, qRgba(pixel, 0));
02080 }
02081 }
02082 }
02083 }
02084
02085
02095 void XCFImageFormat::dissolveAlphaPixels ( QImage& image, int x, int y )
02096 {
02097
02098
02099
02100 for (int l = 0; l < image.height(); l++) {
02101 srand( random_table[(l + y) % RANDOM_TABLE_SIZE]);
02102
02103 for (int k = 0; k < x; k++)
02104 rand();
02105
02106 for (int k = 0; k < image.width(); k++) {
02107 int rand_val = rand() & 0xff;
02108 uchar alpha = image.pixelIndex(k, l);
02109
02110 if (rand_val > alpha) {
02111 image.setPixel(k, l, 0);
02112 }
02113 }
02114 }
02115 }
02116