Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
grain.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2010 Alexandre Prokoudine.
4 Copyright (C) 2010 Bruce Guenter.
5 Copyright (C) 2010-2012 Henrik Andersson.
6 Copyright (C) 2010-2013, 2016 johannes hanika.
7 Copyright (C) 2010 José Carlos García Sogo.
8 Copyright (C) 2010-2011, 2013 Pascal de Bruijn.
9 Copyright (C) 2010 Stuart Henderson.
10 Copyright (C) 2011 Antony Dovgal.
11 Copyright (C) 2011 Olivier Tribout.
12 Copyright (C) 2011 Robert Bieber.
13 Copyright (C) 2011-2014, 2016, 2019 Tobias Ellinghaus.
14 Copyright (C) 2012 Richard Wonka.
15 Copyright (C) 2012, 2014 Ulrich Pegelow.
16 Copyright (C) 2013, 2018-2020, 2022 Pascal Obry.
17 Copyright (C) 2013-2016 Roman Lebedev.
18 Copyright (C) 2013 Simon Spannagel.
19 Copyright (C) 2013 Thomas Pryds.
20 Copyright (C) 2015 Pedro Côrte-Real.
21 Copyright (C) 2016-2017 Andrea Volpato.
22 Copyright (C) 2016 arctee.
23 Copyright (C) 2017 Heiko Bauke.
24 Copyright (C) 2018-2020, 2023, 2025-2026 Aurélien PIERRE.
25 Copyright (C) 2018 Edgardo Hoszowski.
26 Copyright (C) 2018 Maurizio Paglia.
27 Copyright (C) 2018 rawfiner.
28 Copyright (C) 2019 Andreas Schneider.
29 Copyright (C) 2019 Diederik ter Rahe.
30 Copyright (C) 2020 Aldric Renaudin.
31 Copyright (C) 2020, 2022 Diederik Ter Rahe.
32 Copyright (C) 2020 Ralf Brown.
33 Copyright (C) 2021 Chris Elston.
34 Copyright (C) 2022 Martin Bařinka.
35 Copyright (C) 2022 Philipp Lutz.
36
37 darktable is free software: you can redistribute it and/or modify
38 it under the terms of the GNU General Public License as published by
39 the Free Software Foundation, either version 3 of the License, or
40 (at your option) any later version.
41
42 darktable is distributed in the hope that it will be useful,
43 but WITHOUT ANY WARRANTY; without even the implied warranty of
44 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45 GNU General Public License for more details.
46
47 You should have received a copy of the GNU General Public License
48 along with darktable. If not, see <http://www.gnu.org/licenses/>.
49*/
50#ifdef HAVE_CONFIG_H
51#include "config.h"
52#endif
53#include <assert.h>
54#include <stdlib.h>
55#include <string.h>
56
57#include "bauhaus/bauhaus.h"
58#include "common/math.h"
59#include "control/control.h"
60#include "develop/develop.h"
61#include "develop/imageop.h"
62#include "develop/imageop_gui.h"
63
64#include "gui/gtk.h"
65#include "iop/iop_api.h"
66#include <gtk/gtk.h>
67#include <inttypes.h>
68
69#define GRAIN_LIGHTNESS_STRENGTH_SCALE 0.15
70// (m_pi/2)/4 = half hue colorspan
71#define GRAIN_HUE_COLORRANGE 0.392699082
72#define GRAIN_HUE_STRENGTH_SCALE 0.25
73#define GRAIN_SATURATION_STRENGTH_SCALE 0.25
74#define GRAIN_RGB_STRENGTH_SCALE 0.25
75
76#define GRAIN_SCALE_FACTOR 213.2
77
78#define GRAIN_LUT_SIZE 128
79#define GRAIN_LUT_DELTA_MAX 2.0
80#define GRAIN_LUT_DELTA_MIN 0.0001
81#define GRAIN_LUT_PAPER_GAMMA 1.0
82
84
85
93
94typedef struct dt_iop_grain_params_t
95{
96 _dt_iop_grain_channel_t channel; // $DEFAULT: DT_GRAIN_CHANNEL_LIGHTNESS
97 float scale; /* $MIN: 20.0/GRAIN_SCALE_FACTOR
98 $MAX: 6400.0/GRAIN_SCALE_FACTOR
99 $DEFAULT: 1600.0/GRAIN_SCALE_FACTOR
100 $DESCRIPTION: "coarseness" */
101 float strength; // $MIN: 0.0 $MAX: 100.0 $DEFAULT: 25.0
102 float midtones_bias; // $MIN: 0.0 $MAX: 100.0 $DEFAULT: 100.0 $DESCRIPTION: "mid-tones bias"
104
106{
107 GtkWidget *scale, *strength, *midtones_bias; // scale, strength, midtones_bias
109
118
119
120int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version, void *new_params,
121 const int new_version)
122{
123 if(old_version == 1 && new_version == 2)
124 {
125 typedef struct dt_iop_grain_params_v1_t
126 {
128 float scale;
129 float strength;
130 } dt_iop_grain_params_v1_t;
131
132 const dt_iop_grain_params_v1_t *o = old_params;
133 dt_iop_grain_params_t *n = new_params;
134
135 n->channel = o->channel;
136 n->scale = o->scale;
137 n->strength = o->strength;
138 n->midtones_bias = 0.0; // it produces the same results as the old version
139
140 return 0;
141 }
142 return 1;
143}
144
145
146static int grad3[12][3] = { { 1, 1, 0 },
147 { -1, 1, 0 },
148 { 1, -1, 0 },
149 { -1, -1, 0 },
150 { 1, 0, 1 },
151 { -1, 0, 1 },
152 { 1, 0, -1 },
153 { -1, 0, -1 },
154 { 0, 1, 1 },
155 { 0, -1, 1 },
156 { 0, 1, -1 },
157 { 0, -1, -1 } };
158
159static int permutation[]
160 = { 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30,
161 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62,
162 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136,
163 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122,
164 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161,
165 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86,
166 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126,
167 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213,
168 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253,
169 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193,
170 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31,
171 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93,
172 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180 };
173
174static int perm[512];
176{
177 for(int i = 0; i < 512; i++) perm[i] = permutation[i & 255];
178}
179static inline __attribute__((always_inline)) double dot(int g[], double x, double y, double z)
180{
181 return g[0] * x + g[1] * y + g[2] * z;
182}
183
184#define FASTFLOOR(x) (x > 0 ? (int)(x) : (int)(x)-1)
185
186static inline __attribute__((always_inline)) double _simplex_noise(double xin, double yin, double zin)
187{
188 double n0, n1, n2, n3; // Noise contributions from the four corners
189 // Skew the input space to determine which simplex cell we're in
190 const double F3 = 1.0 / 3.0;
191 const double s = (xin + yin + zin) * F3; // Very nice and simple skew factor for 3D
192 const int i = FASTFLOOR(xin + s);
193 const int j = FASTFLOOR(yin + s);
194 const int k = FASTFLOOR(zin + s);
195 const double G3 = 1.0 / 6.0; // Very nice and simple unskew factor, too
196 const double t = (i + j + k) * G3;
197 const double X0 = i - t; // Unskew the cell origin back to (x,y,z) space
198 const double Y0 = j - t;
199 const double Z0 = k - t;
200 const double x0 = xin - X0; // The x,y,z distances from the cell origin
201 const double y0 = yin - Y0;
202 const double z0 = zin - Z0;
203 // For the 3D case, the simplex shape is a slightly irregular tetrahedron.
204 // Determine which simplex we are in.
205 int i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords
206 int i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords
207 if(x0 >= y0)
208 {
209 if(y0 >= z0)
210 {
211 i1 = 1; // X Y Z order
212 j1 = 0;
213 k1 = 0;
214 i2 = 1;
215 j2 = 1;
216 k2 = 0;
217 }
218 else if(x0 >= z0)
219 {
220 i1 = 1; // X Z Y order
221 j1 = 0;
222 k1 = 0;
223 i2 = 1;
224 j2 = 0;
225 k2 = 1;
226 }
227 else
228 {
229 i1 = 0; // Z X Y order
230 j1 = 0;
231 k1 = 1;
232 i2 = 1;
233 j2 = 0;
234 k2 = 1;
235 }
236 }
237 else // x0<y0
238 {
239 if(y0 < z0)
240 {
241 i1 = 0; // Z Y X order
242 j1 = 0;
243 k1 = 1;
244 i2 = 0;
245 j2 = 1;
246 k2 = 1;
247 }
248 else if(x0 < z0)
249 {
250 i1 = 0; // Y Z X order
251 j1 = 1;
252 k1 = 0;
253 i2 = 0;
254 j2 = 1;
255 k2 = 1;
256 }
257 else
258 {
259 i1 = 0; // Y X Z order
260 j1 = 1;
261 k1 = 0;
262 i2 = 1;
263 j2 = 1;
264 k2 = 0;
265 }
266 }
267 // A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z),
268 // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
269 // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
270 // c = 1/6.
271 const double x1 = x0 - i1 + G3; // Offsets for second corner in (x,y,z) coords
272 const double y1 = y0 - j1 + G3;
273 const double z1 = z0 - k1 + G3;
274 const double x2 = x0 - i2 + 2.0 * G3; // Offsets for third corner in (x,y,z) coords
275 const double y2 = y0 - j2 + 2.0 * G3;
276 const double z2 = z0 - k2 + 2.0 * G3;
277 const double x3 = x0 - 1.0 + 3.0 * G3; // Offsets for last corner in (x,y,z) coords
278 const double y3 = y0 - 1.0 + 3.0 * G3;
279 const double z3 = z0 - 1.0 + 3.0 * G3;
280 // Work out the hashed gradient indices of the four simplex corners
281 const int ii = i & 255;
282 const int jj = j & 255;
283 const int kk = k & 255;
284 const int gi0 = perm[ii + perm[jj + perm[kk]]] % 12;
285 const int gi1 = perm[ii + i1 + perm[jj + j1 + perm[kk + k1]]] % 12;
286 const int gi2 = perm[ii + i2 + perm[jj + j2 + perm[kk + k2]]] % 12;
287 const int gi3 = perm[ii + 1 + perm[jj + 1 + perm[kk + 1]]] % 12;
288 // Calculate the contribution from the four corners
289 double t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0;
290 if(t0 < 0)
291 n0 = 0.0;
292 else
293 {
294 t0 *= t0;
295 n0 = t0 * t0 * dot(grad3[gi0], x0, y0, z0);
296 }
297 double t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1;
298 if(t1 < 0)
299 n1 = 0.0;
300 else
301 {
302 t1 *= t1;
303 n1 = t1 * t1 * dot(grad3[gi1], x1, y1, z1);
304 }
305 double t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2;
306 if(t2 < 0)
307 n2 = 0.0;
308 else
309 {
310 t2 *= t2;
311 n2 = t2 * t2 * dot(grad3[gi2], x2, y2, z2);
312 }
313 double t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3;
314 if(t3 < 0)
315 n3 = 0.0;
316 else
317 {
318 t3 *= t3;
319 n3 = t3 * t3 * dot(grad3[gi3], x3, y3, z3);
320 }
321 // Add contributions from each corner to get the final noise value.
322 // The result is scaled to stay just inside [-1,1]
323 return 32.0 * (n0 + n1 + n2 + n3);
324}
325
326#define PRIME_LEVELS 4
327// static uint64_t _low_primes[PRIME_LEVELS] ={ 12503,14029,15649, 11369 };
328// uint64_t _mid_primes[PRIME_LEVELS] ={ 784697,875783, 536461,639259};
329
330/*static double __value_noise(uint32_t level,uint32_t x,uint32_t y)
331{
332 //uint32_t lvl=level%PRIME_LEVELS;
333 uint32_t n = x + y * 57;
334 n = (n<<13) ^ n;
335 return ( 1.0 - (( (n * (n * n * 15731 + 789221) +1376312589) & 0x7fffffff) / 1073741824.0));
336}
337
338static inline __attribute__((always_inline)) double __value_smooth_noise(uint32_t level,double x,double y)
339{
340 double corners = ( __value_noise(level,x-1, y-1)+__value_noise(level,x+1, y-1)+__value_noise(level,x-1,
341y+1)+__value_noise(level,x+1, y+1) ) / 16;
342 double sides = ( __value_noise(level,x-1, y) +__value_noise(level,x+1, y) +__value_noise(level,x, y-1)
343+__value_noise(level,x, y+1) ) / 8;
344 double center = __value_noise(level,x, y) / 4;
345 return corners + sides + center;
346}
347
348static inline __attribute__((always_inline)) double __preline_cosine_interpolate(double a,double b,double x)
349{
350 double ft = x * 3.1415927;
351 double f = (1 - cos(ft)) * .5;
352 return a*(1-f) + b*f;
353}
354
355static inline __attribute__((always_inline)) double __value_interpolate(uint32_t level,double x,double y)
356{
357 double fx = x - (uint32_t)x;
358 double fy = y - (uint32_t)y;
359
360 double v1 = __value_smooth_noise(level,(uint32_t)x, (uint32_t)y);
361 double v2 = __value_smooth_noise(level,(uint32_t)x + 1, (uint32_t)y);
362 double v3 = __value_smooth_noise(level,(uint32_t)x, (uint32_t)y + 1);
363 double v4 = __value_smooth_noise(level,(uint32_t)x + 1, (uint32_t)y + 1);
364
365 double i1 = __preline_cosine_interpolate(v1 , v2 , fx);
366 double i2 = __preline_cosine_interpolate(v3 , v4 , fx);
367
368 return __preline_cosine_interpolate(i1 , i2 , fy);
369}
370__DT_CLONE_TARGETS__
371static double _perlin_2d_noise(double x,double y,uint32_t octaves,double persistance,double z)
372{
373 double f=1,a=1,total=0;
374
375 for(int o=0;o<octaves;o++) {
376 total+= (__value_interpolate(o,x*f/z,y*f/z)*a);
377 f=2*o;
378 a=persistance*o;
379 }
380 return total;
381}*/
382
384static double _simplex_2d_noise(double x, double y, uint32_t octaves, double persistance, double z)
385{
386 double total = 0;
387
388 // parametrization of octaves to match power spectrum of real grain scans
389 static double f[] = {0.4910, 0.9441, 1.7280};
390 static double a[] = {0.2340, 0.7850, 1.2150};
391
392 for(uint32_t o = 0; o < octaves; o++)
393 {
394 total += (_simplex_noise(x * f[o] / z, y * f[o] / z, o) * a[o]);
395 }
396 return total;
397}
398
399static float paper_resp(float exposure, float mb, float gp)
400{
401 const float delta = GRAIN_LUT_DELTA_MAX * expf((mb / 100.0f) * logf(GRAIN_LUT_DELTA_MIN));
402 const float density = (1.0f + 2.0f * delta) / (1.0f + expf( (4.0f * gp * (0.5f - exposure)) / (1.0f + 2.0f * delta) )) - delta;
403 return density;
404}
405
406static float paper_resp_inverse(float density, float mb, float gp)
407{
408 const float delta = GRAIN_LUT_DELTA_MAX * expf((mb / 100.0f) * logf(GRAIN_LUT_DELTA_MIN));
409 const float exposure = -logf((1.0f + 2.0f * delta) / (density + delta) - 1.0f) * (1.0f + 2.0f * delta) / (4.0f * gp) + 0.5f;
410 return exposure;
411}
412
413static void evaluate_grain_lut(float *grain_lut, const float mb)
414{
415 for(int i = 0; i < GRAIN_LUT_SIZE; i++)
416 {
417 for(int j = 0; j < GRAIN_LUT_SIZE; j++)
418 {
419 const float gu = (float)i / (GRAIN_LUT_SIZE - 1) - 0.5;
420 const float l = (float)j / (GRAIN_LUT_SIZE - 1);
421 grain_lut[j * GRAIN_LUT_SIZE + i] = 100.0f * (paper_resp(gu + paper_resp_inverse(l, mb, GRAIN_LUT_PAPER_GAMMA), mb, GRAIN_LUT_PAPER_GAMMA) - l);
422 }
423 }
424}
425
426static inline __attribute__((always_inline)) float dt_lut_lookup_2d_1c(const float *grain_lut, const float x, const float y)
427{
428 const float _x = CLAMPS((x + 0.5) * (GRAIN_LUT_SIZE - 1), 0, GRAIN_LUT_SIZE - 1);
429 const float _y = CLAMPS(y * (GRAIN_LUT_SIZE - 1), 0, GRAIN_LUT_SIZE - 1);
430
431 const int _x0 = _x < GRAIN_LUT_SIZE - 2 ? _x : GRAIN_LUT_SIZE - 2;
432 const int _y0 = _y < GRAIN_LUT_SIZE - 2 ? _y : GRAIN_LUT_SIZE - 2;
433
434 const int _x1 = _x0 + 1;
435 const int _y1 = _y0 + 1;
436
437 const float x_diff = _x - _x0;
438 const float y_diff = _y - _y0;
439
440 const float l00 = grain_lut[_y0 * GRAIN_LUT_SIZE + _x0];
441 const float l01 = grain_lut[_y0 * GRAIN_LUT_SIZE + _x1];
442 const float l10 = grain_lut[_y1 * GRAIN_LUT_SIZE + _x0];
443 const float l11 = grain_lut[_y1 * GRAIN_LUT_SIZE + _x1];
444
445 const float xy0 = (1.0 - y_diff) * l00 + l10 * y_diff;
446 const float xy1 = (1.0 - y_diff) * l01 + l11 * y_diff;
447 return xy0 * (1.0f - x_diff) + xy1 * x_diff;
448}
449
450
451const char *name()
452{
453 return _("grain");
454}
455
456const char **description(struct dt_iop_module_t *self)
457{
458 return dt_iop_set_description(self, _("simulate silver grains from film"),
459 _("creative"),
460 _("non-linear, Lab, display-referred"),
461 _("non-linear, Lab"),
462 _("non-linear, Lab, display-referred"));
463}
464
469
471{
472 return IOP_GROUP_EFFECTS;
473}
474
476{
477 return IOP_CS_LAB;
478}
479
482{
483 default_input_format(self, pipe, piece, dsc);
484 dsc->channels = 4;
485 dsc->datatype = TYPE_FLOAT;
486}
487
488// see: http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
489// this is the modified bernstein
491static unsigned int _hash_string(const char *s)
492{
493 unsigned int h = 0;
494 while(*s) h = 33 * h ^ *s++;
495 return h;
496}
497
499int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid,
500 void *const ovoid)
501{
502 const dt_iop_roi_t *const roi_out = &piece->roi_out;
504
505 unsigned int hash = _hash_string(pipe->dev->image_storage.filename) % (int)fmax(roi_out->width * 0.3, 1.0);
506
507 const int ch = 4;
508 // Apply grain to image
509 const double strength = (data->strength / 100.0);
510 const double octaves = 3;
511 // double zoom=1.0+(8*(data->scale/100.0));
512 const double wd = fminf(piece->buf_in.width, piece->buf_in.height);
513 const double zoom = (1.0 + 8 * data->scale / 100) / 800.0;
514 // in fastpipe mode, skip the downsampling for zoomed-out views
515 const int filter = fabs(roi_out->scale - 1.0f) > 0.01;
516 // filter width depends on world space (i.e. reverse wd norm and roi->scale, as well as buffer input to
517 // pixelpipe iscale)
518 const double filtermul = 1.f / (roi_out->scale * wd);
519 const float fib1 = 34.0, fib2 = 21.0;
520 const float fib1div2 = fib1 / fib2;
522 for(int j = 0; j < roi_out->height; j++)
523 {
524 float *in = ((float *)ivoid) + (size_t)roi_out->width * j * ch;
525 float *out = ((float *)ovoid) + (size_t)roi_out->width * j * ch;
526 const double wy = (roi_out->y + j) / roi_out->scale;
527 const double y = wy / wd;
528 // y: normalized to shorter side of image, so with pixel aspect = 1.
529
530 for(int i = 0; i < roi_out->width; i++)
531 {
532 // calculate x, y in a resolution independent way:
533 // wx,wy: worldspace in full image pixel coords:
534 const double wx = (roi_out->x + i) / roi_out->scale;
535 // x: normalized to shorter side of image, so with pixel aspect = 1.
536 const double x = wx / wd;
537 // double noise=_perlin_2d_noise(x, y, octaves,0.25, zoom)*1.5;
538 double noise = 0.0;
539 if(filter)
540 {
541 // if zoomed out a lot, use rank-1 lattice downsampling
542 for(int l = 0; l < fib2; l++)
543 {
544 float px = l / fib2, py = l * fib1div2;
545 py -= (int)py;
546 float dx = px * filtermul, dy = py * filtermul;
547 noise += (1.0 / fib2) * _simplex_2d_noise(x + dx + hash, y + dy, octaves, 1.0, zoom);
548 }
549 }
550 else
551 {
552 noise = _simplex_2d_noise(x + hash, y, octaves, 1.0, zoom);
553 }
554
555 out[0] = in[0] + dt_lut_lookup_2d_1c(data->grain_lut, (noise * strength) * GRAIN_LIGHTNESS_STRENGTH_SCALE, in[0] / 100.0f);
556 out[1] = in[1];
557 out[2] = in[2];
558 out[3] = in[3];
559
560 out += ch;
561 in += ch;
562 }
563 }
564 return 0;
565}
566
569{
572
573 d->channel = p->channel;
574 d->scale = p->scale;
575 d->strength = p->strength;
576 d->midtones_bias = p->midtones_bias;
577
578 evaluate_grain_lut(d->grain_lut, d->midtones_bias);
579}
580
582{
583 piece->data = dt_calloc_align(sizeof(dt_iop_grain_data_t));
584 piece->data_size = sizeof(dt_iop_grain_data_t);
585}
586
588{
589 dt_free_align(piece->data);
590 piece->data = NULL;
591}
592
594{
596}
597
598void gui_init(struct dt_iop_module_t *self)
599{
601
602 /* courseness */
603 g->scale = dt_bauhaus_slider_from_params(self, "scale");
606 dt_bauhaus_slider_set_format(g->scale, " ISO");
607 gtk_widget_set_tooltip_text(g->scale, _("the grain size (~ISO of the film)"));
608
609 g->strength = dt_bauhaus_slider_from_params(self, N_("strength"));
610 dt_bauhaus_slider_set_format(g->strength, "%");
611 gtk_widget_set_tooltip_text(g->strength, _("the strength of applied grain"));
612
613 g->midtones_bias = dt_bauhaus_slider_from_params(self, "midtones_bias");
614 dt_bauhaus_slider_set_format(g->midtones_bias, "%");
615 gtk_widget_set_tooltip_text(g->midtones_bias, _("amount of mid-tones bias from the photographic paper response modeling. the greater the bias, the more pronounced the fall off of the grain in shadows and highlights"));
616}
617
618// clang-format off
619// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
620// vim: shiftwidth=2 expandtab tabstop=2 cindent
621// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
622// clang-format on
void dt_bauhaus_slider_set_digits(GtkWidget *widget, int val)
Definition bauhaus.c:3534
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
Definition bauhaus.c:3598
void dt_bauhaus_slider_set_factor(GtkWidget *widget, float factor)
Definition bauhaus.c:3611
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
@ IOP_CS_LAB
const dt_aligned_pixel_t f
const dt_colormatrix_t dt_aligned_pixel_t out
const float delta
static float strength(float value, float strength)
Definition colorzones.c:420
#define dt_free_align(ptr)
Definition darktable.h:481
static void * dt_calloc_align(size_t size)
Definition darktable.h:488
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Enable aggressive floating-point arithmetic optimizations, in denormals handling. Set through user pr...
Definition darktable.h:524
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
Definition darktable.h:151
#define __DT_CLONE_TARGETS__
Definition darktable.h:367
#define __OMP_PARALLEL_FOR__(...)
Definition darktable.h:258
void dt_iop_params_t
Definition dev_history.h:41
void default_input_format(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_iop_buffer_dsc_t *dsc)
Definition format.c:57
@ TYPE_FLOAT
Definition format.h:46
static int grad3[12][3]
Definition grain.c:146
static int perm[512]
Definition grain.c:174
static float paper_resp(float exposure, float mb, float gp)
Definition grain.c:399
void commit_params(struct dt_iop_module_t *self, dt_iop_params_t *p1, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition grain.c:567
#define GRAIN_LUT_DELTA_MAX
Definition grain.c:79
const char ** description(struct dt_iop_module_t *self)
Definition grain.c:456
int default_group()
Definition grain.c:470
__DT_CLONE_TARGETS__ int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid, void *const ovoid)
Definition grain.c:499
_dt_iop_grain_channel_t
Definition grain.c:87
@ DT_GRAIN_CHANNEL_RGB
Definition grain.c:91
@ DT_GRAIN_CHANNEL_HUE
Definition grain.c:88
@ DT_GRAIN_CHANNEL_SATURATION
Definition grain.c:89
@ DT_GRAIN_CHANNEL_LIGHTNESS
Definition grain.c:90
static float paper_resp_inverse(float density, float mb, float gp)
Definition grain.c:406
void init_global(struct dt_iop_module_so_t *self)
Definition grain.c:593
#define GRAIN_LIGHTNESS_STRENGTH_SCALE
Definition grain.c:69
static __DT_CLONE_TARGETS__ unsigned int _hash_string(const char *s)
Definition grain.c:491
#define GRAIN_LUT_DELTA_MIN
Definition grain.c:80
static __DT_CLONE_TARGETS__ double _simplex_2d_noise(double x, double y, uint32_t octaves, double persistance, double z)
Definition grain.c:384
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition grain.c:581
const char * name()
Definition grain.c:451
void gui_init(struct dt_iop_module_t *self)
Definition grain.c:598
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
Definition grain.c:475
void input_format(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_iop_buffer_dsc_t *dsc)
Definition grain.c:480
#define GRAIN_LUT_PAPER_GAMMA
Definition grain.c:81
int flags()
Definition grain.c:465
#define GRAIN_SCALE_FACTOR
Definition grain.c:76
static int permutation[]
Definition grain.c:160
static void _simplex_noise_init()
Definition grain.c:175
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition grain.c:587
#define GRAIN_LUT_SIZE
Definition grain.c:78
static void evaluate_grain_lut(float *grain_lut, const float mb)
Definition grain.c:413
#define FASTFLOOR(x)
Definition grain.c:184
int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version, void *new_params, const int new_version)
Definition grain.c:120
const char ** dt_iop_set_description(dt_iop_module_t *module, const char *main_text, const char *purpose, const char *input, const char *process, const char *output)
Definition imageop.c:3141
@ IOP_FLAGS_INCLUDE_IN_STYLES
Definition imageop.h:166
@ IOP_FLAGS_DEPRECATED
Definition imageop.h:168
@ IOP_FLAGS_SUPPORTS_BLENDING
Definition imageop.h:167
@ IOP_GROUP_EFFECTS
Definition imageop.h:142
#define IOP_GUI_ALLOC(module)
Definition imageop.h:599
GtkWidget * dt_bauhaus_slider_from_params(dt_iop_module_t *self, const char *param)
Definition imageop_gui.c:77
void *const ovoid
static const float x
const int t
_dt_iop_grain_channel_t
Definition lightroom.c:94
float *const restrict const size_t k
float *const restrict const size_t const size_t ch
#define CLAMPS(A, L, H)
Definition math.h:76
struct _GtkWidget GtkWidget
Definition splash.h:29
const float noise
struct dt_iop_module_t *void * data
struct dt_develop_t * dev
dt_image_t image_storage
Definition develop.h:259
char filename[DT_MAX_FILENAME_LEN]
Definition image.h:304
unsigned int channels
Definition format.h:54
dt_iop_buffer_type_t datatype
Definition format.h:56
_dt_iop_grain_channel_t channel
Definition grain.c:112
float grain_lut[128 *128]
Definition grain.c:116
float midtones_bias
Definition grain.c:115
GtkWidget * strength
Definition grain.c:107
GtkWidget * midtones_bias
Definition grain.c:107
GtkWidget * scale
Definition grain.c:107
_dt_iop_grain_channel_t channel
Definition lightroom.c:103
Region of interest passed through the pixelpipe.
Definition imageop.h:72
double scale
Definition imageop.h:74