Cleanup: comments (long lines) in blenlib
[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 #include "BLI_math.h"
30 #include "BLI_utildefines.h"
31
32 #include "BLI_strict_flags.h"
33
34 void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b)
35 {
36   float nr, ng, nb;
37
38   nr = fabsf(h * 6.0f - 3.0f) - 1.0f;
39   ng = 2.0f - fabsf(h * 6.0f - 2.0f);
40   nb = 2.0f - fabsf(h * 6.0f - 4.0f);
41
42   CLAMP(nr, 0.0f, 1.0f);
43   CLAMP(nb, 0.0f, 1.0f);
44   CLAMP(ng, 0.0f, 1.0f);
45
46   *r = ((nr - 1.0f) * s + 1.0f) * v;
47   *g = ((ng - 1.0f) * s + 1.0f) * v;
48   *b = ((nb - 1.0f) * s + 1.0f) * v;
49 }
50
51 void hsl_to_rgb(float h, float s, float l, float *r, float *g, float *b)
52 {
53   float nr, ng, nb, chroma;
54
55   nr = fabsf(h * 6.0f - 3.0f) - 1.0f;
56   ng = 2.0f - fabsf(h * 6.0f - 2.0f);
57   nb = 2.0f - fabsf(h * 6.0f - 4.0f);
58
59   CLAMP(nr, 0.0f, 1.0f);
60   CLAMP(nb, 0.0f, 1.0f);
61   CLAMP(ng, 0.0f, 1.0f);
62
63   chroma = (1.0f - fabsf(2.0f * l - 1.0f)) * s;
64
65   *r = (nr - 0.5f) * chroma + l;
66   *g = (ng - 0.5f) * chroma + l;
67   *b = (nb - 0.5f) * chroma + l;
68 }
69
70 /* convenience function for now */
71 void hsv_to_rgb_v(const float hsv[3], float r_rgb[3])
72 {
73   hsv_to_rgb(hsv[0], hsv[1], hsv[2], &r_rgb[0], &r_rgb[1], &r_rgb[2]);
74 }
75
76 /* convenience function for now */
77 void hsl_to_rgb_v(const float hsl[3], float r_rgb[3])
78 {
79   hsl_to_rgb(hsl[0], hsl[1], hsl[2], &r_rgb[0], &r_rgb[1], &r_rgb[2]);
80 }
81
82 void rgb_to_yuv(float r, float g, float b, float *ly, float *lu, float *lv, int colorspace)
83 {
84   float y, u, v;
85
86   switch (colorspace) {
87     case BLI_YUV_ITU_BT601:
88       y = 0.299f * r + 0.587f * g + 0.114f * b;
89       u = -0.147f * r - 0.289f * g + 0.436f * b;
90       v = 0.615f * r - 0.515f * g - 0.100f * b;
91       break;
92     case BLI_YUV_ITU_BT709:
93     default:
94       y = 0.2126f * r + 0.7152f * g + 0.0722f * b;
95       u = -0.09991f * r - 0.33609f * g + 0.436f * b;
96       v = 0.615f * r - 0.55861f * g - 0.05639f * b;
97       break;
98   }
99
100   *ly = y;
101   *lu = u;
102   *lv = v;
103 }
104
105 void yuv_to_rgb(float y, float u, float v, float *lr, float *lg, float *lb, int colorspace)
106 {
107   float r, g, b;
108
109   switch (colorspace) {
110     case BLI_YUV_ITU_BT601:
111       r = y + 1.140f * v;
112       g = y - 0.394f * u - 0.581f * v;
113       b = y + 2.032f * u;
114       break;
115     case BLI_YUV_ITU_BT709:
116       r = y + 1.28033f * v;
117       g = y - 0.21482f * u - 0.38059f * v;
118       b = y + 2.12798f * u;
119       break;
120   }
121
122   *lr = r;
123   *lg = g;
124   *lb = b;
125 }
126
127 /* The RGB inputs are supposed gamma corrected and in the range 0 - 1.0f
128  *
129  * Output YCC have a range of 16-235 and 16-240 except with JFIF_0_255 where the range is 0-255 */
130 void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr, int colorspace)
131 {
132   float sr, sg, sb;
133   float y = 128.0f, cr = 128.0f, cb = 128.0f;
134
135   sr = 255.0f * r;
136   sg = 255.0f * g;
137   sb = 255.0f * b;
138
139   switch (colorspace) {
140     case BLI_YCC_ITU_BT601:
141       y = (0.257f * sr) + (0.504f * sg) + (0.098f * sb) + 16.0f;
142       cb = (-0.148f * sr) - (0.291f * sg) + (0.439f * sb) + 128.0f;
143       cr = (0.439f * sr) - (0.368f * sg) - (0.071f * sb) + 128.0f;
144       break;
145     case BLI_YCC_ITU_BT709:
146       y = (0.183f * sr) + (0.614f * sg) + (0.062f * sb) + 16.0f;
147       cb = (-0.101f * sr) - (0.338f * sg) + (0.439f * sb) + 128.0f;
148       cr = (0.439f * sr) - (0.399f * sg) - (0.040f * sb) + 128.0f;
149       break;
150     case BLI_YCC_JFIF_0_255:
151       y = (0.299f * sr) + (0.587f * sg) + (0.114f * sb);
152       cb = (-0.16874f * sr) - (0.33126f * sg) + (0.5f * sb) + 128.0f;
153       cr = (0.5f * sr) - (0.41869f * sg) - (0.08131f * sb) + 128.0f;
154       break;
155     default:
156       assert(!"invalid colorspace");
157       break;
158   }
159
160   *ly = y;
161   *lcb = cb;
162   *lcr = cr;
163 }
164
165 /* YCC input have a range of 16-235 and 16-240 except with JFIF_0_255 where the range is 0-255 */
166 /* RGB outputs are in the range 0 - 1.0f */
167
168 /* FIXME comment above must be wrong because BLI_YCC_ITU_BT601 y 16.0 cr 16.0 -> r -0.7009 */
169 void ycc_to_rgb(float y, float cb, float cr, float *lr, float *lg, float *lb, int colorspace)
170 {
171   float r = 128.0f, g = 128.0f, b = 128.0f;
172
173   switch (colorspace) {
174     case BLI_YCC_ITU_BT601:
175       r = 1.164f * (y - 16.0f) + 1.596f * (cr - 128.0f);
176       g = 1.164f * (y - 16.0f) - 0.813f * (cr - 128.0f) - 0.392f * (cb - 128.0f);
177       b = 1.164f * (y - 16.0f) + 2.017f * (cb - 128.0f);
178       break;
179     case BLI_YCC_ITU_BT709:
180       r = 1.164f * (y - 16.0f) + 1.793f * (cr - 128.0f);
181       g = 1.164f * (y - 16.0f) - 0.534f * (cr - 128.0f) - 0.213f * (cb - 128.0f);
182       b = 1.164f * (y - 16.0f) + 2.115f * (cb - 128.0f);
183       break;
184     case BLI_YCC_JFIF_0_255:
185       r = y + 1.402f * cr - 179.456f;
186       g = y - 0.34414f * cb - 0.71414f * cr + 135.45984f;
187       b = y + 1.772f * cb - 226.816f;
188       break;
189     default:
190       BLI_assert(0);
191       break;
192   }
193   *lr = r / 255.0f;
194   *lg = g / 255.0f;
195   *lb = b / 255.0f;
196 }
197
198 void hex_to_rgb(char *hexcol, float *r, float *g, float *b)
199 {
200   unsigned int ri, gi, bi;
201
202   if (hexcol[0] == '#') {
203     hexcol++;
204   }
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 /* convenience function for now */
315 void rgb_to_hsl_v(const float rgb[3], float r_hsl[3])
316 {
317   rgb_to_hsl(rgb[0], rgb[1], rgb[2], &r_hsl[0], &r_hsl[1], &r_hsl[2]);
318 }
319
320 void rgb_to_hsv_compat(float r, float g, float b, float *lh, float *ls, float *lv)
321 {
322   const float orig_h = *lh;
323   const float orig_s = *ls;
324
325   rgb_to_hsv(r, g, b, lh, ls, lv);
326
327   if (*lv <= 1e-8) {
328     /* Very low v values will affect the hs values, correct them in post. */
329     *lh = orig_h;
330     *ls = orig_s;
331   }
332   else if (*ls <= 1e-8) {
333     *lh = orig_h;
334   }
335
336   if (*lh == 0.0f && orig_h >= 1.0f) {
337     *lh = 1.0f;
338   }
339 }
340
341 /* convenience function for now */
342 void rgb_to_hsv_compat_v(const float rgb[3], float r_hsv[3])
343 {
344   rgb_to_hsv_compat(rgb[0], rgb[1], rgb[2], &r_hsv[0], &r_hsv[1], &r_hsv[2]);
345 }
346
347 /* clamp hsv to usable values */
348 void hsv_clamp_v(float hsv[3], float v_max)
349 {
350   if (UNLIKELY(hsv[0] < 0.0f || hsv[0] > 1.0f)) {
351     hsv[0] = hsv[0] - floorf(hsv[0]);
352   }
353   CLAMP(hsv[1], 0.0f, 1.0f);
354   CLAMP(hsv[2], 0.0f, v_max);
355 }
356
357 /**
358  * We define a 'cpack' here as a (3 byte color code)
359  * 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 unsigned int hsv_to_cpack(float h, float s, float v)
364 {
365   unsigned int r, g, b;
366   float rf, gf, bf;
367   unsigned int col;
368
369   hsv_to_rgb(h, s, v, &rf, &gf, &bf);
370
371   r = (unsigned int)(rf * 255.0f);
372   g = (unsigned int)(gf * 255.0f);
373   b = (unsigned int)(bf * 255.0f);
374
375   col = (r + (g * 256) + (b * 256 * 256));
376   return col;
377 }
378
379 unsigned int rgb_to_cpack(float r, float g, float b)
380 {
381   unsigned int ir, ig, ib;
382
383   ir = (unsigned int)floorf(255.0f * max_ff(r, 0.0f));
384   ig = (unsigned int)floorf(255.0f * max_ff(g, 0.0f));
385   ib = (unsigned int)floorf(255.0f * max_ff(b, 0.0f));
386
387   if (ir > 255) {
388     ir = 255;
389   }
390   if (ig > 255) {
391     ig = 255;
392   }
393   if (ib > 255) {
394     ib = 255;
395   }
396
397   return (ir + (ig * 256) + (ib * 256 * 256));
398 }
399
400 void cpack_to_rgb(unsigned int col, float *r, float *g, float *b)
401 {
402   *r = ((float)(((col)) & 0xFF)) * (1.0f / 255.0f);
403   *g = ((float)(((col) >> 8) & 0xFF)) * (1.0f / 255.0f);
404   *b = ((float)(((col) >> 16) & 0xFF)) * (1.0f / 255.0f);
405 }
406
407 void rgb_uchar_to_float(float r_col[3], const unsigned char col_ub[3])
408 {
409   r_col[0] = ((float)col_ub[0]) * (1.0f / 255.0f);
410   r_col[1] = ((float)col_ub[1]) * (1.0f / 255.0f);
411   r_col[2] = ((float)col_ub[2]) * (1.0f / 255.0f);
412 }
413
414 void rgba_uchar_to_float(float r_col[4], const unsigned char col_ub[4])
415 {
416   r_col[0] = ((float)col_ub[0]) * (1.0f / 255.0f);
417   r_col[1] = ((float)col_ub[1]) * (1.0f / 255.0f);
418   r_col[2] = ((float)col_ub[2]) * (1.0f / 255.0f);
419   r_col[3] = ((float)col_ub[3]) * (1.0f / 255.0f);
420 }
421
422 void rgb_float_to_uchar(unsigned char r_col[3], const float col_f[3])
423 {
424   unit_float_to_uchar_clamp_v3(r_col, col_f);
425 }
426
427 void rgba_float_to_uchar(unsigned char r_col[4], const float col_f[4])
428 {
429   unit_float_to_uchar_clamp_v4(r_col, col_f);
430 }
431
432 /* ********************************* color transforms ********************************* */
433
434 float srgb_to_linearrgb(float c)
435 {
436   if (c < 0.04045f) {
437     return (c < 0.0f) ? 0.0f : c * (1.0f / 12.92f);
438   }
439   else {
440     return powf((c + 0.055f) * (1.0f / 1.055f), 2.4f);
441   }
442 }
443
444 float linearrgb_to_srgb(float c)
445 {
446   if (c < 0.0031308f) {
447     return (c < 0.0f) ? 0.0f : c * 12.92f;
448   }
449   else {
450     return 1.055f * powf(c, 1.0f / 2.4f) - 0.055f;
451   }
452 }
453
454 void minmax_rgb(short c[3])
455 {
456   if (c[0] > 255) {
457     c[0] = 255;
458   }
459   else if (c[0] < 0) {
460     c[0] = 0;
461   }
462
463   if (c[1] > 255) {
464     c[1] = 255;
465   }
466   else if (c[1] < 0) {
467     c[1] = 0;
468   }
469
470   if (c[2] > 255) {
471     c[2] = 255;
472   }
473   else if (c[2] < 0) {
474     c[2] = 0;
475   }
476 }
477
478 /* If the requested RGB shade contains a negative weight for
479  * one of the primaries, it lies outside the color gamut
480  * accessible from the given triple of primaries.  Desaturate
481  * it by adding white, equal quantities of R, G, and B, enough
482  * to make RGB all positive.  The function returns 1 if the
483  * components were modified, zero otherwise.*/
484 int constrain_rgb(float *r, float *g, float *b)
485 {
486   /* Amount of white needed */
487   const float w = -min_ffff(0.0f, *r, *g, *b);
488
489   /* Add just enough white to make r, g, b all positive. */
490   if (w > 0.0f) {
491     *r += w;
492     *g += w;
493     *b += w;
494
495     return 1; /* Color modified to fit RGB gamut */
496   }
497
498   return 0; /* Color within RGB gamut */
499 }
500
501 /* ********************** lift/gamma/gain / ASC-CDL conversion ********************************* */
502
503 void lift_gamma_gain_to_asc_cdl(
504     float *lift, float *gamma, float *gain, float *offset, float *slope, float *power)
505 {
506   int c;
507   for (c = 0; c < 3; c++) {
508     offset[c] = lift[c] * gain[c];
509     slope[c] = gain[c] * (1.0f - lift[c]);
510     if (gamma[c] == 0) {
511       power[c] = FLT_MAX;
512     }
513     else {
514       power[c] = 1.0f / gamma[c];
515     }
516   }
517 }
518
519 /* ************************************* other ************************************************* */
520
521 /* Applies an hue offset to a float rgb color */
522 void rgb_float_set_hue_float_offset(float rgb[3], float hue_offset)
523 {
524   float hsv[3];
525
526   rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv + 1, hsv + 2);
527
528   hsv[0] += hue_offset;
529   if (hsv[0] > 1.0f) {
530     hsv[0] -= 1.0f;
531   }
532   else if (hsv[0] < 0.0f) {
533     hsv[0] += 1.0f;
534   }
535
536   hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb + 1, rgb + 2);
537 }
538
539 /* Applies an hue offset to a byte rgb color */
540 void rgb_byte_set_hue_float_offset(unsigned char rgb[3], float hue_offset)
541 {
542   float rgb_float[3];
543
544   rgb_uchar_to_float(rgb_float, rgb);
545   rgb_float_set_hue_float_offset(rgb_float, hue_offset);
546   rgb_float_to_uchar(rgb, rgb_float);
547 }
548
549 /* fast sRGB conversion
550  * LUT from linear float to 16-bit short
551  * based on http://mysite.verizon.net/spitzak/conversion/
552  */
553
554 float BLI_color_from_srgb_table[256];
555 unsigned short BLI_color_to_srgb_table[0x10000];
556
557 static unsigned short hipart(const float f)
558 {
559   union {
560     float f;
561     unsigned short us[2];
562   } tmp;
563
564   tmp.f = f;
565
566 #ifdef __BIG_ENDIAN__
567   return tmp.us[0];
568 #else
569   return tmp.us[1];
570 #endif
571 }
572
573 static float index_to_float(const unsigned short i)
574 {
575
576   union {
577     float f;
578     unsigned short us[2];
579   } tmp;
580
581   /* positive and negative zeros, and all gradual underflow, turn into zero: */
582   if (i < 0x80 || (i >= 0x8000 && i < 0x8080)) {
583     return 0;
584   }
585   /* All NaN's and infinity turn into the largest possible legal float: */
586   if (i >= 0x7f80 && i < 0x8000) {
587     return FLT_MAX;
588   }
589   if (i >= 0xff80) {
590     return -FLT_MAX;
591   }
592
593 #ifdef __BIG_ENDIAN__
594   tmp.us[0] = i;
595   tmp.us[1] = 0x8000;
596 #else
597   tmp.us[0] = 0x8000;
598   tmp.us[1] = i;
599 #endif
600
601   return tmp.f;
602 }
603
604 void BLI_init_srgb_conversion(void)
605 {
606   static bool initialized = false;
607   unsigned int i, b;
608
609   if (initialized) {
610     return;
611   }
612   initialized = true;
613
614   /* Fill in the lookup table to convert floats to bytes: */
615   for (i = 0; i < 0x10000; i++) {
616     float f = linearrgb_to_srgb(index_to_float((unsigned short)i)) * 255.0f;
617     if (f <= 0) {
618       BLI_color_to_srgb_table[i] = 0;
619     }
620     else if (f < 255) {
621       BLI_color_to_srgb_table[i] = (unsigned short)(f * 0x100 + 0.5f);
622     }
623     else {
624       BLI_color_to_srgb_table[i] = 0xff00;
625     }
626   }
627
628   /* Fill in the lookup table to convert bytes to float: */
629   for (b = 0; b <= 255; b++) {
630     float f = srgb_to_linearrgb(((float)b) * (1.0f / 255.0f));
631     BLI_color_from_srgb_table[b] = f;
632     i = hipart(f);
633     /* replace entries so byte->float->byte does not change the data: */
634     BLI_color_to_srgb_table[i] = (unsigned short)(b * 0x100);
635   }
636 }
637
638 /* ****************************** blackbody ******************************** */
639
640 /* Calculate color in range 800..12000 using an approximation
641  * a/x+bx+c for R and G and ((at + b)t + c)t + d) for B
642  * Max absolute error for RGB is (0.00095, 0.00077, 0.00057),
643  * which is enough to get the same 8 bit/channel color.
644  */
645
646 static const float blackbody_table_r[6][3] = {
647     {2.52432244e+03f, -1.06185848e-03f, 3.11067539e+00f},
648     {3.37763626e+03f, -4.34581697e-04f, 1.64843306e+00f},
649     {4.10671449e+03f, -8.61949938e-05f, 6.41423749e-01f},
650     {4.66849800e+03f, 2.85655028e-05f, 1.29075375e-01f},
651     {4.60124770e+03f, 2.89727618e-05f, 1.48001316e-01f},
652     {3.78765709e+03f, 9.36026367e-06f, 3.98995841e-01f},
653 };
654
655 static const float blackbody_table_g[6][3] = {
656     {-7.50343014e+02f, 3.15679613e-04f, 4.73464526e-01f},
657     {-1.00402363e+03f, 1.29189794e-04f, 9.08181524e-01f},
658     {-1.22075471e+03f, 2.56245413e-05f, 1.20753416e+00f},
659     {-1.42546105e+03f, -4.01730887e-05f, 1.44002695e+00f},
660     {-1.18134453e+03f, -2.18913373e-05f, 1.30656109e+00f},
661     {-5.00279505e+02f, -4.59745390e-06f, 1.09090465e+00f},
662 };
663
664 static const float blackbody_table_b[6][4] = {
665     {0.0f, 0.0f, 0.0f, 0.0f},
666     {0.0f, 0.0f, 0.0f, 0.0f},
667     {0.0f, 0.0f, 0.0f, 0.0f},
668     {-2.02524603e-11f, 1.79435860e-07f, -2.60561875e-04f, -1.41761141e-02f},
669     {-2.22463426e-13f, -1.55078698e-08f, 3.81675160e-04f, -7.30646033e-01f},
670     {6.72595954e-13f, -2.73059993e-08f, 4.24068546e-04f, -7.52204323e-01f},
671 };
672
673 static void blackbody_temperature_to_rgb(float rgb[3], float t)
674 {
675   if (t >= 12000.0f) {
676     rgb[0] = 0.826270103f;
677     rgb[1] = 0.994478524f;
678     rgb[2] = 1.56626022f;
679   }
680   else if (t < 965.0f) {
681     rgb[0] = 4.70366907f;
682     rgb[1] = 0.0f;
683     rgb[2] = 0.0f;
684   }
685   else {
686     int i = (t >= 6365.0f) ?
687                 5 :
688                 (t >= 3315.0f) ? 4 :
689                                  (t >= 1902.0f) ? 3 : (t >= 1449.0f) ? 2 : (t >= 1167.0f) ? 1 : 0;
690
691     const float *r = blackbody_table_r[i];
692     const float *g = blackbody_table_g[i];
693     const float *b = blackbody_table_b[i];
694
695     const float t_inv = 1.0f / t;
696     rgb[0] = r[0] * t_inv + r[1] * t + r[2];
697     rgb[1] = g[0] * t_inv + g[1] * t + g[2];
698     rgb[2] = ((b[0] * t + b[1]) * t + b[2]) * t + b[3];
699   }
700 }
701
702 void blackbody_temperature_to_rgb_table(float *r_table, int width, float min, float max)
703 {
704   for (int i = 0; i < width; i++) {
705     float temperature = min + (max - min) / (float)width * (float)i;
706
707     float rgb[3];
708     blackbody_temperature_to_rgb(rgb, temperature);
709
710     copy_v3_v3(&r_table[i * 4], rgb);
711     r_table[i * 4 + 3] = 0.0f;
712   }
713 }