fix tricky regression noticed by Vyacheslav Tokarev on Google Reader.
[kdelibs.git] / kimgio / xcf.h
blob96ec34219cb2bd8e43636f3215e21aa10e788065
1 #ifndef XCF_H
2 #define XCF_H
3 /*
4 * qxcfi.cpp: A Qt 3 plug-in for reading GIMP XCF image files
5 * Copyright (C) 2001 lignum Computing, Inc. <allen@lignumcomputing.com>
6 * Copyright (C) 2004 Melchior FRANZ <mfranz@kde.org>
8 * This plug-in is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include <QtGui/QImageIOPlugin>
26 #include <QtGui/QImage>
27 #include <QtCore/QIODevice>
28 #include <QtCore/QVector>
30 #include "gimp.h"
32 class XCFHandler : public QImageIOHandler
34 public:
35 XCFHandler();
37 bool canRead() const;
38 bool read(QImage *image);
39 bool write(const QImage &image);
41 QByteArray name() const;
43 static bool canRead(QIODevice *device);
46 const float INCHESPERMETER = (100.0f / 2.54f);
48 /*!
49 * Each layer in an XCF file is stored as a matrix of
50 * 64-pixel by 64-pixel images. The GIMP has a sophisticated
51 * method of handling very large images as well as implementing
52 * parallel processing on a tile-by-tile basis. Here, though,
53 * we just read them in en-masse and store them in a matrix.
55 typedef QVector<QVector<QImage> > Tiles;
59 class XCFImageFormat {
60 public:
61 XCFImageFormat();
62 bool readXCF(QIODevice *device, QImage *image);
65 private:
66 /*!
67 * Each GIMP image is composed of one or more layers. A layer can
68 * be one of any three basic types: RGB, grayscale or indexed. With an
69 * optional alpha channel, there are six possible types altogether.
71 * Note: there is only ever one instance of this structure. The
72 * layer info is discarded after it is merged into the final QImage.
74 class Layer {
75 public:
76 quint32 width; //!< Width of the layer
77 quint32 height; //!< Height of the layer
78 qint32 type; //!< Type of the layer (GimpImageType)
79 char* name; //!< Name of the layer
80 quint32 hierarchy_offset; //!< File position of Tile hierarchy
81 quint32 mask_offset; //!< File position of mask image
83 uint nrows; //!< Number of rows of tiles (y direction)
84 uint ncols; //!< Number of columns of tiles (x direction)
86 Tiles image_tiles; //!< The basic image
87 //! For Grayscale and Indexed images, the alpha channel is stored
88 //! separately (in this data structure, anyway).
89 Tiles alpha_tiles;
90 Tiles mask_tiles; //!< The layer mask (optional)
92 //! Additional information about a layer mask.
93 struct {
94 quint32 opacity;
95 quint32 visible;
96 quint32 show_masked;
97 uchar red, green, blue;
98 quint32 tattoo;
99 } mask_channel;
101 bool active; //!< Is this layer the active layer?
102 quint32 opacity; //!< The opacity of the layer
103 quint32 visible; //!< Is the layer visible?
104 quint32 linked; //!< Is this layer linked (geometrically)
105 quint32 preserve_transparency; //!< Preserve alpha when drawing on layer?
106 quint32 apply_mask; //!< Apply the layer mask?
107 quint32 edit_mask; //!< Is the layer mask the being edited?
108 quint32 show_mask; //!< Show the layer mask rather than the image?
109 qint32 x_offset; //!< x offset of the layer relative to the image
110 qint32 y_offset; //!< y offset of the layer relative to the image
111 quint32 mode; //!< Combining mode of layer (LayerModeEffects)
112 quint32 tattoo; //!< (unique identifier?)
114 //! As each tile is read from the file, it is buffered here.
115 uchar tile[TILE_WIDTH * TILE_HEIGHT * sizeof(QRgb)];
117 //! The data from tile buffer is copied to the Tile by this
118 //! method. Depending on the type of the tile (RGB, Grayscale,
119 //! Indexed) and use (image or mask), the bytes in the buffer are
120 //! copied in different ways.
121 void (*assignBytes)(Layer& layer, uint i, uint j);
123 Layer(void) : name(0) {}
124 ~Layer(void) { delete[] name; }
129 * The in-memory representation of the XCF Image. It contains a few
130 * metadata items, but is mostly a container for the layer information.
132 class XCFImage {
133 public:
134 quint32 width; //!< width of the XCF image
135 quint32 height; //!< height of the XCF image
136 qint32 type; //!< type of the XCF image (GimpImageBaseType)
138 quint8 compression; //!< tile compression method (CompressionType)
139 float x_resolution; //!< x resolution in dots per inch
140 float y_resolution; //!< y resolution in dots per inch
141 qint32 tattoo; //!< (unique identifier?)
142 quint32 unit; //!< Units of The GIMP (inch, mm, pica, etc...)
143 qint32 num_colors; //!< number of colors in an indexed image
144 QVector<QRgb> palette; //!< indexed image color palette
146 int num_layers; //!< number of layers
147 Layer layer; //!< most recently read layer
149 bool initialized; //!< Is the QImage initialized?
150 QImage image; //!< final QImage
152 XCFImage(void) : initialized(false) {}
156 //! In layer DISSOLVE mode, a random number is chosen to compare to a
157 //! pixel's alpha. If the alpha is greater than the random number, the
158 //! pixel is drawn. This table merely contains the random number seeds
159 //! for each ROW of an image. Therefore, the random numbers chosen
160 //! are consistent from run to run.
161 static int random_table[RANDOM_TABLE_SIZE];
163 //! This table provides the add_pixel saturation values (i.e. 250 + 250 = 255).
164 //static int add_lut[256][256]; - this is so lame waste of 256k of memory
165 static int add_lut( int, int );
167 //! The bottom-most layer is copied into the final QImage by this
168 //! routine.
169 typedef void (*PixelCopyOperation)(Layer& layer, uint i, uint j, int k, int l,
170 QImage& image, int m, int n);
172 //! Higher layers are merged into the final QImage by this routine.
173 typedef void (*PixelMergeOperation)(Layer& layer, uint i, uint j, int k, int l,
174 QImage& image, int m, int n);
176 //! Layer mode static data.
177 typedef struct {
178 bool affect_alpha; //!< Does this mode affect the source alpha?
179 } LayerModes;
181 //! Array of layer mode structures for the modes described by
182 //! LayerModeEffects.
183 static const LayerModes layer_modes[];
185 bool loadImageProperties(QDataStream& xcf_io, XCFImage& image);
186 bool loadProperty(QDataStream& xcf_io, PropType& type, QByteArray& bytes);
187 bool loadLayer(QDataStream& xcf_io, XCFImage& xcf_image);
188 bool loadLayerProperties(QDataStream& xcf_io, Layer& layer);
189 bool composeTiles(XCFImage& xcf_image);
190 void setGrayPalette(QImage& image);
191 void setPalette(XCFImage& xcf_image, QImage& image);
192 static void assignImageBytes(Layer& layer, uint i, uint j);
193 bool loadHierarchy(QDataStream& xcf_io, Layer& layer);
194 bool loadLevel(QDataStream& xcf_io, Layer& layer, qint32 bpp);
195 static void assignMaskBytes(Layer& layer, uint i, uint j);
196 bool loadMask(QDataStream& xcf_io, Layer& layer);
197 bool loadChannelProperties(QDataStream& xcf_io, Layer& layer);
198 bool initializeImage(XCFImage& xcf_image);
199 bool loadTileRLE(QDataStream& xcf_io, uchar* tile, int size,
200 int data_length, qint32 bpp);
201 static void copyLayerToImage(XCFImage& xcf_image);
202 static void copyRGBToRGB(Layer& layer, uint i, uint j, int k, int l,
203 QImage& image, int m, int n);
205 static void copyGrayToGray(Layer& layer, uint i, uint j, int k, int l,
206 QImage& image, int m, int n);
207 static void copyGrayToRGB(Layer& layer, uint i, uint j, int k, int l,
208 QImage& image, int m, int n);
209 static void copyGrayAToRGB(Layer& layer, uint i, uint j, int k, int l,
210 QImage& image, int m, int n);
211 static void copyIndexedToIndexed(Layer& layer, uint i, uint j, int k, int l,
212 QImage& image, int m, int n);
213 static void copyIndexedAToIndexed(Layer& layer, uint i, uint j, int k, int l,
214 QImage& image, int m, int n);
215 static void copyIndexedAToRGB(Layer& layer, uint i, uint j, int k, int l,
216 QImage& image, int m, int n);
218 static void mergeLayerIntoImage(XCFImage& xcf_image);
219 static void mergeRGBToRGB(Layer& layer, uint i, uint j, int k, int l,
220 QImage& image, int m, int n);
221 static void mergeGrayToGray(Layer& layer, uint i, uint j, int k, int l,
222 QImage& image, int m, int n);
223 static void mergeGrayAToGray(Layer& layer, uint i, uint j, int k, int l,
224 QImage& image, int m, int n);
225 static void mergeGrayToRGB(Layer& layer, uint i, uint j, int k, int l,
226 QImage& image, int m, int n);
227 static void mergeGrayAToRGB(Layer& layer, uint i, uint j, int k, int l,
228 QImage& image, int m, int n);
229 static void mergeIndexedToIndexed(Layer& layer, uint i, uint j, int k, int l,
230 QImage& image, int m, int n);
231 static void mergeIndexedAToIndexed(Layer& layer, uint i, uint j, int k, int l,
232 QImage& image, int m, int n);
233 static void mergeIndexedAToRGB(Layer& layer, uint i, uint j, int k, int l,
234 QImage& image, int m, int n);
236 static void dissolveRGBPixels(QImage& image, int x, int y);
237 static void dissolveAlphaPixels(QImage& image, int x, int y);
240 #endif