Blender V4.3
math_color_inline.c
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "BLI_math_base.h"
10#include "BLI_math_color.h"
11#include "BLI_utildefines.h"
12
13#include <math.h>
14
15#ifdef __cplusplus
16extern "C" {
17#endif
18
19#ifndef __MATH_COLOR_INLINE_C__
20# define __MATH_COLOR_INLINE_C__
21
22/******************************** Color Space ********************************/
23
24MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4])
25{
26 srgb_to_linearrgb_v3_v3(linear, srgb);
27 linear[3] = srgb[3];
28}
29
30MINLINE void linearrgb_to_srgb_v4(float srgb[4], const float linear[4])
31{
32 linearrgb_to_srgb_v3_v3(srgb, linear);
33 srgb[3] = linear[3];
34}
35
36MINLINE void linearrgb_to_srgb_uchar3(unsigned char srgb[3], const float linear[3])
37{
38 float srgb_f[3];
39
40 linearrgb_to_srgb_v3_v3(srgb_f, linear);
41 unit_float_to_uchar_clamp_v3(srgb, srgb_f);
42}
43
44MINLINE void linearrgb_to_srgb_uchar4(unsigned char srgb[4], const float linear[4])
45{
46 float srgb_f[4];
47
48 linearrgb_to_srgb_v4(srgb_f, linear);
49 unit_float_to_uchar_clamp_v4(srgb, srgb_f);
50}
51
52/* predivide versions to work on associated/pre-multiplied alpha. if this should
53 * be done or not depends on the background the image will be composited over,
54 * ideally you would never do color space conversion on an image with alpha
55 * because it is ill defined */
56
57MINLINE void srgb_to_linearrgb_predivide_v4(float linear[4], const float srgb[4])
58{
59 float alpha, inv_alpha;
60
61 if (srgb[3] == 1.0f || srgb[3] == 0.0f) {
62 alpha = 1.0f;
63 inv_alpha = 1.0f;
64 }
65 else {
66 alpha = srgb[3];
67 inv_alpha = 1.0f / alpha;
68 }
69
70 linear[0] = srgb[0] * inv_alpha;
71 linear[1] = srgb[1] * inv_alpha;
72 linear[2] = srgb[2] * inv_alpha;
73 linear[3] = srgb[3];
74 srgb_to_linearrgb_v3_v3(linear, linear);
75 linear[0] *= alpha;
76 linear[1] *= alpha;
77 linear[2] *= alpha;
78}
79
80MINLINE void linearrgb_to_srgb_predivide_v4(float srgb[4], const float linear[4])
81{
82 float alpha, inv_alpha;
83
84 if (linear[3] == 1.0f || linear[3] == 0.0f) {
85 alpha = 1.0f;
86 inv_alpha = 1.0f;
87 }
88 else {
89 alpha = linear[3];
90 inv_alpha = 1.0f / alpha;
91 }
92
93 srgb[0] = linear[0] * inv_alpha;
94 srgb[1] = linear[1] * inv_alpha;
95 srgb[2] = linear[2] * inv_alpha;
96 srgb[3] = linear[3];
97 linearrgb_to_srgb_v3_v3(srgb, srgb);
98 srgb[0] *= alpha;
99 srgb[1] *= alpha;
100 srgb[2] *= alpha;
101}
102
103/* LUT accelerated conversions */
104
105extern float BLI_color_from_srgb_table[256];
106extern unsigned short BLI_color_to_srgb_table[0x10000];
107
108MINLINE unsigned short to_srgb_table_lookup(const float f)
109{
110
111 union {
112 float f;
113 unsigned short us[2];
114 } tmp;
115 tmp.f = f;
116# ifdef __BIG_ENDIAN__
117 return BLI_color_to_srgb_table[tmp.us[0]];
118# else
119 return BLI_color_to_srgb_table[tmp.us[1]];
120# endif
121}
122
123MINLINE void linearrgb_to_srgb_ushort4(unsigned short srgb[4], const float linear[4])
124{
125 srgb[0] = to_srgb_table_lookup(linear[0]);
126 srgb[1] = to_srgb_table_lookup(linear[1]);
127 srgb[2] = to_srgb_table_lookup(linear[2]);
128 srgb[3] = unit_float_to_ushort_clamp(linear[3]);
129}
130
131MINLINE void srgb_to_linearrgb_uchar4(float linear[4], const unsigned char srgb[4])
132{
133 linear[0] = BLI_color_from_srgb_table[srgb[0]];
134 linear[1] = BLI_color_from_srgb_table[srgb[1]];
135 linear[2] = BLI_color_from_srgb_table[srgb[2]];
136 linear[3] = srgb[3] * (1.0f / 255.0f);
137}
138
139MINLINE void srgb_to_linearrgb_uchar4_predivide(float linear[4], const unsigned char srgb[4])
140{
141 float fsrgb[4];
142 int i;
143
144 if (srgb[3] == 255 || srgb[3] == 0) {
145 srgb_to_linearrgb_uchar4(linear, srgb);
146 return;
147 }
148
149 for (i = 0; i < 4; i++) {
150 fsrgb[i] = srgb[i] * (1.0f / 255.0f);
151 }
152
153 srgb_to_linearrgb_predivide_v4(linear, fsrgb);
154}
155
157 uchar col[4], const uchar r, const uchar g, const uchar b, const uchar a)
158{
159 col[0] = r;
160 col[1] = g;
161 col[2] = b;
162 col[3] = a;
163}
164
166 float col[4], const float r, const float g, const float b, const float a)
167{
168 col[0] = r;
169 col[1] = g;
170 col[2] = b;
171 col[3] = a;
172}
173
175 uchar col[4], const uchar r, const uchar g, const uchar b, const uchar a)
176{
177 if (col[3] == 0) {
178 col[0] = r;
179 col[1] = g;
180 col[2] = b;
181 col[3] = a;
182 }
183}
184
185MINLINE void cpack_cpy_3ub(unsigned char r_col[3], const unsigned int pack)
186{
187 r_col[0] = ((pack) >> 0) & 0xFF;
188 r_col[1] = ((pack) >> 8) & 0xFF;
189 r_col[2] = ((pack) >> 16) & 0xFF;
190}
191
192/* -------------------------------------------------------------------- */
203MINLINE float rgb_to_grayscale(const float rgb[3])
204{
205 return (0.2126f * rgb[0]) + (0.7152f * rgb[1]) + (0.0722f * rgb[2]);
206}
207
208MINLINE unsigned char rgb_to_grayscale_byte(const unsigned char rgb[3])
209{
210 return (unsigned char)(((54 * (unsigned short)rgb[0]) + (182 * (unsigned short)rgb[1]) +
211 (19 * (unsigned short)rgb[2])) /
212 255);
213}
214
217MINLINE int compare_rgb_uchar(const unsigned char col_a[3],
218 const unsigned char col_b[3],
219 const int limit)
220{
221 const int r = (int)col_a[0] - (int)col_b[0];
222 if (abs(r) < limit) {
223 const int g = (int)col_a[1] - (int)col_b[1];
224 if (abs(g) < limit) {
225 const int b = (int)col_a[2] - (int)col_b[2];
226 if (abs(b) < limit) {
227 return 1;
228 }
229 }
230 }
231
232 return 0;
233}
234
235MINLINE float dither_random_value(float s, float t)
236{
237 /* Using a triangle distribution which gives a more final uniform noise.
238 * See Banding in Games:A Noisy Rant(revision 5) Mikkel Gjøl, Playdead (slide 27) */
239
240 /* Uniform noise in [0..1[ range, using common GLSL hash function.
241 * https://stackoverflow.com/questions/12964279/whats-the-origin-of-this-glsl-rand-one-liner. */
242 float hash0 = sinf(s * 12.9898f + t * 78.233f) * 43758.5453f;
243 float hash1 = sinf(s * 19.9898f + t * 119.233f) * 43798.5453f;
244 hash0 -= floorf(hash0);
245 hash1 -= floorf(hash1);
246 /* Convert uniform distribution into triangle-shaped distribution. */
247 return hash0 + hash1 - 0.5f;
248}
249
251 unsigned char b[3], const float f[3], float dither, float s, float t)
252{
253 float dither_value = dither_random_value(s, t) * 0.0033f * dither;
254
255 b[0] = unit_float_to_uchar_clamp(dither_value + f[0]);
256 b[1] = unit_float_to_uchar_clamp(dither_value + f[1]);
257 b[2] = unit_float_to_uchar_clamp(dither_value + f[2]);
258}
259
260/**************** Alpha Transformations *****************/
261
262MINLINE void premul_to_straight_v4_v4(float straight[4], const float premul[4])
263{
264 if (premul[3] == 0.0f || premul[3] == 1.0f) {
265 straight[0] = premul[0];
266 straight[1] = premul[1];
267 straight[2] = premul[2];
268 straight[3] = premul[3];
269 }
270 else {
271 const float alpha_inv = 1.0f / premul[3];
272 straight[0] = premul[0] * alpha_inv;
273 straight[1] = premul[1] * alpha_inv;
274 straight[2] = premul[2] * alpha_inv;
275 straight[3] = premul[3];
276 }
277}
278
279MINLINE void premul_to_straight_v4(float color[4])
280{
281 premul_to_straight_v4_v4(color, color);
282}
283
284MINLINE void straight_to_premul_v4_v4(float premul[4], const float straight[4])
285{
286 const float alpha = straight[3];
287 premul[0] = straight[0] * alpha;
288 premul[1] = straight[1] * alpha;
289 premul[2] = straight[2] * alpha;
290 premul[3] = straight[3];
291}
292
293MINLINE void straight_to_premul_v4(float color[4])
294{
295 straight_to_premul_v4_v4(color, color);
296}
297
298MINLINE void straight_uchar_to_premul_float(float result[4], const unsigned char color[4])
299{
300 const float alpha = color[3] * (1.0f / 255.0f);
301 const float fac = alpha * (1.0f / 255.0f);
302
303 result[0] = color[0] * fac;
304 result[1] = color[1] * fac;
305 result[2] = color[2] * fac;
306 result[3] = alpha;
307}
308
309MINLINE void premul_float_to_straight_uchar(unsigned char *result, const float color[4])
310{
311 if (color[3] == 0.0f || color[3] == 1.0f) {
312 result[0] = unit_float_to_uchar_clamp(color[0]);
313 result[1] = unit_float_to_uchar_clamp(color[1]);
314 result[2] = unit_float_to_uchar_clamp(color[2]);
315 result[3] = unit_float_to_uchar_clamp(color[3]);
316 }
317 else {
318 const float alpha_inv = 1.0f / color[3];
319
320 /* hopefully this would be optimized */
321 result[0] = unit_float_to_uchar_clamp(color[0] * alpha_inv);
322 result[1] = unit_float_to_uchar_clamp(color[1] * alpha_inv);
323 result[2] = unit_float_to_uchar_clamp(color[2] * alpha_inv);
324 result[3] = unit_float_to_uchar_clamp(color[3]);
325 }
326}
327
328#endif /* !__MATH_COLOR_INLINE_C__ */
329
330#ifdef __cplusplus
331}
332#endif
void linearrgb_to_srgb_v3_v3(float srgb[3], const float linear[3])
void srgb_to_linearrgb_v3_v3(float linear[3], const float srgb[3])
#define MINLINE
unsigned char uchar
local_group_size(16, 16) .push_constant(Type b
#define sinf(x)
#define floorf(x)
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
uint col
#define unit_float_to_ushort_clamp(val)
#define unit_float_to_uchar_clamp(val)
#define unit_float_to_uchar_clamp_v4(v1, v2)
#define unit_float_to_uchar_clamp_v3(v1, v2)
MINLINE void straight_to_premul_v4_v4(float premul[4], const float straight[4])
MINLINE void srgb_to_linearrgb_uchar4_predivide(float linear[4], const unsigned char srgb[4])
MINLINE void rgba_uchar_args_set(uchar col[4], const uchar r, const uchar g, const uchar b, const uchar a)
MINLINE unsigned char rgb_to_grayscale_byte(const unsigned char rgb[3])
MINLINE void straight_uchar_to_premul_float(float result[4], const unsigned char color[4])
MINLINE void premul_to_straight_v4(float color[4])
unsigned short BLI_color_to_srgb_table[0x10000]
MINLINE void straight_to_premul_v4(float color[4])
MINLINE void rgba_float_args_set(float col[4], const float r, const float g, const float b, const float a)
MINLINE void linearrgb_to_srgb_ushort4(unsigned short srgb[4], const float linear[4])
MINLINE void cpack_cpy_3ub(unsigned char r_col[3], const unsigned int pack)
MINLINE float rgb_to_grayscale(const float rgb[3])
MINLINE void linearrgb_to_srgb_predivide_v4(float srgb[4], const float linear[4])
MINLINE void srgb_to_linearrgb_uchar4(float linear[4], const unsigned char srgb[4])
MINLINE int compare_rgb_uchar(const unsigned char col_a[3], const unsigned char col_b[3], const int limit)
MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4])
MINLINE void float_to_byte_dither_v3(unsigned char b[3], const float f[3], float dither, float s, float t)
MINLINE void premul_to_straight_v4_v4(float straight[4], const float premul[4])
MINLINE void linearrgb_to_srgb_uchar4(unsigned char srgb[4], const float linear[4])
MINLINE void rgba_uchar_args_test_set(uchar col[4], const uchar r, const uchar g, const uchar b, const uchar a)
float BLI_color_from_srgb_table[256]
MINLINE unsigned short to_srgb_table_lookup(const float f)
MINLINE void linearrgb_to_srgb_v4(float srgb[4], const float linear[4])
MINLINE void linearrgb_to_srgb_uchar3(unsigned char srgb[3], const float linear[3])
MINLINE void srgb_to_linearrgb_predivide_v4(float linear[4], const float srgb[4])
MINLINE float dither_random_value(float s, float t)
MINLINE void premul_float_to_straight_uchar(unsigned char *result, const float color[4])
ccl_device_inline int abs(int x)
Definition util/math.h:120