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 "BLI_math.h"
28 #include "BLI_utildefines.h"
29 
30 #include "BLI_strict_flags.h"
31 
hsv_to_rgb(float h,float s,float v,float * r_r,float * r_g,float * r_b)32 void hsv_to_rgb(float h, float s, float v, float *r_r, float *r_g, float *r_b)
33 {
34   float nr, ng, nb;
35 
36   nr = fabsf(h * 6.0f - 3.0f) - 1.0f;
37   ng = 2.0f - fabsf(h * 6.0f - 2.0f);
38   nb = 2.0f - fabsf(h * 6.0f - 4.0f);
39 
40   CLAMP(nr, 0.0f, 1.0f);
41   CLAMP(nb, 0.0f, 1.0f);
42   CLAMP(ng, 0.0f, 1.0f);
43 
44   *r_r = ((nr - 1.0f) * s + 1.0f) * v;
45   *r_g = ((ng - 1.0f) * s + 1.0f) * v;
46   *r_b = ((nb - 1.0f) * s + 1.0f) * v;
47 }
48 
hsl_to_rgb(float h,float s,float l,float * r_r,float * r_g,float * r_b)49 void hsl_to_rgb(float h, float s, float l, float *r_r, float *r_g, float *r_b)
50 {
51   float nr, ng, nb, chroma;
52 
53   nr = fabsf(h * 6.0f - 3.0f) - 1.0f;
54   ng = 2.0f - fabsf(h * 6.0f - 2.0f);
55   nb = 2.0f - fabsf(h * 6.0f - 4.0f);
56 
57   CLAMP(nr, 0.0f, 1.0f);
58   CLAMP(nb, 0.0f, 1.0f);
59   CLAMP(ng, 0.0f, 1.0f);
60 
61   chroma = (1.0f - fabsf(2.0f * l - 1.0f)) * s;
62 
63   *r_r = (nr - 0.5f) * chroma + l;
64   *r_g = (ng - 0.5f) * chroma + l;
65   *r_b = (nb - 0.5f) * chroma + l;
66 }
67 
68 /* convenience function for now */
hsv_to_rgb_v(const float hsv[3],float r_rgb[3])69 void hsv_to_rgb_v(const float hsv[3], float r_rgb[3])
70 {
71   hsv_to_rgb(hsv[0], hsv[1], hsv[2], &r_rgb[0], &r_rgb[1], &r_rgb[2]);
72 }
73 
74 /* convenience function for now */
hsl_to_rgb_v(const float hsl[3],float r_rgb[3])75 void hsl_to_rgb_v(const float hsl[3], float r_rgb[3])
76 {
77   hsl_to_rgb(hsl[0], hsl[1], hsl[2], &r_rgb[0], &r_rgb[1], &r_rgb[2]);
78 }
79 
rgb_to_yuv(float r,float g,float b,float * r_y,float * r_u,float * r_v,int colorspace)80 void rgb_to_yuv(float r, float g, float b, float *r_y, float *r_u, float *r_v, int colorspace)
81 {
82   float y, u, v;
83 
84   switch (colorspace) {
85     case BLI_YUV_ITU_BT601:
86       y = 0.299f * r + 0.587f * g + 0.114f * b;
87       u = -0.147f * r - 0.289f * g + 0.436f * b;
88       v = 0.615f * r - 0.515f * g - 0.100f * b;
89       break;
90     case BLI_YUV_ITU_BT709:
91     default:
92       BLI_assert(colorspace == BLI_YUV_ITU_BT709);
93       y = 0.2126f * r + 0.7152f * g + 0.0722f * b;
94       u = -0.09991f * r - 0.33609f * g + 0.436f * b;
95       v = 0.615f * r - 0.55861f * g - 0.05639f * b;
96       break;
97   }
98 
99   *r_y = y;
100   *r_u = u;
101   *r_v = v;
102 }
103 
yuv_to_rgb(float y,float u,float v,float * r_r,float * r_g,float * r_b,int colorspace)104 void yuv_to_rgb(float y, float u, float v, float *r_r, float *r_g, float *r_b, int colorspace)
105 {
106   float r, g, b;
107 
108   switch (colorspace) {
109     case BLI_YUV_ITU_BT601:
110       r = y + 1.140f * v;
111       g = y - 0.394f * u - 0.581f * v;
112       b = y + 2.032f * u;
113       break;
114     case BLI_YUV_ITU_BT709:
115     default:
116       BLI_assert(colorspace == 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   *r_r = r;
124   *r_g = g;
125   *r_b = 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 */
rgb_to_ycc(float r,float g,float b,float * r_y,float * r_cb,float * r_cr,int colorspace)131 void rgb_to_ycc(float r, float g, float b, float *r_y, float *r_cb, float *r_cr, 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       BLI_assert(!"invalid colorspace");
158       break;
159   }
160 
161   *r_y = y;
162   *r_cb = cb;
163   *r_cr = cr;
164 }
165 
166 /* YCC input have a range of 16-235 and 16-240 except with JFIF_0_255 where the range is 0-255 */
167 /* RGB outputs are in the range 0 - 1.0f */
168 
169 /* FIXME comment above must be wrong because BLI_YCC_ITU_BT601 y 16.0 cr 16.0 -> r -0.7009 */
ycc_to_rgb(float y,float cb,float cr,float * r_r,float * r_g,float * r_b,int colorspace)170 void ycc_to_rgb(float y, float cb, float cr, float *r_r, float *r_g, float *r_b, int colorspace)
171 {
172   float r = 128.0f, g = 128.0f, b = 128.0f;
173 
174   switch (colorspace) {
175     case BLI_YCC_ITU_BT601:
176       r = 1.164f * (y - 16.0f) + 1.596f * (cr - 128.0f);
177       g = 1.164f * (y - 16.0f) - 0.813f * (cr - 128.0f) - 0.392f * (cb - 128.0f);
178       b = 1.164f * (y - 16.0f) + 2.017f * (cb - 128.0f);
179       break;
180     case BLI_YCC_ITU_BT709:
181       r = 1.164f * (y - 16.0f) + 1.793f * (cr - 128.0f);
182       g = 1.164f * (y - 16.0f) - 0.534f * (cr - 128.0f) - 0.213f * (cb - 128.0f);
183       b = 1.164f * (y - 16.0f) + 2.115f * (cb - 128.0f);
184       break;
185     case BLI_YCC_JFIF_0_255:
186       r = y + 1.402f * cr - 179.456f;
187       g = y - 0.34414f * cb - 0.71414f * cr + 135.45984f;
188       b = y + 1.772f * cb - 226.816f;
189       break;
190     default:
191       BLI_assert(0);
192       break;
193   }
194   *r_r = r / 255.0f;
195   *r_g = g / 255.0f;
196   *r_b = b / 255.0f;
197 }
198 
hex_to_rgb(const char * hexcol,float * r_r,float * r_g,float * r_b)199 void hex_to_rgb(const char *hexcol, float *r_r, float *r_g, float *r_b)
200 {
201   unsigned int ri, gi, bi;
202 
203   if (hexcol[0] == '#') {
204     hexcol++;
205   }
206 
207   if (sscanf(hexcol, "%02x%02x%02x", &ri, &gi, &bi) == 3) {
208     /* six digit hex colors */
209   }
210   else if (sscanf(hexcol, "%01x%01x%01x", &ri, &gi, &bi) == 3) {
211     /* three digit hex colors (#123 becomes #112233) */
212     ri += ri << 4;
213     gi += gi << 4;
214     bi += bi << 4;
215   }
216   else {
217     /* avoid using un-initialized vars */
218     *r_r = *r_g = *r_b = 0.0f;
219     return;
220   }
221 
222   *r_r = (float)ri * (1.0f / 255.0f);
223   *r_g = (float)gi * (1.0f / 255.0f);
224   *r_b = (float)bi * (1.0f / 255.0f);
225   CLAMP(*r_r, 0.0f, 1.0f);
226   CLAMP(*r_g, 0.0f, 1.0f);
227   CLAMP(*r_b, 0.0f, 1.0f);
228 }
229 
rgb_to_hsv(float r,float g,float b,float * r_h,float * r_s,float * r_v)230 void rgb_to_hsv(float r, float g, float b, float *r_h, float *r_s, float *r_v)
231 {
232   float k = 0.0f;
233   float chroma;
234   float min_gb;
235 
236   if (g < b) {
237     SWAP(float, g, b);
238     k = -1.0f;
239   }
240   min_gb = b;
241   if (r < g) {
242     SWAP(float, r, g);
243     k = -2.0f / 6.0f - k;
244     min_gb = min_ff(g, b);
245   }
246 
247   chroma = r - min_gb;
248 
249   *r_h = fabsf(k + (g - b) / (6.0f * chroma + 1e-20f));
250   *r_s = chroma / (r + 1e-20f);
251   *r_v = r;
252 }
253 
254 /* convenience function for now */
rgb_to_hsv_v(const float rgb[3],float r_hsv[3])255 void rgb_to_hsv_v(const float rgb[3], float r_hsv[3])
256 {
257   rgb_to_hsv(rgb[0], rgb[1], rgb[2], &r_hsv[0], &r_hsv[1], &r_hsv[2]);
258 }
259 
rgb_to_hsl(float r,float g,float b,float * r_h,float * r_s,float * r_l)260 void rgb_to_hsl(float r, float g, float b, float *r_h, float *r_s, float *r_l)
261 {
262   const float cmax = max_fff(r, g, b);
263   const float cmin = min_fff(r, g, b);
264   float h, s, l = min_ff(1.0, (cmax + cmin) / 2.0f);
265 
266   if (cmax == cmin) {
267     h = s = 0.0f; /* achromatic */
268   }
269   else {
270     float d = cmax - cmin;
271     s = l > 0.5f ? d / (2.0f - cmax - cmin) : d / (cmax + cmin);
272     if (cmax == r) {
273       h = (g - b) / d + (g < b ? 6.0f : 0.0f);
274     }
275     else if (cmax == g) {
276       h = (b - r) / d + 2.0f;
277     }
278     else {
279       h = (r - g) / d + 4.0f;
280     }
281   }
282   h /= 6.0f;
283 
284   *r_h = h;
285   *r_s = s;
286   *r_l = l;
287 }
288 
rgb_to_hsl_compat(float r,float g,float b,float * r_h,float * r_s,float * r_l)289 void rgb_to_hsl_compat(float r, float g, float b, float *r_h, float *r_s, float *r_l)
290 {
291   const float orig_s = *r_s;
292   const float orig_h = *r_h;
293 
294   rgb_to_hsl(r, g, b, r_h, r_s, r_l);
295 
296   if (*r_l <= 0.0f) {
297     *r_h = orig_h;
298     *r_s = orig_s;
299   }
300   else if (*r_s <= 0.0f) {
301     *r_h = orig_h;
302     *r_s = orig_s;
303   }
304 
305   if (*r_h == 0.0f && orig_h >= 1.0f) {
306     *r_h = 1.0f;
307   }
308 }
309 
rgb_to_hsl_compat_v(const float rgb[3],float r_hsl[3])310 void rgb_to_hsl_compat_v(const float rgb[3], float r_hsl[3])
311 {
312   rgb_to_hsl_compat(rgb[0], rgb[1], rgb[2], &r_hsl[0], &r_hsl[1], &r_hsl[2]);
313 }
314 
315 /* convenience function for now */
rgb_to_hsl_v(const float rgb[3],float r_hsl[3])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 
rgb_to_hsv_compat(float r,float g,float b,float * r_h,float * r_s,float * r_v)321 void rgb_to_hsv_compat(float r, float g, float b, float *r_h, float *r_s, float *r_v)
322 {
323   const float orig_h = *r_h;
324   const float orig_s = *r_s;
325 
326   rgb_to_hsv(r, g, b, r_h, r_s, r_v);
327 
328   if (*r_v <= 1e-8) {
329     /* Very low v values will affect the hs values, correct them in post. */
330     *r_h = orig_h;
331     *r_s = orig_s;
332   }
333   else if (*r_s <= 1e-8) {
334     *r_h = orig_h;
335   }
336 
337   if (*r_h == 0.0f && orig_h >= 1.0f) {
338     *r_h = 1.0f;
339   }
340 }
341 
342 /* convenience function for now */
rgb_to_hsv_compat_v(const float rgb[3],float r_hsv[3])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 */
hsv_clamp_v(float hsv[3],float v_max)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)
360  * number that can be expressed like 0xFFAA66 or so.
361  * For that reason it is sensitive for endianness... with this function it works correctly.
362  * \see #imm_cpack
363  */
hsv_to_cpack(float h,float s,float v)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 
rgb_to_cpack(float r,float g,float b)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) {
389     ir = 255;
390   }
391   if (ig > 255) {
392     ig = 255;
393   }
394   if (ib > 255) {
395     ib = 255;
396   }
397 
398   return (ir + (ig * 256) + (ib * 256 * 256));
399 }
400 
cpack_to_rgb(unsigned int col,float * r_r,float * r_g,float * r_b)401 void cpack_to_rgb(unsigned int col, float *r_r, float *r_g, float *r_b)
402 {
403   *r_r = ((float)(((col)) & 0xFF)) * (1.0f / 255.0f);
404   *r_g = ((float)(((col) >> 8) & 0xFF)) * (1.0f / 255.0f);
405   *r_b = ((float)(((col) >> 16) & 0xFF)) * (1.0f / 255.0f);
406 }
407 
rgb_uchar_to_float(float r_col[3],const unsigned char col_ub[3])408 void rgb_uchar_to_float(float r_col[3], const unsigned char col_ub[3])
409 {
410   r_col[0] = ((float)col_ub[0]) * (1.0f / 255.0f);
411   r_col[1] = ((float)col_ub[1]) * (1.0f / 255.0f);
412   r_col[2] = ((float)col_ub[2]) * (1.0f / 255.0f);
413 }
414 
rgba_uchar_to_float(float r_col[4],const unsigned char col_ub[4])415 void rgba_uchar_to_float(float r_col[4], const unsigned char col_ub[4])
416 {
417   r_col[0] = ((float)col_ub[0]) * (1.0f / 255.0f);
418   r_col[1] = ((float)col_ub[1]) * (1.0f / 255.0f);
419   r_col[2] = ((float)col_ub[2]) * (1.0f / 255.0f);
420   r_col[3] = ((float)col_ub[3]) * (1.0f / 255.0f);
421 }
422 
rgb_float_to_uchar(unsigned char r_col[3],const float col_f[3])423 void rgb_float_to_uchar(unsigned char r_col[3], const float col_f[3])
424 {
425   unit_float_to_uchar_clamp_v3(r_col, col_f);
426 }
427 
rgba_float_to_uchar(unsigned char r_col[4],const float col_f[4])428 void rgba_float_to_uchar(unsigned char r_col[4], const float col_f[4])
429 {
430   unit_float_to_uchar_clamp_v4(r_col, col_f);
431 }
432 
433 /* ********************************* color transforms ********************************* */
434 
srgb_to_linearrgb(float c)435 float srgb_to_linearrgb(float c)
436 {
437   if (c < 0.04045f) {
438     return (c < 0.0f) ? 0.0f : c * (1.0f / 12.92f);
439   }
440 
441   return powf((c + 0.055f) * (1.0f / 1.055f), 2.4f);
442 }
443 
linearrgb_to_srgb(float c)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 
450   return 1.055f * powf(c, 1.0f / 2.4f) - 0.055f;
451 }
452 
minmax_rgb(short c[3])453 void minmax_rgb(short c[3])
454 {
455   if (c[0] > 255) {
456     c[0] = 255;
457   }
458   else if (c[0] < 0) {
459     c[0] = 0;
460   }
461 
462   if (c[1] > 255) {
463     c[1] = 255;
464   }
465   else if (c[1] < 0) {
466     c[1] = 0;
467   }
468 
469   if (c[2] > 255) {
470     c[2] = 255;
471   }
472   else if (c[2] < 0) {
473     c[2] = 0;
474   }
475 }
476 
477 /* If the requested RGB shade contains a negative weight for
478  * one of the primaries, it lies outside the color gamut
479  * accessible from the given triple of primaries.  Desaturate
480  * it by adding white, equal quantities of R, G, and B, enough
481  * to make RGB all positive.  The function returns 1 if the
482  * components were modified, zero otherwise.*/
constrain_rgb(float * r,float * g,float * b)483 int constrain_rgb(float *r, float *g, float *b)
484 {
485   /* Amount of white needed */
486   const float w = -min_ffff(0.0f, *r, *g, *b);
487 
488   /* Add just enough white to make r, g, b all positive. */
489   if (w > 0.0f) {
490     *r += w;
491     *g += w;
492     *b += w;
493 
494     return 1; /* Color modified to fit RGB gamut */
495   }
496 
497   return 0; /* Color within RGB gamut */
498 }
499 
500 /* ********************** lift/gamma/gain / ASC-CDL conversion ********************************* */
501 
lift_gamma_gain_to_asc_cdl(const float * lift,const float * gamma,const float * gain,float * offset,float * slope,float * power)502 void lift_gamma_gain_to_asc_cdl(const float *lift,
503                                 const float *gamma,
504                                 const float *gain,
505                                 float *offset,
506                                 float *slope,
507                                 float *power)
508 {
509   int c;
510   for (c = 0; c < 3; c++) {
511     offset[c] = lift[c] * gain[c];
512     slope[c] = gain[c] * (1.0f - lift[c]);
513     if (gamma[c] == 0) {
514       power[c] = FLT_MAX;
515     }
516     else {
517       power[c] = 1.0f / gamma[c];
518     }
519   }
520 }
521 
522 /* ************************************* other ************************************************* */
523 
524 /* Applies an hue offset to a float rgb color */
rgb_float_set_hue_float_offset(float rgb[3],float hue_offset)525 void rgb_float_set_hue_float_offset(float rgb[3], float hue_offset)
526 {
527   float hsv[3];
528 
529   rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv + 1, hsv + 2);
530 
531   hsv[0] += hue_offset;
532   if (hsv[0] > 1.0f) {
533     hsv[0] -= 1.0f;
534   }
535   else if (hsv[0] < 0.0f) {
536     hsv[0] += 1.0f;
537   }
538 
539   hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb + 1, rgb + 2);
540 }
541 
542 /* Applies an hue offset to a byte rgb color */
rgb_byte_set_hue_float_offset(unsigned char rgb[3],float hue_offset)543 void rgb_byte_set_hue_float_offset(unsigned char rgb[3], float hue_offset)
544 {
545   float rgb_float[3];
546 
547   rgb_uchar_to_float(rgb_float, rgb);
548   rgb_float_set_hue_float_offset(rgb_float, hue_offset);
549   rgb_float_to_uchar(rgb, rgb_float);
550 }
551 
552 /* fast sRGB conversion
553  * LUT from linear float to 16-bit short
554  * based on http://mysite.verizon.net/spitzak/conversion/
555  */
556 
557 float BLI_color_from_srgb_table[256];
558 unsigned short BLI_color_to_srgb_table[0x10000];
559 
hipart(const float f)560 static unsigned short hipart(const float f)
561 {
562   union {
563     float f;
564     unsigned short us[2];
565   } tmp;
566 
567   tmp.f = f;
568 
569 #ifdef __BIG_ENDIAN__
570   return tmp.us[0];
571 #else
572   return tmp.us[1];
573 #endif
574 }
575 
index_to_float(const unsigned short i)576 static float index_to_float(const unsigned short i)
577 {
578 
579   union {
580     float f;
581     unsigned short us[2];
582   } tmp;
583 
584   /* positive and negative zeros, and all gradual underflow, turn into zero: */
585   if (i < 0x80 || (i >= 0x8000 && i < 0x8080)) {
586     return 0;
587   }
588   /* All NaN's and infinity turn into the largest possible legal float: */
589   if (i >= 0x7f80 && i < 0x8000) {
590     return FLT_MAX;
591   }
592   if (i >= 0xff80) {
593     return -FLT_MAX;
594   }
595 
596 #ifdef __BIG_ENDIAN__
597   tmp.us[0] = i;
598   tmp.us[1] = 0x8000;
599 #else
600   tmp.us[0] = 0x8000;
601   tmp.us[1] = i;
602 #endif
603 
604   return tmp.f;
605 }
606 
BLI_init_srgb_conversion(void)607 void BLI_init_srgb_conversion(void)
608 {
609   static bool initialized = false;
610   unsigned int i, b;
611 
612   if (initialized) {
613     return;
614   }
615   initialized = true;
616 
617   /* Fill in the lookup table to convert floats to bytes: */
618   for (i = 0; i < 0x10000; i++) {
619     float f = linearrgb_to_srgb(index_to_float((unsigned short)i)) * 255.0f;
620     if (f <= 0) {
621       BLI_color_to_srgb_table[i] = 0;
622     }
623     else if (f < 255) {
624       BLI_color_to_srgb_table[i] = (unsigned short)(f * 0x100 + 0.5f);
625     }
626     else {
627       BLI_color_to_srgb_table[i] = 0xff00;
628     }
629   }
630 
631   /* Fill in the lookup table to convert bytes to float: */
632   for (b = 0; b <= 255; b++) {
633     float f = srgb_to_linearrgb(((float)b) * (1.0f / 255.0f));
634     BLI_color_from_srgb_table[b] = f;
635     i = hipart(f);
636     /* replace entries so byte->float->byte does not change the data: */
637     BLI_color_to_srgb_table[i] = (unsigned short)(b * 0x100);
638   }
639 }
640 
641 /* ****************************** blackbody ******************************** */
642 
643 /* Calculate color in range 800..12000 using an approximation
644  * a/x+bx+c for R and G and ((at + b)t + c)t + d) for B
645  * Max absolute error for RGB is (0.00095, 0.00077, 0.00057),
646  * which is enough to get the same 8 bit/channel color.
647  */
648 
649 static const float blackbody_table_r[6][3] = {
650     {2.52432244e+03f, -1.06185848e-03f, 3.11067539e+00f},
651     {3.37763626e+03f, -4.34581697e-04f, 1.64843306e+00f},
652     {4.10671449e+03f, -8.61949938e-05f, 6.41423749e-01f},
653     {4.66849800e+03f, 2.85655028e-05f, 1.29075375e-01f},
654     {4.60124770e+03f, 2.89727618e-05f, 1.48001316e-01f},
655     {3.78765709e+03f, 9.36026367e-06f, 3.98995841e-01f},
656 };
657 
658 static const float blackbody_table_g[6][3] = {
659     {-7.50343014e+02f, 3.15679613e-04f, 4.73464526e-01f},
660     {-1.00402363e+03f, 1.29189794e-04f, 9.08181524e-01f},
661     {-1.22075471e+03f, 2.56245413e-05f, 1.20753416e+00f},
662     {-1.42546105e+03f, -4.01730887e-05f, 1.44002695e+00f},
663     {-1.18134453e+03f, -2.18913373e-05f, 1.30656109e+00f},
664     {-5.00279505e+02f, -4.59745390e-06f, 1.09090465e+00f},
665 };
666 
667 static const float blackbody_table_b[6][4] = {
668     {0.0f, 0.0f, 0.0f, 0.0f},
669     {0.0f, 0.0f, 0.0f, 0.0f},
670     {0.0f, 0.0f, 0.0f, 0.0f},
671     {-2.02524603e-11f, 1.79435860e-07f, -2.60561875e-04f, -1.41761141e-02f},
672     {-2.22463426e-13f, -1.55078698e-08f, 3.81675160e-04f, -7.30646033e-01f},
673     {6.72595954e-13f, -2.73059993e-08f, 4.24068546e-04f, -7.52204323e-01f},
674 };
675 
blackbody_temperature_to_rgb(float rgb[3],float t)676 static void blackbody_temperature_to_rgb(float rgb[3], float t)
677 {
678   if (t >= 12000.0f) {
679     rgb[0] = 0.826270103f;
680     rgb[1] = 0.994478524f;
681     rgb[2] = 1.56626022f;
682   }
683   else if (t < 965.0f) {
684     rgb[0] = 4.70366907f;
685     rgb[1] = 0.0f;
686     rgb[2] = 0.0f;
687   }
688   else {
689     int i = (t >= 6365.0f) ?
690                 5 :
691                 (t >= 3315.0f) ? 4 :
692                                  (t >= 1902.0f) ? 3 : (t >= 1449.0f) ? 2 : (t >= 1167.0f) ? 1 : 0;
693 
694     const float *r = blackbody_table_r[i];
695     const float *g = blackbody_table_g[i];
696     const float *b = blackbody_table_b[i];
697 
698     const float t_inv = 1.0f / t;
699     rgb[0] = r[0] * t_inv + r[1] * t + r[2];
700     rgb[1] = g[0] * t_inv + g[1] * t + g[2];
701     rgb[2] = ((b[0] * t + b[1]) * t + b[2]) * t + b[3];
702   }
703 }
704 
blackbody_temperature_to_rgb_table(float * r_table,int width,float min,float max)705 void blackbody_temperature_to_rgb_table(float *r_table, int width, float min, float max)
706 {
707   for (int i = 0; i < width; i++) {
708     float temperature = min + (max - min) / (float)width * (float)i;
709 
710     float rgb[3];
711     blackbody_temperature_to_rgb(rgb, temperature);
712 
713     copy_v3_v3(&r_table[i * 4], rgb);
714     r_table[i * 4 + 3] = 0.0f;
715   }
716 }
717