libvisual  0.5.0
lv_color.cpp
1 /* Libvisual - The audio visualisation framework.
2  *
3  * Copyright (C) 2012 Libvisual
4  * 2004-2006 Dennis Smit
5  *
6  * Authors: Dennis Smit <ds@nerds-incorporated.org>
7  * Chong Kai Xiong <kaixiong@codeleft.sg>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU Lesser General Public License as
11  * published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  */
23 
24 #include "config.h"
25 #include "lv_color.h"
26 #include "lv_common.h"
27 
28 union pixel16_t {
29  struct {
30  #if VISUAL_LITTLE_ENDIAN == 1
31  uint16_t b:5, g:6, r:5;
32  #else
33  uint16_t r:5, g:6, b:5;
34  #endif
35  } rgb;
36 
37  uint16_t value;
38 };
39 
40 namespace LV {
41 
42  void Color::set_hsv (float h, float s, float v)
43  {
44  int i;
45  float f, w, q, t, r = 0, g = 0, b = 0;
46 
47  if (s == 0.0)
48  s = 0.000001;
49 
50  if (h == 360.0)
51  h = 0.0;
52 
53  h = h / 60.0;
54  i = int (h);
55  f = h - i;
56  w = v * (1.0 - s);
57  q = v * (1.0 - (s * f));
58  t = v * (1.0 - (s * (1.0 - f)));
59 
60  switch (i) {
61  case 0: r = v; g = t; b = w; break;
62  case 1: r = q; g = v; b = w; break;
63  case 2: r = w; g = v; b = t; break;
64  case 3: r = w; g = q; b = v; break;
65  case 4: r = t; g = w; b = v; break;
66  case 5: r = v; g = w; b = q; break;
67 
68  default:
69  break;
70  }
71 
72  set (r * 255, g * 255, b * 255);
73  }
74 
75  void Color::get_hsv (float& h, float& s, float& v) const
76  {
77  float rf = r / 255.0;
78  float gf = g / 255.0;
79  float bf = b / 255.0;
80 
81  float max = rf;
82 
83  if (gf > max)
84  max = gf;
85 
86  if (bf > max)
87  max = bf;
88 
89  float min = rf;
90 
91  if (gf < min)
92  min = gf;
93 
94  if (bf < min)
95  min = bf;
96 
97  v = max;
98 
99  if (max != 0.0)
100  s = (max - min) / max;
101  else
102  s = 0.0;
103 
104  if (s == 0.0) {
105  h = 0.0;
106  } else {
107  float delta = max - min;
108 
109  if (rf == max)
110  h = (gf - bf) / delta;
111  else if (gf == max)
112  h = 2.0 + (bf - rf) / delta;
113  else if (b == max)
114  h = 4.0 + (rf - gf) / delta;
115 
116  h *= 60.0;
117 
118  if (h < 0.0)
119  h += 360;
120  }
121  }
122 
123  void Color::set_from_uint32 (uint32_t rgba)
124  {
125  auto const color = reinterpret_cast<uint8_t*> (&rgba);
126 
127 #if VISUAL_LITTLE_ENDIAN == 1
128  b = color[0];
129  g = color[1];
130  r = color[2];
131  a = color[3];
132 #else
133  a = color[0];
134  r = color[1];
135  g = color[2];
136  b = color[3];
137 #endif // VISUAL_LITTLE_ENDIAN
138  }
139 
140  void Color::set_from_uint16 (uint16_t rgb)
141  {
142  pixel16_t pixel;
143  pixel.value = rgb;
144 
145  r = pixel.rgb.r << 3;
146  g = pixel.rgb.g << 2;
147  b = pixel.rgb.b << 3;
148  }
149 
150  uint32_t Color::to_uint32 () const
151  {
152  return ( (a << 24) | (r << 16) | (g << 8) | b );
153  }
154 
155  uint16_t Color::to_uint16 () const
156  {
157  pixel16_t pixel;
158 
159  pixel.rgb.r = r >> 3;
160  pixel.rgb.g = g >> 2;
161  pixel.rgb.b = b >> 3;
162 
163  return pixel.value;
164  }
165 
166 } // LV namespace