Merging r58196 through r58265 from trunk into soc-2013-depsgraph_mt
[blender.git] / source / blender / blenlib / intern / math_color_inline.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_inline.c
27  *  \ingroup bli
28  */
29
30
31 #include "BLI_math_color.h"
32 #include "BLI_utildefines.h"
33
34 #ifndef __MATH_COLOR_INLINE_C__
35 #define __MATH_COLOR_INLINE_C__
36
37 /******************************** Color Space ********************************/
38
39 MINLINE void srgb_to_linearrgb_v3_v3(float linear[3], const float srgb[3])
40 {
41         linear[0] = srgb_to_linearrgb(srgb[0]);
42         linear[1] = srgb_to_linearrgb(srgb[1]);
43         linear[2] = srgb_to_linearrgb(srgb[2]);
44 }
45
46 MINLINE void linearrgb_to_srgb_v3_v3(float srgb[3], const float linear[3])
47 {
48         srgb[0] = linearrgb_to_srgb(linear[0]);
49         srgb[1] = linearrgb_to_srgb(linear[1]);
50         srgb[2] = linearrgb_to_srgb(linear[2]);
51 }
52
53 MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4])
54 {
55         srgb_to_linearrgb_v3_v3(linear, srgb);
56         linear[3] = srgb[3];
57 }
58
59 MINLINE void linearrgb_to_srgb_v4(float srgb[4], const float linear[4])
60 {
61         linearrgb_to_srgb_v3_v3(srgb, linear);
62         srgb[3] = linear[3];
63 }
64
65 MINLINE void linearrgb_to_srgb_uchar3(unsigned char srgb[3], const float linear[3])
66 {
67         float srgb_f[3];
68
69         linearrgb_to_srgb_v3_v3(srgb_f, linear);
70         F3TOCHAR3(srgb_f, srgb);
71 }
72
73 MINLINE void linearrgb_to_srgb_uchar4(unsigned char srgb[4], const float linear[4])
74 {
75         float srgb_f[4];
76
77         linearrgb_to_srgb_v4(srgb_f, linear);
78         F4TOCHAR4(srgb_f, srgb);
79 }
80
81 /* predivide versions to work on associated/pre-multiplied alpha. if this should
82  * be done or not depends on the background the image will be composited over,
83  * ideally you would never do color space conversion on an image with alpha
84  * because it is ill defined */
85
86 MINLINE void srgb_to_linearrgb_predivide_v4(float linear[4], const float srgb[4])
87 {
88         float alpha, inv_alpha;
89
90         if (srgb[3] == 1.0f || srgb[3] == 0.0f) {
91                 alpha = 1.0f;
92                 inv_alpha = 1.0f;
93         }
94         else {
95                 alpha = srgb[3];
96                 inv_alpha = 1.0f / alpha;
97         }
98
99         linear[0] = srgb_to_linearrgb(srgb[0] * inv_alpha) * alpha;
100         linear[1] = srgb_to_linearrgb(srgb[1] * inv_alpha) * alpha;
101         linear[2] = srgb_to_linearrgb(srgb[2] * inv_alpha) * alpha;
102         linear[3] = srgb[3];
103 }
104
105 MINLINE void linearrgb_to_srgb_predivide_v4(float srgb[4], const float linear[4])
106 {
107         float alpha, inv_alpha;
108
109         if (linear[3] == 1.0f || linear[3] == 0.0f) {
110                 alpha = 1.0f;
111                 inv_alpha = 1.0f;
112         }
113         else {
114                 alpha = linear[3];
115                 inv_alpha = 1.0f / alpha;
116         }
117
118         srgb[0] = linearrgb_to_srgb(linear[0] * inv_alpha) * alpha;
119         srgb[1] = linearrgb_to_srgb(linear[1] * inv_alpha) * alpha;
120         srgb[2] = linearrgb_to_srgb(linear[2] * inv_alpha) * alpha;
121         srgb[3] = linear[3];
122 }
123
124 /* LUT accelerated conversions */
125
126 extern float BLI_color_from_srgb_table[256];
127 extern unsigned short BLI_color_to_srgb_table[0x10000];
128
129 MINLINE unsigned short to_srgb_table_lookup(const float f)
130 {
131
132         union {
133                 float f;
134                 unsigned short us[2];
135         } tmp;
136         tmp.f = f;
137 #ifdef __BIG_ENDIAN__
138         return BLI_color_to_srgb_table[tmp.us[0]];
139 #else
140         return BLI_color_to_srgb_table[tmp.us[1]];
141 #endif
142 }
143
144 MINLINE void linearrgb_to_srgb_ushort4(unsigned short srgb[4], const float linear[4])
145 {
146         srgb[0] = to_srgb_table_lookup(linear[0]);
147         srgb[1] = to_srgb_table_lookup(linear[1]);
148         srgb[2] = to_srgb_table_lookup(linear[2]);
149         srgb[3] = FTOUSHORT(linear[3]);
150 }
151
152 MINLINE void srgb_to_linearrgb_uchar4(float linear[4], const unsigned char srgb[4])
153 {
154         linear[0] = BLI_color_from_srgb_table[srgb[0]];
155         linear[1] = BLI_color_from_srgb_table[srgb[1]];
156         linear[2] = BLI_color_from_srgb_table[srgb[2]];
157         linear[3] = srgb[3] * (1.0f / 255.0f);
158 }
159
160 MINLINE void srgb_to_linearrgb_uchar4_predivide(float linear[4], const unsigned char srgb[4])
161 {
162         float fsrgb[4];
163         int i;
164
165         if (srgb[3] == 255 || srgb[3] == 0) {
166                 srgb_to_linearrgb_uchar4(linear, srgb);
167                 return;
168         }
169
170         for (i = 0; i < 4; i++)
171                 fsrgb[i] = srgb[i] * (1.0f / 255.0f);
172
173         srgb_to_linearrgb_predivide_v4(linear, fsrgb);
174 }
175
176 /* color macros for themes */
177 #define rgba_char_args_set_fl(col, r, g, b, a) \
178         rgba_char_args_set(col, (r) * 255, (g) * 255, (b) * 255, (a) * 255)
179
180 MINLINE void rgba_char_args_set(char col[4], const char r, const char g, const char b, const char a)
181 {
182         col[0] = r;
183         col[1] = g;
184         col[2] = b;
185         col[3] = a;
186 }
187
188 MINLINE void rgba_char_args_test_set(char col[4], const char r, const char g, const char b, const char a)
189 {
190         if (col[3] == 0) {
191                 col[0] = r;
192                 col[1] = g;
193                 col[2] = b;
194                 col[3] = a;
195         }
196 }
197
198 MINLINE void cpack_cpy_3ub(unsigned char r_col[3], const unsigned int pack)
199 {
200         r_col[0] = ((pack) >>  0) & 0xFF;
201         r_col[1] = ((pack) >>  8) & 0xFF;
202         r_col[2] = ((pack) >> 16) & 0xFF;
203 }
204
205 /* TODO:
206  *
207  * regarding #rgb_to_bw vs #rgb_to_grayscale,
208  * it seems nobody knows why we have both functions which convert color to grays
209  * but with different influences, this is quite stupid, and should be resolved
210  * by someone who knows this stuff: see this thread
211  * http://lists.blender.org/pipermail/bf-committers/2012-June/037180.html
212  *
213  * Only conclusion is that rgb_to_grayscale is used more for compositing.
214  */
215 MINLINE float rgb_to_bw(const float rgb[3])
216 {
217         return 0.35f * rgb[0] + 0.45f * rgb[1] + 0.2f * rgb[2];
218 }
219
220 /* non-linear luma from ITU-R BT.601-2
221  * see: http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC11
222  * note: the values used for are not exact matches to those documented above,
223  * but they are from the same */
224 MINLINE float rgb_to_grayscale(const float rgb[3])
225 {
226         return 0.3f * rgb[0] + 0.58f * rgb[1] + 0.12f * rgb[2];
227 }
228
229 MINLINE unsigned char rgb_to_grayscale_byte(const unsigned char rgb[3])
230 {
231         return (76 * (unsigned short) rgb[0] + 148 * (unsigned short) rgb[1] + 31 * (unsigned short) rgb[2]) / 255;
232 }
233
234 /* luma from defined by 'YCC_JFIF', see #rgb_to_ycc */
235 MINLINE float rgb_to_luma(const float rgb[3])
236 {
237         return 0.299f * rgb[0] + 0.587f * rgb[1] + 0.114f * rgb[2];
238 }
239
240 MINLINE unsigned char rgb_to_luma_byte(const unsigned char rgb[3])
241 {
242         return (76 * (unsigned short) rgb[0] + 150 * (unsigned short) rgb[1] + 29 * (unsigned short) rgb[2]) / 255;
243 }
244
245 /* gamma-corrected RGB --> CIE XYZ
246  * for this function we only get the Y component
247  * see: http://software.intel.com/sites/products/documentation/hpc/ipp/ippi/ippi_ch6/ch6_color_models.html
248  *
249  * also known as:
250  * luminance rec. 709 */
251 MINLINE float rgb_to_luma_y(const float rgb[3])
252 {
253         return 0.212671f * rgb[0] + 0.71516f * rgb[1] + 0.072169f * rgb[2];
254 }
255
256 MINLINE int compare_rgb_uchar(const unsigned char col_a[3], const unsigned char col_b[3], const int limit)
257 {
258         int r = (int)col_a[0] - (int)col_b[0];
259         if (ABS(r) < limit) {
260                 int g = (int)col_a[1] - (int)col_b[1];
261                 if (ABS(g) < limit) {
262                         int b = (int)col_a[2] - (int)col_b[2];
263                         if (ABS(b) < limit) {
264                                 return 1;
265                         }
266                 }
267         }
268
269         return 0;
270 }
271
272 /**************** Alpha Transformations *****************/
273
274 MINLINE void premul_to_straight_v4_v4(float straight[4], const float premul[4])
275 {
276         if (premul[3] == 0.0f || premul[3] == 1.0f) {
277                 straight[0] = premul[0];
278                 straight[1] = premul[1];
279                 straight[2] = premul[2];
280                 straight[3] = premul[3];
281         }
282         else {
283                 float alpha_inv = 1.0f / premul[3];
284                 straight[0] = premul[0] * alpha_inv;
285                 straight[1] = premul[1] * alpha_inv;
286                 straight[2] = premul[2] * alpha_inv;
287                 straight[3] = premul[3];
288         }
289 }
290
291 MINLINE void premul_to_straight_v4(float color[4])
292 {
293         premul_to_straight_v4_v4(color, color);
294 }
295
296 MINLINE void straight_to_premul_v4_v4(float premul[4], const float straight[4])
297 {
298         float alpha = straight[3];
299         premul[0] = straight[0] * alpha;
300         premul[1] = straight[1] * alpha;
301         premul[2] = straight[2] * alpha;
302         premul[3] = straight[3];
303 }
304
305 MINLINE void straight_to_premul_v4(float color[4])
306 {
307         straight_to_premul_v4_v4(color, color);
308 }
309
310 MINLINE void straight_uchar_to_premul_float(float result[4], const unsigned char color[4])
311 {
312         float alpha = color[3] * (1.0f / 255.0f);
313         float fac = alpha * (1.0f / 255.0f);
314
315         result[0] = color[0] * fac;
316         result[1] = color[1] * fac;
317         result[2] = color[2] * fac;
318         result[3] = alpha;
319 }
320
321 MINLINE void premul_float_to_straight_uchar(unsigned char *result, const float color[4])
322 {
323         if (color[3] == 0.0f || color[3] == 1.0f) {
324                 result[0] = FTOCHAR(color[0]);
325                 result[1] = FTOCHAR(color[1]);
326                 result[2] = FTOCHAR(color[2]);
327                 result[3] = FTOCHAR(color[3]);
328         }
329         else {
330                 float alpha_inv = 1.0f / color[3];
331
332                 /* hopefully this would be optimized */
333                 result[0] = FTOCHAR(color[0] * alpha_inv);
334                 result[1] = FTOCHAR(color[1] * alpha_inv);
335                 result[2] = FTOCHAR(color[2] * alpha_inv);
336                 result[3] = FTOCHAR(color[3]);
337         }
338 }
339
340 #endif /* __MATH_COLOR_INLINE_C__ */