move one line color conversion functions to be inline.
[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 "MEM_guardedalloc.h"
34
35 #include "BLI_math.h"
36 #include "BLI_rand.h"
37 #include "BLI_utildefines.h"
38
39 void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b)
40 {
41         int i;
42         float f, p, q, t;
43
44         if (s == 0.0f) {
45                 *r = v;
46                 *g = v;
47                 *b = v;
48         }
49         else {
50                 h = (h - floorf(h)) * 6.0f;
51
52                 i = (int)floorf(h);
53                 f = h - i;
54                 p = v * (1.0f - s);
55                 q = v * (1.0f - (s * f));
56                 t = v * (1.0f - (s * (1.0f - f)));
57
58                 switch (i) {
59                         case 0:
60                                 *r = v;
61                                 *g = t;
62                                 *b = p;
63                                 break;
64                         case 1:
65                                 *r = q;
66                                 *g = v;
67                                 *b = p;
68                                 break;
69                         case 2:
70                                 *r = p;
71                                 *g = v;
72                                 *b = t;
73                                 break;
74                         case 3:
75                                 *r = p;
76                                 *g = q;
77                                 *b = v;
78                                 break;
79                         case 4:
80                                 *r = t;
81                                 *g = p;
82                                 *b = v;
83                                 break;
84                         case 5:
85                                 *r = v;
86                                 *g = p;
87                                 *b = q;
88                                 break;
89                 }
90         }
91 }
92
93 /* convenience function for now */
94 void hsv_to_rgb_v(const float hsv[3], float r_rgb[3])
95 {
96         hsv_to_rgb(hsv[0], hsv[1], hsv[2], &r_rgb[0], &r_rgb[1], &r_rgb[2]);
97 }
98
99 void rgb_to_yuv(float r, float g, float b, float *ly, float *lu, float *lv)
100 {
101         float y, u, v;
102         y = 0.299f * r + 0.587f * g + 0.114f * b;
103         u = -0.147f * r - 0.289f * g + 0.436f * b;
104         v = 0.615f * r - 0.515f * g - 0.100f * b;
105
106         *ly = y;
107         *lu = u;
108         *lv = v;
109 }
110
111 void yuv_to_rgb(float y, float u, float v, float *lr, float *lg, float *lb)
112 {
113         float r, g, b;
114         r = y + 1.140f * v;
115         g = y - 0.394f * u - 0.581f * v;
116         b = y + 2.032f * u;
117
118         *lr = r;
119         *lg = g;
120         *lb = b;
121 }
122
123 /* The RGB inputs are supposed gamma corrected and in the range 0 - 1.0f
124  *
125  * Output YCC have a range of 16-235 and 16-240 except with JFIF_0_255 where the range is 0-255 */
126 void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr, int colorspace)
127 {
128         float sr, sg, sb;
129         float y = 128.f, cr = 128.f, cb = 128.f;
130
131         sr = 255.0f * r;
132         sg = 255.0f * g;
133         sb = 255.0f * b;
134
135         switch (colorspace) {
136                 case BLI_YCC_ITU_BT601:
137                         y = (0.257f * sr) + (0.504f * sg) + (0.098f * sb) + 16.0f;
138                         cb = (-0.148f * sr) - (0.291f * sg) + (0.439f * sb) + 128.0f;
139                         cr = (0.439f * sr) - (0.368f * sg) - (0.071f * sb) + 128.0f;
140                         break;
141                 case BLI_YCC_ITU_BT709:
142                         y = (0.183f * sr) + (0.614f * sg) + (0.062f * sb) + 16.0f;
143                         cb = (-0.101f * sr) - (0.338f * sg) + (0.439f * sb) + 128.0f;
144                         cr = (0.439f * sr) - (0.399f * sg) - (0.040f * sb) + 128.0f;
145                         break;
146                 case BLI_YCC_JFIF_0_255:
147                         y = (0.299f * sr) + (0.587f * sg) + (0.114f * sb);
148                         cb = (-0.16874f * sr) - (0.33126f * sg) + (0.5f * sb) + 128.0f;
149                         cr = (0.5f * sr) - (0.41869f * sg) - (0.08131f * sb) + 128.0f;
150                         break;
151                 default:
152                         assert(!"invalid colorspace");
153         }
154
155         *ly = y;
156         *lcb = cb;
157         *lcr = cr;
158 }
159
160
161 /* YCC input have a range of 16-235 and 16-240 except with JFIF_0_255 where the range is 0-255 */
162 /* RGB outputs are in the range 0 - 1.0f */
163
164 /* FIXME comment above must be wrong because BLI_YCC_ITU_BT601 y 16.0 cr 16.0 -> r -0.7009 */
165 void ycc_to_rgb(float y, float cb, float cr, float *lr, float *lg, float *lb, int colorspace)
166 {
167         float r = 128.f, g = 128.f, b = 128.f;
168
169         switch (colorspace) {
170                 case BLI_YCC_ITU_BT601:
171                         r = 1.164f * (y - 16.0f) + 1.596f * (cr - 128.0f);
172                         g = 1.164f * (y - 16.0f) - 0.813f * (cr - 128.0f) - 0.392f * (cb - 128.0f);
173                         b = 1.164f * (y - 16.0f) + 2.017f * (cb - 128.0f);
174                         break;
175                 case BLI_YCC_ITU_BT709:
176                         r = 1.164f * (y - 16.0f) + 1.793f * (cr - 128.0f);
177                         g = 1.164f * (y - 16.0f) - 0.534f * (cr - 128.0f) - 0.213f * (cb - 128.0f);
178                         b = 1.164f * (y - 16.0f) + 2.115f * (cb - 128.0f);
179                         break;
180                 case BLI_YCC_JFIF_0_255:
181                         r = y + 1.402f * cr - 179.456f;
182                         g = y - 0.34414f * cb - 0.71414f * cr + 135.45984f;
183                         b = y + 1.772f * cb - 226.816f;
184                         break;
185                 default:
186                         assert(!"invalid colorspace");
187         }
188         *lr = r / 255.0f;
189         *lg = g / 255.0f;
190         *lb = b / 255.0f;
191 }
192
193 void hex_to_rgb(char *hexcol, float *r, float *g, float *b)
194 {
195         unsigned int ri, gi, bi;
196
197         if (hexcol[0] == '#') hexcol++;
198
199         if (sscanf(hexcol, "%02x%02x%02x", &ri, &gi, &bi) == 3) {
200                 *r = ri / 255.0f;
201                 *g = gi / 255.0f;
202                 *b = bi / 255.0f;
203                 CLAMP(*r, 0.0f, 1.0f);
204                 CLAMP(*g, 0.0f, 1.0f);
205                 CLAMP(*b, 0.0f, 1.0f);
206         }
207         else {
208                 /* avoid using un-initialized vars */
209                 *r = *g = *b = 0.0f;
210         }
211 }
212
213 void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv)
214 {
215         float h, s, v;
216         float cmax, cmin, cdelta;
217         float rc, gc, bc;
218
219         cmax = r;
220         cmin = r;
221         cmax = (g > cmax ? g : cmax);
222         cmin = (g < cmin ? g : cmin);
223         cmax = (b > cmax ? b : cmax);
224         cmin = (b < cmin ? b : cmin);
225
226         v = cmax; /* value */
227         if (cmax != 0.0f)
228                 s = (cmax - cmin) / cmax;
229         else {
230                 s = 0.0f;
231         }
232         if (s == 0.0f)
233                 h = -1.0f;
234         else {
235                 cdelta = cmax - cmin;
236                 rc = (cmax - r) / cdelta;
237                 gc = (cmax - g) / cdelta;
238                 bc = (cmax - b) / cdelta;
239
240                 if (r == cmax) {
241                         h = bc - gc;
242                 }
243                 else if (g == cmax) {
244                         h = 2.0f + rc - bc;
245                 }
246                 else {
247                         h = 4.0f + gc - rc;
248                 }
249
250                 h = h * 60.0f;
251                 if (h < 0.0f)
252                         h += 360.0f;
253         }
254
255         *ls = s;
256         *lh = h / 360.0f;
257         if (*lh < 0.0f) *lh = 0.0f;
258         *lv = v;
259 }
260
261 /* convenience function for now */
262 void rgb_to_hsv_v(const float rgb[3], float r_hsv[3])
263 {
264         rgb_to_hsv(rgb[0], rgb[1], rgb[2], &r_hsv[0], &r_hsv[1], &r_hsv[2]);
265 }
266
267 void rgb_to_hsl(float r, float g, float b, float *lh, float *ls, float *ll)
268 {
269         float cmax = MAX3(r, g, b);
270         float cmin = MIN3(r, g, b);
271         float h, s, l = (cmax + cmin) / 2.0f;
272
273         if (cmax == cmin) {
274                 h = s = 0.0f; // achromatic
275         }
276         else {
277                 float d = cmax - cmin;
278                 s = l > 0.5f ? d / (2.0f - cmax - cmin) : d / (cmax + cmin);
279                 if (cmax == r) {
280                         h = (g - b) / d + (g < b ? 6.0f : 0.0f);
281                 }
282                 else if (cmax == g) {
283                         h = (b - r) / d + 2.0f;
284                 }
285                 else {
286                         h = (r - g) / d + 4.0f;
287                 }
288         }
289         h /= 6.0f;
290
291         *lh = h;
292         *ls = s;
293         *ll = l;
294 }
295
296 void rgb_to_hsv_compat(float r, float g, float b, float *lh, float *ls, float *lv)
297 {
298         float orig_h = *lh;
299         float orig_s = *ls;
300
301         rgb_to_hsv(r, g, b, lh, ls, lv);
302
303         if (*lv <= 0.0f) {
304                 *lh = orig_h;
305                 *ls = orig_s;
306         }
307         else if (*ls <= 0.0f) {
308                 *lh = orig_h;
309         }
310
311         if (*lh == 0.0f && orig_h >= 1.0f) {
312                 *lh = 1.0f;
313         }
314 }
315
316 /* convenience function for now */
317 void rgb_to_hsv_compat_v(const float rgb[3], float r_hsv[3])
318 {
319         rgb_to_hsv_compat(rgb[0], rgb[1], rgb[2], &r_hsv[0], &r_hsv[1], &r_hsv[2]);
320 }
321
322 /*http://brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html */
323
324 void xyz_to_rgb(float xc, float yc, float zc, float *r, float *g, float *b, int colorspace)
325 {
326         switch (colorspace) {
327                 case BLI_XYZ_SMPTE:
328                         *r = (3.50570f * xc) + (-1.73964f * yc) + (-0.544011f * zc);
329                         *g = (-1.06906f * xc) + (1.97781f * yc) + (0.0351720f * zc);
330                         *b = (0.0563117f * xc) + (-0.196994f * yc) + (1.05005f * zc);
331                         break;
332                 case BLI_XYZ_REC709_SRGB:
333                         *r = (3.240476f * xc) + (-1.537150f * yc) + (-0.498535f * zc);
334                         *g = (-0.969256f * xc) + (1.875992f * yc) + (0.041556f * zc);
335                         *b = (0.055648f * xc) + (-0.204043f * yc) + (1.057311f * zc);
336                         break;
337                 case BLI_XYZ_CIE:
338                         *r = (2.28783848734076f * xc) + (-0.833367677835217f * yc) + (-0.454470795871421f * zc);
339                         *g = (-0.511651380743862f * xc) + (1.42275837632178f * yc) + (0.0888930017552939f * zc);
340                         *b = (0.00572040983140966f * xc) + (-0.0159068485104036f * yc) + (1.0101864083734f * zc);
341                         break;
342         }
343 }
344
345 /* we define a 'cpack' here as a (3 byte color code) number that can be expressed like 0xFFAA66 or so.
346  * for that reason it is sensitive for endianness... with this function it works correctly
347  */
348
349 unsigned int hsv_to_cpack(float h, float s, float v)
350 {
351         short r, g, b;
352         float rf, gf, bf;
353         unsigned int col;
354
355         hsv_to_rgb(h, s, v, &rf, &gf, &bf);
356
357         r = (short) (rf * 255.0f);
358         g = (short) (gf * 255.0f);
359         b = (short) (bf * 255.0f);
360
361         col = (r + (g * 256) + (b * 256 * 256));
362         return col;
363 }
364
365 unsigned int rgb_to_cpack(float r, float g, float b)
366 {
367         int ir, ig, ib;
368
369         ir = (int)floor(255.0f * r);
370         if (ir < 0) ir = 0;
371         else if (ir > 255) ir = 255;
372         ig = (int)floor(255.0f * g);
373         if (ig < 0) ig = 0;
374         else if (ig > 255) ig = 255;
375         ib = (int)floor(255.0f * b);
376         if (ib < 0) ib = 0;
377         else if (ib > 255) ib = 255;
378
379         return (ir + (ig * 256) + (ib * 256 * 256));
380 }
381
382 void cpack_to_rgb(unsigned int col, float *r, float *g, float *b)
383 {
384
385         *r = (float)((col) & 0xFF);
386         *r /= 255.0f;
387
388         *g = (float)(((col) >> 8) & 0xFF);
389         *g /= 255.0f;
390
391         *b = (float)(((col) >> 16) & 0xFF);
392         *b /= 255.0f;
393 }
394
395 void rgb_uchar_to_float(float col_r[3], const unsigned char col_ub[3])
396 {
397         col_r[0] = ((float)col_ub[0]) / 255.0f;
398         col_r[1] = ((float)col_ub[1]) / 255.0f;
399         col_r[2] = ((float)col_ub[2]) / 255.0f;
400 }
401
402 void rgba_uchar_to_float(float col_r[4], const unsigned char col_ub[4])
403 {
404         col_r[0] = ((float)col_ub[0]) / 255.0f;
405         col_r[1] = ((float)col_ub[1]) / 255.0f;
406         col_r[2] = ((float)col_ub[2]) / 255.0f;
407         col_r[3] = ((float)col_ub[3]) / 255.0f;
408 }
409
410 void rgb_float_to_uchar(unsigned char col_r[3], const float col_f[3])
411 {
412         F3TOCHAR3(col_f, col_r);
413 }
414
415 void rgba_float_to_uchar(unsigned char col_r[4], const float col_f[4])
416 {
417         F4TOCHAR4(col_f, col_r);
418 }
419
420 /* ********************************* color transforms ********************************* */
421
422
423 void gamma_correct(float *c, float gamma)
424 {
425         *c = powf((*c), gamma);
426 }
427
428 float rec709_to_linearrgb(float c)
429 {
430         if (c < 0.081f)
431                 return (c < 0.0f) ? 0.0f : c * (1.0f / 4.5f);
432         else
433                 return powf((c + 0.099f) * (1.0f / 1.099f), (1.0f / 0.45f));
434 }
435
436 float linearrgb_to_rec709(float c)
437 {
438         if (c < 0.018f)
439                 return (c < 0.0f) ? 0.0f : c * 4.5f;
440         else
441                 return 1.099f * powf(c, 0.45f) - 0.099f;
442 }
443
444 float srgb_to_linearrgb(float c)
445 {
446         if (c < 0.04045f)
447                 return (c < 0.0f) ? 0.0f : c * (1.0f / 12.92f);
448         else
449                 return powf((c + 0.055f) * (1.0f / 1.055f), 2.4f);
450 }
451
452 float linearrgb_to_srgb(float c)
453 {
454         if (c < 0.0031308f)
455                 return (c < 0.0f) ? 0.0f : c * 12.92f;
456         else
457                 return 1.055f * powf(c, 1.0f / 2.4f) - 0.055f;
458 }
459
460 void minmax_rgb(short c[])
461 {
462         if (c[0] > 255) c[0] = 255;
463         else if (c[0] < 0) c[0] = 0;
464         if (c[1] > 255) c[1] = 255;
465         else if (c[1] < 0) c[1] = 0;
466         if (c[2] > 255) c[2] = 255;
467         else if (c[2] < 0) c[2] = 0;
468 }
469
470 /*If the requested RGB shade contains a negative weight for
471  * one of the primaries, it lies outside the color gamut
472  * accessible from the given triple of primaries.  Desaturate
473  * it by adding white, equal quantities of R, G, and B, enough
474  * to make RGB all positive.  The function returns 1 if the
475  * components were modified, zero otherwise.*/
476 int constrain_rgb(float *r, float *g, float *b)
477 {
478         float w;
479
480         /* Amount of white needed is w = - min(0, *r, *g, *b) */
481
482         w = (0 < *r) ? 0 : *r;
483         w = (w < *g) ? w : *g;
484         w = (w < *b) ? w : *b;
485         w = -w;
486
487         /* Add just enough white to make r, g, b all positive. */
488
489         if (w > 0) {
490                 *r += w;
491                 *g += w;
492                 *b += w;
493                 return 1; /* Color modified to fit RGB gamut */
494         }
495
496         return 0; /* Color within RGB gamut */
497 }
498
499 /* ********************************* lift/gamma/gain / ASC-CDL conversion ********************************* */
500
501 void lift_gamma_gain_to_asc_cdl(float *lift, float *gamma, float *gain, float *offset, float *slope, float *power)
502 {
503         int c;
504         for (c = 0; c < 3; c++) {
505                 offset[c] = lift[c] * gain[c];
506                 slope[c] = gain[c] * (1.0f - lift[c]);
507                 if (gamma[c] == 0)
508                         power[c] = FLT_MAX;
509                 else
510                         power[c] = 1.0f / gamma[c];
511         }
512 }
513
514 /* ******************************************** other ************************************************* */
515
516 /* Applies an hue offset to a float rgb color */
517 void rgb_float_set_hue_float_offset(float rgb[3], float hue_offset)
518 {
519         float hsv[3];
520
521         rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv + 1, hsv + 2);
522
523         hsv[0] += hue_offset;
524         if (hsv[0] > 1.0f) hsv[0] -= 1.0f;
525         else if (hsv[0] < 0.0f) hsv[0] += 1.0f;
526
527         hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb + 1, rgb + 2);
528 }
529
530 /* Applies an hue offset to a byte rgb color */
531 void rgb_byte_set_hue_float_offset(unsigned char rgb[3], float hue_offset)
532 {
533         float rgb_float[3];
534
535         rgb_uchar_to_float(rgb_float, rgb);
536         rgb_float_set_hue_float_offset(rgb_float, hue_offset);
537         rgb_float_to_uchar(rgb, rgb_float);
538 }
539
540
541 /* fast sRGB conversion
542  * LUT from linear float to 16-bit short
543  * based on http://mysite.verizon.net/spitzak/conversion/
544  */
545
546 float BLI_color_from_srgb_table[256];
547 unsigned short BLI_color_to_srgb_table[0x10000];
548
549 static unsigned short hipart(const float f)
550 {
551         union {
552                 float f;
553                 unsigned short us[2];
554         } tmp;
555
556         tmp.f = f;
557
558 #ifdef __BIG_ENDIAN__
559         return tmp.us[0];
560 #else
561         return tmp.us[1];
562 #endif
563 }
564
565 static float index_to_float(const unsigned short i)
566 {
567
568         union {
569                 float f;
570                 unsigned short us[2];
571         } tmp;
572
573         /* positive and negative zeros, and all gradual underflow, turn into zero: */
574         if (i < 0x80 || (i >= 0x8000 && i < 0x8080)) return 0;
575         /* All NaN's and infinity turn into the largest possible legal float: */
576         if (i >= 0x7f80 && i < 0x8000) return FLT_MAX;
577         if (i >= 0xff80) return -FLT_MAX;
578
579 #ifdef __BIG_ENDIAN__
580         tmp.us[0] = i;
581         tmp.us[1] = 0x8000;
582 #else
583         tmp.us[0] = 0x8000;
584         tmp.us[1] = i;
585 #endif
586
587         return tmp.f;
588 }
589
590 void BLI_init_srgb_conversion(void)
591 {
592         static int initialized = 0;
593         int i, b;
594
595         if (initialized) return;
596         initialized = 1;
597
598         /* Fill in the lookup table to convert floats to bytes: */
599         for (i = 0; i < 0x10000; i++) {
600                 float f = linearrgb_to_srgb(index_to_float(i)) * 255.0f;
601                 if (f <= 0) BLI_color_to_srgb_table[i] = 0;
602                 else if (f < 255) BLI_color_to_srgb_table[i] = (unsigned short) (f * 0x100 + 0.5f);
603                 else BLI_color_to_srgb_table[i] = 0xff00;
604         }
605
606         /* Fill in the lookup table to convert bytes to float: */
607         for (b = 0; b <= 255; b++) {
608                 float f = srgb_to_linearrgb(((float)b) * (1.0f / 255.0f));
609                 BLI_color_from_srgb_table[b] = f;
610                 i = hipart(f);
611                 /* replace entries so byte->float->byte does not change the data: */
612                 BLI_color_to_srgb_table[i] = b * 0x100;
613         }
614 }
615 static float inverse_srgb_companding(float v)
616 {
617         if (v > 0.04045f) {
618                 return powf((v + 0.055f) / 1.055f, 2.4);
619         }
620         else {
621                 return v / 12.92f;
622         }
623 }
624
625 void rgb_to_xyz(float r, float g, float b, float *x, float *y, float *z)
626 {
627         r = inverse_srgb_companding(r) * 100.0f;
628         g = inverse_srgb_companding(g) * 100.0f;
629         b = inverse_srgb_companding(b) * 100.0f;
630
631         *x = r * 0.412453f + g * 0.357580f + b * 0.180423f;
632         *y = r * 0.212671f + g * 0.715160f + b * 0.072169f;
633         *z = r * 0.019334f + g * 0.119193f + b * 0.950227f;
634 }
635
636 static float xyz_to_lab_component(float v)
637 {
638         const float eps = 0.008856f;
639         const float k = 903.3f;
640
641         if (v > eps) {
642                 return pow(v, 1.0f / 3.0f);
643         }
644         else {
645                 return (k * v + 16.0f) / 116.0f;
646         }
647 }
648
649 void xyz_to_lab(float x, float y, float z, float *l, float *a, float *b)
650 {
651         float xr = x / 95.047f;
652         float yr = y / 100.0f;
653         float zr = z / 108.883f;
654
655         float fx = xyz_to_lab_component(xr);
656         float fy = xyz_to_lab_component(yr);
657         float fz = xyz_to_lab_component(zr);
658
659         *l = 116.0f * fy - 16.0f;
660         *a = 500.0f * (fx - fy);
661         *b = 200.0f * (fy - fz);
662 }
663
664 void rgb_to_lab(float r, float g, float b, float *ll, float *la, float *lb)
665 {
666         float x, y, z;
667         rgb_to_xyz(r, g, b, &x, &y, &z);
668         xyz_to_lab(x, y, z, ll, la, lb);
669 }