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