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 {true},
00056 {true},
00057 {true},
00058 };
00059
00060
00062 inline QRgb qRgba ( const QRgb& rgb, int a )
00063 {
00064 return ((a & 0xff) << 24 | (rgb & RGB_MASK));
00065 }
00066
00067
00072 XCFImageFormat::XCFImageFormat()
00073 {
00074
00075 srand(RANDOM_SEED);
00076
00077 for (int i = 0; i < RANDOM_TABLE_SIZE; i++)
00078 random_table[i] = rand();
00079
00080 for (int i = 0; i < RANDOM_TABLE_SIZE; i++) {
00081 int tmp;
00082 int swap = i + rand() % (RANDOM_TABLE_SIZE - i);
00083 tmp = random_table[i];
00084 random_table[i] = random_table[swap];
00085 random_table[swap] = tmp;
00086 }
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 }
00097
00098 inline
00099 int XCFImageFormat::add_lut( int a, int b ) {
00100 return qMin( a + b, 255 );
00101 }
00102
00103 bool XCFImageFormat::readXCF(QIODevice *device, QImage *outImage)
00104 {
00105 XCFImage xcf_image;
00106 QDataStream xcf_io(device);
00107
00108 char tag[14];;
00109
00110 if (xcf_io.readRawData(tag, sizeof(tag)) != sizeof(tag)) {
00111 kDebug(399) << "XCF: read failure on header tag";
00112 return false;
00113 }
00114
00115 xcf_io >> xcf_image.width >> xcf_image.height >> xcf_image.type;
00116
00117 kDebug() << tag << " " << xcf_image.width << " " << xcf_image.height << " " << xcf_image.type;
00118 if (!loadImageProperties(xcf_io, xcf_image))
00119 return false;
00120
00121
00122
00123
00124
00125
00126
00127 QStack<qint32> layer_offsets;
00128
00129 while (true) {
00130 qint32 layer_offset;
00131
00132 xcf_io >> layer_offset;
00133
00134 if (layer_offset == 0)
00135 break;
00136
00137 layer_offsets.push(layer_offset);
00138 }
00139
00140 xcf_image.num_layers = layer_offsets.size();
00141
00142 if (layer_offsets.size() == 0) {
00143 kDebug(399) << "XCF: no layers!";
00144 return false;
00145 }
00146
00147
00148 while (!layer_offsets.isEmpty()) {
00149 qint32 layer_offset = layer_offsets.pop();
00150
00151 xcf_io.device()->seek(layer_offset);
00152
00153 if (!loadLayer(xcf_io, xcf_image))
00154 return false;
00155 }
00156
00157 if (!xcf_image.initialized) {
00158 kDebug(399) << "XCF: no visible layers!";
00159 return false;
00160 }
00161
00162 *outImage = xcf_image.image;
00163 return true;
00164 }
00165
00166
00174 bool XCFImageFormat::loadImageProperties(QDataStream& xcf_io, XCFImage& xcf_image)
00175 {
00176 while (true) {
00177 PropType type;
00178 QByteArray bytes;
00179
00180 if (!loadProperty(xcf_io, type, bytes)) {
00181 kDebug(399) << "XCF: error loading global image properties";
00182 return false;
00183 }
00184
00185 QDataStream property(bytes);
00186
00187 switch (type) {
00188 case PROP_END:
00189 return true;
00190
00191 case PROP_COMPRESSION:
00192 property >> xcf_image.compression;
00193 break;
00194
00195 case PROP_RESOLUTION:
00196 property >> xcf_image.x_resolution >> xcf_image.y_resolution;
00197 break;
00198
00199 case PROP_TATTOO:
00200 property >> xcf_image.tattoo;
00201 break;
00202
00203 case PROP_PARASITES:
00204 while (!property.atEnd()) {
00205 char* tag;
00206 quint32 size;
00207
00208 property.readBytes(tag, size);
00209
00210 quint32 flags;
00211 char* data=0;
00212 property >> flags >> data;
00213
00214 if (tag && strncmp(tag, "gimp-comment", strlen("gimp-comment")) == 0)
00215 xcf_image.image.setText("Comment", 0, data);
00216
00217 delete[] tag;
00218 delete[] data;
00219 }
00220 break;
00221
00222 case PROP_UNIT:
00223 property >> xcf_image.unit;
00224 break;
00225
00226 case PROP_PATHS:
00227 break;
00228
00229 case PROP_USER_UNIT:
00230 break;
00231
00232 case PROP_COLORMAP:
00233 property >> xcf_image.num_colors;
00234 if(xcf_image.num_colors < 0 || xcf_image.num_colors > 65535)
00235 return false;
00236
00237 xcf_image.palette.reserve(xcf_image.num_colors);
00238
00239 for (int i = 0; i < xcf_image.num_colors; i++) {
00240 uchar r, g, b;
00241 property >> r >> g >> b;
00242 xcf_image.palette.push_back( qRgb(r,g,b) );
00243 }
00244 break;
00245
00246 default:
00247 kDebug(399) << "XCF: unimplemented image property" << type
00248 << ", size " << bytes.size() << endl;
00249 }
00250 }
00251 }
00252
00253
00261 bool XCFImageFormat::loadProperty(QDataStream& xcf_io, PropType& type, QByteArray& bytes)
00262 {
00263 quint32 foo;
00264 xcf_io >> foo;
00265 type=PropType(foo);
00266
00267 char* data = 0;
00268 quint32 size;
00269
00270
00271
00272
00273
00274 if (type == PROP_COLORMAP) {
00275 xcf_io >> size;
00276
00277 if(size > 65535 || size < 4)
00278 return false;
00279
00280 size = 3 * (size - 4) + 4;
00281 data = new char[size];
00282
00283 xcf_io.readRawData(data, size);
00284 } else if (type == PROP_USER_UNIT) {
00285
00286 float factor;
00287 qint32 digits;
00288
00289 xcf_io >> size >> factor >> digits;
00290
00291 for (int i = 0; i < 5; i++) {
00292 char* unit_strings;
00293
00294 xcf_io >> unit_strings;
00295
00296 delete[] unit_strings;
00297
00298 if (xcf_io.device()->atEnd()) {
00299 kDebug(399) << "XCF: read failure on property " << type;
00300 return false;
00301 }
00302 }
00303
00304 size = 0;
00305 } else {
00306 xcf_io >> size;
00307 if(size >256000)
00308 return false;
00309 data = new char[size];
00310 xcf_io.readRawData(data, size);
00311 }
00312
00313 if (size != 0 && data)
00314 bytes = QByteArray(data,size);
00315
00316 delete [] data;
00317
00318 return true;
00319 }
00320
00321
00330 bool XCFImageFormat::loadLayer(QDataStream& xcf_io, XCFImage& xcf_image)
00331 {
00332 Layer& layer(xcf_image.layer);
00333 delete[] layer.name;
00334
00335 xcf_io >> layer.width >> layer.height >> layer.type >> layer.name;
00336
00337 if (!loadLayerProperties(xcf_io, layer))
00338 return false;
00339 #if 0
00340 cout << "layer: \"" << layer.name << "\", size: " << layer.width << " x "
00341 << layer.height << ", type: " << layer.type << ", mode: " << layer.mode
00342 << ", opacity: " << layer.opacity << ", visible: " << layer.visible
00343 << ", offset: " << layer.x_offset << ", " << layer.y_offset << endl;
00344 #endif
00345
00346
00347
00348
00349 if (layer.visible == 0)
00350 return true;
00351
00352
00353
00354 xcf_io >> layer.hierarchy_offset >> layer.mask_offset;
00355
00356
00357
00358
00359 if( !composeTiles(xcf_image))
00360 return false;
00361 xcf_io.device()->seek(layer.hierarchy_offset);
00362
00363
00364
00365
00366
00367 layer.assignBytes = assignImageBytes;
00368
00369 if (!loadHierarchy(xcf_io, layer))
00370 return false;
00371
00372 if (layer.mask_offset != 0) {
00373 xcf_io.device()->seek(layer.mask_offset);
00374
00375 if (!loadMask(xcf_io, layer))
00376 return false;
00377 }
00378
00379
00380
00381
00382
00383 if (!xcf_image.initialized) {
00384 if( !initializeImage(xcf_image))
00385 return false;
00386 copyLayerToImage(xcf_image);
00387 xcf_image.initialized = true;
00388 } else
00389 mergeLayerIntoImage(xcf_image);
00390
00391 return true;
00392 }
00393
00394
00402 bool XCFImageFormat::loadLayerProperties(QDataStream& xcf_io, Layer& layer)
00403 {
00404 while (true) {
00405 PropType type;
00406 QByteArray bytes;
00407
00408 if (!loadProperty(xcf_io, type, bytes)) {
00409 kDebug(399) << "XCF: error loading layer properties";
00410 return false;
00411 }
00412
00413 QDataStream property(bytes);
00414
00415 switch (type) {
00416 case PROP_END:
00417 return true;
00418
00419 case PROP_ACTIVE_LAYER:
00420 layer.active = true;
00421 break;
00422
00423 case PROP_OPACITY:
00424 property >> layer.opacity;
00425 break;
00426
00427 case PROP_VISIBLE:
00428 property >> layer.visible;
00429 break;
00430
00431 case PROP_LINKED:
00432 property >> layer.linked;
00433 break;
00434
00435 case PROP_PRESERVE_TRANSPARENCY:
00436 property >> layer.preserve_transparency;
00437 break;
00438
00439 case PROP_APPLY_MASK:
00440 property >> layer.apply_mask;
00441 break;
00442
00443 case PROP_EDIT_MASK:
00444 property >> layer.edit_mask;
00445 break;
00446
00447 case PROP_SHOW_MASK:
00448 property >> layer.show_mask;
00449 break;
00450
00451 case PROP_OFFSETS:
00452 property >> layer.x_offset >> layer.y_offset;
00453 break;
00454
00455 case PROP_MODE:
00456 property >> layer.mode;
00457 break;
00458
00459 case PROP_TATTOO:
00460 property >> layer.tattoo;
00461 break;
00462
00463 default:
00464 kDebug(399) << "XCF: unimplemented layer property " << type
00465 << ", size " << bytes.size() << endl;
00466 }
00467 }
00468 }
00469
00470
00476 bool XCFImageFormat::composeTiles(XCFImage& xcf_image)
00477 {
00478 Layer& layer(xcf_image.layer);
00479
00480 layer.nrows = (layer.height + TILE_HEIGHT - 1) / TILE_HEIGHT;
00481 layer.ncols = (layer.width + TILE_WIDTH - 1) / TILE_WIDTH;
00482
00483 layer.image_tiles.resize(layer.nrows);
00484
00485 if (layer.type == GRAYA_GIMAGE || layer.type == INDEXEDA_GIMAGE)
00486 layer.alpha_tiles.resize(layer.nrows);
00487
00488 if (layer.mask_offset != 0)
00489 layer.mask_tiles.resize(layer.nrows);
00490
00491 for (uint j = 0; j < layer.nrows; j++) {
00492 layer.image_tiles[j].resize(layer.ncols);
00493
00494 if (layer.type == GRAYA_GIMAGE || layer.type == INDEXEDA_GIMAGE)
00495 layer.alpha_tiles[j].resize(layer.ncols);
00496
00497 if (layer.mask_offset != 0)
00498 layer.mask_tiles[j].resize(layer.ncols);
00499 }
00500
00501 for (uint j = 0; j < layer.nrows; j++) {
00502 for (uint i = 0; i < layer.ncols; i++) {
00503
00504 uint tile_width = (i + 1) * TILE_WIDTH <= layer.width
00505 ? TILE_WIDTH : layer.width - i * TILE_WIDTH;
00506
00507 uint tile_height = (j + 1) * TILE_HEIGHT <= layer.height
00508 ? TILE_HEIGHT : layer.height - j * TILE_HEIGHT;
00509
00510
00511
00512
00513 switch (layer.type) {
00514 case RGB_GIMAGE:
00515 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_RGB32);
00516 layer.image_tiles[j][i].setNumColors(0);
00517 if( layer.image_tiles[j][i].isNull())
00518 return false;
00519 break;
00520
00521 case RGBA_GIMAGE:
00522 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_ARGB32);
00523 layer.image_tiles[j][i].setNumColors(0);
00524 if( layer.image_tiles[j][i].isNull())
00525 return false;
00526 break;
00527
00528 case GRAY_GIMAGE:
00529 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
00530 layer.image_tiles[j][i].setNumColors(256);
00531 if( layer.image_tiles[j][i].isNull())
00532 return false;
00533 setGrayPalette(layer.image_tiles[j][i]);
00534 break;
00535
00536 case GRAYA_GIMAGE:
00537 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
00538 layer.image_tiles[j][i].setNumColors(256);
00539 if( layer.image_tiles[j][i].isNull())
00540 return false;
00541 setGrayPalette(layer.image_tiles[j][i]);
00542
00543 layer.alpha_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
00544 layer.alpha_tiles[j][i].setNumColors(256);
00545 if( layer.alpha_tiles[j][i].isNull())
00546 return false;
00547 setGrayPalette(layer.alpha_tiles[j][i]);
00548 break;
00549
00550 case INDEXED_GIMAGE:
00551 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
00552 layer.image_tiles[j][i].setNumColors(xcf_image.num_colors);
00553 if( layer.image_tiles[j][i].isNull())
00554 return false;
00555 setPalette(xcf_image, layer.image_tiles[j][i]);
00556 break;
00557
00558 case INDEXEDA_GIMAGE:
00559 layer.image_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
00560 layer.image_tiles[j][i].setNumColors(xcf_image.num_colors);
00561 if( layer.image_tiles[j][i].isNull())
00562 return false;
00563 setPalette(xcf_image, layer.image_tiles[j][i]);
00564
00565 layer.alpha_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
00566 layer.alpha_tiles[j][i].setNumColors(256);
00567 if( layer.alpha_tiles[j][i].isNull())
00568 return false;
00569 setGrayPalette(layer.alpha_tiles[j][i]);
00570 }
00571
00572 if (layer.mask_offset != 0) {
00573 layer.mask_tiles[j][i] = QImage(tile_width, tile_height, QImage::Format_Indexed8);
00574 layer.mask_tiles[j][i].setNumColors(256);
00575 if( layer.mask_tiles[j][i].isNull())
00576 return false;
00577 setGrayPalette(layer.mask_tiles[j][i]);
00578 }
00579 }
00580 }
00581 return true;
00582 }
00583
00584
00591 void XCFImageFormat::setGrayPalette(QImage& image)
00592 {
00593 for (int i = 0; i < 256; i++)
00594 image.setColor(i, qRgb(i, i, i));
00595 }
00596
00597
00603 void XCFImageFormat::setPalette(XCFImage& xcf_image, QImage& image)
00604 {
00605 for (int i = 0; i < xcf_image.num_colors; i++)
00606 image.setColor(i, xcf_image.palette[i]);
00607 }
00608
00609
00617 void XCFImageFormat::assignImageBytes(Layer& layer, uint i, uint j)
00618 {
00619 uchar* tile = layer.tile;
00620
00621 switch (layer.type) {
00622 case RGB_GIMAGE:
00623 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
00624 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
00625 layer.image_tiles[j][i].setPixel(k, l,
00626 qRgb(tile[0], tile[1], tile[2]));
00627 tile += sizeof(QRgb);
00628 }
00629 }
00630 break;
00631
00632 case RGBA_GIMAGE:
00633 for ( int l = 0; l < layer.image_tiles[j][i].height(); l++ ) {
00634 for ( int k = 0; k < layer.image_tiles[j][i].width(); k++ ) {
00635 layer.image_tiles[j][i].setPixel(k, l,
00636 qRgba(tile[0], tile[1], tile[2], tile[3]));
00637 tile += sizeof(QRgb);
00638 }
00639 }
00640 break;
00641
00642 case GRAY_GIMAGE:
00643 case INDEXED_GIMAGE:
00644 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
00645 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
00646 layer.image_tiles[j][i].setPixel(k, l, tile[0]);
00647 tile += sizeof(QRgb);
00648 }
00649 }
00650 break;
00651
00652 case GRAYA_GIMAGE:
00653 case INDEXEDA_GIMAGE:
00654 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
00655 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
00656
00657
00658
00659
00660
00661 if (tile[0] < layer.image_tiles[j][i].numColors())
00662 layer.image_tiles[j][i].setPixel(k, l, tile[0]);
00663
00664 layer.alpha_tiles[j][i].setPixel(k, l, tile[1]);
00665 tile += sizeof(QRgb);
00666 }
00667 }
00668 break;
00669 }
00670 }
00671
00672
00681 bool XCFImageFormat::loadHierarchy(QDataStream& xcf_io, Layer& layer)
00682 {
00683 qint32 width;
00684 qint32 height;
00685 qint32 bpp;
00686 quint32 offset;
00687
00688 xcf_io >> width >> height >> bpp >> offset;
00689
00690
00691
00692
00693
00694 quint32 junk;
00695 do {
00696 xcf_io >> junk;
00697
00698 if (xcf_io.device()->atEnd()) {
00699 kDebug(399) << "XCF: read failure on layer " << layer.name << " level offsets";
00700 return false;
00701 }
00702 } while (junk != 0);
00703
00704 qint64 saved_pos = xcf_io.device()->pos();
00705
00706 xcf_io.device()->seek(offset);
00707 if (!loadLevel(xcf_io, layer, bpp))
00708 return false;
00709
00710 xcf_io.device()->seek(saved_pos);
00711 return true;
00712 }
00713
00714
00723 bool XCFImageFormat::loadLevel(QDataStream& xcf_io, Layer& layer, qint32 bpp)
00724 {
00725 qint32 width;
00726 qint32 height;
00727 quint32 offset;
00728
00729 xcf_io >> width >> height >> offset;
00730
00731 if (offset == 0)
00732 return true;
00733
00734 for (uint j = 0; j < layer.nrows; j++) {
00735 for (uint i = 0; i < layer.ncols; i++) {
00736
00737 if (offset == 0) {
00738 kDebug(399) << "XCF: incorrect number of tiles in layer " << layer.name;
00739 return false;
00740 }
00741
00742 qint64 saved_pos = xcf_io.device()->pos();
00743 quint32 offset2;
00744 xcf_io >> offset2;
00745
00746
00747
00748 if (offset2 == 0)
00749 offset2 = offset + (uint)(TILE_WIDTH * TILE_HEIGHT * 4 * 1.5);
00750
00751 xcf_io.device()->seek(offset);
00752 int size = layer.image_tiles[j][i].width() * layer.image_tiles[j][i].height();
00753
00754 if (!loadTileRLE(xcf_io, layer.tile, size, offset2 - offset, bpp))
00755 return false;
00756
00757
00758
00759
00760
00761 layer.assignBytes(layer, i, j);
00762
00763 xcf_io.device()->seek(saved_pos);
00764 xcf_io >> offset;
00765 }
00766 }
00767
00768 return true;
00769 }
00770
00771
00778 bool XCFImageFormat::loadMask(QDataStream& xcf_io, Layer& layer)
00779 {
00780 qint32 width;
00781 qint32 height;
00782 char* name;
00783
00784 xcf_io >> width >> height >> name;
00785
00786 delete name;
00787
00788 if (!loadChannelProperties(xcf_io, layer))
00789 return false;
00790
00791 quint32 hierarchy_offset;
00792 xcf_io >> hierarchy_offset;
00793
00794 xcf_io.device()->seek(hierarchy_offset);
00795 layer.assignBytes = assignMaskBytes;
00796
00797 if (!loadHierarchy(xcf_io, layer))
00798 return false;
00799
00800 return true;
00801 }
00802
00803
00827 bool XCFImageFormat::loadTileRLE(QDataStream& xcf_io, uchar* tile, int image_size,
00828 int data_length, qint32 bpp)
00829 {
00830 uchar* data;
00831
00832 uchar* xcfdata;
00833 uchar* xcfodata;
00834 uchar* xcfdatalimit;
00835
00836 xcfdata = xcfodata = new uchar[data_length];
00837
00838 xcf_io.readRawData((char*)xcfdata, data_length);
00839
00840 if (!xcf_io.device()->isOpen()) {
00841 delete[] xcfodata;
00842 kDebug(399) << "XCF: read failure on tile";
00843 return false;
00844 }
00845
00846 xcfdatalimit = &xcfodata[data_length - 1];
00847
00848 for (int i = 0; i < bpp; ++i) {
00849
00850 data = tile + i;
00851
00852 int count = 0;
00853 int size = image_size;
00854
00855 while (size > 0) {
00856 if (xcfdata > xcfdatalimit)
00857 goto bogus_rle;
00858
00859 uchar val = *xcfdata++;
00860 uint length = val;
00861
00862 if (length >= 128) {
00863 length = 255 - (length - 1);
00864 if (length == 128) {
00865 if (xcfdata >= xcfdatalimit)
00866 goto bogus_rle;
00867
00868 length = (*xcfdata << 8) + xcfdata[1];
00869
00870 xcfdata += 2;
00871 }
00872
00873 count += length;
00874 size -= length;
00875
00876 if (size < 0)
00877 goto bogus_rle;
00878
00879 if (&xcfdata[length - 1] > xcfdatalimit)
00880 goto bogus_rle;
00881
00882 while (length-- > 0) {
00883 *data = *xcfdata++;
00884 data += sizeof(QRgb);
00885 }
00886 } else {
00887 length += 1;
00888 if (length == 128) {
00889 if (xcfdata >= xcfdatalimit)
00890 goto bogus_rle;
00891
00892 length = (*xcfdata << 8) + xcfdata[1];
00893 xcfdata += 2;
00894 }
00895
00896 count += length;
00897 size -= length;
00898
00899 if (size < 0)
00900 goto bogus_rle;
00901
00902 if (xcfdata > xcfdatalimit)
00903 goto bogus_rle;
00904
00905 val = *xcfdata++;
00906
00907 while (length-- > 0) {
00908 *data = val;
00909 data += sizeof(QRgb);
00910 }
00911 }
00912 }
00913 }
00914
00915 delete[] xcfodata;
00916 return true;
00917
00918 bogus_rle:
00919
00920 kDebug(399) << "The run length encoding could not be decoded properly";
00921 delete[] xcfodata;
00922 return false;
00923 }
00924
00925
00933 bool XCFImageFormat::loadChannelProperties(QDataStream& xcf_io, Layer& layer)
00934 {
00935 while (true) {
00936 PropType type;
00937 QByteArray bytes;
00938
00939 if (!loadProperty(xcf_io, type, bytes)) {
00940 kDebug(399) << "XCF: error loading channel properties";
00941 return false;
00942 }
00943
00944 QDataStream property(bytes);
00945
00946 switch (type) {
00947 case PROP_END:
00948 return true;
00949
00950 case PROP_OPACITY:
00951 property >> layer.mask_channel.opacity;
00952 break;
00953
00954 case PROP_VISIBLE:
00955 property >> layer.mask_channel.visible;
00956 break;
00957
00958 case PROP_SHOW_MASKED:
00959 property >> layer.mask_channel.show_masked;
00960 break;
00961
00962 case PROP_COLOR:
00963 property >> layer.mask_channel.red >> layer.mask_channel.green
00964 >> layer.mask_channel.blue;
00965 break;
00966
00967 case PROP_TATTOO:
00968 property >> layer.mask_channel.tattoo;
00969 break;
00970
00971 default:
00972 kDebug(399) << "XCF: unimplemented channel property " << type
00973 << ", size " << bytes.size() << endl;
00974 }
00975 }
00976 }
00977
00978
00985 void XCFImageFormat::assignMaskBytes(Layer& layer, uint i, uint j)
00986 {
00987 uchar* tile = layer.tile;
00988
00989 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
00990 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
00991 layer.mask_tiles[j][i].setPixel(k, l, tile[0]);
00992 tile += sizeof(QRgb);
00993 }
00994 }
00995 }
00996
00997
01026 bool XCFImageFormat::initializeImage(XCFImage& xcf_image)
01027 {
01028
01029 Layer& layer(xcf_image.layer);
01030 QImage& image(xcf_image.image);
01031
01032 switch (layer.type) {
01033 case RGB_GIMAGE:
01034 if (layer.opacity == OPAQUE_OPACITY) {
01035 image = QImage( xcf_image.width, xcf_image.height, QImage::Format_RGB32);
01036 if( image.isNull())
01037 return false;
01038 image.fill(qRgb(255, 255, 255));
01039 break;
01040 }
01041
01042 case RGBA_GIMAGE:
01043 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_ARGB32);
01044 if( image.isNull())
01045 return false;
01046 image.fill(qRgba(255, 255, 255, 0));
01047 break;
01048
01049 case GRAY_GIMAGE:
01050 if (layer.opacity == OPAQUE_OPACITY) {
01051 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_Indexed8);
01052 image.setNumColors(256);
01053 if( image.isNull())
01054 return false;
01055 setGrayPalette(image);
01056 image.fill(255);
01057 break;
01058 }
01059
01060 case GRAYA_GIMAGE:
01061 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_ARGB32);
01062 if( image.isNull())
01063 return false;
01064 image.fill(qRgba(255, 255, 255, 0));
01065 break;
01066
01067 case INDEXED_GIMAGE:
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080 if (xcf_image.num_colors <= 2) {
01081 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_MonoLSB);
01082 image.setNumColors(xcf_image.num_colors);
01083 if( image.isNull())
01084 return false;
01085 image.fill(0);
01086 setPalette(xcf_image, image);
01087 } else if (xcf_image.num_colors <= 256) {
01088 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_Indexed8);
01089 image.setNumColors(xcf_image.num_colors);
01090 if( image.isNull())
01091 return false;
01092 image.fill(0);
01093 setPalette(xcf_image, image);
01094 }
01095 break;
01096
01097 case INDEXEDA_GIMAGE:
01098 if (xcf_image.num_colors == 1) {
01099
01100 xcf_image.num_colors++;
01101 xcf_image.palette.resize(xcf_image.num_colors);
01102 xcf_image.palette[1] = xcf_image.palette[0];
01103 xcf_image.palette[0] = qRgba(255, 255, 255, 0);
01104
01105 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_MonoLSB);
01106 image.setNumColors(xcf_image.num_colors);
01107 if( image.isNull())
01108 return false;
01109 image.fill(0);
01110 setPalette(xcf_image, image);
01111 } else if (xcf_image.num_colors < 256) {
01112
01113 xcf_image.num_colors++;
01114 xcf_image.palette.resize(xcf_image.num_colors);
01115 for (int c = xcf_image.num_colors - 1; c >= 1; c--)
01116 xcf_image.palette[c] = xcf_image.palette[c - 1];
01117
01118 xcf_image.palette[0] = qRgba(255, 255, 255, 0);
01119 image = QImage( xcf_image.width, xcf_image.height, QImage::Format_Indexed8);
01120 image.setNumColors(xcf_image.num_colors);
01121 if( image.isNull())
01122 return false;
01123 image.fill(0);
01124 setPalette(xcf_image, image);
01125 } else {
01126
01127
01128
01129 image = QImage(xcf_image.width, xcf_image.height, QImage::Format_ARGB32);
01130 if( image.isNull())
01131 return false;
01132 image.fill(qRgba(255, 255, 255, 0));
01133 }
01134 break;
01135 }
01136
01137 image.setDotsPerMeterX((int)(xcf_image.x_resolution * INCHESPERMETER));
01138 image.setDotsPerMeterY((int)(xcf_image.y_resolution * INCHESPERMETER));
01139 return true;
01140 }
01141
01142
01148 void XCFImageFormat::copyLayerToImage(XCFImage& xcf_image)
01149 {
01150 Layer& layer(xcf_image.layer);
01151 QImage& image(xcf_image.image);
01152 PixelCopyOperation copy = 0;
01153
01154 switch (layer.type) {
01155 case RGB_GIMAGE:
01156 case RGBA_GIMAGE:
01157 copy = copyRGBToRGB;
01158 break;
01159 case GRAY_GIMAGE:
01160 if (layer.opacity == OPAQUE_OPACITY)
01161 copy = copyGrayToGray;
01162 else
01163 copy = copyGrayToRGB;
01164 break;
01165 case GRAYA_GIMAGE:
01166 copy = copyGrayAToRGB;
01167 break;
01168 case INDEXED_GIMAGE:
01169 copy = copyIndexedToIndexed;
01170 break;
01171 case INDEXEDA_GIMAGE:
01172 if (xcf_image.image.depth() <= 8)
01173 copy = copyIndexedAToIndexed;
01174 else
01175 copy = copyIndexedAToRGB;
01176 }
01177
01178
01179
01180 for (uint j = 0; j < layer.nrows; j++) {
01181 uint y = j * TILE_HEIGHT;
01182
01183 for (uint i = 0; i < layer.ncols; i++) {
01184 uint x = i * TILE_WIDTH;
01185
01186
01187
01188
01189
01190
01191 if (layer.mode == DISSOLVE_MODE) {
01192 if (layer.type == RGBA_GIMAGE)
01193 dissolveRGBPixels(layer.image_tiles[j][i], x, y);
01194
01195 else if (layer.type == GRAYA_GIMAGE)
01196 dissolveAlphaPixels(layer.alpha_tiles[j][i], x, y);
01197 }
01198
01199 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
01200 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
01201
01202 int m = x + k + layer.x_offset;
01203 int n = y + l + layer.y_offset;
01204
01205 if (m < 0 || m >= image.width() || n < 0 || n >= image.height())
01206 continue;
01207
01208 (*copy)(layer, i, j, k, l, image, m, n);
01209 }
01210 }
01211 }
01212 }
01213 }
01214
01215
01229 void XCFImageFormat::copyRGBToRGB(Layer& layer, uint i, uint j, int k, int l,
01230 QImage& image, int m, int n)
01231 {
01232 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01233 uchar src_a = layer.opacity;
01234
01235 if (layer.type == RGBA_GIMAGE)
01236 src_a = INT_MULT(src_a, qAlpha(src));
01237
01238
01239
01240 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
01241 layer.mask_tiles[j].size() > (int)i)
01242 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01243
01244 image.setPixel(m, n, qRgba(src, src_a));
01245 }
01246
01247
01259 void XCFImageFormat::copyGrayToGray(Layer& layer, uint i, uint j, int k, int l,
01260 QImage& image, int m, int n)
01261 {
01262 int src = layer.image_tiles[j][i].pixelIndex(k, l);
01263 image.setPixel(m, n, src);
01264 }
01265
01266
01280 void XCFImageFormat::copyGrayToRGB(Layer& layer, uint i, uint j, int k, int l,
01281 QImage& image, int m, int n)
01282 {
01283 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01284 uchar src_a = layer.opacity;
01285 image.setPixel(m, n, qRgba(src, src_a));
01286 }
01287
01288
01302 void XCFImageFormat::copyGrayAToRGB(Layer& layer, uint i, uint j, int k, int l,
01303 QImage& image, int m, int n)
01304 {
01305 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01306 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
01307 src_a = INT_MULT(src_a, layer.opacity);
01308
01309
01310
01311 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
01312 layer.mask_tiles[j].size() > (int)i)
01313 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01314
01315 image.setPixel(m, n, qRgba(src, src_a));
01316 }
01317
01318
01330 void XCFImageFormat::copyIndexedToIndexed(Layer& layer, uint i, uint j, int k, int l,
01331 QImage& image, int m, int n)
01332 {
01333 int src = layer.image_tiles[j][i].pixelIndex(k, l);
01334 image.setPixel(m, n, src);
01335 }
01336
01337
01349 void XCFImageFormat::copyIndexedAToIndexed(Layer& layer, uint i, uint j, int k, int l,
01350 QImage& image, int m, int n)
01351 {
01352 uchar src = layer.image_tiles[j][i].pixelIndex(k, l);
01353 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
01354 src_a = INT_MULT(src_a, layer.opacity);
01355
01356 if (layer.apply_mask == 1 &&
01357 layer.mask_tiles.size() > (int)j &&
01358 layer.mask_tiles[j].size() > (int)i)
01359 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01360
01361 if (src_a > 127)
01362 src++;
01363 else
01364 src = 0;
01365
01366 image.setPixel(m, n, src);
01367 }
01368
01369
01383 void XCFImageFormat::copyIndexedAToRGB(Layer& layer, uint i, uint j, int k, int l,
01384 QImage& image, int m, int n)
01385 {
01386 QRgb src = layer.image_tiles[j][i].pixel(k, l);
01387 uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
01388 src_a = INT_MULT(src_a, layer.opacity);
01389
01390
01391 if (layer.apply_mask == 1 && layer.mask_tiles.size() > (int)j &&
01392 layer.mask_tiles[j].size() > (int)i)
01393 src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
01394
01395
01396 if (src_a <= 127)
01397 src_a = 0;
01398 else
01399 src_a = OPAQUE_OPACITY;
01400
01401 image.setPixel(m, n, qRgba(src, src_a));
01402 }
01403
01404
01409 void XCFImageFormat::mergeLayerIntoImage(XCFImage& xcf_image)
01410 {
01411 Layer& layer(xcf_image.layer);
01412 QImage& image(xcf_image.image);
01413
01414 PixelMergeOperation merge = 0;
01415
01416 switch (layer.type) {
01417 case RGB_GIMAGE:
01418 case RGBA_GIMAGE:
01419 merge = mergeRGBToRGB;
01420 break;
01421 case GRAY_GIMAGE:
01422 if (layer.opacity == OPAQUE_OPACITY)
01423 merge = mergeGrayToGray;
01424 else
01425 merge = mergeGrayToRGB;
01426 break;
01427 case GRAYA_GIMAGE:
01428 if (xcf_image.image.depth() <= 8)
01429 merge = mergeGrayAToGray;
01430 else
01431 merge = mergeGrayAToRGB;
01432 break;
01433 case INDEXED_GIMAGE:
01434 merge = mergeIndexedToIndexed;
01435 break;
01436 case INDEXEDA_GIMAGE:
01437 if (xcf_image.image.depth() <= 8)
01438 merge = mergeIndexedAToIndexed;
01439 else
01440 merge = mergeIndexedAToRGB;
01441 }
01442
01443 for (uint j = 0; j < layer.nrows; j++) {
01444 uint y = j * TILE_HEIGHT;
01445
01446 for (uint i = 0; i < layer.ncols; i++) {
01447 uint x = i * TILE_WIDTH;
01448
01449
01450
01451
01452
01453
01454 if (layer.mode == DISSOLVE_MODE) {
01455 if (layer.type == RGBA_GIMAGE)
01456 dissolveRGBPixels(layer.image_tiles[j][i], x, y);
01457
01458 else if (layer.type == GRAYA_GIMAGE)
01459 dissolveAlphaPixels(layer.alpha_tiles[j][i], x, y);
01460 }
01461
01462 for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
01463 for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
01464
01465 int m = x + k + layer.x_offset;
01466 int n = y + l + layer.y_offset;
01467
01468 if (m < 0 || m >= image.width() || n < 0 || n >= image.height())
01469 continue;
01470
01471 (*merge)(layer, i, j, k, l, image, m, n);
01472 }
01473 }
01474 }
01475 }
01476 }
01477
01478
01492 void XCFImageFormat::mergeRGBToRGB(Layer& layer, uint i, uint j, int k, int l,
01493 QImage& image, int m, int n)
01494 {