svn merge ^/trunk/blender -r42927:42931
[blender.git] / source / blender / blenlib / intern / math_color.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  
21  * The Original Code is: some of this file.
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  * */
25
26 /** \file blender/blenlib/intern/math_color.c
27  *  \ingroup bli
28  */
29
30
31 #include <assert.h>
32
33 #include "BLI_math.h"
34
35 void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b)
36 {
37         int i;
38         float f, p, q, t;
39
40         if(s==0.0f) {
41                 *r = v;
42                 *g = v;
43                 *b = v;
44         }
45         else {
46                 h= (h - floorf(h))*6.0f;
47
48                 i = (int)floorf(h);
49                 f = h - i;
50                 p = v*(1.0f-s);
51                 q = v*(1.0f-(s*f));
52                 t = v*(1.0f-(s*(1.0f-f)));
53                 
54                 switch (i) {
55                 case 0 :
56                         *r = v;
57                         *g = t;
58                         *b = p;
59                         break;
60                 case 1 :
61                         *r = q;
62                         *g = v;
63                         *b = p;
64                         break;
65                 case 2 :
66                         *r = p;
67                         *g = v;
68                         *b = t;
69                         break;
70                 case 3 :
71                         *r = p;
72                         *g = q;
73                         *b = v;
74                         break;
75                 case 4 :
76                         *r = t;
77                         *g = p;
78                         *b = v;
79                         break;
80                 case 5 :
81                         *r = v;
82                         *g = p;
83                         *b = q;
84                         break;
85                 }
86         }
87 }
88
89 void rgb_to_yuv(float r, float g, float b, float *ly, float *lu, float *lv)
90 {
91         float y, u, v;
92         y= 0.299f*r + 0.587f*g + 0.114f*b;
93         u=-0.147f*r - 0.289f*g + 0.436f*b;
94         v= 0.615f*r - 0.515f*g - 0.100f*b;
95         
96         *ly=y;
97         *lu=u;
98         *lv=v;
99 }
100
101 void yuv_to_rgb(float y, float u, float v, float *lr, float *lg, float *lb)
102 {
103         float r, g, b;
104         r=y+1.140f*v;
105         g=y-0.394f*u - 0.581f*v;
106         b=y+2.032f*u;
107         
108         *lr=r;
109         *lg=g;
110         *lb=b;
111 }
112
113 /* The RGB inputs are supposed gamma corrected and in the range 0 - 1.0f */
114 /* Output YCC have a range of 16-235 and 16-240 except with JFIF_0_255 where the range is 0-255 */
115 void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr, int colorspace)
116 {
117         float sr,sg, sb;
118         float y = 128.f, cr = 128.f, cb = 128.f;
119         
120         sr=255.0f*r;
121         sg=255.0f*g;
122         sb=255.0f*b;
123         
124         switch (colorspace) {
125         case BLI_YCC_ITU_BT601 :
126                 y=(0.257f*sr)+(0.504f*sg)+(0.098f*sb)+16.0f;
127                 cb=(-0.148f*sr)-(0.291f*sg)+(0.439f*sb)+128.0f;
128                 cr=(0.439f*sr)-(0.368f*sg)-(0.071f*sb)+128.0f;
129                 break;
130         case BLI_YCC_ITU_BT709 :
131                 y=(0.183f*sr)+(0.614f*sg)+(0.062f*sb)+16.0f;
132                 cb=(-0.101f*sr)-(0.338f*sg)+(0.439f*sb)+128.0f;
133                 cr=(0.439f*sr)-(0.399f*sg)-(0.040f*sb)+128.0f;
134                 break;
135         case BLI_YCC_JFIF_0_255 :
136                 y=(0.299f*sr)+(0.587f*sg)+(0.114f*sb);
137                 cb=(-0.16874f*sr)-(0.33126f*sg)+(0.5f*sb)+128.0f;
138                 cr=(0.5f*sr)-(0.41869f*sg)-(0.08131f*sb)+128.0f;
139                 break;
140         default:
141                 assert(!"invalid colorspace");
142         }
143         
144         *ly=y;
145         *lcb=cb;
146         *lcr=cr;
147 }
148
149
150 /* YCC input have a range of 16-235 and 16-240 except with JFIF_0_255 where the range is 0-255 */
151 /* RGB outputs are in the range 0 - 1.0f */
152 /* FIXME comment above must be wrong because BLI_YCC_ITU_BT601 y 16.0 cr 16.0 -> r -0.7009 */
153 void ycc_to_rgb(float y, float cb, float cr, float *lr, float *lg, float *lb, int colorspace)
154 {
155         float r = 128.f, g = 128.f, b = 128.f;
156         
157         switch (colorspace) {
158         case BLI_YCC_ITU_BT601 :
159                 r=1.164f*(y-16.0f)+1.596f*(cr-128.0f);
160                 g=1.164f*(y-16.0f)-0.813f*(cr-128.0f)-0.392f*(cb-128.0f);
161                 b=1.164f*(y-16.0f)+2.017f*(cb-128.0f);
162                 break;
163         case BLI_YCC_ITU_BT709 :
164                 r=1.164f*(y-16.0f)+1.793f*(cr-128.0f);
165                 g=1.164f*(y-16.0f)-0.534f*(cr-128.0f)-0.213f*(cb-128.0f);
166                 b=1.164f*(y-16.0f)+2.115f*(cb-128.0f);
167                 break;
168         case BLI_YCC_JFIF_0_255 :
169                 r=y+1.402f*cr - 179.456f;
170                 g=y-0.34414f*cb - 0.71414f*cr + 135.45984f;
171                 b=y+1.772f*cb - 226.816f;
172                 break;
173         default:
174                 assert(!"invalid colorspace");
175         }
176         *lr=r/255.0f;
177         *lg=g/255.0f;
178         *lb=b/255.0f;
179 }
180
181 void hex_to_rgb(char *hexcol, float *r, float *g, float *b)
182 {
183         unsigned int ri, gi, bi;
184
185         if (hexcol[0] == '#') hexcol++;
186
187         if (sscanf(hexcol, "%02x%02x%02x", &ri, &gi, &bi)==3) {
188                 *r = ri / 255.0f;
189                 *g = gi / 255.0f;
190                 *b = bi / 255.0f;
191                 CLAMP(*r, 0.0f, 1.0f);
192                 CLAMP(*g, 0.0f, 1.0f);
193                 CLAMP(*b, 0.0f, 1.0f);
194         }
195         else {
196                 /* avoid using un-initialized vars */
197                 *r= *g= *b= 0.0f;
198         }
199 }
200
201 void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv)
202 {
203         float h, s, v;
204         float cmax, cmin, cdelta;
205         float rc, gc, bc;
206
207         cmax = r;
208         cmin = r;
209         cmax = (g>cmax ? g:cmax);
210         cmin = (g<cmin ? g:cmin);
211         cmax = (b>cmax ? b:cmax);
212         cmin = (b<cmin ? b:cmin);
213
214         v = cmax;               /* value */
215         if (cmax != 0.0f)
216                 s = (cmax - cmin)/cmax;
217         else {
218                 s = 0.0f;
219         }
220         if (s == 0.0f)
221                 h = -1.0f;
222         else {
223                 cdelta = cmax-cmin;
224                 rc = (cmax-r)/cdelta;
225                 gc = (cmax-g)/cdelta;
226                 bc = (cmax-b)/cdelta;
227                 if (r==cmax)
228                         h = bc-gc;
229                 else
230                         if (g==cmax)
231                                 h = 2.0f+rc-bc;
232                         else
233                                 h = 4.0f+gc-rc;
234                 h = h*60.0f;
235                 if (h < 0.0f)
236                         h += 360.0f;
237         }
238         
239         *ls = s;
240         *lh = h / 360.0f;
241         if(*lh < 0.0f) *lh= 0.0f;
242         *lv = v;
243 }
244
245 void rgb_to_hsv_compat(float r, float g, float b, float *lh, float *ls, float *lv)
246 {
247         float orig_h= *lh;
248         float orig_s= *ls;
249
250         rgb_to_hsv(r, g, b, lh, ls, lv);
251
252         if(*lv <= 0.0f) {
253                 *lh= orig_h;
254                 *ls= orig_s;
255         }
256         else if (*ls <= 0.0f) {
257                 *lh= orig_h;
258         }
259
260         if(*lh==0.0f && orig_h >= 1.0f) {
261                 *lh= 1.0f;
262         }
263 }
264
265 /*http://brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html */
266
267 void xyz_to_rgb(float xc, float yc, float zc, float *r, float *g, float *b, int colorspace)
268 {
269         switch (colorspace) { 
270         case BLI_XYZ_SMPTE:
271                 *r = (3.50570f   * xc) + (-1.73964f      * yc) + (-0.544011f * zc);
272                 *g = (-1.06906f  * xc) + (1.97781f       * yc) + (0.0351720f * zc);
273                 *b = (0.0563117f * xc) + (-0.196994f * yc) + (1.05005f   * zc);
274                 break;
275         case BLI_XYZ_REC709_SRGB:
276                 *r = (3.240476f  * xc) + (-1.537150f * yc) + (-0.498535f * zc);
277                 *g = (-0.969256f * xc) + (1.875992f  * yc) + (0.041556f  * zc);
278                 *b = (0.055648f  * xc) + (-0.204043f * yc) + (1.057311f  * zc);
279                 break;
280         case BLI_XYZ_CIE:
281                 *r = (2.28783848734076f * xc) + (-0.833367677835217f    * yc) + (-0.454470795871421f    * zc);
282                 *g = (-0.511651380743862f * xc) + (1.42275837632178f * yc) + (0.0888930017552939f * zc);
283                 *b = (0.00572040983140966f      * xc) + (-0.0159068485104036f   * yc) + (1.0101864083734f       * zc);
284                 break;
285         }
286 }
287
288 /* we define a 'cpack' here as a (3 byte color code) number that can be expressed like 0xFFAA66 or so.
289    for that reason it is sensitive for endianness... with this function it works correctly
290 */
291
292 unsigned int hsv_to_cpack(float h, float s, float v)
293 {
294         short r, g, b;
295         float rf, gf, bf;
296         unsigned int col;
297         
298         hsv_to_rgb(h, s, v, &rf, &gf, &bf);
299         
300         r= (short)(rf*255.0f);
301         g= (short)(gf*255.0f);
302         b= (short)(bf*255.0f);
303         
304         col= ( r + (g*256) + (b*256*256) );
305         return col;
306 }
307
308
309 unsigned int rgb_to_cpack(float r, float g, float b)
310 {
311         int ir, ig, ib;
312         
313         ir= (int)floor(255.0f*r);
314         if(ir<0) ir= 0; else if(ir>255) ir= 255;
315         ig= (int)floor(255.0f*g);
316         if(ig<0) ig= 0; else if(ig>255) ig= 255;
317         ib= (int)floor(255.0f*b);
318         if(ib<0) ib= 0; else if(ib>255) ib= 255;
319         
320         return (ir+ (ig*256) + (ib*256*256));
321 }
322
323 void cpack_to_rgb(unsigned int col, float *r, float *g, float *b)
324 {
325         
326         *r= (float)((col)&0xFF);
327         *r /= 255.0f;
328
329         *g= (float)(((col)>>8)&0xFF);
330         *g /= 255.0f;
331
332         *b= (float)(((col)>>16)&0xFF);
333         *b /= 255.0f;
334 }
335
336 void rgb_byte_to_float(const unsigned char *in, float *out)
337 {
338         out[0]= ((float)in[0]) / 255.0f;
339         out[1]= ((float)in[1]) / 255.0f;
340         out[2]= ((float)in[2]) / 255.0f;
341 }
342
343 void rgb_float_to_byte(const float *in, unsigned char *out)
344 {
345         int r, g, b;
346         
347         r= (int)(in[0] * 255.0f);
348         g= (int)(in[1] * 255.0f);
349         b= (int)(in[2] * 255.0f);
350         
351         out[0]= (char)((r <= 0)? 0 : (r >= 255)? 255 : r);
352         out[1]= (char)((g <= 0)? 0 : (g >= 255)? 255 : g);
353         out[2]= (char)((b <= 0)? 0 : (b >= 255)? 255 : b);
354 }
355
356 /* ********************************* color transforms ********************************* */
357
358
359 void gamma_correct(float *c, float gamma)
360 {
361         *c = powf((*c), gamma);
362 }
363
364 float rec709_to_linearrgb(float c)
365 {
366         if (c < 0.081f)
367                 return (c < 0.0f)? 0.0f: c * (1.0f/4.5f);
368         else
369                 return powf((c + 0.099f)*(1.0f/1.099f), (1.0f/0.45f));
370 }
371
372 float linearrgb_to_rec709(float c)
373 {
374         if (c < 0.018f)
375                 return (c < 0.0f)? 0.0f: c * 4.5f;
376         else
377                 return 1.099f * powf(c, 0.45f) - 0.099f;
378 }
379
380 float srgb_to_linearrgb(float c)
381 {
382         if (c < 0.04045f)
383                 return (c < 0.0f)? 0.0f: c * (1.0f/12.92f);
384         else
385                 return powf((c + 0.055f)*(1.0f/1.055f), 2.4f);
386 }
387
388 float linearrgb_to_srgb(float c)
389 {
390         if (c < 0.0031308f)
391                 return (c < 0.0f)? 0.0f: c * 12.92f;
392         else
393                 return  1.055f * powf(c, 1.0f/2.4f) - 0.055f;
394 }
395
396 void minmax_rgb(short c[])
397 {
398         if(c[0]>255) c[0]=255;
399         else if(c[0]<0) c[0]=0;
400         if(c[1]>255) c[1]=255;
401         else if(c[1]<0) c[1]=0;
402         if(c[2]>255) c[2]=255;
403         else if(c[2]<0) c[2]=0;
404 }
405
406 /*If the requested RGB shade contains a negative weight for
407   one of the primaries, it lies outside the color gamut 
408   accessible from the given triple of primaries.  Desaturate
409   it by adding white, equal quantities of R, G, and B, enough
410   to make RGB all positive.  The function returns 1 if the
411   components were modified, zero otherwise.*/
412 int constrain_rgb(float *r, float *g, float *b)
413 {
414         float w;
415
416         /* Amount of white needed is w = - min(0, *r, *g, *b) */
417
418         w = (0 < *r) ? 0 : *r;
419         w = (w < *g) ? w : *g;
420         w = (w < *b) ? w : *b;
421         w = -w;
422
423         /* Add just enough white to make r, g, b all positive. */
424
425         if (w > 0) {
426                 *r += w;  *g += w; *b += w;
427                 return 1;                     /* Color modified to fit RGB gamut */
428         }
429
430         return 0;                         /* Color within RGB gamut */
431 }
432
433 float rgb_to_grayscale(float rgb[3])
434 {
435         return 0.3f*rgb[0] + 0.58f*rgb[1] + 0.12f*rgb[2];
436 }
437
438 unsigned char rgb_to_grayscale_byte(unsigned char rgb[3])
439 {
440         return (76*(unsigned short)rgb[0] + 148*(unsigned short)rgb[1] + 31*(unsigned short)rgb[2]) / 255;
441 }
442
443 /* ********************************* lift/gamma/gain / ASC-CDL conversion ********************************* */
444
445 void lift_gamma_gain_to_asc_cdl(float *lift, float *gamma, float *gain, float *offset, float *slope, float *power)
446 {
447         int c;
448         for(c=0; c<3; c++) {
449                 offset[c]= lift[c]*gain[c];
450                 slope[c]=  gain[c]*(1.0f-lift[c]);
451                 if(gamma[c] == 0)
452                         power[c]= FLT_MAX;
453                 else
454                         power[c]= 1.0f/gamma[c];
455         }
456 }
457
458 /* ******************************************** other ************************************************* */
459
460 /* Applies an hue offset to a float rgb color */
461 void rgb_float_set_hue_float_offset(float rgb[3], float hue_offset)
462 {
463         float hsv[3];
464         
465         rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
466         
467         hsv[0]+= hue_offset;
468         if(hsv[0] > 1.0f)               hsv[0] -= 1.0f;
469         else if(hsv[0] < 0.0f)  hsv[0] += 1.0f;
470         
471         hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2);
472 }
473
474 /* Applies an hue offset to a byte rgb color */
475 void rgb_byte_set_hue_float_offset(unsigned char rgb[3], float hue_offset)
476 {
477         float rgb_float[3];
478         
479         rgb_byte_to_float(rgb, rgb_float);
480         rgb_float_set_hue_float_offset(rgb_float, hue_offset);
481         rgb_float_to_byte(rgb_float, rgb);
482 }