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