Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
src/iop/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
21#ifndef DT_IOP_NOISE_GENERATOR_H
22#define DT_IOP_NOISE_GENERATOR_H
23
24#include "math/openmp_maths.h"
25
26
28{
29 DT_NOISE_UNIFORM = 0, // $DESCRIPTION: "uniform"
30 DT_NOISE_GAUSSIAN = 1, // $DESCRIPTION: "gaussian"
31 DT_NOISE_POISSONIAN = 2 // $DESCRIPTION: "poissonian"
33
34
37{
38 // fast random number generator
39 // reference : http://prng.di.unimi.it/splitmix64.c
40 uint64_t result = (seed ^ (seed >> 33)) * 0x62a9d9ed799705f5ul;
41 result = (result ^ (result >> 28)) * 0xcb24d0a5c88c35b3ul;
42 return (uint32_t)(result >> 32);
43}
44
45
47static inline uint32_t rol32(const uint32_t x, const int k)
48{
49 return (x << k) | (x >> (32 - k));
50}
51
52
55{
56 // fast random number generator
57 // reference : http://prng.di.unimi.it/
58 const unsigned int result = state[0] + state[3];
59 const unsigned int t = state[1] << 9;
60
61 state[2] ^= state[0];
62 state[3] ^= state[1];
63 state[1] ^= state[2];
64 state[0] ^= state[3];
65
66 state[2] ^= t;
67 state[3] = rol32(state[3], 11);
68
69 return (float)(result >> 8) * 0x1.0p-24f; // take the first 24 bits and put them in mantissa
70}
71
72
74static inline float uniform_noise(const float mu, const float sigma, uint32_t state[4])
75{
76 return mu + 2.0f * (xoshiro128plus(state) - 0.5f) * sigma;
77}
78
79
81static inline float gaussian_noise(const float mu, const float sigma, const int flip, uint32_t state[4])
82{
83 // Create gaussian noise centered in mu of standard deviation sigma
84 // state should be initialized with xoshiro256_init() before calling and private in thread
85 // flip needs to be flipped every next iteration
86 // reference : https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform
87
88 const float u1 = fmaxf(xoshiro128plus(state), FLT_MIN);
89 const float u2 = xoshiro128plus(state);
90 const float noise = (flip) ? sqrtf(-2.0f * logf(u1)) * cosf(2.f * M_PI * u2) :
91 sqrtf(-2.0f * logf(u1)) * sinf(2.f * M_PI * u2);
92 return noise * sigma + mu;
93}
94
95
97static inline float poisson_noise(const float mu, const float sigma, const int flip, uint32_t state[4])
98{
99 // create poisson noise - It's just gaussian noise with Anscombe transform applied
100 const float u1 = fmaxf(xoshiro128plus(state), FLT_MIN);
101 const float u2 = xoshiro128plus(state);
102 const float noise = (flip) ? sqrtf(-2.0f * logf(u1)) * cosf(2.f * M_PI * u2) :
103 sqrtf(-2.0f * logf(u1)) * sinf(2.f * M_PI * u2);
104 const float r = noise * sigma + 2.0f * sqrtf(fmaxf(mu + 3.f / 8.f, 0.0f));
105 return (r * r - sigma * sigma) / 4.f - 3.f / 8.f;
106}
107
108
111 const float mu, const float param, const int flip, uint32_t state[4])
112{
113 // scalar version
114
115 switch(distribution)
116 {
117 case(DT_NOISE_UNIFORM):
118 default:
119 return uniform_noise(mu, param, state);
120
121 case(DT_NOISE_GAUSSIAN):
122 return gaussian_noise(mu, param, flip, state);
123
125 return poisson_noise(mu, param, flip, state);
126 }
127}
128
131 uint32_t state[4], dt_aligned_pixel_t out)
132{
134
136 out[c] = mu[c] + 2.0f * (noise[c] - 0.5f) * sigma[c];
137}
138
139
142 const int flip[4], uint32_t state[4], dt_aligned_pixel_t out)
143{
144 // Create gaussian noise centered in mu of standard deviation sigma
145 // state should be initialized with xoshiro256_init() before calling and private in thread
146 // flip needs to be flipped every next iteration
147 // reference : https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform
148
149 dt_aligned_pixel_t u1 = { 0.f };
150 dt_aligned_pixel_t u2 = { 0.f };
151
152
153 for(size_t c = 0; c < 3; c++)
155
156
157 for(size_t c = 0; c < 3; c++)
158 u2[c] = xoshiro128plus(state);
159
160 dt_aligned_pixel_t noise = { 0.f };
161
163 {
164 noise[c] = (flip[c]) ? sqrtf(-2.0f * logf(u1[c])) * cosf(2.f * M_PI * u2[c]) :
165 sqrtf(-2.0f * logf(u1[c])) * sinf(2.f * M_PI * u2[c]);
166 }
167
169 out[c] = noise[c] * sigma[c] + mu[c];
170}
171
172
175 uint32_t state[4], dt_aligned_pixel_t out)
176{
177 // create poissonian noise - It's just gaussian noise with Anscombe transform applied
178 dt_aligned_pixel_t u1 = { 0.f };
179 dt_aligned_pixel_t u2 = { 0.f };
180
181 for(size_t c = 0; c < 3; c++)
182 {
185 }
186
187 dt_aligned_pixel_t noise = { 0.f };
188
190 {
191 noise[c] = (flip[c]) ? sqrtf(-2.0f * logf(u1[c])) * cosf(2.f * M_PI * u2[c]) :
192 sqrtf(-2.0f * logf(u1[c])) * sinf(2.f * M_PI * u2[c]);
193 }
194
195 // now we have gaussian noise, then apply Anscombe transform to get poissonian one
196 dt_aligned_pixel_t r = { 0.f };
197
199 {
200 r[c] = noise[c] * sigma[c] + 2.0f * sqrtf(fmaxf(mu[c] + 3.f / 8.f, 0.0f));
201 out[c] = (r[c] * r[c] - sigma[c] * sigma[c]) / 4.f - 3.f / 8.f;
202 }
203}
204
205
209 const int flip[4], uint32_t state[4], dt_aligned_pixel_t out)
210{
211 // vector version
212
213 switch(distribution)
214 {
215 case(DT_NOISE_UNIFORM):
216 default:
217 {
219 break;
220 }
221
222 case(DT_NOISE_GAUSSIAN):
223 {
225 break;
226 }
227
229 {
231 break;
232 }
233 }
234}
235
236#endif // DT_IOP_NOISE_GENERATOR_H
237
238// clang-format off
239// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
240// vim: shiftwidth=2 expandtab tabstop=2 cindent
241// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
242// clang-format on
243
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
static const float x
const int t
const dt_colormatrix_t dt_aligned_pixel_t out
static float4 dt_noise_generator_simd(const dt_noise_distribution_t distribution, const float4 mu, const float4 param, uint state[4])
static float4 uniform_noise_simd(const float4 mu, const float4 sigma, uint state[4])
static float4 poisson_noise_simd(const float4 mu, const float4 sigma, uint state[4])
static float4 gaussian_noise_simd(const float4 mu, const float4 sigma, uint state[4])
float *const restrict const size_t k
#define M_PI
Definition math.h:47
#define __OMP_DECLARE_SIMD__(...)
Definition openmp.h:65
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
Definition simd.h:53
#define for_each_channel(_var,...)
Definition simd.h:87
const float uint32_t state[4]
dt_noise_distribution_t
@ DT_NOISE_GAUSSIAN
@ DT_NOISE_POISSONIAN
const float sigma
const float const float param
return noise *sigma mu
const float u2
const float r
const float const int flip
const float noise
static uint32_t rol32(const uint32_t x, const int k)
static float xoshiro128plus(uint32_t state[4])
static uint32_t splitmix32(const uint64_t seed)
unsigned __int64 uint64_t
Definition strptime.c:75