code cleanup
[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/premultipled 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         union {
132                 float f;
133                 unsigned short us[2];
134         } tmp;
135         tmp.f = f;
136 #ifdef __BIG_ENDIAN__
137         return BLI_color_to_srgb_table[tmp.us[0]];
138 #else
139         return BLI_color_to_srgb_table[tmp.us[1]];
140 #endif
141 }
142
143 MINLINE void linearrgb_to_srgb_ushort4(unsigned short srgb[4], const float linear[4])
144 {
145         srgb[0] = to_srgb_table_lookup(linear[0]);
146         srgb[1] = to_srgb_table_lookup(linear[1]);
147         srgb[2] = to_srgb_table_lookup(linear[2]);
148         srgb[3] = FTOUSHORT(linear[3]);
149 }
150
151 MINLINE void linearrgb_to_srgb_ushort4_predivide(unsigned short srgb[4], const float linear[4])
152 {
153         float alpha, inv_alpha, t;
154         int i;
155
156         if(linear[3] == 1.0f || linear[3] == 0.0f) {
157                 linearrgb_to_srgb_ushort4(srgb, linear);
158                 return;
159         }
160
161         alpha = linear[3];
162         inv_alpha = 1.0f/alpha;
163
164         for(i=0; i<3; ++i) {
165                 t = linear[i] * inv_alpha;
166                 srgb[i] = (t < 1.0f)? (unsigned short)(to_srgb_table_lookup(t) * alpha) : FTOUSHORT(linearrgb_to_srgb(t) * alpha);
167         }
168
169         srgb[3] = FTOUSHORT(linear[3]);
170 }
171
172 MINLINE void srgb_to_linearrgb_uchar4(float linear[4], const unsigned char srgb[4])
173 {
174         linear[0] = BLI_color_from_srgb_table[srgb[0]];
175         linear[1] = BLI_color_from_srgb_table[srgb[1]];
176         linear[2] = BLI_color_from_srgb_table[srgb[2]];
177         linear[3] = srgb[3] * (1.0f/255.0f);
178 }
179
180 MINLINE void srgb_to_linearrgb_uchar4_predivide(float linear[4], const unsigned char srgb[4])
181 {
182         float fsrgb[4];
183         int i;
184
185         if(srgb[3] == 255 || srgb[3] == 0) {
186                 srgb_to_linearrgb_uchar4(linear, srgb);
187                 return;
188         }
189
190         for (i=0; i<4; i++)
191                 fsrgb[i] = srgb[i] * (1.0f/255.0f);
192
193         srgb_to_linearrgb_predivide_v4(linear, fsrgb);
194 }
195
196 #endif /* __MATH_COLOR_INLINE_C__ */