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
12typedef 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
22const uint TILE_WIDTH = 64; //!< Width of a tile in the XCF file.
23const uint TILE_HEIGHT = 64; //!< Height of a tile in the XCF file.
24
25// From GIMP "paint_funcs.c" v1.2
26
27const int RANDOM_TABLE_SIZE = 4096; //!< Size of dissolve random number table.
28const int RANDOM_SEED = 314159265; //!< Seed for dissolve random number table.
29const double EPSILON = 0.0001; //!< Roundup in alpha blending.
30
31// From GIMP "paint_funcs.h" v1.2
32
33const 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
41typedef enum {
42 RGB,
43 GRAY,
44 INDEXED,
45} GimpImageBaseType;
46
47// From GIMP "libgimp/gimpenums.h" v2.4
48
49// From GIMP "paint_funcs.c" v1.2
50
51/*!
52 * Multiply two color components. Really expects the arguments to be
53 * 8-bit quantities.
54 * \param a first minuend.
55 * \param b second minuend.
56 * \return product of arguments.
57 */
58inline int INT_MULT(int a, int b)
59{
60 int c = a * b + 0x80;
61 return ((c >> 8) + c) >> 8;
62}
63
64/*!
65 * Blend the two color components in the proportion alpha:
66 *
67 * result = alpha a + ( 1 - alpha ) b
68 *
69 * \param a first component.
70 * \param b second component.
71 * \param alpha blend proportion.
72 * \return blended color components.
73 */
74
75inline int INT_BLEND(int a, int b, int alpha)
76{
77 return INT_MULT(a: a - b, b: alpha) + b;
78}
79
80// From GIMP "gimpcolorspace.c" v1.2
81
82/*!
83 * Convert a color in RGB space to HSV space (Hue, Saturation, Value).
84 * \param red the red component (modified in place).
85 * \param green the green component (modified in place).
86 * \param blue the blue component (modified in place).
87 */
88static void RGBTOHSV(uchar &red, uchar &green, uchar &blue)
89{
90 int r, g, b;
91 double h, s, v;
92 int min, max;
93
94 h = 0.;
95
96 r = red;
97 g = green;
98 b = blue;
99
100 if (r > g) {
101 max = qMax(a: r, b);
102 min = qMin(a: g, b);
103 } else {
104 max = qMax(a: g, b);
105 min = qMin(a: r, b);
106 }
107
108 v = max;
109
110 if (max != 0) {
111 s = ((max - min) * 255) / (double)max;
112 } else {
113 s = 0;
114 }
115
116 if (s == 0) {
117 h = 0;
118 } else {
119 int delta = max - min;
120 if (r == max) {
121 h = (g - b) / (double)delta;
122 } else if (g == max) {
123 h = 2 + (b - r) / (double)delta;
124 } else if (b == max) {
125 h = 4 + (r - g) / (double)delta;
126 }
127 h *= 42.5;
128
129 if (h < 0) {
130 h += 255;
131 }
132 if (h > 255) {
133 h -= 255;
134 }
135 }
136
137 red = (uchar)h;
138 green = (uchar)s;
139 blue = (uchar)v;
140}
141
142/*!
143 * Convert a color in HSV space to RGB space.
144 * \param hue the hue component (modified in place).
145 * \param saturation the saturation component (modified in place).
146 * \param value the value component (modified in place).
147 */
148static void HSVTORGB(uchar &hue, uchar &saturation, uchar &value)
149{
150 if (saturation == 0) {
151 hue = value;
152 saturation = value;
153 // value = value;
154 } else {
155 double h = hue * 6. / 255.;
156 double s = saturation / 255.;
157 double v = value / 255.;
158
159 double f = h - (int)h;
160 double p = v * (1. - s);
161 double q = v * (1. - (s * f));
162 double t = v * (1. - (s * (1. - f)));
163
164 // Worth a note here that gcc 2.96 will generate different results
165 // depending on optimization mode on i386.
166
167 switch ((int)h) {
168 case 0:
169 hue = (uchar)(v * 255);
170 saturation = (uchar)(t * 255);
171 value = (uchar)(p * 255);
172 break;
173 case 1:
174 hue = (uchar)(q * 255);
175 saturation = (uchar)(v * 255);
176 value = (uchar)(p * 255);
177 break;
178 case 2:
179 hue = (uchar)(p * 255);
180 saturation = (uchar)(v * 255);
181 value = (uchar)(t * 255);
182 break;
183 case 3:
184 hue = (uchar)(p * 255);
185 saturation = (uchar)(q * 255);
186 value = (uchar)(v * 255);
187 break;
188 case 4:
189 hue = (uchar)(t * 255);
190 saturation = (uchar)(p * 255);
191 value = (uchar)(v * 255);
192 break;
193 case 5:
194 hue = (uchar)(v * 255);
195 saturation = (uchar)(p * 255);
196 value = (uchar)(q * 255);
197 }
198 }
199}
200
201/*!
202 * Convert a color in RGB space to HLS space (Hue, Lightness, Saturation).
203 * \param red the red component (modified in place).
204 * \param green the green component (modified in place).
205 * \param blue the blue component (modified in place).
206 */
207static void RGBTOHLS(uchar &red, uchar &green, uchar &blue)
208{
209 int r = red;
210 int g = green;
211 int b = blue;
212
213 int min, max;
214
215 if (r > g) {
216 max = qMax(a: r, b);
217 min = qMin(a: g, b);
218 } else {
219 max = qMax(a: g, b);
220 min = qMin(a: r, b);
221 }
222
223 double h;
224 double l = (max + min) / 2.;
225 double s;
226
227 if (max == min) {
228 s = 0.;
229 h = 0.;
230 } else {
231 int delta = max - min;
232
233 if (l < 128) {
234 s = 255 * (double)delta / (double)(max + min);
235 } else {
236 s = 255 * (double)delta / (double)(511 - max - min);
237 }
238
239 if (r == max) {
240 h = (g - b) / (double)delta;
241 } else if (g == max) {
242 h = 2 + (b - r) / (double)delta;
243 } else {
244 h = 4 + (r - g) / (double)delta;
245 }
246
247 h *= 42.5;
248
249 if (h < 0) {
250 h += 255;
251 } else if (h > 255) {
252 h -= 255;
253 }
254 }
255
256 red = (uchar)h;
257 green = (uchar)l;
258 blue = (uchar)s;
259}
260
261/*!
262 * Implement the HLS "double hex-cone".
263 * \param n1 lightness fraction (?)
264 * \param n2 saturation fraction (?)
265 * \param hue hue "angle".
266 * \return HLS value.
267 */
268static int HLSVALUE(double n1, double n2, double hue)
269{
270 double value;
271
272 if (hue > 255) {
273 hue -= 255;
274 } else if (hue < 0) {
275 hue += 255;
276 }
277
278 if (hue < 42.5) {
279 value = n1 + (n2 - n1) * (hue / 42.5);
280 } else if (hue < 127.5) {
281 value = n2;
282 } else if (hue < 170) {
283 value = n1 + (n2 - n1) * ((170 - hue) / 42.5);
284 } else {
285 value = n1;
286 }
287
288 return (int)(value * 255);
289}
290
291/*!
292 * Convert a color in HLS space to RGB space.
293 * \param hue the hue component (modified in place).
294 * \param lightness the lightness component (modified in place).
295 * \param saturation the saturation component (modified in place).
296 */
297static void HLSTORGB(uchar &hue, uchar &lightness, uchar &saturation)
298{
299 double h = hue;
300 double l = lightness;
301 double s = saturation;
302
303 if (s == 0) {
304 hue = (uchar)l;
305 lightness = (uchar)l;
306 saturation = (uchar)l;
307 } else {
308 double m1, m2;
309
310 if (l < 128) {
311 m2 = (l * (255 + s)) / 65025.;
312 } else {
313 m2 = (l + s - (l * s) / 255.) / 255.;
314 }
315
316 m1 = (l / 127.5) - m2;
317
318 hue = HLSVALUE(n1: m1, n2: m2, hue: h + 85);
319 lightness = HLSVALUE(n1: m1, n2: m2, hue: h);
320 saturation = HLSVALUE(n1: m1, n2: m2, hue: h - 85);
321 }
322}
323#endif
324

source code of kimageformats/src/imageformats/gimp_p.h