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
8
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/* -------------------------------------------------------------------- */
202
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
216
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
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
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) {
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);
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
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a color
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)
ushort BLI_color_to_srgb_table[0x10000]
float BLI_color_from_srgb_table[256]
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])
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)
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