1 /* -*- c++ -*-
2     gimp.h: Header for a Qt 3 plug-in for reading GIMP XCF image files
3     SPDX-FileCopyrightText: 2001 lignum Computing Inc. <allen@lignumcomputing.com>
4     SPDX-FileCopyrightText: 2004 Melchior FRANZ <mfranz@kde.org>
5 
6     SPDX-License-Identifier: LGPL-2.1-or-later
7 */
8 
9 #ifndef GIMP_H
10 #define GIMP_H
11 
12 typedef unsigned char uchar;
13 
14 /*
15  * These are the constants and functions I extracted from The GIMP source
16  * code. If the reader fails to work, this is probably the place to start
17  * looking for discontinuities.
18  */
19 
20 // From GIMP "tile.h" v1.2
21 
22 const uint TILE_WIDTH = 64; //!< Width of a tile in the XCF file.
23 const uint TILE_HEIGHT = 64; //!< Height of a tile in the XCF file.
24 
25 // From GIMP "paint_funcs.c" v1.2
26 
27 const int RANDOM_TABLE_SIZE = 4096; //!< Size of dissolve random number table.
28 const int RANDOM_SEED = 314159265; //!< Seed for dissolve random number table.
29 const double EPSILON = 0.0001; //!< Roundup in alpha blending.
30 
31 // From GIMP "paint_funcs.h" v1.2
32 
33 const uchar OPAQUE_OPACITY = 255; //!< Opaque value for 8-bit alpha component.
34 
35 // From GIMP "apptypes.h" v1.2
36 
37 //! Basic GIMP image type. QImage converter may produce a deeper image
38 //! than is specified here. For example, a grayscale image with an
39 //! alpha channel must (currently) use a 32-bit Qt image.
40 
41 typedef enum {
42     RGB,
43     GRAY,
44     INDEXED,
45 } GimpImageBaseType;
46 
47 // From GIMP "libgimp/gimpenums.h" v2.4
48 
49 //! Effect to apply when layers are merged together.
50 
51 typedef enum {
52     NORMAL_MODE,
53     DISSOLVE_MODE,
54     BEHIND_MODE,
55     MULTIPLY_MODE,
56     SCREEN_MODE,
57     OVERLAY_MODE,
58     DIFFERENCE_MODE,
59     ADDITION_MODE,
60     SUBTRACT_MODE,
61     DARKEN_ONLY_MODE,
62     LIGHTEN_ONLY_MODE,
63     HUE_MODE,
64     SATURATION_MODE,
65     COLOR_MODE,
66     VALUE_MODE,
67     DIVIDE_MODE,
68     DODGE_MODE,
69     BURN_MODE,
70     HARDLIGHT_MODE,
71     SOFTLIGHT_MODE,
72     GRAIN_EXTRACT_MODE,
73     GRAIN_MERGE_MODE
74 } LayerModeEffects;
75 
76 // From GIMP "paint_funcs.c" v1.2
77 
78 /*!
79  * Multiply two color components. Really expects the arguments to be
80  * 8-bit quantities.
81  * \param a first minuend.
82  * \param b second minuend.
83  * \return product of arguments.
84  */
INT_MULT(int a,int b)85 inline int INT_MULT(int a, int b)
86 {
87     int c = a * b + 0x80;
88     return ((c >> 8) + c) >> 8;
89 }
90 
91 /*!
92  * Blend the two color components in the proportion alpha:
93  *
94  * result = alpha a + ( 1 - alpha ) b
95  *
96  * \param a first component.
97  * \param b second component.
98  * \param alpha blend proportion.
99  * \return blended color components.
100  */
101 
INT_BLEND(int a,int b,int alpha)102 inline int INT_BLEND(int a, int b, int alpha)
103 {
104     return INT_MULT(a - b, alpha) + b;
105 }
106 
107 // From GIMP "gimpcolorspace.c" v1.2
108 
109 /*!
110  * Convert a color in RGB space to HSV space (Hue, Saturation, Value).
111  * \param red the red component (modified in place).
112  * \param green the green component (modified in place).
113  * \param blue the blue component (modified in place).
114  */
RGBTOHSV(uchar & red,uchar & green,uchar & blue)115 static void RGBTOHSV(uchar &red, uchar &green, uchar &blue)
116 {
117     int r, g, b;
118     double h, s, v;
119     int min, max;
120 
121     h = 0.;
122 
123     r = red;
124     g = green;
125     b = blue;
126 
127     if (r > g) {
128         max = qMax(r, b);
129         min = qMin(g, b);
130     } else {
131         max = qMax(g, b);
132         min = qMin(r, b);
133     }
134 
135     v = max;
136 
137     if (max != 0) {
138         s = ((max - min) * 255) / (double)max;
139     } else {
140         s = 0;
141     }
142 
143     if (s == 0) {
144         h = 0;
145     } else {
146         int delta = max - min;
147         if (r == max) {
148             h = (g - b) / (double)delta;
149         } else if (g == max) {
150             h = 2 + (b - r) / (double)delta;
151         } else if (b == max) {
152             h = 4 + (r - g) / (double)delta;
153         }
154         h *= 42.5;
155 
156         if (h < 0) {
157             h += 255;
158         }
159         if (h > 255) {
160             h -= 255;
161         }
162     }
163 
164     red = (uchar)h;
165     green = (uchar)s;
166     blue = (uchar)v;
167 }
168 
169 /*!
170  * Convert a color in HSV space to RGB space.
171  * \param hue the hue component (modified in place).
172  * \param saturation the saturation component (modified in place).
173  * \param value the value component (modified in place).
174  */
HSVTORGB(uchar & hue,uchar & saturation,uchar & value)175 static void HSVTORGB(uchar &hue, uchar &saturation, uchar &value)
176 {
177     if (saturation == 0) {
178         hue = value;
179         saturation = value;
180         // value      = value;
181     } else {
182         double h = hue * 6. / 255.;
183         double s = saturation / 255.;
184         double v = value / 255.;
185 
186         double f = h - (int)h;
187         double p = v * (1. - s);
188         double q = v * (1. - (s * f));
189         double t = v * (1. - (s * (1. - f)));
190 
191         // Worth a note here that gcc 2.96 will generate different results
192         // depending on optimization mode on i386.
193 
194         switch ((int)h) {
195         case 0:
196             hue = (uchar)(v * 255);
197             saturation = (uchar)(t * 255);
198             value = (uchar)(p * 255);
199             break;
200         case 1:
201             hue = (uchar)(q * 255);
202             saturation = (uchar)(v * 255);
203             value = (uchar)(p * 255);
204             break;
205         case 2:
206             hue = (uchar)(p * 255);
207             saturation = (uchar)(v * 255);
208             value = (uchar)(t * 255);
209             break;
210         case 3:
211             hue = (uchar)(p * 255);
212             saturation = (uchar)(q * 255);
213             value = (uchar)(v * 255);
214             break;
215         case 4:
216             hue = (uchar)(t * 255);
217             saturation = (uchar)(p * 255);
218             value = (uchar)(v * 255);
219             break;
220         case 5:
221             hue = (uchar)(v * 255);
222             saturation = (uchar)(p * 255);
223             value = (uchar)(q * 255);
224         }
225     }
226 }
227 
228 /*!
229  * Convert a color in RGB space to HLS space (Hue, Lightness, Saturation).
230  * \param red the red component (modified in place).
231  * \param green the green component (modified in place).
232  * \param blue the blue component (modified in place).
233  */
RGBTOHLS(uchar & red,uchar & green,uchar & blue)234 static void RGBTOHLS(uchar &red, uchar &green, uchar &blue)
235 {
236     int r = red;
237     int g = green;
238     int b = blue;
239 
240     int min, max;
241 
242     if (r > g) {
243         max = qMax(r, b);
244         min = qMin(g, b);
245     } else {
246         max = qMax(g, b);
247         min = qMin(r, b);
248     }
249 
250     double h;
251     double l = (max + min) / 2.;
252     double s;
253 
254     if (max == min) {
255         s = 0.;
256         h = 0.;
257     } else {
258         int delta = max - min;
259 
260         if (l < 128) {
261             s = 255 * (double)delta / (double)(max + min);
262         } else {
263             s = 255 * (double)delta / (double)(511 - max - min);
264         }
265 
266         if (r == max) {
267             h = (g - b) / (double)delta;
268         } else if (g == max) {
269             h = 2 + (b - r) / (double)delta;
270         } else {
271             h = 4 + (r - g) / (double)delta;
272         }
273 
274         h *= 42.5;
275 
276         if (h < 0) {
277             h += 255;
278         } else if (h > 255) {
279             h -= 255;
280         }
281     }
282 
283     red = (uchar)h;
284     green = (uchar)l;
285     blue = (uchar)s;
286 }
287 
288 /*!
289  * Implement the HLS "double hex-cone".
290  * \param n1 lightness fraction (?)
291  * \param n2 saturation fraction (?)
292  * \param hue hue "angle".
293  * \return HLS value.
294  */
HLSVALUE(double n1,double n2,double hue)295 static int HLSVALUE(double n1, double n2, double hue)
296 {
297     double value;
298 
299     if (hue > 255) {
300         hue -= 255;
301     } else if (hue < 0) {
302         hue += 255;
303     }
304 
305     if (hue < 42.5) {
306         value = n1 + (n2 - n1) * (hue / 42.5);
307     } else if (hue < 127.5) {
308         value = n2;
309     } else if (hue < 170) {
310         value = n1 + (n2 - n1) * ((170 - hue) / 42.5);
311     } else {
312         value = n1;
313     }
314 
315     return (int)(value * 255);
316 }
317 
318 /*!
319  * Convert a color in HLS space to RGB space.
320  * \param hue the hue component (modified in place).
321  * \param lightness the lightness component (modified in place).
322  * \param saturation the saturation component (modified in place).
323  */
HLSTORGB(uchar & hue,uchar & lightness,uchar & saturation)324 static void HLSTORGB(uchar &hue, uchar &lightness, uchar &saturation)
325 {
326     double h = hue;
327     double l = lightness;
328     double s = saturation;
329 
330     if (s == 0) {
331         hue = (uchar)l;
332         lightness = (uchar)l;
333         saturation = (uchar)l;
334     } else {
335         double m1, m2;
336 
337         if (l < 128) {
338             m2 = (l * (255 + s)) / 65025.;
339         } else {
340             m2 = (l + s - (l * s) / 255.) / 255.;
341         }
342 
343         m1 = (l / 127.5) - m2;
344 
345         hue = HLSVALUE(m1, m2, h + 85);
346         lightness = HLSVALUE(m1, m2, h);
347         saturation = HLSVALUE(m1, m2, h - 85);
348     }
349 }
350 #endif
351