~ubuntu-branches/ubuntu/precise/koffice/precise

« back to all changes in this revision

Viewing changes to krita/kritacolor/kis_color_conversions.cc

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2006-04-20 21:38:53 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20060420213853-j5lxluqvymxt2zny
Tags: 1:1.5.0-0ubuntu2
UbuntuĀ uploadĀ 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org>
 
3
 *
 
4
 *  This program is free software; you can redistribute it and/or modify
 
5
 *  it under the terms of the GNU General Public License as published by
 
6
 *  the Free Software Foundation; either version 2 of the License, or
 
7
 *  (at your option) any later version.
 
8
 *
 
9
 *  This program is distributed in the hope that it will be useful,
 
10
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 *  GNU General Public License for more details.
 
13
 *
 
14
 *  You should have received a copy of the GNU General Public License
 
15
 *  along with this program; if not, write to the Free Software
 
16
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 
17
 */
 
18
 
 
19
#include <cmath>
 
20
 
 
21
#include <qglobal.h>
 
22
 
 
23
#include "kis_color_conversions.h"
 
24
 
 
25
/**
 
26
 * A number of often-used conversions between color models
 
27
 */
 
28
 
 
29
void rgb_to_hsv(int R, int G, int B, int *H, int *S, int *V)
 
30
{
 
31
    unsigned int max = R;
 
32
    unsigned int min = R;
 
33
    unsigned char maxValue = 0; // r = 0, g = 1, b = 2
 
34
 
 
35
    // find maximum and minimum RGB values
 
36
    if(static_cast<unsigned int>(G) > max) {
 
37
        max = G;
 
38
        maxValue = 1;
 
39
    }
 
40
    
 
41
    if (static_cast<unsigned int>(B) > max)
 
42
    {
 
43
        max = B;
 
44
        maxValue = 2;
 
45
    }
 
46
 
 
47
    if(static_cast<unsigned int>(G) < min)
 
48
        min = G;
 
49
        
 
50
    if(static_cast<unsigned int>(B) < min )
 
51
        min = B;
 
52
 
 
53
    int delta = max - min;
 
54
 
 
55
    // To prevent division by zero later on.
 
56
    if (delta == 0) delta = 1;
 
57
    
 
58
    *V = max; // value
 
59
    *S = max ? (510 * delta + max) / ( 2 * max) : 0; // saturation
 
60
    
 
61
    // calc hue
 
62
    if(*S == 0)
 
63
        *H = -1; // undefined hue
 
64
    else
 
65
    {
 
66
        switch(maxValue)
 
67
        {
 
68
        case 0:  // red
 
69
            if(G >= B)
 
70
                *H = (120 * (G - B) + delta) / (2 * delta);
 
71
            else
 
72
                *H = (120 * (G - B + delta) + delta) / (2 * delta) + 300;
 
73
            break;
 
74
        case 1:  // green
 
75
            if(B > R)
 
76
                *H = 120 + (120 * (B - R) + delta) / (2 * delta);
 
77
            else
 
78
                *H = 60 + (120 * (B - R + delta) + delta) / (2 * delta);
 
79
            break;
 
80
        case 2:  // blue
 
81
            if(R > G)
 
82
                *H = 240 + (120 * (R - G) + delta) / (2 * delta);
 
83
            else
 
84
                *H = 180 + (120 * (R - G + delta) + delta) / (2 * delta);
 
85
            break;
 
86
        }
 
87
    }
 
88
}
 
89
 
 
90
void hsv_to_rgb(int H, int S, int V, int *R, int *G, int *B)
 
91
{
 
92
    *R = *G = *B = V;
 
93
 
 
94
    if (S != 0 && H != -1) { // chromatic
 
95
 
 
96
        if (H >= 360) {
 
97
            // angle > 360
 
98
            H %= 360;
 
99
        }
 
100
 
 
101
        unsigned int f = H % 60;
 
102
        H /= 60;
 
103
        unsigned int p = static_cast<unsigned int>(2*V*(255-S)+255)/510;
 
104
        unsigned int q, t;
 
105
 
 
106
        if (H & 1) {
 
107
            q = static_cast<unsigned int>(2 * V * (15300 - S * f) + 15300) / 30600;
 
108
            switch (H) {
 
109
            case 1:
 
110
                *R = static_cast<int>(q);
 
111
                *G = static_cast<int>(V);
 
112
                *B = static_cast<int>(p);
 
113
                break;
 
114
            case 3:
 
115
                *R = static_cast<int>(p);
 
116
                *G = static_cast<int>(q);
 
117
                *B = static_cast<int>(V);
 
118
                break;
 
119
            case 5:
 
120
                *R = static_cast<int>(V);
 
121
                *G = static_cast<int>(p);
 
122
                *B = static_cast<int>(q);
 
123
                break;
 
124
            }
 
125
        } else {
 
126
            t = static_cast<unsigned int>(2 * V * (15300 - (S * (60 - f))) + 15300) / 30600;
 
127
            switch (H) {
 
128
            case 0:
 
129
                *R = static_cast<int>(V);
 
130
                *G = static_cast<int>(t);
 
131
                *B = static_cast<int>(p);
 
132
                break;
 
133
            case 2:
 
134
                *R = static_cast<int>(p);
 
135
                *G = static_cast<int>(V);
 
136
                *B = static_cast<int>(t);
 
137
                break;
 
138
            case 4:
 
139
                *R = static_cast<int>(t);
 
140
                *G = static_cast<int>(p);
 
141
                *B = static_cast<int>(V);
 
142
                break;
 
143
            }
 
144
        }
 
145
    }
 
146
}
 
147
 
 
148
#define EPSILON 1e-6
 
149
#define UNDEFINED_HUE -1
 
150
 
 
151
void RGBToHSV(float r, float g, float b, float *h, float *s, float *v)
 
152
{
 
153
    float max = QMAX(r, QMAX(g, b));
 
154
    float min = QMIN(r, QMIN(g, b));
 
155
 
 
156
    *v = max;
 
157
 
 
158
    if (max > EPSILON) {
 
159
        *s = (max - min) / max;
 
160
    } else {
 
161
        *s = 0;
 
162
    }
 
163
 
 
164
    if (*s < EPSILON) {
 
165
        *h = UNDEFINED_HUE;
 
166
    } else {
 
167
        float delta = max - min;
 
168
 
 
169
        if (r == max) {
 
170
            *h = (g - b) / delta;
 
171
        } else if (g == max) {
 
172
            *h = 2 + (b - r) / delta;
 
173
        } else {
 
174
            *h = 4 + (r - g) / delta;
 
175
        }
 
176
 
 
177
        *h *= 60;
 
178
        if (*h < 0) {
 
179
            *h += 360;
 
180
        }
 
181
    }
 
182
}
 
183
 
 
184
void HSVToRGB(float h, float s, float v, float *r, float *g, float *b)
 
185
{
 
186
    if (s < EPSILON || h == UNDEFINED_HUE) {
 
187
        // Achromatic case
 
188
 
 
189
        *r = v;
 
190
        *g = v;
 
191
        *b = v;
 
192
    } else {
 
193
        float f, p, q, t;
 
194
        int i;
 
195
 
 
196
        if (h > 360 - EPSILON) {
 
197
            h -= 360;
 
198
        }
 
199
 
 
200
        h /= 60;
 
201
        i = static_cast<int>(floor(h));
 
202
        f = h - i;
 
203
        p = v * (1 - s);
 
204
        q = v * (1 - (s * f));
 
205
        t = v * (1 - (s * (1 - f)));
 
206
 
 
207
        switch (i) {
 
208
        case 0:
 
209
            *r = v;
 
210
            *g = t;
 
211
            *b = p;
 
212
            break;
 
213
        case 1:
 
214
            *r = q;
 
215
            *g = v;
 
216
            *b = p;
 
217
            break;
 
218
        case 2:
 
219
            *r = p;
 
220
            *g = v;
 
221
            *b = t;
 
222
            break;
 
223
        case 3:
 
224
            *r = p;
 
225
            *g = q;
 
226
            *b = v;
 
227
            break;
 
228
        case 4:
 
229
            *r = t;
 
230
            *g = p;
 
231
            *b = v;
 
232
            break;
 
233
        case 5:
 
234
            *r = v;
 
235
            *g = p;
 
236
            *b = q;
 
237
            break;
 
238
        }
 
239
    }
 
240
}
 
241
 
 
242
void rgb_to_hls(Q_UINT8 red, Q_UINT8 green, Q_UINT8 blue, float * hue, float * lightness, float * saturation)
 
243
{
 
244
    float r = red / 255.0;
 
245
    float g = green / 255.0;
 
246
    float b = blue / 255.0;
 
247
    float h = 0;
 
248
    float l = 0;
 
249
    float s = 0;
 
250
 
 
251
    float max, min, delta;
 
252
 
 
253
    max = QMAX(r, g);
 
254
    max = QMAX(max, b);
 
255
    
 
256
    min = QMIN(r, g);
 
257
    min = QMIN(min, b);
 
258
 
 
259
    delta = max - min;
 
260
 
 
261
    l = (max + min) / 2;
 
262
 
 
263
    if (delta == 0) {
 
264
        // This is a gray, no chroma...
 
265
        h = 0;
 
266
        s = 0;
 
267
    }
 
268
    else {
 
269
        if ( l < 0.5)
 
270
            s = delta / ( max + min );
 
271
        else
 
272
            s = delta / ( 2 - max - min );
 
273
 
 
274
        float delta_r, delta_g, delta_b;
 
275
 
 
276
        delta_r = (( max - r ) / 6 ) / delta;
 
277
        delta_g = (( max - g ) / 6 ) / delta;
 
278
        delta_b = (( max - b ) / 6 ) / delta;
 
279
 
 
280
        if ( r == max )
 
281
            h = delta_b - delta_g;
 
282
        else if ( g == max)
 
283
            h = ( 1.0 / 3 ) + delta_r - delta_b;
 
284
        else if ( b == max)
 
285
            h = ( 2.0 / 3 ) + delta_g - delta_r;
 
286
 
 
287
        if (h < 0) h += 1;
 
288
        if (h > 1) h += 1;
 
289
        
 
290
    }
 
291
 
 
292
    *hue = h * 360;
 
293
    *saturation = s;
 
294
    *lightness = l;
 
295
}
 
296
 
 
297
float hue_value(float n1, float n2, float hue)
 
298
{
 
299
    if (hue > 360 )
 
300
        hue = hue -360;
 
301
    else if (hue < 0 )
 
302
        hue = hue +360;
 
303
    if (hue < 60  )
 
304
        return n1 + (((n2 - n1) * hue) / 60);
 
305
    else if (hue < 180 )
 
306
        return n2;
 
307
    else if (hue < 240 )
 
308
        return n1 + (((n2 - n1) * (240 - hue)) / 60);
 
309
    else return n1;
 
310
}
 
311
 
 
312
 
 
313
void hls_to_rgb(float h, float l, float s, Q_UINT8 * r, Q_UINT8 * g, Q_UINT8 * b)
 
314
{
 
315
    float m1, m2;
 
316
 
 
317
    if (l <= 0.5 )
 
318
        m2 = l * ( 1 + s );
 
319
    else 
 
320
        m2 = l + s - l * s;
 
321
 
 
322
    m1 = 2 * l - m2;
 
323
    
 
324
    *r = (Q_UINT8)(hue_value(m1, m2, h + 120) * 255 + 0.5);
 
325
    *g = (Q_UINT8)(hue_value(m1, m2, h) * 255 + 0.5);
 
326
    *b = (Q_UINT8)(hue_value(m1, m2, h - 120) * 255 + 0.5);
 
327
 
 
328
}
 
329
 
 
330
void rgb_to_hls(Q_UINT8 r, Q_UINT8 g, Q_UINT8 b, int * h, int * l, int * s)
 
331
{
 
332
    float hue, saturation, lightness;
 
333
 
 
334
    rgb_to_hls(r, g, b, &hue, &lightness, &saturation);
 
335
    *h = (int)(hue + 0.5);
 
336
    *l = (int)(lightness * 255 + 0.5);
 
337
    *s = (int)(saturation * 255 + 0.5);
 
338
}
 
339
 
 
340
void hls_to_rgb(int h, int l, int s, Q_UINT8 * r, Q_UINT8 * g, Q_UINT8 * b)
 
341
{
 
342
    float hue = h;
 
343
    float lightness = l / 255.0;
 
344
    float saturation = s / 255.0;
 
345
 
 
346
    hls_to_rgb(hue, lightness, saturation, r, g, b);
 
347
}
 
348
 
 
349
/*
 
350
A Fast HSL-to-RGB Transform
 
351
by Ken Fishkin
 
352
from "Graphics Gems", Academic Press, 1990
 
353
*/
 
354
 
 
355
void RGBToHSL(float r, float g, float b, float *h, float *s, float *l)
 
356
{
 
357
    float v;
 
358
    float m;
 
359
    float vm;
 
360
    float r2, g2, b2;
 
361
 
 
362
    v = QMAX(r,g);
 
363
    v = QMAX(v,b);
 
364
    m = QMIN(r,g);
 
365
    m = QMIN(m,b);
 
366
 
 
367
    if ((*l = (m + v) / 2.0) <= 0.0) {
 
368
        *h = UNDEFINED_HUE;
 
369
        *s = 0;
 
370
        return;
 
371
    }
 
372
    if ((*s = vm = v - m) > 0.0) {
 
373
        *s /= (*l <= 0.5) ? (v + m ) :
 
374
              (2.0 - v - m) ;
 
375
    } else {
 
376
        *h = UNDEFINED_HUE;
 
377
        return;
 
378
    }
 
379
 
 
380
 
 
381
    r2 = (v - r) / vm;
 
382
    g2 = (v - g) / vm;
 
383
    b2 = (v - b) / vm;
 
384
 
 
385
    if (r == v)
 
386
        *h = (g == m ? 5.0 + b2 : 1.0 - g2);
 
387
    else if (g == v)
 
388
        *h = (b == m ? 1.0 + r2 : 3.0 - b2);
 
389
    else
 
390
        *h = (r == m ? 3.0 + g2 : 5.0 - r2);
 
391
 
 
392
    *h *= 60;
 
393
}
 
394
 
 
395
void HSLToRGB(float h, float sl, float l, float *r, float *g, float *b)
 
396
 
 
397
{
 
398
    float v;
 
399
 
 
400
    v = (l <= 0.5) ? (l * (1.0 + sl)) : (l + sl - l * sl);
 
401
    if (v <= 0) {
 
402
        *r = *g = *b = 0.0;
 
403
    } else {
 
404
        float m;
 
405
        float sv;
 
406
        int sextant;
 
407
        float fract, vsf, mid1, mid2;
 
408
 
 
409
        m = l + l - v;
 
410
        sv = (v - m ) / v;
 
411
        h /= 60.0;
 
412
        sextant = static_cast<int>(h);    
 
413
        fract = h - sextant;
 
414
        vsf = v * sv * fract;
 
415
        mid1 = m + vsf;
 
416
        mid2 = v - vsf;
 
417
        switch (sextant) {
 
418
        case 0: *r = v; *g = mid1; *b = m; break;
 
419
        case 1: *r = mid2; *g = v; *b = m; break;
 
420
        case 2: *r = m; *g = v; *b = mid1; break;
 
421
        case 3: *r = m; *g = mid2; *b = v; break;
 
422
        case 4: *r = mid1; *g = m; *b = v; break;
 
423
        case 5: *r = v; *g = m; *b = mid2; break;
 
424
        }
 
425
    }
 
426
}
 
427