Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
src/develop/noise_generator.h
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2020 - darktable developers.
4
5 darktable is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 darktable is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with darktable. If not, see <http://www.gnu.org/licenses/>.
17*/
18
20
21
23{
24 DT_NOISE_UNIFORM = 0, // $DESCRIPTION: "uniform"
25 DT_NOISE_GAUSSIAN = 1, // $DESCRIPTION: "gaussian"
26 DT_NOISE_POISSONIAN = 2 // $DESCRIPTION: "poissonian"
28
29
30#ifdef _OPENMP
31#pragma omp declare simd
32#endif
33static inline uint32_t splitmix32(const uint64_t seed)
34{
35 // fast random number generator
36 // reference : http://prng.di.unimi.it/splitmix64.c
37 uint64_t result = (seed ^ (seed >> 33)) * 0x62a9d9ed799705f5ul;
38 result = (result ^ (result >> 28)) * 0xcb24d0a5c88c35b3ul;
39 return (uint32_t)(result >> 32);
40}
41
42
43#ifdef _OPENMP
44#pragma omp declare simd uniform(k)
45#endif
46static inline uint32_t rol32(const uint32_t x, const int k)
47{
48 return (x << k) | (x >> (32 - k));
49}
50
51
52#ifdef _OPENMP
53#pragma omp declare simd aligned(state:64)
54#endif
55static inline float xoshiro128plus(uint32_t state[4])
56{
57 // fast random number generator
58 // reference : http://prng.di.unimi.it/
59 const unsigned int result = state[0] + state[3];
60 const unsigned int t = state[1] << 9;
61
62 state[2] ^= state[0];
63 state[3] ^= state[1];
64 state[1] ^= state[2];
65 state[0] ^= state[3];
66
67 state[2] ^= t;
68 state[3] = rol32(state[3], 11);
69
70 return (float)(result >> 8) * 0x1.0p-24f; // take the first 24 bits and put them in mantissa
71}
72
73
74#ifdef _OPENMP
75#pragma omp declare simd uniform(sigma) aligned(state:64)
76#endif
77static inline float uniform_noise(const float mu, const float sigma, uint32_t state[4])
78{
79 return mu + 2.0f * (xoshiro128plus(state) - 0.5f) * sigma;
80}
81
82
83#ifdef _OPENMP
84#pragma omp declare simd uniform(sigma) aligned(state:64)
85#endif
86static inline float gaussian_noise(const float mu, const float sigma, const int flip, uint32_t state[4])
87{
88 // Create gaussian noise centered in mu of standard deviation sigma
89 // state should be initialized with xoshiro256_init() before calling and private in thread
90 // flip needs to be flipped every next iteration
91 // reference : https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform
92
93 const float u1 = fmaxf(xoshiro128plus(state), FLT_MIN);
94 const float u2 = xoshiro128plus(state);
95 const float noise = (flip) ? sqrtf(-2.0f * logf(u1)) * cosf(2.f * M_PI * u2) :
96 sqrtf(-2.0f * logf(u1)) * sinf(2.f * M_PI * u2);
97 return noise * sigma + mu;
98}
99
100
101#ifdef _OPENMP
102#pragma omp declare simd uniform(sigma) aligned(state:64)
103#endif
104static inline float poisson_noise(const float mu, const float sigma, const int flip, uint32_t state[4])
105{
106 // create poisson noise - It's just gaussian noise with Anscombe transform applied
107 const float u1 = fmaxf(xoshiro128plus(state), FLT_MIN);
108 const float u2 = xoshiro128plus(state);
109 const float noise = (flip) ? sqrtf(-2.0f * logf(u1)) * cosf(2.f * M_PI * u2) :
110 sqrtf(-2.0f * logf(u1)) * sinf(2.f * M_PI * u2);
111 const float r = noise * sigma + 2.0f * sqrtf(fmaxf(mu + 3.f / 8.f, 0.0f));
112 return (r * r - sigma * sigma) / 4.f - 3.f / 8.f;
113}
114
115
116#ifdef _OPENMP
117#pragma omp declare simd uniform(distribution, param) aligned(state:64)
118#endif
119static inline float dt_noise_generator(const dt_noise_distribution_t distribution,
120 const float mu, const float param, const int flip, uint32_t state[4])
121{
122 // scalar version
123
124 switch(distribution)
125 {
126 case(DT_NOISE_UNIFORM):
127 default:
128 return uniform_noise(mu, param, state);
129
130 case(DT_NOISE_GAUSSIAN):
131 return gaussian_noise(mu, param, flip, state);
132
134 return poisson_noise(mu, param, flip, state);
135 }
136}
137
138#ifdef _OPENMP
139#pragma omp declare simd uniform(sigma) aligned(state:64) aligned(mu, sigma, out:16)
140#endif
141static inline void uniform_noise_simd(const dt_aligned_pixel_t mu, const dt_aligned_pixel_t sigma,
142 uint32_t state[4], dt_aligned_pixel_t out)
143{
144 const dt_aligned_pixel_t noise = { xoshiro128plus(state), xoshiro128plus(state), xoshiro128plus(state) };
145
147 out[c] = mu[c] + 2.0f * (noise[c] - 0.5f) * sigma[c];
148}
149
150
151#ifdef _OPENMP
152#pragma omp declare simd uniform(sigma) aligned(state:64) aligned(mu, sigma, flip, out:16)
153#endif
154static inline void gaussian_noise_simd(const dt_aligned_pixel_t mu, const dt_aligned_pixel_t sigma,
155 const int flip[4], uint32_t state[4], dt_aligned_pixel_t out)
156{
157 // Create gaussian noise centered in mu of standard deviation sigma
158 // state should be initialized with xoshiro256_init() before calling and private in thread
159 // flip needs to be flipped every next iteration
160 // reference : https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform
161
162 dt_aligned_pixel_t u1 = { 0.f };
163 dt_aligned_pixel_t u2 = { 0.f };
164
165 #pragma unroll
166 for(size_t c = 0; c < 3; c++)
167 u1[c] = fmaxf(xoshiro128plus(state), FLT_MIN);
168
169 #pragma unroll
170 for(size_t c = 0; c < 3; c++)
171 u2[c] = xoshiro128plus(state);
172
173 dt_aligned_pixel_t noise = { 0.f };
174
176 {
177 noise[c] = (flip[c]) ? sqrtf(-2.0f * logf(u1[c])) * cosf(2.f * M_PI * u2[c]) :
178 sqrtf(-2.0f * logf(u1[c])) * sinf(2.f * M_PI * u2[c]);
179 }
180
182 out[c] = noise[c] * sigma[c] + mu[c];
183}
184
185
186#ifdef _OPENMP
187#pragma omp declare simd uniform(sigma) aligned(state:64) aligned(mu, sigma, flip, out:16)
188#endif
189static inline void poisson_noise_simd(const dt_aligned_pixel_t mu, const dt_aligned_pixel_t sigma, const int flip[4],
190 uint32_t state[4], dt_aligned_pixel_t out)
191{
192 // create poissonian noise - It's just gaussian noise with Anscombe transform applied
193 dt_aligned_pixel_t u1 = { 0.f };
194 dt_aligned_pixel_t u2 = { 0.f };
195
196 #pragma unroll
197 for(size_t c = 0; c < 3; c++)
198 {
199 u1[c] = fmaxf(xoshiro128plus(state), FLT_MIN);
200 u2[c] = xoshiro128plus(state);
201 }
202
203 dt_aligned_pixel_t noise = { 0.f };
204
206 {
207 noise[c] = (flip[c]) ? sqrtf(-2.0f * logf(u1[c])) * cosf(2.f * M_PI * u2[c]) :
208 sqrtf(-2.0f * logf(u1[c])) * sinf(2.f * M_PI * u2[c]);
209 }
210
211 // now we have gaussian noise, then apply Anscombe transform to get poissonian one
212 dt_aligned_pixel_t r = { 0.f };
213
214 #pragma unroll
216 {
217 r[c] = noise[c] * sigma[c] + 2.0f * sqrtf(fmaxf(mu[c] + 3.f / 8.f, 0.0f));
218 out[c] = (r[c] * r[c] - sigma[c] * sigma[c]) / 4.f - 3.f / 8.f;
219 }
220}
221
222
223#ifdef _OPENMP
224#pragma omp declare simd uniform(distribution, param) aligned(state:64) aligned(mu, param, flip, out:16)
225#endif
226static inline void dt_noise_generator_simd(const dt_noise_distribution_t distribution,
227 const dt_aligned_pixel_t mu, const dt_aligned_pixel_t param,
228 const int flip[4], uint32_t state[4], dt_aligned_pixel_t out)
229{
230 // vector version
231
232 switch(distribution)
233 {
234 case(DT_NOISE_UNIFORM):
235 default:
236 {
237 uniform_noise_simd(mu, param, state, out);
238 break;
239 }
240
241 case(DT_NOISE_GAUSSIAN):
242 {
243 gaussian_noise_simd(mu, param, flip, state, out);
244 break;
245 }
246
248 {
249 poisson_noise_simd(mu, param, flip, state, out);
250 break;
251 }
252 }
253}
254// clang-format off
255// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
256// vim: shiftwidth=2 expandtab tabstop=2 cindent
257// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
258// clang-format on
259
#define for_each_channel(_var,...)
Definition darktable.h:411
dt_noise_distribution_t
Definition data/kernels/noise_generator.h:23
static void flip(float *x, float *y)
Definition lightroom.c:1035
#define M_PI
Definition math.h:37
dt_noise_distribution_t
Definition src/develop/noise_generator.h:23
@ DT_NOISE_GAUSSIAN
Definition src/develop/noise_generator.h:25
@ DT_NOISE_POISSONIAN
Definition src/develop/noise_generator.h:26
@ DT_NOISE_UNIFORM
Definition src/develop/noise_generator.h:24
static void gaussian_noise_simd(const dt_aligned_pixel_t mu, const dt_aligned_pixel_t sigma, const int flip[4], uint32_t state[4], dt_aligned_pixel_t out)
Definition src/develop/noise_generator.h:154
static float dt_noise_generator(const dt_noise_distribution_t distribution, const float mu, const float param, const int flip, uint32_t state[4])
Definition src/develop/noise_generator.h:119
static float poisson_noise(const float mu, const float sigma, const int flip, uint32_t state[4])
Definition src/develop/noise_generator.h:104
static void dt_noise_generator_simd(const dt_noise_distribution_t distribution, const dt_aligned_pixel_t mu, const dt_aligned_pixel_t param, const int flip[4], uint32_t state[4], dt_aligned_pixel_t out)
Definition src/develop/noise_generator.h:226
static float uniform_noise(const float mu, const float sigma, uint32_t state[4])
Definition src/develop/noise_generator.h:77
static void poisson_noise_simd(const dt_aligned_pixel_t mu, const dt_aligned_pixel_t sigma, const int flip[4], uint32_t state[4], dt_aligned_pixel_t out)
Definition src/develop/noise_generator.h:189
static float gaussian_noise(const float mu, const float sigma, const int flip, uint32_t state[4])
Definition src/develop/noise_generator.h:86
static uint32_t rol32(const uint32_t x, const int k)
Definition src/develop/noise_generator.h:46
static float xoshiro128plus(uint32_t state[4])
Definition src/develop/noise_generator.h:55
static void uniform_noise_simd(const dt_aligned_pixel_t mu, const dt_aligned_pixel_t sigma, uint32_t state[4], dt_aligned_pixel_t out)
Definition src/develop/noise_generator.h:141
static uint32_t splitmix32(const uint64_t seed)
Definition src/develop/noise_generator.h:33
unsigned __int64 uint64_t
Definition strptime.c:71