• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kimgio
 

kimgio

  • kimgio
xcf.cpp
1 /*
2  * qxcfi.cpp: A Qt 3 plug-in for reading GIMP XCF image files
3  * Copyright (C) 2001 lignum Computing, Inc. <allen@lignumcomputing.com>
4  * Copyright (C) 2004 Melchior FRANZ <mfranz@kde.org>
5  *
6  * This plug-in is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  *
20  */
21 
22 #include <stdlib.h>
23 #include <tqimage.h>
24 #include <tqiodevice.h>
25 #include <tqvaluestack.h>
26 #include <tqvaluevector.h>
27 
28 #include <kdebug.h>
29 #include "xcf.h"
30 
31 
33 
34 
35 KDE_EXPORT void kimgio_xcf_read(TQImageIO *io)
36 {
37  XCFImageFormat xcfif;
38  xcfif.readXCF(io);
39 }
40 
41 
42 KDE_EXPORT void kimgio_xcf_write(TQImageIO *io)
43 {
44  kdDebug(399) << "XCF: write support not implemented" << endl;
45  io->setStatus(-1);
46 }
47 
49 
50 
51 
52 int XCFImageFormat::random_table[RANDOM_TABLE_SIZE];
53 
54 //int XCFImageFormat::add_lut[256][256];
55 
56 
57 const XCFImageFormat::LayerModes XCFImageFormat::layer_modes[] = {
58  {true}, // NORMAL_MODE
59  {true}, // DISSOLVE_MODE
60  {true}, // BEHIND_MODE
61  {false}, // MULTIPLY_MODE
62  {false}, // SCREEN_MODE
63  {false}, // OVERLAY_MODE
64  {false}, // DIFFERENCE_MODE
65  {false}, // ADDITION_MODE
66  {false}, // SUBTRACT_MODE
67  {false}, // DARKEN_ONLY_MODE
68  {false}, // LIGHTEN_ONLY_MODE
69  {false}, // HUE_MODE
70  {false}, // SATURATION_MODE
71  {false}, // COLOR_MODE
72  {false}, // VALUE_MODE
73  {false}, // DIVIDE_MODE
74  {true}, // ERASE_MODE
75  {true}, // REPLACE_MODE
76  {true}, // ANTI_ERASE_MODE
77 };
78 
79 
81 inline QRgb tqRgba ( QRgb rgb, int a )
82 {
83  return ((a & 0xff) << 24 | (rgb & TQRGB_MASK));
84 }
85 
86 
91 XCFImageFormat::XCFImageFormat()
92 {
93  // From GIMP "paint_funcs.c" v1.2
94  srand(RANDOM_SEED);
95 
96  for (int i = 0; i < RANDOM_TABLE_SIZE; i++)
97  random_table[i] = rand();
98 
99  for (int i = 0; i < RANDOM_TABLE_SIZE; i++) {
100  int tmp;
101  int swap = i + rand() % (RANDOM_TABLE_SIZE - i);
102  tmp = random_table[i];
103  random_table[i] = random_table[swap];
104  random_table[swap] = tmp;
105  }
106 
107 // for (int j = 0; j < 256; j++) {
108 // for (int k = 0; k < 256; k++) {
109 // int tmp_sum = j + k;
110 // if (tmp_sum > 255)
111 // tmp_sum = 255;
112 // add_lut[j][k] = tmp_sum;
113 // }
114 // }
115 }
116 
117 inline
118 int XCFImageFormat::add_lut( int a, int b ) {
119  return TQMIN( a + b, 255 );
120 }
121 
122 void XCFImageFormat::readXCF(TQImageIO *io)
123 {
124  XCFImage xcf_image;
125  TQDataStream xcf_io(io->ioDevice());
126 
127  char tag[14];
128  xcf_io.readRawBytes(tag, sizeof(tag));
129 
130  if (xcf_io.device()->status() != IO_Ok) {
131  kdDebug(399) << "XCF: read failure on header tag" << endl;
132  return;
133  }
134 
135  xcf_io >> xcf_image.width >> xcf_image.height >> xcf_image.type;
136 
137  if (xcf_io.device()->status() != IO_Ok) {
138  kdDebug(399) << "XCF: read failure on image info" << endl;
139  return;
140  }
141 
142 kdDebug() << tag << " " << xcf_image.width << " " << xcf_image.height << " " << xcf_image.type << endl;
143  if (!loadImageProperties(xcf_io, xcf_image))
144  return;
145 
146  // The layers appear to be stored in top-to-bottom order. This is
147  // the reverse of how a merged image must be computed. So, the layer
148  // offsets are pushed onto a LIFO stack (thus, we don't have to load
149  // all the data of all layers before beginning to construct the
150  // merged image).
151 
152  TQValueStack<TQ_INT32> layer_offsets;
153 
154  while (true) {
155  TQ_INT32 layer_offset;
156 
157  xcf_io >> layer_offset;
158 
159  if (xcf_io.device()->status() != IO_Ok) {
160  kdDebug(399) << "XCF: read failure on layer offsets" << endl;
161  return;
162  }
163 
164  if (layer_offset == 0)
165  break;
166 
167  layer_offsets.push(layer_offset);
168  }
169 
170  xcf_image.num_layers = layer_offsets.size();
171 
172  if (layer_offsets.size() == 0) {
173  kdDebug(399) << "XCF: no layers!" << endl;
174  return;
175  }
176 
177  // Load each layer and add it to the image
178  while (!layer_offsets.isEmpty()) {
179  TQ_INT32 layer_offset = layer_offsets.pop();
180 
181  xcf_io.device()->at(layer_offset);
182 
183  if (!loadLayer(xcf_io, xcf_image))
184  return;
185  }
186 
187  if (!xcf_image.initialized) {
188  kdDebug(399) << "XCF: no visible layers!" << endl;
189  return;
190  }
191 
192  io->setImage(xcf_image.image);
193  io->setStatus(0);
194 }
195 
196 
204 bool XCFImageFormat::loadImageProperties(TQDataStream& xcf_io, XCFImage& xcf_image)
205 {
206  while (true) {
207  PropType type;
208  TQByteArray bytes;
209 
210  if (!loadProperty(xcf_io, type, bytes)) {
211  kdDebug(399) << "XCF: error loading global image properties" << endl;
212  return false;
213  }
214 
215  TQDataStream property(bytes, IO_ReadOnly);
216 
217  switch (type) {
218  case PROP_END:
219  return true;
220 
221  case PROP_COMPRESSION:
222  property >> xcf_image.compression;
223  break;
224 
225  case PROP_RESOLUTION:
226  property >> xcf_image.x_resolution >> xcf_image.y_resolution;
227  break;
228 
229  case PROP_TATTOO:
230  property >> xcf_image.tattoo;
231  break;
232 
233  case PROP_PARASITES:
234  while (!property.atEnd()) {
235  char* tag;
236  TQ_UINT32 size;
237 
238  property.readBytes(tag, size);
239 
240  TQ_UINT32 flags;
241  char* data=0;
242  property >> flags >> data;
243 
244  if (tag && strncmp(tag, "gimp-comment", strlen("gimp-comment")) == 0)
245  xcf_image.image.setText("Comment", 0, data);
246 
247  delete[] tag;
248  delete[] data;
249  }
250  break;
251 
252  case PROP_UNIT:
253  property >> xcf_image.unit;
254  break;
255 
256  case PROP_PATHS: // This property is ignored.
257  break;
258 
259  case PROP_USER_UNIT: // This property is ignored.
260  break;
261 
262  case PROP_COLORMAP:
263  property >> xcf_image.num_colors;
264  if(xcf_image.num_colors < 0 || xcf_image.num_colors > 65535)
265  return false;
266 
267  xcf_image.palette.reserve(xcf_image.num_colors);
268 
269  for (int i = 0; i < xcf_image.num_colors; i++) {
270  uchar r, g, b;
271  property >> r >> g >> b;
272  xcf_image.palette.push_back( tqRgb(r,g,b) );
273  }
274  break;
275 
276  default:
277  kdDebug(399) << "XCF: unimplemented image property" << type
278  << ", size " << bytes.size() << endl;
279  }
280  }
281 }
282 
283 
291 bool XCFImageFormat::loadProperty(TQDataStream& xcf_io, PropType& type, TQByteArray& bytes)
292 {
293  TQ_UINT32 foo;
294  xcf_io >> foo;
295  type=PropType(foo); // TODO urks
296 
297  if (xcf_io.device()->status() != IO_Ok) {
298  kdDebug(399) << "XCF: read failure on property type" << type << endl;
299  return false;
300  }
301 
302  char* data;
303  TQ_UINT32 size;
304 
305  // The colormap property size is not the correct number of bytes:
306  // The GIMP source xcf.c has size = 4 + ncolors, but it should be
307  // 4 + 3 * ncolors
308 
309  if (type == PROP_COLORMAP) {
310  xcf_io >> size;
311 
312  if (xcf_io.device()->status() != IO_Ok) {
313  kdDebug(399) << "XCF: read failure on property " << type << " size" << endl;
314  return false;
315  }
316 
317  if(size > 65535 || size < 4)
318  return false;
319 
320  size = 3 * (size - 4) + 4;
321  data = new char[size];
322 
323  xcf_io.readRawBytes(data, size);
324  } else if (type == PROP_USER_UNIT) {
325  // The USER UNIT property size is not correct. I'm not sure why, though.
326  float factor;
327  TQ_INT32 digits;
328  char* unit_strings;
329 
330  xcf_io >> size >> factor >> digits;
331 
332  if (xcf_io.device()->status() != IO_Ok) {
333  kdDebug(399) << "XCF: read failure on property " << type << endl;
334  return false;
335  }
336 
337  for (int i = 0; i < 5; i++) {
338  xcf_io >> unit_strings;
339 
340  if (xcf_io.device()->status() != IO_Ok) {
341  kdDebug(399) << "XCF: read failure on property " << type << endl;
342  return false;
343  }
344 
345  delete[] unit_strings;
346  }
347 
348  size = 0;
349  } else {
350  xcf_io >> size;
351  if(size >256000)
352  return false;
353  data = new char[size];
354  xcf_io.readRawBytes(data, size);
355  }
356 
357  if (xcf_io.device()->status() != IO_Ok) {
358  kdDebug(399) << "XCF: read failure on property " << type << " data, size " << size << endl;
359  return false;
360  }
361 
362  if (size != 0 && data) {
363  bytes.assign(data,size);
364  }
365 
366  return true;
367 }
368 
369 
378 bool XCFImageFormat::loadLayer(TQDataStream& xcf_io, XCFImage& xcf_image)
379 {
380  Layer& layer(xcf_image.layer);
381  delete[] layer.name;
382 
383  xcf_io >> layer.width >> layer.height >> layer.type >> layer.name;
384 
385  if (xcf_io.device()->status() != IO_Ok) {
386  kdDebug(399) << "XCF: read failure on layer" << endl;
387  return false;
388  }
389 
390  if (!loadLayerProperties(xcf_io, layer))
391  return false;
392 #if 0
393  cout << "layer: \"" << layer.name << "\", size: " << layer.width << " x "
394  << layer.height << ", type: " << layer.type << ", mode: " << layer.mode
395  << ", opacity: " << layer.opacity << ", visible: " << layer.visible
396  << ", offset: " << layer.x_offset << ", " << layer.y_offset << endl;
397 #endif
398  // Skip reading the rest of it if it is not visible. Typically, when
399  // you export an image from the The GIMP it flattens (or merges) only
400  // the visible layers into the output image.
401 
402  if (layer.visible == 0)
403  return true;
404 
405  // If there are any more layers, merge them into the final TQImage.
406 
407  xcf_io >> layer.hierarchy_offset >> layer.mask_offset;
408  if (xcf_io.device()->status() != IO_Ok) {
409  kdDebug(399) << "XCF: read failure on layer image offsets" << endl;
410  return false;
411  }
412 
413  // Allocate the individual tile QImages based on the size and type
414  // of this layer.
415 
416  if( !composeTiles(xcf_image))
417  return false;
418  xcf_io.device()->at(layer.hierarchy_offset);
419 
420  // As tiles are loaded, they are copied into the layers tiles by
421  // this routine. (loadMask(), below, uses a slightly different
422  // version of assignBytes().)
423 
424  layer.assignBytes = assignImageBytes;
425 
426  if (!loadHierarchy(xcf_io, layer))
427  return false;
428 
429  if (layer.mask_offset != 0) {
430  xcf_io.device()->at(layer.mask_offset);
431 
432  if (!loadMask(xcf_io, layer))
433  return false;
434  }
435 
436  // Now we should have enough information to initialize the final
437  // TQImage. The first visible layer determines the attributes
438  // of the TQImage.
439 
440  if (!xcf_image.initialized) {
441  if( !initializeImage(xcf_image))
442  return false;
443  copyLayerToImage(xcf_image);
444  xcf_image.initialized = true;
445  } else
446  mergeLayerIntoImage(xcf_image);
447 
448  return true;
449 }
450 
451 
459 bool XCFImageFormat::loadLayerProperties(TQDataStream& xcf_io, Layer& layer)
460 {
461  while (true) {
462  PropType type;
463  TQByteArray bytes;
464 
465  if (!loadProperty(xcf_io, type, bytes)) {
466  kdDebug(399) << "XCF: error loading layer properties" << endl;
467  return false;
468  }
469 
470  TQDataStream property(bytes, IO_ReadOnly);
471 
472  switch (type) {
473  case PROP_END:
474  return true;
475 
476  case PROP_ACTIVE_LAYER:
477  layer.active = true;
478  break;
479 
480  case PROP_OPACITY:
481  property >> layer.opacity;
482  break;
483 
484  case PROP_VISIBLE:
485  property >> layer.visible;
486  break;
487 
488  case PROP_LINKED:
489  property >> layer.linked;
490  break;
491 
492  case PROP_PRESERVE_TRANSPARENCY:
493  property >> layer.preserve_transparency;
494  break;
495 
496  case PROP_APPLY_MASK:
497  property >> layer.apply_mask;
498  break;
499 
500  case PROP_EDIT_MASK:
501  property >> layer.edit_mask;
502  break;
503 
504  case PROP_SHOW_MASK:
505  property >> layer.show_mask;
506  break;
507 
508  case PROP_OFFSETS:
509  property >> layer.x_offset >> layer.y_offset;
510  break;
511 
512  case PROP_MODE:
513  property >> layer.mode;
514  break;
515 
516  case PROP_TATTOO:
517  property >> layer.tattoo;
518  break;
519 
520  default:
521  kdDebug(399) << "XCF: unimplemented layer property " << type
522  << ", size " << bytes.size() << endl;
523  }
524  }
525 }
526 
527 
533 bool XCFImageFormat::composeTiles(XCFImage& xcf_image)
534 {
535  Layer& layer(xcf_image.layer);
536 
537  layer.nrows = (layer.height + TILE_HEIGHT - 1) / TILE_HEIGHT;
538  layer.ncols = (layer.width + TILE_WIDTH - 1) / TILE_WIDTH;
539 
540  layer.image_tiles.resize(layer.nrows);
541 
542  if (layer.type == GRAYA_GIMAGE || layer.type == INDEXEDA_GIMAGE)
543  layer.alpha_tiles.resize(layer.nrows);
544 
545  if (layer.mask_offset != 0)
546  layer.mask_tiles.resize(layer.nrows);
547 
548  for (uint j = 0; j < layer.nrows; j++) {
549  layer.image_tiles[j].resize(layer.ncols);
550 
551  if (layer.type == GRAYA_GIMAGE || layer.type == INDEXEDA_GIMAGE)
552  layer.alpha_tiles[j].resize(layer.ncols);
553 
554  if (layer.mask_offset != 0)
555  layer.mask_tiles[j].resize(layer.ncols);
556  }
557 
558  for (uint j = 0; j < layer.nrows; j++) {
559  for (uint i = 0; i < layer.ncols; i++) {
560 
561  uint tile_width = (i + 1) * TILE_WIDTH <= layer.width
562  ? TILE_WIDTH : layer.width - i * TILE_WIDTH;
563 
564  uint tile_height = (j + 1) * TILE_HEIGHT <= layer.height
565  ? TILE_HEIGHT : layer.height - j * TILE_HEIGHT;
566 
567  // Try to create the most appropriate TQImage (each GIMP layer
568  // type is treated slightly differently)
569 
570  switch (layer.type) {
571  case RGB_GIMAGE:
572  layer.image_tiles[j][i] = TQImage(tile_width, tile_height, 32, 0);
573  if( layer.image_tiles[j][i].isNull())
574  return false;
575  layer.image_tiles[j][i].setAlphaBuffer(false);
576  break;
577 
578  case RGBA_GIMAGE:
579  layer.image_tiles[j][i] = TQImage(tile_width, tile_height, 32, 0);
580  if( layer.image_tiles[j][i].isNull())
581  return false;
582  layer.image_tiles[j][i].setAlphaBuffer(true);
583  break;
584 
585  case GRAY_GIMAGE:
586  layer.image_tiles[j][i] = TQImage(tile_width, tile_height, 8, 256);
587  if( layer.image_tiles[j][i].isNull())
588  return false;
589  setGrayPalette(layer.image_tiles[j][i]);
590  break;
591 
592  case GRAYA_GIMAGE:
593  layer.image_tiles[j][i] = TQImage(tile_width, tile_height, 8, 256);
594  if( layer.image_tiles[j][i].isNull())
595  return false;
596  setGrayPalette(layer.image_tiles[j][i]);
597 
598  layer.alpha_tiles[j][i] = TQImage( tile_width, tile_height, 8, 256);
599  if( layer.alpha_tiles[j][i].isNull())
600  return false;
601  setGrayPalette(layer.alpha_tiles[j][i]);
602  break;
603 
604  case INDEXED_GIMAGE:
605  layer.image_tiles[j][i] = TQImage(tile_width, tile_height, 8,
606  xcf_image.num_colors);
607  if( layer.image_tiles[j][i].isNull())
608  return false;
609  setPalette(xcf_image, layer.image_tiles[j][i]);
610  break;
611 
612  case INDEXEDA_GIMAGE:
613  layer.image_tiles[j][i] = TQImage(tile_width, tile_height,8,
614  xcf_image.num_colors);
615  if( layer.image_tiles[j][i].isNull())
616  return false;
617  setPalette(xcf_image, layer.image_tiles[j][i]);
618 
619  layer.alpha_tiles[j][i] = TQImage(tile_width, tile_height, 8, 256);
620  if( layer.alpha_tiles[j][i].isNull())
621  return false;
622  setGrayPalette(layer.alpha_tiles[j][i]);
623  }
624 
625  if (layer.mask_offset != 0) {
626  layer.mask_tiles[j][i] = TQImage(tile_width, tile_height, 8, 256);
627  if( layer.mask_tiles[j][i].isNull())
628  return false;
629  setGrayPalette(layer.mask_tiles[j][i]);
630  }
631  }
632  }
633  return true;
634 }
635 
636 
643 void XCFImageFormat::setGrayPalette(TQImage& image)
644 {
645  for (int i = 0; i < 256; i++)
646  image.setColor(i, tqRgb(i, i, i));
647 }
648 
649 
655 void XCFImageFormat::setPalette(XCFImage& xcf_image, TQImage& image)
656 {
657  for (int i = 0; i < xcf_image.num_colors; i++)
658  image.setColor(i, xcf_image.palette[i]);
659 }
660 
661 
669 void XCFImageFormat::assignImageBytes(Layer& layer, uint i, uint j)
670 {
671  uchar* tile = layer.tile;
672 
673  switch (layer.type) {
674  case RGB_GIMAGE:
675  for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
676  for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
677  layer.image_tiles[j][i].setPixel(k, l,
678  tqRgb(tile[0], tile[1], tile[2]));
679  tile += sizeof(QRgb);
680  }
681  }
682  break;
683 
684  case RGBA_GIMAGE:
685  for ( int l = 0; l < layer.image_tiles[j][i].height(); l++ ) {
686  for ( int k = 0; k < layer.image_tiles[j][i].width(); k++ ) {
687  layer.image_tiles[j][i].setPixel(k, l,
688  tqRgba(tile[0], tile[1], tile[2], tile[3]));
689  tile += sizeof(QRgb);
690  }
691  }
692  break;
693 
694  case GRAY_GIMAGE:
695  case INDEXED_GIMAGE:
696  for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
697  for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
698  layer.image_tiles[j][i].setPixel(k, l, tile[0]);
699  tile += sizeof(QRgb);
700  }
701  }
702  break;
703 
704  case GRAYA_GIMAGE:
705  case INDEXEDA_GIMAGE:
706  for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
707  for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
708 
709  // The "if" here should not be necessary, but apparently there
710  // are some cases where the image can contain larger indices
711  // than there are colors in the palette. (A bug in The GIMP?)
712 
713  if (tile[0] < layer.image_tiles[j][i].numColors())
714  layer.image_tiles[j][i].setPixel(k, l, tile[0]);
715 
716  layer.alpha_tiles[j][i].setPixel(k, l, tile[1]);
717  tile += sizeof(QRgb);
718  }
719  }
720  break;
721  }
722 }
723 
724 
733 bool XCFImageFormat::loadHierarchy(TQDataStream& xcf_io, Layer& layer)
734 {
735  TQ_INT32 width;
736  TQ_INT32 height;
737  TQ_INT32 bpp;
738  TQ_UINT32 offset;
739 
740  xcf_io >> width >> height >> bpp >> offset;
741 
742  if (xcf_io.device()->status() != IO_Ok) {
743  kdDebug(399) << "XCF: read failure on layer " << layer.name << " image header" << endl;
744  return false;
745  }
746 
747  // GIMP stores images in a "mipmap"-like format (multiple levels of
748  // increasingly lower resolution). Only the top level is used here,
749  // however.
750 
751  TQ_UINT32 junk;
752  do {
753  xcf_io >> junk;
754 
755  if (xcf_io.device()->status() != IO_Ok) {
756  kdDebug(399) << "XCF: read failure on layer " << layer.name << " level offsets" << endl;
757  return false;
758  }
759  } while (junk != 0);
760 
761  TQIODevice::Offset saved_pos = xcf_io.device()->at();
762 
763  xcf_io.device()->at(offset);
764  if (!loadLevel(xcf_io, layer, bpp))
765  return false;
766 
767  xcf_io.device()->at(saved_pos);
768  return true;
769 }
770 
771 
780 bool XCFImageFormat::loadLevel(TQDataStream& xcf_io, Layer& layer, TQ_INT32 bpp)
781 {
782  TQ_INT32 width;
783  TQ_INT32 height;
784  TQ_UINT32 offset;
785 
786  xcf_io >> width >> height >> offset;
787 
788  if (xcf_io.device()->status() != IO_Ok) {
789  kdDebug(399) << "XCF: read failure on layer " << layer.name << " level info" << endl;
790  return false;
791  }
792 
793  if (offset == 0)
794  return true;
795 
796  for (uint j = 0; j < layer.nrows; j++) {
797  for (uint i = 0; i < layer.ncols; i++) {
798 
799  if (offset == 0) {
800  kdDebug(399) << "XCF: incorrect number of tiles in layer " << layer.name << endl;
801  return false;
802  }
803 
804  TQIODevice::Offset saved_pos = xcf_io.device()->at();
805  TQ_UINT32 offset2;
806  xcf_io >> offset2;
807 
808  if (xcf_io.device()->status() != IO_Ok) {
809  kdDebug(399) << "XCF: read failure on layer " << layer.name << " level offset look-ahead" << endl;
810  return false;
811  }
812 
813  // Evidently, RLE can occasionally expand a tile instead of compressing it!
814 
815  if (offset2 == 0)
816  offset2 = offset + (uint)(TILE_WIDTH * TILE_HEIGHT * 4 * 1.5);
817 
818  xcf_io.device()->at(offset);
819  int size = layer.image_tiles[j][i].width() * layer.image_tiles[j][i].height();
820 
821  if (!loadTileRLE(xcf_io, layer.tile, size, offset2 - offset, bpp))
822  return false;
823 
824  // The bytes in the layer tile are juggled differently depending on
825  // the target TQImage. The caller has set layer.assignBytes to the
826  // appropriate routine.
827 
828  layer.assignBytes(layer, i, j);
829 
830  xcf_io.device()->at(saved_pos);
831  xcf_io >> offset;
832 
833  if (xcf_io.device()->status() != IO_Ok) {
834  kdDebug(399) << "XCF: read failure on layer " << layer.name << " level offset" << endl;
835  return false;
836  }
837  }
838  }
839 
840  return true;
841 }
842 
843 
850 bool XCFImageFormat::loadMask(TQDataStream& xcf_io, Layer& layer)
851 {
852  TQ_INT32 width;
853  TQ_INT32 height;
854  char* name;
855 
856  xcf_io >> width >> height >> name;
857 
858  if (xcf_io.device()->status() != IO_Ok) {
859  kdDebug(399) << "XCF: read failure on mask info" << endl;
860  return false;
861  }
862 
863  delete name;
864 
865  if (!loadChannelProperties(xcf_io, layer))
866  return false;
867 
868  TQ_UINT32 hierarchy_offset;
869  xcf_io >> hierarchy_offset;
870 
871  if (xcf_io.device()->status() != IO_Ok) {
872  kdDebug(399) << "XCF: read failure on mask image offset" << endl;
873  return false;
874  }
875 
876  xcf_io.device()->at(hierarchy_offset);
877  layer.assignBytes = assignMaskBytes;
878 
879  if (!loadHierarchy(xcf_io, layer))
880  return false;
881 
882  return true;
883 }
884 
885 
909 bool XCFImageFormat::loadTileRLE(TQDataStream& xcf_io, uchar* tile, int image_size,
910  int data_length, TQ_INT32 bpp)
911 {
912  uchar* data;
913 
914  uchar* xcfdata;
915  uchar* xcfodata;
916  uchar* xcfdatalimit;
917 
918  xcfdata = xcfodata = new uchar[data_length];
919 
920  xcf_io.readRawBytes((char*)xcfdata, data_length);
921 
922  if (xcf_io.device()->status() != IO_Ok) {
923  delete[] xcfodata;
924  kdDebug(399) << "XCF: read failure on tile" << endl;
925  return false;
926  }
927 
928  xcfdatalimit = &xcfodata[data_length - 1];
929 
930  for (int i = 0; i < bpp; ++i) {
931 
932  data = tile + i;
933 
934  int count = 0;
935  int size = image_size;
936 
937  while (size > 0) {
938  if (xcfdata > xcfdatalimit)
939  goto bogus_rle;
940 
941  uchar val = *xcfdata++;
942  uint length = val;
943 
944  if (length >= 128) {
945  length = 255 - (length - 1);
946  if (length == 128) {
947  if (xcfdata >= xcfdatalimit)
948  goto bogus_rle;
949 
950  length = (*xcfdata << 8) + xcfdata[1];
951 
952  xcfdata += 2;
953  }
954 
955  count += length;
956  size -= length;
957 
958  if (size < 0)
959  goto bogus_rle;
960 
961  if (&xcfdata[length - 1] > xcfdatalimit)
962  goto bogus_rle;
963 
964  while (length-- > 0) {
965  *data = *xcfdata++;
966  data += sizeof(QRgb);
967  }
968  } else {
969  length += 1;
970  if (length == 128) {
971  if (xcfdata >= xcfdatalimit)
972  goto bogus_rle;
973 
974  length = (*xcfdata << 8) + xcfdata[1];
975  xcfdata += 2;
976  }
977 
978  count += length;
979  size -= length;
980 
981  if (size < 0)
982  goto bogus_rle;
983 
984  if (xcfdata > xcfdatalimit)
985  goto bogus_rle;
986 
987  val = *xcfdata++;
988 
989  while (length-- > 0) {
990  *data = val;
991  data += sizeof(QRgb);
992  }
993  }
994  }
995  }
996 
997  delete[] xcfodata;
998  return true;
999 
1000 bogus_rle:
1001 
1002  kdDebug(399) << "The run length encoding could not be decoded properly" << endl;
1003  delete[] xcfodata;
1004  return false;
1005 }
1006 
1007 
1015 bool XCFImageFormat::loadChannelProperties(TQDataStream& xcf_io, Layer& layer)
1016 {
1017  while (true) {
1018  PropType type;
1019  TQByteArray bytes;
1020 
1021  if (!loadProperty(xcf_io, type, bytes)) {
1022  kdDebug(399) << "XCF: error loading channel properties" << endl;
1023  return false;
1024  }
1025 
1026  TQDataStream property(bytes, IO_ReadOnly);
1027 
1028  switch (type) {
1029  case PROP_END:
1030  return true;
1031 
1032  case PROP_OPACITY:
1033  property >> layer.mask_channel.opacity;
1034  break;
1035 
1036  case PROP_VISIBLE:
1037  property >> layer.mask_channel.visible;
1038  break;
1039 
1040  case PROP_SHOW_MASKED:
1041  property >> layer.mask_channel.show_masked;
1042  break;
1043 
1044  case PROP_COLOR:
1045  property >> layer.mask_channel.red >> layer.mask_channel.green
1046  >> layer.mask_channel.blue;
1047  break;
1048 
1049  case PROP_TATTOO:
1050  property >> layer.mask_channel.tattoo;
1051  break;
1052 
1053  default:
1054  kdDebug(399) << "XCF: unimplemented channel property " << type
1055  << ", size " << bytes.size() << endl;
1056  }
1057  }
1058 }
1059 
1060 
1067 void XCFImageFormat::assignMaskBytes(Layer& layer, uint i, uint j)
1068 {
1069  uchar* tile = layer.tile;
1070 
1071  for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
1072  for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
1073  layer.mask_tiles[j][i].setPixel(k, l, tile[0]);
1074  tile += sizeof(QRgb);
1075  }
1076  }
1077 }
1078 
1079 
1108 bool XCFImageFormat::initializeImage(XCFImage& xcf_image)
1109 {
1110  // (Aliases to make the code look a little better.)
1111  Layer& layer(xcf_image.layer);
1112  TQImage& image(xcf_image.image);
1113 
1114  switch (layer.type) {
1115  case RGB_GIMAGE:
1116  if (layer.opacity == OPAQUE_OPACITY) {
1117  image.create( xcf_image.width, xcf_image.height, 32);
1118  if( image.isNull())
1119  return false;
1120  image.fill(tqRgb(255, 255, 255));
1121  break;
1122  } // else, fall through to 32-bit representation
1123 
1124  case RGBA_GIMAGE:
1125  image.create(xcf_image.width, xcf_image.height, 32);
1126  if( image.isNull())
1127  return false;
1128  image.fill(tqRgba(255, 255, 255, 0));
1129  // Turning this on prevents fill() from affecting the alpha channel,
1130  // by the way.
1131  image.setAlphaBuffer(true);
1132  break;
1133 
1134  case GRAY_GIMAGE:
1135  if (layer.opacity == OPAQUE_OPACITY) {
1136  image.create(xcf_image.width, xcf_image.height, 8, 256);
1137  if( image.isNull())
1138  return false;
1139  setGrayPalette(image);
1140  image.fill(255);
1141  break;
1142  } // else, fall through to 32-bit representation
1143 
1144  case GRAYA_GIMAGE:
1145  image.create(xcf_image.width, xcf_image.height, 32);
1146  if( image.isNull())
1147  return false;
1148  image.fill(tqRgba(255, 255, 255, 0));
1149  image.setAlphaBuffer(true);
1150  break;
1151 
1152  case INDEXED_GIMAGE:
1153  // As noted in the table above, there are quite a few combinations
1154  // which are possible with indexed images, depending on the
1155  // presense of transparency (note: not translucency, which is not
1156  // supported by The GIMP for indexed images) and the number of
1157  // individual colors.
1158 
1159  // Note: Qt treats a bitmap with a Black and White color palette
1160  // as a mask, so only the "on" bits are drawn, regardless of the
1161  // order color table entries. Otherwise (i.e., at least one of the
1162  // color table entries is not black or white), it obeys the one-
1163  // or two-color palette. Have to ask about this...
1164 
1165  if (xcf_image.num_colors <= 2) {
1166  image.create(xcf_image.width, xcf_image.height,
1167  1, xcf_image.num_colors,
1168  TQImage::LittleEndian);
1169  if( image.isNull())
1170  return false;
1171  image.fill(0);
1172  setPalette(xcf_image, image);
1173  } else if (xcf_image.num_colors <= 256) {
1174  image.create(xcf_image.width, xcf_image.height,
1175  8, xcf_image.num_colors,
1176  TQImage::LittleEndian);
1177  if( image.isNull())
1178  return false;
1179  image.fill(0);
1180  setPalette(xcf_image, image);
1181  }
1182  break;
1183 
1184  case INDEXEDA_GIMAGE:
1185  if (xcf_image.num_colors == 1) {
1186  // Plenty(!) of room to add a transparent color
1187  xcf_image.num_colors++;
1188  xcf_image.palette.resize(xcf_image.num_colors);
1189  xcf_image.palette[1] = xcf_image.palette[0];
1190  xcf_image.palette[0] = tqRgba(255, 255, 255, 0);
1191 
1192  image.create(xcf_image.width, xcf_image.height,
1193  1, xcf_image.num_colors,
1194  TQImage::LittleEndian);
1195  if( image.isNull())
1196  return false;
1197  image.fill(0);
1198  setPalette(xcf_image, image);
1199  image.setAlphaBuffer(true);
1200  } else if (xcf_image.num_colors < 256) {
1201  // Plenty of room to add a transparent color
1202  xcf_image.num_colors++;
1203  xcf_image.palette.resize(xcf_image.num_colors);
1204  for (int c = xcf_image.num_colors - 1; c >= 1; c--)
1205  xcf_image.palette[c] = xcf_image.palette[c - 1];
1206 
1207  xcf_image.palette[0] = tqRgba(255, 255, 255, 0);
1208  image.create( xcf_image.width, xcf_image.height,
1209  8, xcf_image.num_colors);
1210  if( image.isNull())
1211  return false;
1212  image.fill(0);
1213  setPalette(xcf_image, image);
1214  image.setAlphaBuffer(true);
1215  } else {
1216  // No room for a transparent color, so this has to be promoted to
1217  // true color. (There is no equivalent PNG representation output
1218  // from The GIMP as of v1.2.)
1219  image.create(xcf_image.width, xcf_image.height, 32);
1220  if( image.isNull())
1221  return false;
1222  image.fill(tqRgba(255, 255, 255, 0));
1223  image.setAlphaBuffer(true);
1224  }
1225  break;
1226  }
1227 
1228  image.setDotsPerMeterX((int)(xcf_image.x_resolution * INCHESPERMETER));
1229  image.setDotsPerMeterY((int)(xcf_image.y_resolution * INCHESPERMETER));
1230  return true;
1231 }
1232 
1233 
1239 void XCFImageFormat::copyLayerToImage(XCFImage& xcf_image)
1240 {
1241  Layer& layer(xcf_image.layer);
1242  TQImage& image(xcf_image.image);
1243  PixelCopyOperation copy = 0;
1244 
1245  switch (layer.type) {
1246  case RGB_GIMAGE:
1247  case RGBA_GIMAGE:
1248  copy = copyRGBToRGB;
1249  break;
1250  case GRAY_GIMAGE:
1251  if (layer.opacity == OPAQUE_OPACITY)
1252  copy = copyGrayToGray;
1253  else
1254  copy = copyGrayToRGB;
1255  break;
1256  case GRAYA_GIMAGE:
1257  copy = copyGrayAToRGB;
1258  break;
1259  case INDEXED_GIMAGE:
1260  copy = copyIndexedToIndexed;
1261  break;
1262  case INDEXEDA_GIMAGE:
1263  if (xcf_image.image.depth() <= 8)
1264  copy = copyIndexedAToIndexed;
1265  else
1266  copy = copyIndexedAToRGB;
1267  }
1268 
1269  // For each tile...
1270 
1271  for (uint j = 0; j < layer.nrows; j++) {
1272  uint y = j * TILE_HEIGHT;
1273 
1274  for (uint i = 0; i < layer.ncols; i++) {
1275  uint x = i * TILE_WIDTH;
1276 
1277  // This seems the best place to apply the dissolve because it
1278  // depends on the global position of each tile's
1279  // pixels. Apparently it's the only mode which can apply to a
1280  // single layer.
1281 
1282  if (layer.mode == DISSOLVE_MODE) {
1283  if (layer.type == RGBA_GIMAGE)
1284  dissolveRGBPixels(layer.image_tiles[j][i], x, y);
1285 
1286  else if (layer.type == GRAYA_GIMAGE)
1287  dissolveAlphaPixels(layer.alpha_tiles[j][i], x, y);
1288  }
1289 
1290  for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
1291  for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
1292 
1293  int m = x + k + layer.x_offset;
1294  int n = y + l + layer.y_offset;
1295 
1296  if (m < 0 || m >= image.width() || n < 0 || n >= image.height())
1297  continue;
1298 
1299  (*copy)(layer, i, j, k, l, image, m, n);
1300  }
1301  }
1302  }
1303  }
1304 }
1305 
1306 
1320 void XCFImageFormat::copyRGBToRGB(Layer& layer, uint i, uint j, int k, int l,
1321  TQImage& image, int m, int n)
1322 {
1323  QRgb src = layer.image_tiles[j][i].pixel(k, l);
1324  uchar src_a = layer.opacity;
1325 
1326  if (layer.type == RGBA_GIMAGE)
1327  src_a = INT_MULT(src_a, tqAlpha(src));
1328 
1329  // Apply the mask (if any)
1330 
1331  if (layer.apply_mask == 1 && layer.mask_tiles.size() > j &&
1332  layer.mask_tiles[j].size() > i)
1333  src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
1334 
1335  image.setPixel(m, n, tqRgba(src, src_a));
1336 }
1337 
1338 
1350 void XCFImageFormat::copyGrayToGray(Layer& layer, uint i, uint j, int k, int l,
1351  TQImage& image, int m, int n)
1352 {
1353  int src = layer.image_tiles[j][i].pixelIndex(k, l);
1354  image.setPixel(m, n, src);
1355 }
1356 
1357 
1371 void XCFImageFormat::copyGrayToRGB(Layer& layer, uint i, uint j, int k, int l,
1372  TQImage& image, int m, int n)
1373 {
1374  QRgb src = layer.image_tiles[j][i].pixel(k, l);
1375  uchar src_a = layer.opacity;
1376  image.setPixel(m, n, tqRgba(src, src_a));
1377 }
1378 
1379 
1393 void XCFImageFormat::copyGrayAToRGB(Layer& layer, uint i, uint j, int k, int l,
1394  TQImage& image, int m, int n)
1395 {
1396  QRgb src = layer.image_tiles[j][i].pixel(k, l);
1397  uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
1398  src_a = INT_MULT(src_a, layer.opacity);
1399 
1400  // Apply the mask (if any)
1401 
1402  if (layer.apply_mask == 1 && layer.mask_tiles.size() > j &&
1403  layer.mask_tiles[j].size() > i)
1404  src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
1405 
1406  image.setPixel(m, n, tqRgba(src, src_a));
1407 }
1408 
1409 
1421 void XCFImageFormat::copyIndexedToIndexed(Layer& layer, uint i, uint j, int k, int l,
1422  TQImage& image, int m, int n)
1423 {
1424  int src = layer.image_tiles[j][i].pixelIndex(k, l);
1425  image.setPixel(m, n, src);
1426 }
1427 
1428 
1440 void XCFImageFormat::copyIndexedAToIndexed(Layer& layer, uint i, uint j, int k, int l,
1441  TQImage& image, int m, int n)
1442 {
1443  uchar src = layer.image_tiles[j][i].pixelIndex(k, l);
1444  uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
1445  src_a = INT_MULT(src_a, layer.opacity);
1446 
1447  if (layer.apply_mask == 1 &&
1448  layer.mask_tiles.size() > j &&
1449  layer.mask_tiles[j].size() > i)
1450  src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
1451 
1452  if (src_a > 127)
1453  src++;
1454  else
1455  src = 0;
1456 
1457 image.setPixel(m, n, src);
1458 }
1459 
1460 
1474 void XCFImageFormat::copyIndexedAToRGB(Layer& layer, uint i, uint j, int k, int l,
1475  TQImage& image, int m, int n)
1476 {
1477  QRgb src = layer.image_tiles[j][i].pixel(k, l);
1478  uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
1479  src_a = INT_MULT(src_a, layer.opacity);
1480 
1481  // Apply the mask (if any)
1482  if (layer.apply_mask == 1 && layer.mask_tiles.size() > j &&
1483  layer.mask_tiles[j].size() > i)
1484  src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
1485 
1486  // This is what appears in the GIMP window
1487  if (src_a <= 127)
1488  src_a = 0;
1489  else
1490  src_a = OPAQUE_OPACITY;
1491 
1492  image.setPixel(m, n, tqRgba(src, src_a));
1493 }
1494 
1495 
1500 void XCFImageFormat::mergeLayerIntoImage(XCFImage& xcf_image)
1501 {
1502  Layer& layer(xcf_image.layer);
1503  TQImage& image(xcf_image.image);
1504 
1505  PixelMergeOperation merge = 0;
1506 
1507  switch (layer.type) {
1508  case RGB_GIMAGE:
1509  case RGBA_GIMAGE:
1510  merge = mergeRGBToRGB;
1511  break;
1512  case GRAY_GIMAGE:
1513  if (layer.opacity == OPAQUE_OPACITY)
1514  merge = mergeGrayToGray;
1515  else
1516  merge = mergeGrayToRGB;
1517  break;
1518  case GRAYA_GIMAGE:
1519  if (xcf_image.image.depth() <= 8)
1520  merge = mergeGrayAToGray;
1521  else
1522  merge = mergeGrayAToRGB;
1523  break;
1524  case INDEXED_GIMAGE:
1525  merge = mergeIndexedToIndexed;
1526  break;
1527  case INDEXEDA_GIMAGE:
1528  if (xcf_image.image.depth() <= 8)
1529  merge = mergeIndexedAToIndexed;
1530  else
1531  merge = mergeIndexedAToRGB;
1532  }
1533 
1534  for (uint j = 0; j < layer.nrows; j++) {
1535  uint y = j * TILE_HEIGHT;
1536 
1537  for (uint i = 0; i < layer.ncols; i++) {
1538  uint x = i * TILE_WIDTH;
1539 
1540  // This seems the best place to apply the dissolve because it
1541  // depends on the global position of each tile's
1542  // pixels. Apparently it's the only mode which can apply to a
1543  // single layer.
1544 
1545  if (layer.mode == DISSOLVE_MODE) {
1546  if (layer.type == RGBA_GIMAGE)
1547  dissolveRGBPixels(layer.image_tiles[j][i], x, y);
1548 
1549  else if (layer.type == GRAYA_GIMAGE)
1550  dissolveAlphaPixels(layer.alpha_tiles[j][i], x, y);
1551  }
1552 
1553  for (int l = 0; l < layer.image_tiles[j][i].height(); l++) {
1554  for (int k = 0; k < layer.image_tiles[j][i].width(); k++) {
1555 
1556  int m = x + k + layer.x_offset;
1557  int n = y + l + layer.y_offset;
1558 
1559  if (m < 0 || m >= image.width() || n < 0 || n >= image.height())
1560  continue;
1561 
1562  (*merge)(layer, i, j, k, l, image, m, n);
1563  }
1564  }
1565  }
1566  }
1567 }
1568 
1569 
1583 void XCFImageFormat::mergeRGBToRGB(Layer& layer, uint i, uint j, int k, int l,
1584  TQImage& image, int m, int n)
1585 {
1586  QRgb src = layer.image_tiles[j][i].pixel(k, l);
1587  QRgb dst = image.pixel(m, n);
1588 
1589  uchar src_r = tqRed(src);
1590  uchar src_g = tqGreen(src);
1591  uchar src_b = tqBlue(src);
1592  uchar src_a = tqAlpha(src);
1593 
1594  uchar dst_r = tqRed(dst);
1595  uchar dst_g = tqGreen(dst);
1596  uchar dst_b = tqBlue(dst);
1597  uchar dst_a = tqAlpha(dst);
1598 
1599  switch (layer.mode) {
1600  case MULTIPLY_MODE: {
1601  src_r = INT_MULT(src_r, dst_r);
1602  src_g = INT_MULT(src_g, dst_g);
1603  src_b = INT_MULT(src_b, dst_b);
1604  src_a = KMIN(src_a, dst_a);
1605  }
1606  break;
1607  case DIVIDE_MODE: {
1608  src_r = KMIN((dst_r * 256) / (1 + src_r), 255);
1609  src_g = KMIN((dst_g * 256) / (1 + src_g), 255);
1610  src_b = KMIN((dst_b * 256) / (1 + src_b), 255);
1611  src_a = KMIN(src_a, dst_a);
1612  }
1613  break;
1614  case SCREEN_MODE: {
1615  src_r = 255 - INT_MULT(255 - dst_r, 255 - src_r);
1616  src_g = 255 - INT_MULT(255 - dst_g, 255 - src_g);
1617  src_b = 255 - INT_MULT(255 - dst_b, 255 - src_b);
1618  src_a = KMIN(src_a, dst_a);
1619  }
1620  break;
1621  case OVERLAY_MODE: {
1622  src_r = INT_MULT(dst_r, dst_r + INT_MULT(2 * src_r, 255 - dst_r));
1623  src_g = INT_MULT(dst_g, dst_g + INT_MULT(2 * src_g, 255 - dst_g));
1624  src_b = INT_MULT(dst_b, dst_b + INT_MULT(2 * src_b, 255 - dst_b));
1625  src_a = KMIN(src_a, dst_a);
1626  }
1627  break;
1628  case DIFFERENCE_MODE: {
1629  src_r = dst_r > src_r ? dst_r - src_r : src_r - dst_r;
1630  src_g = dst_g > src_g ? dst_g - src_g : src_g - dst_g;
1631  src_b = dst_b > src_b ? dst_b - src_b : src_b - dst_b;
1632  src_a = KMIN(src_a, dst_a);
1633  }
1634  break;
1635  case ADDITION_MODE: {
1636  src_r = add_lut(dst_r,src_r);
1637  src_g = add_lut(dst_g,src_g);
1638  src_b = add_lut(dst_b,src_b);
1639  src_a = KMIN(src_a, dst_a);
1640  }
1641  break;
1642  case SUBTRACT_MODE: {
1643  src_r = dst_r > src_r ? dst_r - src_r : 0;
1644  src_g = dst_g > src_g ? dst_g - src_g : 0;
1645  src_b = dst_b > src_b ? dst_b - src_b : 0;
1646  src_a = KMIN(src_a, dst_a);
1647  }
1648  break;
1649  case DARKEN_ONLY_MODE: {
1650  src_r = dst_r < src_r ? dst_r : src_r;
1651  src_g = dst_g < src_g ? dst_g : src_g;
1652  src_b = dst_b < src_b ? dst_b : src_b;
1653  src_a = KMIN( src_a, dst_a );
1654  }
1655  break;
1656  case LIGHTEN_ONLY_MODE: {
1657  src_r = dst_r < src_r ? src_r : dst_r;
1658  src_g = dst_g < src_g ? src_g : dst_g;
1659  src_b = dst_b < src_b ? src_b : dst_b;
1660  src_a = KMIN(src_a, dst_a);
1661  }
1662  break;
1663  case HUE_MODE: {
1664  uchar new_r = dst_r;
1665  uchar new_g = dst_g;
1666  uchar new_b = dst_b;
1667 
1668  RGBTOHSV(src_r, src_g, src_b);
1669  RGBTOHSV(new_r, new_g, new_b);
1670 
1671  new_r = src_r;
1672 
1673  HSVTORGB(new_r, new_g, new_b);
1674 
1675  src_r = new_r;
1676  src_g = new_g;
1677  src_b = new_b;
1678  src_a = KMIN( src_a, dst_a );
1679  }
1680  break;
1681  case SATURATION_MODE: {
1682  uchar new_r = dst_r;
1683  uchar new_g = dst_g;
1684  uchar new_b = dst_b;
1685 
1686  RGBTOHSV(src_r, src_g, src_b);
1687  RGBTOHSV(new_r, new_g, new_b);
1688 
1689  new_g = src_g;
1690 
1691  HSVTORGB(new_r, new_g, new_b);
1692 
1693  src_r = new_r;
1694  src_g = new_g;
1695  src_b = new_b;
1696  src_a = KMIN(src_a, dst_a);
1697  }
1698  break;
1699  case VALUE_MODE: {
1700  uchar new_r = dst_r;
1701  uchar new_g = dst_g;
1702  uchar new_b = dst_b;
1703 
1704  RGBTOHSV(src_r, src_g, src_b);
1705  RGBTOHSV(new_r, new_g, new_b);
1706 
1707  new_b = src_b;
1708 
1709  HSVTORGB(new_r, new_g, new_b);
1710 
1711  src_r = new_r;
1712  src_g = new_g;
1713  src_b = new_b;
1714  src_a = KMIN(src_a, dst_a);
1715  }
1716  break;
1717  case COLOR_MODE: {
1718  uchar new_r = dst_r;
1719  uchar new_g = dst_g;
1720  uchar new_b = dst_b;
1721 
1722  RGBTOHLS(src_r, src_g, src_b);
1723  RGBTOHLS(new_r, new_g, new_b);
1724 
1725  new_r = src_r;
1726  new_b = src_b;
1727 
1728  HLSTORGB(new_r, new_g, new_b);
1729 
1730  src_r = new_r;
1731  src_g = new_g;
1732  src_b = new_b;
1733  src_a = KMIN(src_a, dst_a);
1734  }
1735  break;
1736  }
1737 
1738  src_a = INT_MULT(src_a, layer.opacity);
1739 
1740  // Apply the mask (if any)
1741 
1742  if (layer.apply_mask == 1 && layer.mask_tiles.size() > j &&
1743  layer.mask_tiles[j].size() > i)
1744  src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
1745 
1746  uchar new_r, new_g, new_b, new_a;
1747  new_a = dst_a + INT_MULT(OPAQUE_OPACITY - dst_a, src_a);
1748 
1749  float src_ratio = (float)src_a / new_a;
1750  float dst_ratio = 1.0 - src_ratio;
1751 
1752  new_r = (uchar)(src_ratio * src_r + dst_ratio * dst_r + EPSILON);
1753  new_g = (uchar)(src_ratio * src_g + dst_ratio * dst_g + EPSILON);
1754  new_b = (uchar)(src_ratio * src_b + dst_ratio * dst_b + EPSILON);
1755 
1756  if (!layer_modes[layer.mode].affect_alpha)
1757  new_a = dst_a;
1758 
1759  image.setPixel(m, n, tqRgba(new_r, new_g, new_b, new_a));
1760 }
1761 
1762 
1774 void XCFImageFormat::mergeGrayToGray(Layer& layer, uint i, uint j, int k, int l,
1775  TQImage& image, int m, int n)
1776 {
1777  int src = layer.image_tiles[j][i].pixelIndex(k, l);
1778  image.setPixel(m, n, src);
1779 }
1780 
1781 
1793 void XCFImageFormat::mergeGrayAToGray(Layer& layer, uint i, uint j, int k, int l,
1794  TQImage& image, int m, int n)
1795 {
1796  int src = tqGray(layer.image_tiles[j][i].pixel(k, l));
1797  int dst = image.pixelIndex(m, n);
1798 
1799  uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
1800 
1801  switch (layer.mode) {
1802  case MULTIPLY_MODE: {
1803  src = INT_MULT( src, dst );
1804  }
1805  break;
1806  case DIVIDE_MODE: {
1807  src = KMIN((dst * 256) / (1 + src), 255);
1808  }
1809  break;
1810  case SCREEN_MODE: {
1811  src = 255 - INT_MULT(255 - dst, 255 - src);
1812  }
1813  break;
1814  case OVERLAY_MODE: {
1815  src = INT_MULT(dst, dst + INT_MULT(2 * src, 255 - dst));
1816  }
1817  break;
1818  case DIFFERENCE_MODE: {
1819  src = dst > src ? dst - src : src - dst;
1820  }
1821  break;
1822  case ADDITION_MODE: {
1823  src = add_lut(dst,src);
1824  }
1825  break;
1826  case SUBTRACT_MODE: {
1827  src = dst > src ? dst - src : 0;
1828  }
1829  break;
1830  case DARKEN_ONLY_MODE: {
1831  src = dst < src ? dst : src;
1832  }
1833  break;
1834  case LIGHTEN_ONLY_MODE: {
1835  src = dst < src ? src : dst;
1836  }
1837  break;
1838  }
1839 
1840  src_a = INT_MULT(src_a, layer.opacity);
1841 
1842  // Apply the mask (if any)
1843 
1844  if (layer.apply_mask == 1 && layer.mask_tiles.size() > j &&
1845  layer.mask_tiles[j].size() > i)
1846  src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
1847 
1848  uchar new_a = OPAQUE_OPACITY;
1849 
1850  float src_ratio = (float)src_a / new_a;
1851  float dst_ratio = 1.0 - src_ratio;
1852 
1853  uchar new_g = (uchar)(src_ratio * src + dst_ratio * dst + EPSILON);
1854 
1855  image.setPixel(m, n, new_g);
1856 }
1857 
1858 
1872 void XCFImageFormat::mergeGrayToRGB(Layer& layer, uint i, uint j, int k, int l,
1873  TQImage& image, int m, int n)
1874 {
1875  QRgb src = layer.image_tiles[j][i].pixel(k, l);
1876  uchar src_a = layer.opacity;
1877  image.setPixel(m, n, tqRgba(src, src_a));
1878 }
1879 
1880 
1894 void XCFImageFormat::mergeGrayAToRGB(Layer& layer, uint i, uint j, int k, int l,
1895  TQImage& image, int m, int n)
1896 {
1897  int src = tqGray(layer.image_tiles[j][i].pixel(k, l));
1898  int dst = tqGray(image.pixel(m, n));
1899 
1900  uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
1901  uchar dst_a = tqAlpha(image.pixel(m, n));
1902 
1903  switch (layer.mode) {
1904  case MULTIPLY_MODE: {
1905  src = INT_MULT(src, dst);
1906  src_a = KMIN(src_a, dst_a);
1907  }
1908  break;
1909  case DIVIDE_MODE: {
1910  src = KMIN((dst * 256) / (1 + src), 255);
1911  src_a = KMIN(src_a, dst_a);
1912  }
1913  break;
1914  case SCREEN_MODE: {
1915  src = 255 - INT_MULT(255 - dst, 255 - src);
1916  src_a = KMIN(src_a, dst_a);
1917  }
1918  break;
1919  case OVERLAY_MODE: {
1920  src = INT_MULT( dst, dst + INT_MULT(2 * src, 255 - dst));
1921  src_a = KMIN(src_a, dst_a);
1922  }
1923  break;
1924  case DIFFERENCE_MODE: {
1925  src = dst > src ? dst - src : src - dst;
1926  src_a = KMIN(src_a, dst_a);
1927  }
1928  break;
1929  case ADDITION_MODE: {
1930  src = add_lut(dst,src);
1931  src_a = KMIN(src_a, dst_a);
1932  }
1933  break;
1934  case SUBTRACT_MODE: {
1935  src = dst > src ? dst - src : 0;
1936  src_a = KMIN(src_a, dst_a);
1937  }
1938  break;
1939  case DARKEN_ONLY_MODE: {
1940  src = dst < src ? dst : src;
1941  src_a = KMIN(src_a, dst_a);
1942  }
1943  break;
1944  case LIGHTEN_ONLY_MODE: {
1945  src = dst < src ? src : dst;
1946  src_a = KMIN(src_a, dst_a);
1947  }
1948  break;
1949  }
1950 
1951  src_a = INT_MULT(src_a, layer.opacity);
1952 
1953  // Apply the mask (if any)
1954  if (layer.apply_mask == 1 && layer.mask_tiles.size() > j &&
1955  layer.mask_tiles[j].size() > i)
1956  src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
1957 
1958  uchar new_a = dst_a + INT_MULT(OPAQUE_OPACITY - dst_a, src_a);
1959 
1960  float src_ratio = (float)src_a / new_a;
1961  float dst_ratio = 1.0 - src_ratio;
1962 
1963  uchar new_g = (uchar)(src_ratio * src + dst_ratio * dst + EPSILON);
1964 
1965  if (!layer_modes[layer.mode].affect_alpha)
1966  new_a = dst_a;
1967 
1968  image.setPixel(m, n, tqRgba(new_g, new_g, new_g, new_a));
1969 }
1970 
1971 
1983 void XCFImageFormat::mergeIndexedToIndexed(Layer& layer, uint i, uint j, int k, int l,
1984  TQImage& image, int m, int n)
1985 {
1986  int src = layer.image_tiles[j][i].pixelIndex(k, l);
1987  image.setPixel(m, n, src);
1988 }
1989 
1990 
2002 void XCFImageFormat::mergeIndexedAToIndexed(Layer& layer, uint i, uint j, int k, int l,
2003  TQImage& image, int m, int n)
2004 {
2005  uchar src = layer.image_tiles[j][i].pixelIndex(k, l);
2006  uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
2007  src_a = INT_MULT( src_a, layer.opacity );
2008 
2009  if ( layer.apply_mask == 1 &&
2010  layer.mask_tiles.size() > j &&
2011  layer.mask_tiles[j].size() > i)
2012  src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
2013 
2014  if (src_a > 127) {
2015  src++;
2016  image.setPixel(m, n, src);
2017  }
2018 }
2019 
2020 
2034 void XCFImageFormat::mergeIndexedAToRGB(Layer& layer, uint i, uint j, int k, int l,
2035  TQImage& image, int m, int n)
2036 {
2037  QRgb src = layer.image_tiles[j][i].pixel(k, l);
2038  uchar src_a = layer.alpha_tiles[j][i].pixelIndex(k, l);
2039  src_a = INT_MULT(src_a, layer.opacity);
2040 
2041  // Apply the mask (if any)
2042  if (layer.apply_mask == 1 && layer.mask_tiles.size() > j &&
2043  layer.mask_tiles[j].size() > i)
2044  src_a = INT_MULT(src_a, layer.mask_tiles[j][i].pixelIndex(k, l));
2045 
2046  // This is what appears in the GIMP window
2047  if (src_a <= 127)
2048  src_a = 0;
2049  else
2050  src_a = OPAQUE_OPACITY;
2051 
2052  image.setPixel(m, n, tqRgba(src, src_a));
2053 }
2054 
2055 
2063 void XCFImageFormat::dissolveRGBPixels ( TQImage& image, int x, int y )
2064 {
2065  // The apparently spurious rand() calls are to wind the random
2066  // numbers up to the same point for each tile.
2067 
2068  for (int l = 0; l < image.height(); l++) {
2069  srand(random_table[( l + y ) % RANDOM_TABLE_SIZE]);
2070 
2071  for (int k = 0; k < x; k++)
2072  rand();
2073 
2074  for (int k = 0; k < image.width(); k++) {
2075  int rand_val = rand() & 0xff;
2076  QRgb pixel = image.pixel(k, l);
2077 
2078  if (rand_val > tqAlpha(pixel)) {
2079  image.setPixel(k, l, tqRgba(pixel, 0));
2080  }
2081  }
2082  }
2083 }
2084 
2085 
2095 void XCFImageFormat::dissolveAlphaPixels ( TQImage& image, int x, int y )
2096 {
2097  // The apparently spurious rand() calls are to wind the random
2098  // numbers up to the same point for each tile.
2099 
2100  for (int l = 0; l < image.height(); l++) {
2101  srand( random_table[(l + y) % RANDOM_TABLE_SIZE]);
2102 
2103  for (int k = 0; k < x; k++)
2104  rand();
2105 
2106  for (int k = 0; k < image.width(); k++) {
2107  int rand_val = rand() & 0xff;
2108  uchar alpha = image.pixelIndex(k, l);
2109 
2110  if (rand_val > alpha) {
2111  image.setPixel(k, l, 0);
2112  }
2113  }
2114  }
2115 }
2116 

kimgio

Skip menu "kimgio"
  • Main Page
  • File List
  • Related Pages

kimgio

Skip menu "kimgio"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  •     tdecore
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  • tdeioslave
  •   http
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for kimgio by doxygen 1.8.8
This website is maintained by Timothy Pearson.