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