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