cgv
Loading...
Searching...
No Matches
color_operations.h
1#pragma once
2#include <cgv/math/vec.h>
3#include <cgv/math/mat.h>
4#include <iostream>
5#include <string>
6
7namespace cgv{
8 namespace math{
9
10
22
23template <typename T>
24inline mat<T> create_color_map(unsigned steps=256,std::string name="jet")
25{
26
27 mat<T> map;
28 map.resize(3,steps);
29
30 if(name == "gray")
31 {
32 vec<T> ls = lin_space<T>(0,1,steps);
33
34 //a linear grayscale colormap.
35 for(unsigned i = 0; i < steps;i++)
36 {
37 map(0,i)=ls(i);
38 map(1,i)=ls(i);
39 map(2,i)=ls(i);
40 }
41 return map;
42 }
43 if(name == "bone")
44 {
45 vec<T> x;
46 x=lin_space<T>(0,1,steps);
47 //bone
48 //is a grayscale colormap with a higher value for the blue component.
49 //This colormap is useful for adding an "electronic" look to grayscale images.
50 for(unsigned i = 0; i < steps;i++)
51 {
52 if(x(i) < 3.0f/4.0f)
53 map(0,i)=(7.0f/8.0f * x(i));
54 else
55 map(0,i)=(11.0f/8.0f * x(i) - 3.0f/8.0f);
56
57 if(x(i) < 3.0f/8.0f)
58 map(1,i)=(7.0f/8.0f * x(i));
59 else if(x(i) < 3.0f/4.0f)
60 map(1,i)=(29.0f/24.0f * x(i) - 1.0f/8.0f);
61 else
62 map(1,i)=(7.0f/8.0f * x(i) + 1.0f/8.0f);
63
64 if(x(i) < 3.0f/8.0f)
65 map(2,i)= (29.0f/24.0f * x(i));
66 else
67 map(2,i)=(7.0f/8.0f * x(i) + 1.0f/8.0f);
68
69
70 }
71 return map;
72 }
73 if(name == "jet")
74 {
75 vec<T> x;
76 x=lin_space<T>(0,1,steps);
77
78 for(unsigned i = 0; i < steps;i++)
79 {
80 map(0,i)=map(1,i)=map(2,i)=0.0f;
81
82 if((x(i) >= 3.0f/8.0f) && (x(i) < 5.0f/8.0f))
83 map(0,i) = (4.0f * x(i) - 3.0f/2.0f);
84
85 if((x(i) >= 5.0f/8.0f) && (x(i) < 7.0f/8.0f))
86 {
87 map(0,i)=1.0f;
88 }
89 if(x(i) >= 7.0f/8.0f)
90 map(0,i)+= -4.0f * x(i) + 9.0f/2.0f;
91
92
93 if(x(i) >= 1.0f/8.0f && x(i) < 3.0f/8.0f)
94 map(1,i)= (4.0f * x(i) - 1.0f/2.0f);
95
96 if(x(i) >= 3.0f/8.0f && x(i) < 5.0f/8.0f)
97 {
98 map(1,i)=1;
99 }
100 if(x(i) >= 5.0f/8.0f && x(i) < 7.0f/8.0f)
101 map(1,i)+= (-4.0f * x(i) + 7.0f/2.0f);
102
103
104 if(x(i) < 1.0f/8.0f)
105 map(2,i)= (4.0f * x(i) + 1.0f/2.0f);
106
107 if(x(i) >= 1.0f/8.0f && x(i) < 3.0f/8.0f)
108 {
109 map(2,i)=1.0;
110 }
111 if(x(i) >= 3.0f/8.0f && x(i) < 5.0f/8.0f)
112 map(2,i) += -4.0f * x(i) + 5.0f/2.0f;
113
114
115
116
117 }
118 return map;
119 }
120 if(name == "hot")
121 {
122 vec<T> x;
123 x=lin_space<T>(0,1,steps);
124
125 for(unsigned i = 0; i < steps;i++)
126 {
127 map(0,i)=map(1,i)=map(2,i)=0.0f;
128
129 if(x(i) <= 1.0f/3.0f)
130 map(0,i) = 3.0f*x(i);
131 else
132 map(0,i) = 1.0f;
133
134
135 if(x(i) > 1.0f/3.0f && x(i) < 2.0f/3.0f)
136 map(1,i)= 3.0f*x(i) -1.0f;
137 if(x(i) >=2.0/3.0f)
138 map(1,i)=1.0f;
139
140
141 if(x(i) >= 2.0f/3.0f)
142 map(2,i)=3.0f*x(i)-2.0f;
143
144
145 }
146 return map;
147 }
148 if(name == "hsv")
149 {
150 vec<T> x;
151 x=lin_space<T>(0,1,steps);
152
153 for(unsigned i = 0; i < steps;i++)
154 {
155 map(0,i)=map(1,i)=map(2,i)=0.0f;
156
157 if(x(i) <= 1.0f/5.0f)
158 map(0,i) = 1.0f;
159 if(x(i) > 1.0f/5.0f && x(i) <=2.0f/5.0f)
160 map(0,i) = -5.0f*x(i) + 2.0f;
161 if(x(i) > 4.0f/5.0f)
162 map(0,i) = 5.0f*x(i)-4.0f;
163
164 if(x(i) <= 1.0f/5.0f)
165 map(1,i) = 5.0f*x(i);
166 if(x(i) > 1.0f/5.0f && x(i) <=3.0f/5.0f)
167 map(1,i) = 1.0f;
168 if(x(i) > 3.0f/5.0f && x(i) <= 4.0f/5.0f)
169 map(1,i) = -5.0f*x(i)+4.0f;
170
171
172
173 if(x(i) > 2.0f/5.0f && x(i) <=3.0f/5.0f)
174 map(2,i) = 5.0f*x(i)-2.0f;
175 if(x(i) > 3.0f/5.0f && x(i) <= 4.0f/5.0f)
176 map(2,i) = 1.0f;
177 if(x(i) >4.0f/5.0f)
178 map(2,i) = -5.0f*x(i)+5.0f;
179
180
181
182 }
183 return map;
184 }
185 if(name == "thermo")
186 {
187 vec<T> x;
188 x=lin_space<T>(0,1,steps);
189
190 for(unsigned i = 0; i < steps;i++)
191 {
192 map(0,i)=map(1,i)=map(2,i)=0.0f;
193
194
195 if(x(i) <= 1.0f/7.0f)
196 map(0,i) = 7.0f*x(i);
197 if(x(i) > 1.0f/7.0f && x(i) <=2.0f/7.0f)
198 map(0,i) = -7.0f*x(i) + 2.0f;
199 if(x(i) > 4.0f/7.0f && x(i) <=5.0f/7.0f)
200 map(0,i) = 7.0f*x(i)-4.0f;
201 if(x(i) >5.0f/7.0f)
202 map(0,i) = 1.0f;
203
204 if(x(i) >=2.0f/7.0f && x(i) <= 3.0f/7.0f)
205 map(1,i) = 7.0f*x(i)-2.0f;
206 else if(x(i) > 3.0f/7.0f && x(i) <=5.0f/7.0f)
207 map(1,i) = 1.0f;
208 else if(x(i) > 5.0f/7.0f && x(i) <=6.0f/7.0f)
209 map(1,i) = -7.0f*x(i)+6.0f;
210 else if(x(i) > 6.0f/7.0f)
211 map(1,i) = 7.0f*x(i)-6.0f;
212
213 if(x(i) <= 1.0f/7.0f)
214 map(2,i) = 7.0f*x(i);
215 if(x(i) > 1.0f/7.0f && x(i) <=3.0f/7.0f)
216 map(2,i) = 1.0f;
217 if(x(i) > 3.0f/7.0f && x(i) <=4.0f/7.0f)
218 map(2,i) = -7.0f*x(i)+4.0f;
219 if(x(i) > 6.0f/7.0f)
220 map(2,i) = 7.0f*x(i)-6.0f;
221
222
223 }
224 return map;
225
226 }
227 assert(false); //colormap not found
228 return map;
229}
230
231
232template <typename T>
233 math::vec<T> rgb_2_cmy(const math::vec<T>& rgb)
234 {
235 math::vec<T> cmy(3);
236 cmy.fill(1);
237 cmy-=rgb;
238 return cmy;
239 }
240
241 template <typename T>
242 void rgb_2_cmy(math::mat<T>& m)
243 {
244 for(unsigned i = 0; i < m.ncols();i++)
245 m.set_col(i,rgb_2_cmy(m.col(i)));
246
247 }
248
249 template <typename T>
250 math::vec<T> cmy_2_rgb(const math::vec<T>& cmy)
251 {
252 math::vec<T> rgb(3);
253 rgb.fill(1);
254 rgb-=cmy;
255 return rgb;
256 }
257
258 template <typename T>
259 void cmy_2_rgb(math::mat<T>& m)
260 {
261 for(unsigned i = 0; i < m.ncols();i++)
262 m.set_col(i,cmy_2_rgb(m.col(i)));
263
264 }
265
266
267
268 template <typename T>
269 math::vec<T> rgb_2_hsv(const math::vec<T>& rgb)
270 {
271 T _min, _max, _delta;
272 _min = minimum( rgb(0), rgb(1), rgb(2) );
273 _max = maximum( rgb(0), rgb(1), rgb(2) );
274 vec<T> hsv(3);
275
276 hsv(2) = _max; // v
277 _delta = _max - _min;
278 if( _max != (T)0 )
279 hsv(1) = _delta / _max; // s
280 else
281 {
282 hsv(1) = (T)0;
283 hsv(0) = (T)-1;
284 return hsv;
285 }
286 if( rgb(0) == _max )
287 hsv(0) = ( rgb(1) - rgb(2) ) / _delta; // between yellow & magenta
288 else if( rgb(1) == _max )
289 hsv(0) = 2 + ( rgb(2) - rgb(0) ) / _delta; // between cyan & yellow
290 else
291 hsv(0) = 4 + ( rgb(0) - rgb(1) ) / _delta; // between magenta & cyan
292 hsv(0) *= (T)60; // degrees
293 if( hsv(0) < (T)0 )
294 hsv(0) += (T)360;
295 return hsv;
296
297 }
298
299 template <typename T>
300 void rgb_2_hsv(math::mat<T>& m)
301 {
302 for(unsigned i = 0; i < m.ncols();i++)
303 m.set_col(i,rgb_2_hsv(m.col(i)));
304 }
305
306 template <typename T>
307 math::vec<T> hsv_2_rgb(const math::vec<T>& hsv)
308 {
309 math::vec<T> rgb(3);
310 int i;
311 T f, p, q, t;
312 if( hsv(1) == 0 ) {
313 // achromatic (grey)
314 rgb.fill(hsv(2));
315 return rgb;
316 }
317 T h =hsv(0)/ (T)60; // sector 0 to 5
318 i = (int)floor( hsv(0) );
319 f = h - (T)i; // factorial part of h
320 p = hsv(2) * ( (T)1 - hsv(1) );
321 q = hsv(2) * ( (T)1 - hsv(1) * f );
322 t = hsv(2) * ( (T)1 - hsv(1) * ( (T)1 - f ) );
323 switch( i ) {
324 case 0:
325 rgb(0) = hsv(2);
326 rgb(1) = t;
327 rgb(2) = p;
328 break;
329 case 1:
330 rgb(0) = q;
331 rgb(1) = hsv(2);
332 rgb(2) = p;
333 break;
334 case 2:
335 rgb(0) = p;
336 rgb(1) = hsv(2);
337 rgb(2) = t;
338 break;
339 case 3:
340 rgb(0) = p;
341 rgb(1) = q;
342 rgb(2) = hsv(2);
343 break;
344 case 4:
345 rgb(0) = t;
346 rgb(1) = p;
347 rgb(2) = hsv(2);
348 break;
349 default: // case 5:
350 rgb(0) = hsv(2);
351 rgb(1) = p;
352 rgb(2) = q;
353 break;
354 }
355 return rgb;
356 }
357
358 template <typename T>
359 void hsvb_2_rgb(math::mat<T>& m)
360 {
361 for(unsigned i = 0; i < m.ncols();i++)
362 m.set_col(i,hsv_2_rgb(m.col(i)));
363 }
364
365 template <typename T>
366 math::vec<T> rgb_2_yiq(const math::vec<T>& rgb)
367 {
368 math::vec<T> yiq(3);
369 yiq(0) = (T)0.299*rgb(0) + (T)0.587*rgb(1) + (T)0.114*rgb(2);
370 yiq(1) = (T)0.596*rgb(0) - (T)0.275*rgb(1) - (T)0.321*rgb(2);
371 yiq(2) = (T)0.212*rgb(0) - (T)0.523*rgb(1) + (T)0.311*rgb(2);
372 return yiq;
373 }
374
375 template <typename T>
376 T rgb_2_gray(const math::vec<T>& rgb)
377 {
378 return (T)0.299*rgb(0) + (T)0.587*rgb(1) + (T)0.114*rgb(2);
379 }
380
381 template <typename T>
382 void rgb_2_gray(const math::mat<T>& rgb, math::vec<T>& g)
383 {
384 g.resize(rgb.ncols());
385
386 for(unsigned i = 0; i < m.ncols();i++)
387 g(i)= (T)0.299*rgb(0,i) + (T)0.587*rgb(1,i) + (T)0.114*rgb(2,i);
388
389 }
390
391 template <typename T>
392 void rgb_2_gray(math::mat<T>& rgb)
393 {
394
395
396 for(unsigned i = 0; i < rgb.ncols();i++)
397 {
398 rgb(0,i)= (T)0.299*rgb(0,i) + (T)0.587*rgb(1,i) + (T)0.114*rgb(2,i);
399 rgb(1,i)=rgb(2,i)=rgb(0,i);
400 }
401
402 }
403
404 template <typename T>
405 void rgb_2_yiq(math::mat<T>& m)
406 {
407 for(unsigned i = 0; i < m.ncols();i++)
408 m.set_col(i,rgb_2_yiq(m.col(i)));
409 }
410
411 template <typename T>
412 math::vec<T> yiq_2_rgb(const math::vec<T>& yiq)
413 {
414 math::vec<T> rgb(3);
415 rgb(0) = yiq(0) + (T)0.956*yiq(1) + (T)0.621*yiq(2);
416 rgb(1) = yiq(0) - (T)0.272*yiq(1) - (T)0.647*yiq(2);
417 rgb(2) = yiq(0) - (T)1.105*yiq(1) + (T)1.702*yiq(2);
418 return rgb;
419 }
420
421 template <typename T>
422 void yiq_2_rgb(math::mat<T>& m)
423 {
424 for(unsigned i = 0; i < m.ncols();i++)
425 m.set_col(i,yiq_2_rgb(m.col(i)));
426 }
427
428 template <typename T>
429 math::vec<T> rgb_2_xyz(const math::vec<T>& rgb)
430 {
431 math::vec<T> xyz(3);
432 xyz(0) = (T)0.412453*rgb(0) + (T)0.357580*rgb(1) + (T)0.180423*rgb(2);
433 xyz(1) = (T)0.212671*rgb(0) + (T)0.715160*rgb(1) + (T)0.072169*rgb(2);
434 xyz(2) = (T)0.019334*rgb(0) + (T)0.119193*rgb(1) + (T)0.950227*rgb(2);
435 return xyz;
436 }
437
439 template <typename T>
440 void rgb_2_xyz(math::mat<T>& m)
441 {
442 for(unsigned i = 0; i < m.ncols();i++)
443 m.set_col(i,rgb_2_xyz(m.col(i)));
444 }
445
447 template <typename T>
448 math::vec<T> xyz_2_rgb(const math::vec<T>& xyz)
449 {
450 math::vec<T> rgb(3);
451 rgb(0) = (T)3.240479*xyz(0) - (T)1.537150*xyz(1) - (T)0.498535*xyz(2);
452 rgb(1) = -(T)0.969256*xyz(0) + (T)1.875992*xyz(1) + (T)0.041556*xyz(2);
453 rgb(2) = (T)0.055648*xyz(0) - (T)0.204043*xyz(1) + (T)1.057311*xyz(2);
454 return rgb;
455 }
456
458 template <typename T>
459 void xyz_2_rgb(math::mat<T>& m)
460 {
461 for(unsigned i = 0; i < m.ncols();i++)
462 m.set_col(i,xyz_2_rgb(m.col(i)));
463 }
464
465
466
467
468}
469}
the cgv namespace
Definition print.h:11
cgv::media::color< float, cgv::media::RGB > rgb
declare rgb color type with 32 bit components
Definition color.h:853