summaryrefslogtreecommitdiff
path: root/apps/plugins/lib/rgb_hsv.c
blob: 0d424b914959b0cf1e63703bc0e4080bdee20057 (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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 * $Id$
 *
 * Copyright (C) 2006 Antoine Cellerier <dionoea -at- videolan -dot- org>
 *
 * All files in this archive are subject to the GNU General Public License.
 * See the file COPYING in the source tree root for full license agreement.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ****************************************************************************/

#include "rgb_hsv.h"

/***********************************************************************
 * Colorspace transformations
 ***********************************************************************
 * r, g and b range from 0 to 255
 * h ranges from 0 to 3599 (which in fact means 0.0 to 359.9).
 *   360 is the same as 0 (it loops)
 * s and v range from 0 to 255 (which in fact means 0.00 to 1.00)
 ***********************************************************************/

void rgb2hsv( int r, int g, int b, int *h, int *s, int *v )
{
    int max;
    int min;

    max = r > g ? r : g;
    if( b > max ) max = b;

    min = r < g ? r : g;
    if( b < min ) min = b;

    if( max == 0 )
    {
        *v = 0;
        *h = 0; *s = 0; /* Random since it's black */
        return;
    }
    else if( max == min )
    {
        *h = 0; /* Random since it's gray */
    }
    else if( max == r && g >= b )
    {
        *h = ( 10 * 60 * ( g - b )/( max - min ) );
    }
    else if( max == r && g < b )
    {
        *h = ( 10 * ( 60 * ( g - b )/( max - min ) + 360 ));
    }
    else if( max == g )
    {
        *h = ( 10 * ( 60 * ( b - r )/( max - min ) + 120 ));
    }
    else// if( max == b )
    {
        *h = ( 10 * ( 60 * ( r - g )/( max - min ) + 240 ));
    }

    /* Just in case ? */
    while( *h < 0 ) *h += 3600;
    while( *h >= 3600 ) *h-= 3600;

    *s = (( max - min )*255)/max;
    *v = max;
}

void hsv2rgb( int h, int s, int v, int *r, int *g, int *b )
{
    int f, p, q, t;
    while( h < 0 ) h += 3600;
    while( h >= 3600 ) h-= 3600;
    f = h%600;
    p = ( v * ( 255 - s ) ) / ( 255 );
    q = ( v * ( 600*255 - f*s ) ) / ( 255 * 600 );
    t = ( v * ( 600*255 - ( 600 - f ) * s ) ) / ( 255 * 600 );


    if( s == 0 ) /* gray */
    {
        *r = v;
        *g = *r;
        *b = *r;
        return;
    }

    switch( h/600 )
    {
        case 0:
            *r = v;
            *g = t;
            *b = p;
            break;
        case 1:
            *r = q;
            *g = v;
            *b = p;
            break;
        case 2:
            *r = p;
            *g = v;
            *b = t;
            break;
        case 3:
            *r = p;
            *g = q;
            *b = v;
            break;
        case 4:
            *r = t;
            *g = p;
            *b = v;
            break;
        case 5:
            *r = v;
            *g = p;
            *b = q;
            break;
    }
}