summaryrefslogtreecommitdiffstats
path: root/src/graphics/core/color.cpp
blob: f0b74f85ec00ebbd16cbe8fc96b266e00525ff56 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// * This file is part of the COLOBOT source code
// * Copyright (C) 2012, Polish Portal of Colobot (PPC)
// *
// * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or
// * (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have received a copy of the GNU General Public License
// * along with this program. If not, see  http://www.gnu.org/licenses/.


#include "graphics/core/color.h"

#include "math/func.h"


// Graphics module namespace
namespace Gfx {


ColorHSV RGB2HSV(Color color)
{
    ColorHSV result;

    float min = Math::Min(color.r, color.g, color.b);
    float max = Math::Max(color.r, color.g, color.b);

    result.v = max;  // intensity

    if ( max == 0.0f )
    {
        result.s = 0.0f;  // saturation
        result.h = 0.0f;  // undefined color!
    }
    else
    {
        float delta = max-min;
        result.s = delta/max;  // saturation

        if ( color.r == max )  // between yellow & magenta
        {
        result.h = (color.g-color.b)/delta;
        }
        else if ( color.g == max )  // between cyan & yellow
        {
        result.h = 2.0f+(color.b-color.r)/delta;
        }
        else  // between magenta & cyan
        {
        result.h = 4.0f+(color.r-color.g)/delta;
        }

        result.h *= 60.0f;  // in degrees
        if ( result.h < 0.0f )  result.h += 360.0f;
        result.h /= 360.0f;  // 0..1
    }

    return result;
}

Color HSV2RGB(ColorHSV color)
{
    Color result;

    color.h = Math::Norm(color.h)*360.0f;
    color.s = Math::Norm(color.s);
    color.v = Math::Norm(color.v);

    if ( color.s == 0.0f )  // zero saturation?
    {
        result.r = color.v;
        result.g = color.v;
        result.b = color.v;  // gray
    }
    else
    {
        if ( color.h == 360.0f )  color.h = 0.0f;
        color.h /= 60.0f;
        int i = static_cast<int>(color.h);  // integer part (0 .. 5)
        float f = color.h-i;   // fractional part

        float v = color.v;
        float p = color.v*(1.0f-color.s);
        float q = color.v*(1.0f-(color.s*f));
        float t = color.v*(1.0f-(color.s*(1.0f-f)));

        switch (i)
        {
        case 0:  result.r=v; result.g=t; result.b=p;  break;
        case 1:  result.r=q; result.g=v; result.b=p;  break;
        case 2:  result.r=p; result.g=v; result.b=t;  break;
        case 3:  result.r=p; result.g=q; result.b=v;  break;
        case 4:  result.r=t; result.g=p; result.b=v;  break;
        case 5:  result.r=v; result.g=p; result.b=q;  break;
        }
    }

    return result;
}


} // namespace Gfx