doxygen: add newline after \file
[blender.git] / source / blender / blenlib / intern / math_color.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  *
19  * The Original Code is: some of this file.
20  *
21  * */
22
23 /** \file
24  * \ingroup bli
25  */
26
27 #include <assert.h>
28
29
30 #include "BLI_math.h"
31 #include "BLI_utildefines.h"
32
33 #include "BLI_strict_flags.h"
34
35 void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b)
36 {
37         float nr, ng, nb;
38
39         nr =        fabsf(h * 6.0f - 3.0f) - 1.0f;
40         ng = 2.0f - fabsf(h * 6.0f - 2.0f);
41         nb = 2.0f - fabsf(h * 6.0f - 4.0f);
42
43         CLAMP(nr, 0.0f, 1.0f);
44         CLAMP(nb, 0.0f, 1.0f);
45         CLAMP(ng, 0.0f, 1.0f);
46
47         *r = ((nr - 1.0f) * s + 1.0f) * v;
48         *g = ((ng - 1.0f) * s + 1.0f) * v;
49         *b = ((nb - 1.0f) * s + 1.0f) * v;
50 }
51
52 void hsl_to_rgb(float h, float s, float l, float *r, float *g, float *b)
53 {
54         float nr, ng, nb, chroma;
55
56         nr =        fabsf(h * 6.0f - 3.0f) - 1.0f;
57         ng = 2.0f - fabsf(h * 6.0f - 2.0f);
58         nb = 2.0f - fabsf(h * 6.0f - 4.0f);
59
60         CLAMP(nr, 0.0f, 1.0f);
61         CLAMP(nb, 0.0f, 1.0f);
62         CLAMP(ng, 0.0f, 1.0f);
63
64         chroma = (1.0f - fabsf(2.0f * l - 1.0f)) * s;
65
66         *r = (nr - 0.5f) * chroma + l;
67         *g = (ng - 0.5f) * chroma + l;
68         *b = (nb - 0.5f) * chroma + l;
69 }
70
71 /* convenience function for now */
72 void hsv_to_rgb_v(const float hsv[3], float r_rgb[3])
73 {
74         hsv_to_rgb(hsv[0], hsv[1], hsv[2], &r_rgb[0], &r_rgb[1], &r_rgb[2]);
75 }
76
77 /* convenience function for now */
78 void hsl_to_rgb_v(const float hsl[3], float r_rgb[3])
79 {
80         hsl_to_rgb(hsl[0], hsl[1], hsl[2], &r_rgb[0], &r_rgb[1], &r_rgb[2]);
81 }
82
83 void rgb_to_yuv(float r, float g, float b, float *ly, float *lu, float *lv, int colorspace)
84 {
85         float y, u, v;
86
87         switch (colorspace) {
88                 case BLI_YUV_ITU_BT601:
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                         break;
93                 case BLI_YUV_ITU_BT709:
94                 default:
95                         y = 0.2126f * r + 0.7152f * g + 0.0722f * b;
96                         u = -0.09991f * r - 0.33609f * g + 0.436f * b;
97                         v = 0.615f * r - 0.55861f * g - 0.05639f * b;
98                         break;
99         }
100
101         *ly = y;
102         *lu = u;
103         *lv = v;
104 }
105
106 void yuv_to_rgb(float y, float u, float v, float *lr, float *lg, float *lb, int colorspace)
107 {
108         float r, g, b;
109
110         switch (colorspace) {
111                 case BLI_YUV_ITU_BT601:
112                         r = y + 1.140f * v;
113                         g = y - 0.394f * u - 0.581f * v;
114                         b = y + 2.032f * u;
115                         break;
116                 case BLI_YUV_ITU_BT709:
117                         r = y + 1.28033f * v;
118                         g = y - 0.21482f * u - 0.38059f * v;
119                         b = y + 2.12798f * u;
120                         break;
121         }
122
123         *lr = r;
124         *lg = g;
125         *lb = b;
126 }
127
128 /* The RGB inputs are supposed gamma corrected and in the range 0 - 1.0f
129  *
130  * Output YCC have a range of 16-235 and 16-240 except with JFIF_0_255 where the range is 0-255 */
131 void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr, int colorspace)
132 {
133         float sr, sg, sb;
134         float y = 128.0f, cr = 128.0f, cb = 128.0f;
135
136         sr = 255.0f * r;
137         sg = 255.0f * g;
138         sb = 255.0f * b;
139
140         switch (colorspace) {
141                 case BLI_YCC_ITU_BT601:
142                         y = (0.257f * sr) + (0.504f * sg) + (0.098f * sb) + 16.0f;
143                         cb = (-0.148f * sr) - (0.291f * sg) + (0.439f * sb) + 128.0f;
144                         cr = (0.439f * sr) - (0.368f * sg) - (0.071f * sb) + 128.0f;
145                         break;
146                 case BLI_YCC_ITU_BT709:
147                         y = (0.183f * sr) + (0.614f * sg) + (0.062f * sb) + 16.0f;
148                         cb = (-0.101f * sr) - (0.338f * sg) + (0.439f * sb) + 128.0f;
149                         cr = (0.439f * sr) - (0.399f * sg) - (0.040f * sb) + 128.0f;
150                         break;
151                 case BLI_YCC_JFIF_0_255:
152                         y = (0.299f * sr) + (0.587f * sg) + (0.114f * sb);
153                         cb = (-0.16874f * sr) - (0.33126f * sg) + (0.5f * sb) + 128.0f;
154                         cr = (0.5f * sr) - (0.41869f * sg) - (0.08131f * sb) + 128.0f;
155                         break;
156                 default:
157                         assert(!"invalid colorspace");
158                         break;
159         }
160
161         *ly = y;
162         *lcb = cb;
163         *lcr = cr;
164 }
165
166
167 /* YCC input have a range of 16-235 and 16-240 except with JFIF_0_255 where the range is 0-255 */
168 /* RGB outputs are in the range 0 - 1.0f */
169
170 /* FIXME comment above must be wrong because BLI_YCC_ITU_BT601 y 16.0 cr 16.0 -> r -0.7009 */
171 void ycc_to_rgb(float y, float cb, float cr, float *lr, float *lg, float *lb, int colorspace)
172 {
173         float r = 128.0f, g = 128.0f, b = 128.0f;
174
175         switch (colorspace) {
176                 case BLI_YCC_ITU_BT601:
177                         r = 1.164f * (y - 16.0f) + 1.596f * (cr - 128.0f);
178                         g = 1.164f * (y - 16.0f) - 0.813f * (cr - 128.0f) - 0.392f * (cb - 128.0f);
179                         b = 1.164f * (y - 16.0f) + 2.017f * (cb - 128.0f);
180                         break;
181                 case BLI_YCC_ITU_BT709:
182                         r = 1.164f * (y - 16.0f) + 1.793f * (cr - 128.0f);
183                         g = 1.164f * (y - 16.0f) - 0.534f * (cr - 128.0f) - 0.213f * (cb - 128.0f);
184                         b = 1.164f * (y - 16.0f) + 2.115f * (cb - 128.0f);
185                         break;
186                 case BLI_YCC_JFIF_0_255:
187                         r = y + 1.402f * cr - 179.456f;
188                         g = y - 0.34414f * cb - 0.71414f * cr + 135.45984f;
189                         b = y + 1.772f * cb - 226.816f;
190                         break;
191                 default:
192                         BLI_assert(0);
193                         break;
194         }
195         *lr = r / 255.0f;
196         *lg = g / 255.0f;
197         *lb = b / 255.0f;
198 }
199
200 void hex_to_rgb(char *hexcol, float *r, float *g, float *b)
201 {
202         unsigned int ri, gi, bi;
203
204         if (hexcol[0] == '#') hexcol++;
205
206         if (sscanf(hexcol, "%02x%02x%02x", &ri, &gi, &bi) == 3) {
207                 /* six digit hex colors */
208         }
209         else if (sscanf(hexcol, "%01x%01x%01x", &ri, &gi, &bi) == 3) {
210                 /* three digit hex colors (#123 becomes #112233) */
211                 ri += ri << 4;
212                 gi += gi << 4;
213                 bi += bi << 4;
214         }
215         else {
216                 /* avoid using un-initialized vars */
217                 *r = *g = *b = 0.0f;
218                 return;
219         }
220
221         *r = (float)ri * (1.0f / 255.0f);
222         *g = (float)gi * (1.0f / 255.0f);
223         *b = (float)bi * (1.0f / 255.0f);
224         CLAMP(*r, 0.0f, 1.0f);
225         CLAMP(*g, 0.0f, 1.0f);
226         CLAMP(*b, 0.0f, 1.0f);
227 }
228
229 void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv)
230 {
231         float k = 0.0f;
232         float chroma;
233         float min_gb;
234
235         if (g < b) {
236                 SWAP(float, g, b);
237                 k = -1.0f;
238         }
239         min_gb = b;
240         if (r < g) {
241                 SWAP(float, r, g);
242                 k = -2.0f / 6.0f - k;
243                 min_gb = min_ff(g, b);
244         }
245
246         chroma = r - min_gb;
247
248         *lh = fabsf(k + (g - b) / (6.0f * chroma + 1e-20f));
249         *ls = chroma / (r + 1e-20f);
250         *lv = r;
251 }
252
253 /* convenience function for now */
254 void rgb_to_hsv_v(const float rgb[3], float r_hsv[3])
255 {
256         rgb_to_hsv(rgb[0], rgb[1], rgb[2], &r_hsv[0], &r_hsv[1], &r_hsv[2]);
257 }
258
259 void rgb_to_hsl(float r, float g, float b, float *lh, float *ls, float *ll)
260 {
261         const float cmax = max_fff(r, g, b);
262         const float cmin = min_fff(r, g, b);
263         float h, s, l = min_ff(1.0, (cmax + cmin) / 2.0f);
264
265         if (cmax == cmin) {
266                 h = s = 0.0f; // achromatic
267         }
268         else {
269                 float d = cmax - cmin;
270                 s = l > 0.5f ? d / (2.0f - cmax - cmin) : d / (cmax + cmin);
271                 if (cmax == r) {
272                         h = (g - b) / d + (g < b ? 6.0f : 0.0f);
273                 }
274                 else if (cmax == g) {
275                         h = (b - r) / d + 2.0f;
276                 }
277                 else {
278                         h = (r - g) / d + 4.0f;
279                 }
280         }
281         h /= 6.0f;
282
283         *lh = h;
284         *ls = s;
285         *ll = l;
286 }
287
288 void rgb_to_hsl_compat(float r, float g, float b, float *lh, float *ls, float *ll)
289 {
290         const float orig_s = *ls;
291         const float orig_h = *lh;
292
293         rgb_to_hsl(r, g, b, lh, ls, ll);
294
295         if (*ll <= 0.0f) {
296                 *lh = orig_h;
297                 *ls = orig_s;
298         }
299         else if (*ls <= 0.0f) {
300                 *lh = orig_h;
301                 *ls = orig_s;
302         }
303
304         if (*lh == 0.0f && orig_h >= 1.0f) {
305                 *lh = 1.0f;
306         }
307 }
308
309 void rgb_to_hsl_compat_v(const float rgb[3], float r_hsl[3])
310 {
311         rgb_to_hsl_compat(rgb[0], rgb[1], rgb[2], &r_hsl[0], &r_hsl[1], &r_hsl[2]);
312 }
313
314
315 /* convenience function for now */
316 void rgb_to_hsl_v(const float rgb[3], float r_hsl[3])
317 {
318         rgb_to_hsl(rgb[0], rgb[1], rgb[2], &r_hsl[0], &r_hsl[1], &r_hsl[2]);
319 }
320
321 void rgb_to_hsv_compat(float r, float g, float b, float *lh, float *ls, float *lv)
322 {
323         const float orig_h = *lh;
324         const float orig_s = *ls;
325
326         rgb_to_hsv(r, g, b, lh, ls, lv);
327
328         if (*lv <= 1e-8) {
329                 /* Very low v values will affect the hs values, correct them in post. */
330                 *lh = orig_h;
331                 *ls = orig_s;
332         }
333         else if (*ls <= 1e-8) {
334                 *lh = orig_h;
335         }
336
337         if (*lh == 0.0f && orig_h >= 1.0f) {
338                 *lh = 1.0f;
339         }
340 }
341
342 /* convenience function for now */
343 void rgb_to_hsv_compat_v(const float rgb[3], float r_hsv[3])
344 {
345         rgb_to_hsv_compat(rgb[0], rgb[1], rgb[2], &r_hsv[0], &r_hsv[1], &r_hsv[2]);
346 }
347
348 /* clamp hsv to usable values */
349 void hsv_clamp_v(float hsv[3], float v_max)
350 {
351         if (UNLIKELY(hsv[0] < 0.0f || hsv[0] > 1.0f)) {
352                 hsv[0] = hsv[0] - floorf(hsv[0]);
353         }
354         CLAMP(hsv[1], 0.0f, 1.0f);
355         CLAMP(hsv[2], 0.0f, v_max);
356 }
357
358 /**
359  * We define a 'cpack' here as a (3 byte color code) number that can be expressed like 0xFFAA66 or so.
360  * for that reason it is sensitive for endianness... with this function it works correctly.
361  * \see #imm_cpack
362  */
363
364 unsigned int hsv_to_cpack(float h, float s, float v)
365 {
366         unsigned int r, g, b;
367         float rf, gf, bf;
368         unsigned int col;
369
370         hsv_to_rgb(h, s, v, &rf, &gf, &bf);
371
372         r = (unsigned int) (rf * 255.0f);
373         g = (unsigned int) (gf * 255.0f);
374         b = (unsigned int) (bf * 255.0f);
375
376         col = (r + (g * 256) + (b * 256 * 256));
377         return col;
378 }
379
380 unsigned int rgb_to_cpack(float r, float g, float b)
381 {
382         unsigned int ir, ig, ib;
383
384         ir = (unsigned int)floorf(255.0f * max_ff(r, 0.0f));
385         ig = (unsigned int)floorf(255.0f * max_ff(g, 0.0f));
386         ib = (unsigned int)floorf(255.0f * max_ff(b, 0.0f));
387
388         if (ir > 255) ir = 255;
389         if (ig > 255) ig = 255;
390         if (ib > 255) ib = 255;
391
392         return (ir + (ig * 256) + (ib * 256 * 256));
393 }
394
395 void cpack_to_rgb(unsigned int col, float *r, float *g, float *b)
396 {
397         *r = ((float)(((col)      ) & 0xFF)) * (1.0f / 255.0f);
398         *g = ((float)(((col) >>  8) & 0xFF)) * (1.0f / 255.0f);
399         *b = ((float)(((col) >> 16) & 0xFF)) * (1.0f / 255.0f);
400 }
401
402 void rgb_uchar_to_float(float r_col[3], const unsigned char col_ub[3])
403 {
404         r_col[0] = ((float)col_ub[0]) * (1.0f / 255.0f);
405         r_col[1] = ((float)col_ub[1]) * (1.0f / 255.0f);
406         r_col[2] = ((float)col_ub[2]) * (1.0f / 255.0f);
407 }
408
409 void rgba_uchar_to_float(float r_col[4], const unsigned char col_ub[4])
410 {
411         r_col[0] = ((float)col_ub[0]) * (1.0f / 255.0f);
412         r_col[1] = ((float)col_ub[1]) * (1.0f / 255.0f);
413         r_col[2] = ((float)col_ub[2]) * (1.0f / 255.0f);
414         r_col[3] = ((float)col_ub[3]) * (1.0f / 255.0f);
415 }
416
417 void rgb_float_to_uchar(unsigned char r_col[3], const float col_f[3])
418 {
419         unit_float_to_uchar_clamp_v3(r_col, col_f);
420 }
421
422 void rgba_float_to_uchar(unsigned char r_col[4], const float col_f[4])
423 {
424         unit_float_to_uchar_clamp_v4(r_col, col_f);
425 }
426
427 /* ********************************* color transforms ********************************* */
428
429
430 float srgb_to_linearrgb(float c)
431 {
432         if (c < 0.04045f)
433                 return (c < 0.0f) ? 0.0f : c * (1.0f / 12.92f);
434         else
435                 return powf((c + 0.055f) * (1.0f / 1.055f), 2.4f);
436 }
437
438 float linearrgb_to_srgb(float c)
439 {
440         if (c < 0.0031308f)
441                 return (c < 0.0f) ? 0.0f : c * 12.92f;
442         else
443                 return 1.055f * powf(c, 1.0f / 2.4f) - 0.055f;
444 }
445
446 void minmax_rgb(short c[3])
447 {
448         if (c[0] > 255) c[0] = 255;
449         else if (c[0] < 0) c[0] = 0;
450         if (c[1] > 255) c[1] = 255;
451         else if (c[1] < 0) c[1] = 0;
452         if (c[2] > 255) c[2] = 255;
453         else if (c[2] < 0) c[2] = 0;
454 }
455
456 /* If the requested RGB shade contains a negative weight for
457  * one of the primaries, it lies outside the color gamut
458  * accessible from the given triple of primaries.  Desaturate
459  * it by adding white, equal quantities of R, G, and B, enough
460  * to make RGB all positive.  The function returns 1 if the
461  * components were modified, zero otherwise.*/
462 int constrain_rgb(float *r, float *g, float *b)
463 {
464         /* Amount of white needed */
465         const float w = -min_ffff(0.0f, *r, *g, *b);
466
467         /* Add just enough white to make r, g, b all positive. */
468         if (w > 0.0f) {
469                 *r += w;
470                 *g += w;
471                 *b += w;
472
473                 return 1; /* Color modified to fit RGB gamut */
474         }
475
476         return 0; /* Color within RGB gamut */
477 }
478
479 /* ********************** lift/gamma/gain / ASC-CDL conversion ********************************* */
480
481 void lift_gamma_gain_to_asc_cdl(float *lift, float *gamma, float *gain, float *offset, float *slope, float *power)
482 {
483         int c;
484         for (c = 0; c < 3; c++) {
485                 offset[c] = lift[c] * gain[c];
486                 slope[c] = gain[c] * (1.0f - lift[c]);
487                 if (gamma[c] == 0)
488                         power[c] = FLT_MAX;
489                 else
490                         power[c] = 1.0f / gamma[c];
491         }
492 }
493
494 /* ************************************* other ************************************************* */
495
496 /* Applies an hue offset to a float rgb color */
497 void rgb_float_set_hue_float_offset(float rgb[3], float hue_offset)
498 {
499         float hsv[3];
500
501         rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv + 1, hsv + 2);
502
503         hsv[0] += hue_offset;
504         if (hsv[0] > 1.0f) hsv[0] -= 1.0f;
505         else if (hsv[0] < 0.0f) hsv[0] += 1.0f;
506
507         hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb + 1, rgb + 2);
508 }
509
510 /* Applies an hue offset to a byte rgb color */
511 void rgb_byte_set_hue_float_offset(unsigned char rgb[3], float hue_offset)
512 {
513         float rgb_float[3];
514
515         rgb_uchar_to_float(rgb_float, rgb);
516         rgb_float_set_hue_float_offset(rgb_float, hue_offset);
517         rgb_float_to_uchar(rgb, rgb_float);
518 }
519
520
521 /* fast sRGB conversion
522  * LUT from linear float to 16-bit short
523  * based on http://mysite.verizon.net/spitzak/conversion/
524  */
525
526 float BLI_color_from_srgb_table[256];
527 unsigned short BLI_color_to_srgb_table[0x10000];
528
529 static unsigned short hipart(const float f)
530 {
531         union {
532                 float f;
533                 unsigned short us[2];
534         } tmp;
535
536         tmp.f = f;
537
538 #ifdef __BIG_ENDIAN__
539         return tmp.us[0];
540 #else
541         return tmp.us[1];
542 #endif
543 }
544
545 static float index_to_float(const unsigned short i)
546 {
547
548         union {
549                 float f;
550                 unsigned short us[2];
551         } tmp;
552
553         /* positive and negative zeros, and all gradual underflow, turn into zero: */
554         if (i < 0x80 || (i >= 0x8000 && i < 0x8080)) return 0;
555         /* All NaN's and infinity turn into the largest possible legal float: */
556         if (i >= 0x7f80 && i < 0x8000) return FLT_MAX;
557         if (i >= 0xff80) return -FLT_MAX;
558
559 #ifdef __BIG_ENDIAN__
560         tmp.us[0] = i;
561         tmp.us[1] = 0x8000;
562 #else
563         tmp.us[0] = 0x8000;
564         tmp.us[1] = i;
565 #endif
566
567         return tmp.f;
568 }
569
570 void BLI_init_srgb_conversion(void)
571 {
572         static bool initialized = false;
573         unsigned int i, b;
574
575         if (initialized)
576                 return;
577         initialized = true;
578
579         /* Fill in the lookup table to convert floats to bytes: */
580         for (i = 0; i < 0x10000; i++) {
581                 float f = linearrgb_to_srgb(index_to_float((unsigned short)i)) * 255.0f;
582                 if (f <= 0) BLI_color_to_srgb_table[i] = 0;
583                 else if (f < 255) BLI_color_to_srgb_table[i] = (unsigned short) (f * 0x100 + 0.5f);
584                 else BLI_color_to_srgb_table[i] = 0xff00;
585         }
586
587         /* Fill in the lookup table to convert bytes to float: */
588         for (b = 0; b <= 255; b++) {
589                 float f = srgb_to_linearrgb(((float)b) * (1.0f / 255.0f));
590                 BLI_color_from_srgb_table[b] = f;
591                 i = hipart(f);
592                 /* replace entries so byte->float->byte does not change the data: */
593                 BLI_color_to_srgb_table[i] = (unsigned short)(b * 0x100);
594         }
595 }
596
597 /* ****************************** blackbody ******************************** */
598
599 /* Calculate color in range 800..12000 using an approximation
600  * a/x+bx+c for R and G and ((at + b)t + c)t + d) for B
601  * Max absolute error for RGB is (0.00095, 0.00077, 0.00057),
602  * which is enough to get the same 8 bit/channel color.
603  */
604
605 static const float blackbody_table_r[6][3] = {
606         {  2.52432244e+03f, -1.06185848e-03f, 3.11067539e+00f },
607         {  3.37763626e+03f, -4.34581697e-04f, 1.64843306e+00f },
608         {  4.10671449e+03f, -8.61949938e-05f, 6.41423749e-01f },
609         {  4.66849800e+03f,  2.85655028e-05f, 1.29075375e-01f },
610         {  4.60124770e+03f,  2.89727618e-05f, 1.48001316e-01f },
611         {  3.78765709e+03f,  9.36026367e-06f, 3.98995841e-01f },
612 };
613
614 static const float blackbody_table_g[6][3] = {
615         { -7.50343014e+02f,  3.15679613e-04f, 4.73464526e-01f },
616         { -1.00402363e+03f,  1.29189794e-04f, 9.08181524e-01f },
617         { -1.22075471e+03f,  2.56245413e-05f, 1.20753416e+00f },
618         { -1.42546105e+03f, -4.01730887e-05f, 1.44002695e+00f },
619         { -1.18134453e+03f, -2.18913373e-05f, 1.30656109e+00f },
620         { -5.00279505e+02f, -4.59745390e-06f, 1.09090465e+00f },
621 };
622
623 static const float blackbody_table_b[6][4] = {
624         { 0.0f, 0.0f, 0.0f, 0.0f },
625         { 0.0f, 0.0f, 0.0f, 0.0f },
626         { 0.0f, 0.0f, 0.0f, 0.0f },
627         { -2.02524603e-11f,  1.79435860e-07f, -2.60561875e-04f, -1.41761141e-02f },
628         { -2.22463426e-13f, -1.55078698e-08f,  3.81675160e-04f, -7.30646033e-01f },
629         {  6.72595954e-13f, -2.73059993e-08f,  4.24068546e-04f, -7.52204323e-01f },
630 };
631
632 static void blackbody_temperature_to_rgb(float rgb[3], float t)
633 {
634         if (t >= 12000.0f) {
635                 rgb[0] = 0.826270103f;
636                 rgb[1] = 0.994478524f;
637                 rgb[2] = 1.56626022f;
638         }
639         else if (t < 965.0f) {
640                 rgb[0] = 4.70366907f;
641                 rgb[1] = 0.0f;
642                 rgb[2] = 0.0f;
643         }
644         else {
645                 int i = (t >= 6365.0f) ? 5 :
646                         (t >= 3315.0f) ? 4 :
647                         (t >= 1902.0f) ? 3 :
648                         (t >= 1449.0f) ? 2 :
649                         (t >= 1167.0f) ? 1 : 0;
650
651                 const float *r = blackbody_table_r[i];
652                 const float *g = blackbody_table_g[i];
653                 const float *b = blackbody_table_b[i];
654
655                 const float t_inv = 1.0f / t;
656                 rgb[0] = r[0] * t_inv + r[1] * t + r[2];
657                 rgb[1] = g[0] * t_inv + g[1] * t + g[2];
658                 rgb[2] = ((b[0] * t + b[1]) * t + b[2]) * t + b[3];
659         }
660 }
661
662 void blackbody_temperature_to_rgb_table(float *r_table, int width, float min, float max)
663 {
664         for (int i = 0; i < width; i++) {
665                 float temperature = min + (max - min) / (float)width * (float)i;
666
667                 float rgb[3];
668                 blackbody_temperature_to_rgb(rgb, temperature);
669
670                 copy_v3_v3(&r_table[i * 4], rgb);
671                 r_table[i * 4 + 3] = 0.0f;
672         }
673 }