bugfix [#23355] Square Color picker moving by itself and locking up
[blender-staging.git] / source / blender / blenlib / intern / math_color.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  
23  * The Original Code is: some of this file.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  * */
27
28 #include <assert.h>
29
30 #include "BLI_math.h"
31
32 void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b)
33 {
34         int i;
35         float f, p, q, t;
36
37         if(s==0.0f) {
38                 *r = v;
39                 *g = v;
40                 *b = v;
41         }
42         else {
43                 h= (h - floor(h))*6.0f;
44
45                 i = (int)floor(h);
46                 f = h - i;
47                 p = v*(1.0f-s);
48                 q = v*(1.0f-(s*f));
49                 t = v*(1.0f-(s*(1.0f-f)));
50                 
51                 switch (i) {
52                 case 0 :
53                         *r = v;
54                         *g = t;
55                         *b = p;
56                         break;
57                 case 1 :
58                         *r = q;
59                         *g = v;
60                         *b = p;
61                         break;
62                 case 2 :
63                         *r = p;
64                         *g = v;
65                         *b = t;
66                         break;
67                 case 3 :
68                         *r = p;
69                         *g = q;
70                         *b = v;
71                         break;
72                 case 4 :
73                         *r = t;
74                         *g = p;
75                         *b = v;
76                         break;
77                 case 5 :
78                         *r = v;
79                         *g = p;
80                         *b = q;
81                         break;
82                 }
83         }
84 }
85
86 void rgb_to_yuv(float r, float g, float b, float *ly, float *lu, float *lv)
87 {
88         float y, u, v;
89         y= 0.299f*r + 0.587f*g + 0.114f*b;
90         u=-0.147f*r - 0.289f*g + 0.436f*b;
91         v= 0.615f*r - 0.515f*g - 0.100f*b;
92         
93         *ly=y;
94         *lu=u;
95         *lv=v;
96 }
97
98 void yuv_to_rgb(float y, float u, float v, float *lr, float *lg, float *lb)
99 {
100         float r, g, b;
101         r=y+1.140f*v;
102         g=y-0.394f*u - 0.581f*v;
103         b=y+2.032f*u;
104         
105         *lr=r;
106         *lg=g;
107         *lb=b;
108 }
109
110 /* The RGB inputs are supposed gamma corrected and in the range 0 - 1.0f */
111 /* Output YCC have a range of 16-235 and 16-240 except with JFIF_0_255 where the range is 0-255 */
112 void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr, int colorspace)
113 {
114         float sr,sg, sb;
115         float y, cr, cb;
116         
117         sr=255.0f*r;
118         sg=255.0f*g;
119         sb=255.0f*b;
120         
121         switch (colorspace) {
122         case BLI_YCC_ITU_BT601 :
123                 y=(0.257f*sr)+(0.504f*sg)+(0.098f*sb)+16.0f;
124                 cb=(-0.148f*sr)-(0.291f*sg)+(0.439f*sb)+128.0f;
125                 cr=(0.439f*sr)-(0.368f*sg)-(0.071f*sb)+128.0f;
126                 break;
127         case BLI_YCC_ITU_BT709 :
128                 y=(0.183f*sr)+(0.614f*sg)+(0.062f*sb)+16.0f;
129                 cb=(-0.101f*sr)-(0.338f*sg)+(0.439f*sb)+128.0f;
130                 cr=(0.439f*sr)-(0.399f*sg)-(0.040f*sb)+128.0f;
131                 break;
132         case BLI_YCC_JFIF_0_255 :
133                 y=(0.299f*sr)+(0.587f*sg)+(0.114f*sb);
134                 cb=(-0.16874f*sr)-(0.33126f*sg)+(0.5f*sb)+128.0f;
135                 cr=(0.5f*sr)-(0.41869f*sg)-(0.08131f*sb)+128.0f;
136                 break;
137         default:
138                 assert(!"invalid colorspace");
139         }
140         
141         *ly=y;
142         *lcb=cb;
143         *lcr=cr;
144 }
145
146
147 /* YCC input have a range of 16-235 and 16-240 exepect with JFIF_0_255 where the range is 0-255 */
148 /* RGB outputs are in the range 0 - 1.0f */
149 void ycc_to_rgb(float y, float cb, float cr, float *lr, float *lg, float *lb, int colorspace)
150 {
151         float r,g,b;
152         
153         switch (colorspace) {
154         case BLI_YCC_ITU_BT601 :
155                 r=1.164f*(y-16.0f)+1.596f*(cr-128.0f);
156                 g=1.164f*(y-16.0f)-0.813f*(cr-128.0f)-0.392f*(cb-128.0f);
157                 b=1.164f*(y-16.0f)+2.017f*(cb-128.0f);
158                 break;
159         case BLI_YCC_ITU_BT709 :
160                 r=1.164f*(y-16.0f)+1.793f*(cr-128.0f);
161                 g=1.164f*(y-16.0f)-0.534f*(cr-128.0f)-0.213f*(cb-128.0f);
162                 b=1.164f*(y-16.0f)+2.115f*(cb-128.0f);
163                 break;
164         case BLI_YCC_JFIF_0_255 :
165                 r=y+1.402f*cr - 179.456f;
166                 g=y-0.34414f*cb - 0.71414f*cr + 135.45984f;
167                 b=y+1.772f*cb - 226.816f;
168                 break;
169         default:
170                 assert(!"invalid colorspace");
171         }
172         *lr=r/255.0f;
173         *lg=g/255.0f;
174         *lb=b/255.0f;
175 }
176
177 void hex_to_rgb(char *hexcol, float *r, float *g, float *b)
178 {
179         unsigned int ri, gi, bi;
180         
181         if (hexcol[0] == '#') hexcol++;
182         
183         if (sscanf(hexcol, "%02x%02x%02x", &ri, &gi, &bi)) {
184                 *r = ri / 255.0f;
185                 *g = gi / 255.0f;               
186                 *b = bi / 255.0f;
187         }
188 }
189
190 void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv)
191 {
192         float h, s, v;
193         float cmax, cmin, cdelta;
194         float rc, gc, bc;
195
196         cmax = r;
197         cmin = r;
198         cmax = (g>cmax ? g:cmax);
199         cmin = (g<cmin ? g:cmin);
200         cmax = (b>cmax ? b:cmax);
201         cmin = (b<cmin ? b:cmin);
202
203         v = cmax;               /* value */
204         if (cmax != 0.0f)
205                 s = (cmax - cmin)/cmax;
206         else {
207                 s = 0.0f;
208                 h = 0.0f;
209         }
210         if (s == 0.0f)
211                 h = -1.0f;
212         else {
213                 cdelta = cmax-cmin;
214                 rc = (cmax-r)/cdelta;
215                 gc = (cmax-g)/cdelta;
216                 bc = (cmax-b)/cdelta;
217                 if (r==cmax)
218                         h = bc-gc;
219                 else
220                         if (g==cmax)
221                                 h = 2.0f+rc-bc;
222                         else
223                                 h = 4.0f+gc-rc;
224                 h = h*60.0f;
225                 if (h < 0.0f)
226                         h += 360.0f;
227         }
228         
229         *ls = s;
230         *lh = h / 360.0f;
231         if(*lh < 0.0f) *lh= 0.0f;
232         *lv = v;
233 }
234
235 void rgb_to_hsv_compat(float r, float g, float b, float *lh, float *ls, float *lv)
236 {
237         float orig_h= *lh;
238         float orig_s= *ls;
239
240         rgb_to_hsv(r, g, b, lh, ls, lv);
241
242         if(*lv <= 0.0f) {
243                 *lh= orig_h;
244                 *ls= orig_s;
245         }
246         else if (*ls <= 0.0f) {
247                 *lh= orig_h;
248         }
249
250         if(*lh==0.0f && orig_h >= 1.0f) {
251                 *lh= 1.0f;
252         }
253 }
254
255 /*http://brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html */
256
257 void xyz_to_rgb(float xc, float yc, float zc, float *r, float *g, float *b, int colorspace)
258 {
259         switch (colorspace) { 
260         case BLI_XYZ_SMPTE:
261                 *r = (3.50570f   * xc) + (-1.73964f      * yc) + (-0.544011f * zc);
262                 *g = (-1.06906f  * xc) + (1.97781f       * yc) + (0.0351720f * zc);
263                 *b = (0.0563117f * xc) + (-0.196994f * yc) + (1.05005f   * zc);
264                 break;
265         case BLI_XYZ_REC709_SRGB:
266                 *r = (3.240476f  * xc) + (-1.537150f * yc) + (-0.498535f * zc);
267                 *g = (-0.969256f * xc) + (1.875992f  * yc) + (0.041556f  * zc);
268                 *b = (0.055648f  * xc) + (-0.204043f * yc) + (1.057311f  * zc);
269                 break;
270         case BLI_XYZ_CIE:
271                 *r = (2.28783848734076f * xc) + (-0.833367677835217f    * yc) + (-0.454470795871421f    * zc);
272                 *g = (-0.511651380743862f * xc) + (1.42275837632178f * yc) + (0.0888930017552939f * zc);
273                 *b = (0.00572040983140966f      * xc) + (-0.0159068485104036f   * yc) + (1.0101864083734f       * zc);
274                 break;
275         }
276 }
277
278 /* we define a 'cpack' here as a (3 byte color code) number that can be expressed like 0xFFAA66 or so.
279    for that reason it is sensitive for endianness... with this function it works correctly
280 */
281
282 unsigned int hsv_to_cpack(float h, float s, float v)
283 {
284         short r, g, b;
285         float rf, gf, bf;
286         unsigned int col;
287         
288         hsv_to_rgb(h, s, v, &rf, &gf, &bf);
289         
290         r= (short)(rf*255.0f);
291         g= (short)(gf*255.0f);
292         b= (short)(bf*255.0f);
293         
294         col= ( r + (g*256) + (b*256*256) );
295         return col;
296 }
297
298
299 unsigned int rgb_to_cpack(float r, float g, float b)
300 {
301         int ir, ig, ib;
302         
303         ir= (int)floor(255.0*r);
304         if(ir<0) ir= 0; else if(ir>255) ir= 255;
305         ig= (int)floor(255.0*g);
306         if(ig<0) ig= 0; else if(ig>255) ig= 255;
307         ib= (int)floor(255.0*b);
308         if(ib<0) ib= 0; else if(ib>255) ib= 255;
309         
310         return (ir+ (ig*256) + (ib*256*256));
311 }
312
313 void cpack_to_rgb(unsigned int col, float *r, float *g, float *b)
314 {
315         
316         *r= (float)((col)&0xFF);
317         *r /= 255.0f;
318
319         *g= (float)(((col)>>8)&0xFF);
320         *g /= 255.0f;
321
322         *b= (float)(((col)>>16)&0xFF);
323         *b /= 255.0f;
324 }
325
326 void rgb_byte_to_float(char *in, float *out)
327 {
328         out[0]= ((float)in[0]) / 255.0f;
329         out[1]= ((float)in[1]) / 255.0f;
330         out[2]= ((float)in[2]) / 255.0f;
331 }
332
333 void rgb_float_to_byte(float *in, char *out)
334 {
335         int r, g, b;
336         
337         r= (int)(in[0] * 255.0);
338         g= (int)(in[1] * 255.0); 
339         b= (int)(in[2] * 255.0); 
340         
341         out[0]= (char)((r <= 0)? 0 : (r >= 255)? 255 : r);
342         out[1]= (char)((g <= 0)? 0 : (g >= 255)? 255 : g);
343         out[2]= (char)((b <= 0)? 0 : (b >= 255)? 255 : b);
344 }
345
346 /* ********************************* color transforms ********************************* */
347
348
349 void gamma_correct(float *c, float gamma)
350 {
351         *c = powf((*c), gamma);
352 }
353
354 float rec709_to_linearrgb(float c)
355 {
356         if (c < 0.081f)
357                 return (c < 0.0f)? 0.0f: c * (1.0f/4.5f);
358         else
359                 return powf((c + 0.099f)*(1.0f/1.099f), (1.0f/0.45f));
360 }
361
362 float linearrgb_to_rec709(float c)
363 {
364         if (c < 0.018f)
365                 return (c < 0.0f)? 0.0f: c * 4.5f;
366         else
367                 return 1.099f * powf(c, 0.45f) - 0.099f;
368 }
369
370 float srgb_to_linearrgb(float c)
371 {
372         if (c < 0.04045f)
373                 return (c < 0.0f)? 0.0f: c * (1.0f/12.92f);
374         else
375                 return powf((c + 0.055f)*(1.0f/1.055f), 2.4f);
376 }
377
378 float linearrgb_to_srgb(float c)
379 {
380         if (c < 0.0031308f)
381                 return (c < 0.0f)? 0.0f: c * 12.92f;
382         else
383                 return  1.055f * powf(c, 1.0f/2.4f) - 0.055f;
384 }
385
386 void srgb_to_linearrgb_v3_v3(float *col_to, float *col_from)
387 {
388         col_to[0] = srgb_to_linearrgb(col_from[0]);
389         col_to[1] = srgb_to_linearrgb(col_from[1]);
390         col_to[2] = srgb_to_linearrgb(col_from[2]);
391 }
392
393 void linearrgb_to_srgb_v3_v3(float *col_to, float *col_from)
394 {
395         col_to[0] = linearrgb_to_srgb(col_from[0]);
396         col_to[1] = linearrgb_to_srgb(col_from[1]);
397         col_to[2] = linearrgb_to_srgb(col_from[2]);
398 }
399
400 /* todo, should these be moved elsewhere?, they dont belong in imbuf */
401 void srgb_to_linearrgb_rgba_buf(float *col, int tot)
402 {
403         while(tot--) {
404                 srgb_to_linearrgb_v3_v3(col, col);
405                 col += 4;
406         }
407 }
408
409 void linearrgb_to_srgb_rgba_buf(float *col, int tot)
410 {
411         while(tot--) {
412                 linearrgb_to_srgb_v3_v3(col, col);
413                 col += 4;
414         }
415 }
416
417 void srgb_to_linearrgb_rgba_rgba_buf(float *col_to, float *col_from, int tot)
418 {
419         while(tot--) {
420                 srgb_to_linearrgb_v3_v3(col_to, col_from);
421                 col_to[3]= col_from[3];
422                 col_to += 4;
423                 col_from += 4;
424         }
425 }
426
427 void linearrgb_to_srgb_rgba_rgba_buf(float *col_to, float *col_from, int tot)
428 {
429         while(tot--) {
430                 linearrgb_to_srgb_v3_v3(col_to, col_from);
431                 col_to[3]= col_from[3];
432                 col_to += 4;
433                 col_from += 4;
434         }
435 }
436
437 void minmax_rgb(short c[])
438 {
439         if(c[0]>255) c[0]=255;
440         else if(c[0]<0) c[0]=0;
441         if(c[1]>255) c[1]=255;
442         else if(c[1]<0) c[1]=0;
443         if(c[2]>255) c[2]=255;
444         else if(c[2]<0) c[2]=0;
445 }
446
447 /*If the requested RGB shade contains a negative weight for
448   one of the primaries, it lies outside the colour gamut 
449   accessible from the given triple of primaries.  Desaturate
450   it by adding white, equal quantities of R, G, and B, enough
451   to make RGB all positive.  The function returns 1 if the
452   components were modified, zero otherwise.*/
453 int constrain_rgb(float *r, float *g, float *b)
454 {
455         float w;
456
457         /* Amount of white needed is w = - min(0, *r, *g, *b) */
458     
459         w = (0 < *r) ? 0 : *r;
460         w = (w < *g) ? w : *g;
461         w = (w < *b) ? w : *b;
462         w = -w;
463
464         /* Add just enough white to make r, g, b all positive. */
465     
466         if (w > 0) {
467                 *r += w;  *g += w; *b += w;
468                 return 1;                     /* Color modified to fit RGB gamut */
469         }
470
471         return 0;                         /* Color within RGB gamut */
472 }
473
474 float rgb_to_grayscale(float rgb[3])
475 {
476         return 0.3f*rgb[0] + 0.58f*rgb[1] + 0.12f*rgb[2];
477 }
478
479 /* ********************************* lift/gamma/gain / ASC-CDL conversion ********************************* */
480
481 void lift_gamma_gain_to_asc_cdl(float *lift, float *gamma, float *gain, float *offset, float *slope, float *power)
482 {
483         int c;
484         for(c=0; c<3; c++) {
485                 offset[c]= lift[c]*gain[c];
486                 slope[c]=  gain[c]*(1.0f-lift[c]);
487                 if(gamma[c] == 0)
488                         power[c]= FLT_MAX;
489                 else
490                         power[c]= 1.0f/gamma[c];
491         }
492 }
493
494 /* ******************************************** other ************************************************* */
495
496 /* Applies an hue offset to a float rgb color */
497 void rgb_float_set_hue_float_offset(float rgb[3], float hue_offset)
498 {
499         float hsv[3];
500         
501         rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
502         
503         hsv[0]+= hue_offset;
504         if(hsv[0]>1.0)          hsv[0]-=1.0;
505         else if(hsv[0]<0.0)     hsv[0]+= 1.0;
506         
507         hsv_to_rgb(hsv[0], hsv[1], hsv[2], rgb, rgb+1, rgb+2);
508 }
509
510 /* Applies an hue offset to a byte rgb color */
511 void rgb_byte_set_hue_float_offset(char rgb[3], float hue_offset)
512 {
513         float rgb_float[3];
514         
515         rgb_byte_to_float(rgb, rgb_float);
516         rgb_float_set_hue_float_offset(rgb_float, hue_offset);
517         rgb_float_to_byte(rgb_float, rgb);
518 }