vil_colour_space.cxx
Go to the documentation of this file.
1 // This is core/vil/algo/vil_colour_space.cxx
2 //:
3 // \file
4 // \author fsm
5 
6 #include <cstdlib>
7 #include <algorithm>
8 #include <cmath>
9 #include "vil_colour_space.h"
10 #ifdef _MSC_VER
11 # include <vcl_msvc_warnings.h>
12 #endif
13 
14 template <class T>
15 void vil_colour_space_RGB_to_YIQ(T const in[3], T out[3])
16 {
17  out[0] = T(0.299) * in[0] + T(0.587) * in[1] + T(0.114) * in[2];
18  out[1] = T(0.595716) * in[0] - T(0.274453) * in[1] - T(0.321263) * in[2];
19  out[2] = T(0.211456) * in[0] - T(0.522591) * in[1] + T(0.311135) * in[2];
20 }
21 
22 template <class T>
23 void vil_colour_space_YIQ_to_RGB(T const in[3], T out[3])
24 {
25  out[0] = in[0] + T(0.956296) * in[1] + T(0.621024) * in[2];
26  out[1] = in[0] - T(0.272122) * in[1] - T(0.647381) * in[2];
27  out[2] = in[0] - T(1.106989) * in[1] + T(1.704615) * in[2];
28 }
29 
30 //:
31 // \verbatim
32 // green --- yellow //
33 // / \ / \ //
34 // cyan --- white ---- red //
35 // \ / \ / //
36 // blue --- magenta //
37 // //
38 // \endverbatim
39 
40 template <class T>
41 void vil_colour_space_RGB_to_HSV(T r, T g, T b, T *h, T *s, T *v)
42 {
43  T max = std::max(r, std::max(g, b));
44  T min = std::min(r, std::min(g, b));
45 
46  // The value v is just the maximum.
47  *v = max;
48 
49  // Next, saturation.
50  if (max > 0)
51  *s = (max - min)/max;
52  else
53  *s = 0;
54 
55  // Lastly, the hue:
56  if (*s == 0)
57  *h = T(); // The hue is undefined in the achromatic case.
58  else {
59  T delta = max - min;
60  if (r == max)
61  *h = (g - b)/delta;
62  else if (g == max)
63  *h = 2 + (b - r)/delta;
64  else if (b == max)
65  *h = 4 + (r - g)/delta;
66  else
67  std::abort();
68 
69  *h *= 60;
70  if (*h < 0)
71  *h += 360;
72  }
73 }
74 
75 template <class T>
76 void vil_colour_space_HSV_to_RGB(T h, T s, T v, T *r, T *g, T *b)
77 {
78  T p1, p2, p3, f, nr=0, ng=0, nb=0;
79  T xh;
80  int i;
81 
82  v = v/255;
83 
84 #if 0
85  extern float hue, s, v; // hue (0.0 to 360.0, is circular, 0=360)
86  // s and v are from 0.0 to 1.0
87  extern long r2, g2, b2; // values from 0 to 63
88 #endif
89 
90  h -= int(h/360)*360; // (THIS LOOKS BACKWARDS)
91  if (h < 0) h += 360;
92 
93  xh = h / 60; // convert hue to be in [0,6)
94  i = (int)std::floor((double)xh);// i = greatest integer <= xh
95  f = xh - i; // f = fractional part of xh
96  p1 = v * (1 - s);
97  p2 = v * (1 - (s * f));
98  p3 = v * (1 - (s * (1 - f)));
99 
100  switch (i)
101  {
102  case 0:
103  nr = v;
104  ng = p3;
105  nb = p1;
106  break;
107  case 1:
108  nr = p2;
109  ng = v;
110  nb = p1;
111  break;
112  case 2:
113  nr = p1;
114  ng = v;
115  nb = p3;
116  break;
117  case 3:
118  nr = p1;
119  ng = p2;
120  nb = v;
121  break;
122  case 4:
123  nr = p3;
124  ng = p1;
125  nb = v;
126  break;
127  case 5:
128  nr = v;
129  ng = p1;
130  nb = p2;
131  break;
132  default:
133  break; // cannot be reached
134  }
135 
136  *r = nr * 255; // Normalize the values to 63
137  *g = ng * 255;
138  *b = nb * 255;
139  return;
140 }
141 
142 
143 template <class T>
144 void vil_colour_space_RGB_to_YUV(T const in[3], T out[3])
145 {
146  out[0] = T(0.299) * in[0] + T(0.587) * in[1] + T(0.114) * in[2];
147  out[1] = T(0.492) * (in[2] - out[0]);
148  out[2] = T(0.877) * (in[0] - out[0]);
149 }
150 
151 
152 template <class T>
153 void vil_colour_space_YUV_to_RGB(T const in[3], T out[3])
154 {
155  // the coefficient of the inverse are given here to higher precision
156  // than typically used. This allows for more accurate results when
157  // working with floating point color representations
158  out[0] = in[0] + T(1.1402508551881) * in[2];
159  out[1] = in[0] - T(0.39473137491174) * in[1] - T(0.5808092090311) * in[2];
160  out[2] = in[0] + T(2.0325203252033) * in[1];
161 }
162 
163 // YPbPr (ITU-R BT.601)
164 // ========================================================
165 // Y' = + 0.299 * R' + 0.587 * G' + 0.114 * B'
166 // Pb = - 0.168736 * R' - 0.331264 * G' + 0.5 * B'
167 // Pr = + 0.5 * R' - 0.418688 * G' - 0.081312 * B'
168 // ........................................................
169 // R', G', B' in [0; 1]
170 // Y' in [0; 1]
171 // Pb in [-0.5; 0.5]
172 // Pr in [-0.5; 0.5]
173 template <class T>
174 void vil_colour_space_RGB_to_YPbPr_601(T const RGB[3], T YPbPr[3])
175 {
176  YPbPr[0] = T(0.299) * RGB[0] + T(0.587) * RGB[1] + T(0.114) * RGB[2];
177  YPbPr[1] = T(-0.168736)* RGB[0] - T(0.331264) * RGB[1] + T(0.5) * RGB[2];
178  YPbPr[2] = T(0.5) * RGB[0] - T(0.418688) * RGB[1] - T(0.081312) * RGB[2];
179 }
180 
181 // YPbPr (ITU-R BT.601)
182 // ==========================================================
183 // R' = + 0.299 * Y' + 0.587 * Pb' + 0.114 * Pr'
184 // G' = - 0.168736 * Y' - 0.331264 * Pb' + 0.5 * Pr'
185 // B' = + 0.5 * Y' - 0.418688 * Pb' - 0.081312 * Pr'
186 // ..........................................................
187 // Y' in [0; 1]
188 // Pb in [-0.5; 0.5]
189 // Pr in [-0.5; 0.5]
190 // R', G', B' in [0; 1]
191 template <class T>
192 void vil_colour_space_YPbPr_601_to_RGB(T const YPbPr[3], T RGB[3])
193 {
194  RGB[0] = std::max(T(0.0), std::min(T(1.0), (YPbPr[0] + T(1.402) * YPbPr[2])));
195  RGB[1] = std::max(T(0.0), std::min(T(1.0), (YPbPr[0] - T(0.344136) * YPbPr[1] - T(0.714136) * YPbPr[2])));
196  RGB[2] = std::max(T(0.0), std::min(T(1.0), (YPbPr[0] + T(1.772) * YPbPr[1] )));
197 }
198 
199 // YCbCr (601) from "digital 8-bit R'G'B' "
200 // ========================================================================
201 // Y' = 16 + 1/256 * ( 65.738 * R'd + 129.057 * G'd + 25.064 * B'd)
202 // Cb = 128 + 1/256 * ( - 37.945 * R'd - 74.494 * G'd + 112.439 * B'd)
203 // Cr = 128 + 1/256 * ( 112.439 * R'd - 94.154 * G'd - 18.285 * B'd)
204 // ........................................................................
205 // R'd, G'd, B'd in {0, 1, 2, ..., 255}
206 // Y' in {16, 17, ..., 235}
207 // with footroom in {1, 2, ..., 15}
208 // headroom in {236, 237, ..., 254}
209 // sync. in {0, 255}
210 // Cb, Cr in {16, 17, ..., 240}
211 void vil_colour_space_RGB_to_YCbCr_601(const unsigned char RGB[3], unsigned char YCbCr[3])
212 {
213  // Add an extra 0.5555555 to round instead of truncate
214  YCbCr[0] = static_cast<unsigned char>(
215  16.0 + ( 65.738 * RGB[0] + 129.057 * RGB[1] + 25.064 * RGB[2])/256.0 + 0.55555555);
216  YCbCr[1] = static_cast<unsigned char>(
217  128.0 + ( -37.945 * RGB[0] - 74.494 * RGB[1] + 112.439 * RGB[2])/256.0 + 0.55555555);
218  YCbCr[2] = static_cast<unsigned char>(
219  128.0 + ( 112.439 * RGB[0] - 94.154 * RGB[1] - 18.285 * RGB[2])/256.0 + 0.55555555);
220 }
221 
222 // 8-bit R'G'B' from YCbCr (601)
223 // =====================================================================
224 // R'd = ( 298.082 * Y' + 408.583 * Cr ) / 256 - 222.921
225 // G'd = ( 298.082 * Y' - 100.291 * Cb - 208.120 * Cr ) / 256 + 135.576
226 // B'd = ( 298.082 * Y' + 516.412 * Cb ) / 256 - 276.836
227 void vil_colour_space_YCbCr_601_to_RGB(const unsigned char YCbCr[3], unsigned char RGB[3])
228 {
229  RGB[0] = static_cast<unsigned char>(
230  (298.082 * YCbCr[0] + 408.583 * YCbCr[2]) / 256.0 - 222.921);
231  RGB[1] = static_cast<unsigned char>(
232  (298.082 * YCbCr[0] - 100.291 * YCbCr[1] - 208.120 * YCbCr[2]) / 256.0 + 135.576);
233  RGB[2] = static_cast<unsigned char>(
234  (298.082 * YCbCr[0] + 516.412 * YCbCr[1] ) / 256.0 - 276.836);
235 }
236 
237 
238 //----------------------------------------------------------------------
239 
240 #define inst(T) \
241 template void vil_colour_space_RGB_to_YIQ(T const [3], T [3]); \
242 template void vil_colour_space_YIQ_to_RGB(T const [3], T [3]); \
243 template void vil_colour_space_RGB_to_HSV(T, T, T, T *, T *, T *); \
244 template void vil_colour_space_HSV_to_RGB(T, T, T, T *, T *, T *); \
245 template void vil_colour_space_RGB_to_YUV(T const [3], T [3]); \
246 template void vil_colour_space_YUV_to_RGB(T const [3], T [3]); \
247 template void vil_colour_space_RGB_to_YPbPr_601(T const RGB[3], T YPbPr[3]); \
248 template void vil_colour_space_YPbPr_601_to_RGB(T const YPbPr[3], T RGB[3])
249 
250 inst(double);
251 inst(float);
void vil_colour_space_HSV_to_RGB(T h, T s, T v, T *r, T *g, T *b)
Transform from HSV to RGB colour space.
void vil_colour_space_YPbPr_601_to_RGB(T const YPbPr[3], T RGB[3])
Transformation from analog YPbPr to RGB colour spaces.
void vil_colour_space_YUV_to_RGB(T const in[3], T out[3])
Linear transformation from YUV to RGB colour spaces.
void vil_colour_space_RGB_to_YPbPr_601(T const RGB[3], T YPbPr[3])
Transformation from analog RGB to analog YPbPr colour spaces.
#define v
void vil_colour_space_RGB_to_YIQ(T const in[3], T out[3])
Linear transformation from RGB to YIQ colour spaces.
void vil_colour_space_RGB_to_HSV(T r, T g, T b, T *h, T *s, T *v)
Transform from RGB to HSV colour spaces.
#define inst(T)
void vil_colour_space_RGB_to_YCbCr_601(const unsigned char RGB[3], unsigned char YCbCr[3])
Transformation from 8 bit RGB to 8 bit YCbCr colour spaces.
vnl_decnum max(vnl_decnum const &x, vnl_decnum const &y)
void vil_colour_space_YIQ_to_RGB(T const in[3], T out[3])
Linear transformation from YIQ to RGB colour spaces.
vnl_decnum min(vnl_decnum const &x, vnl_decnum const &y)
void vil_colour_space_RGB_to_YUV(T const in[3], T out[3])
Linear transformation from RGB to YUV colour spaces.
void vil_colour_space_YCbCr_601_to_RGB(const unsigned char YCbCr[3], unsigned char RGB[3])
Transformation from 8 bit YCbCr to 8 bit RGB colour spaces.
Functions to convert between different colour spaces.