2
This file is part of darktable,
3
copyright (c) 2010 Henrik Andersson.
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.
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.
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/>.
28
#include "develop/develop.h"
29
#include "develop/imageop.h"
30
#include "control/control.h"
31
#include "dtgtk/slider.h"
32
#include "dtgtk/resetlabel.h"
37
#define GRAIN_LIGHTNESS_STRENGTH_SCALE 0.15
38
// (m_pi/2)/4 = half hue colorspan
39
#define GRAIN_HUE_COLORRANGE 0.392699082
40
#define GRAIN_HUE_STRENGTH_SCALE 0.25
41
#define GRAIN_SATURATION_STRENGTH_SCALE 0.25
42
#define GRAIN_RGB_STRENGTH_SCALE 0.25
44
#define CLIP(x) ((x<0)?0.0:(x>1.0)?1.0:x)
47
typedef enum _dt_iop_grain_channel_t
49
DT_GRAIN_CHANNEL_HUE=0,
50
DT_GRAIN_CHANNEL_SATURATION,
51
DT_GRAIN_CHANNEL_LIGHTNESS,
54
_dt_iop_grain_channel_t;
56
typedef struct dt_iop_grain_params_t
58
_dt_iop_grain_channel_t channel;
62
dt_iop_grain_params_t;
64
typedef struct dt_iop_grain_gui_data_t
66
GtkVBox *vbox1, *vbox2;
67
GtkWidget *label1,*label2,*label3; // channel, scale, strength
68
GtkDarktableSlider *scale1,*scale2; // scale, strength
70
dt_iop_grain_gui_data_t;
72
typedef struct dt_iop_grain_data_t
74
_dt_iop_grain_channel_t channel;
81
static int grad3[12][3] = {{1,1,0},{-1,1,0},{1,-1,0},{-1,-1,0},
82
{1,0,1},{-1,0,1},{1,0,-1},{-1,0,-1},
83
{0,1,1},{0,-1,1},{0,1,-1},{0,-1,-1}
86
static int p[] = {151,160,137,91,90,15,
87
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
88
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
89
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
90
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
91
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
92
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
93
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
94
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
95
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
96
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
97
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
98
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180
101
static int perm[512];
102
static void _simplex_noise_init()
104
for(int i=0; i<512; i++) perm[i] = p[i & 255];
106
static double dot(int g[], double x, double y, double z)
108
return g[0]*x + g[1]*y + g[2]*z;
111
#define FASTFLOOR(x) ( x>0 ? (int)(x) : (int)(x)-1 )
113
static double _simplex_noise(double xin, double yin, double zin)
115
double n0, n1, n2, n3; // Noise contributions from the four corners
116
// Skew the input space to determine which simplex cell we're in
118
double s = (xin+yin+zin)*F3; // Very nice and simple skew factor for 3D
119
int i = FASTFLOOR(xin+s);
120
int j = FASTFLOOR(yin+s);
121
int k = FASTFLOOR(zin+s);
122
double G3 = 1.0/6.0; // Very nice and simple unskew factor, too
123
double t = (i+j+k)*G3;
124
double X0 = i-t; // Unskew the cell origin back to (x,y,z) space
127
double x0 = xin-X0; // The x,y,z distances from the cell origin
130
// For the 3D case, the simplex shape is a slightly irregular tetrahedron.
131
// Determine which simplex we are in.
132
int i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords
133
int i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords
194
// A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z),
195
// a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
196
// a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
198
double x1 = x0 - i1 + G3; // Offsets for second corner in (x,y,z) coords
199
double y1 = y0 - j1 + G3;
200
double z1 = z0 - k1 + G3;
201
double x2 = x0 - i2 + 2.0*G3; // Offsets for third corner in (x,y,z) coords
202
double y2 = y0 - j2 + 2.0*G3;
203
double z2 = z0 - k2 + 2.0*G3;
204
double x3 = x0 - 1.0 + 3.0*G3; // Offsets for last corner in (x,y,z) coords
205
double y3 = y0 - 1.0 + 3.0*G3;
206
double z3 = z0 - 1.0 + 3.0*G3;
207
// Work out the hashed gradient indices of the four simplex corners
211
int gi0 = perm[ii+perm[jj+perm[kk]]] % 12;
212
int gi1 = perm[ii+i1+perm[jj+j1+perm[kk+k1]]] % 12;
213
int gi2 = perm[ii+i2+perm[jj+j2+perm[kk+k2]]] % 12;
214
int gi3 = perm[ii+1+perm[jj+1+perm[kk+1]]] % 12;
215
// Calculate the contribution from the four corners
216
double t0 = 0.6 - x0*x0 - y0*y0 - z0*z0;
221
n0 = t0 * t0 * dot(grad3[gi0], x0, y0, z0);
223
double t1 = 0.6 - x1*x1 - y1*y1 - z1*z1;
228
n1 = t1 * t1 * dot(grad3[gi1], x1, y1, z1);
230
double t2 = 0.6 - x2*x2 - y2*y2 - z2*z2;
235
n2 = t2 * t2 * dot(grad3[gi2], x2, y2, z2);
237
double t3 = 0.6 - x3*x3 - y3*y3 - z3*z3;
242
n3 = t3 * t3 * dot(grad3[gi3], x3, y3, z3);
244
// Add contributions from each corner to get the final noise value.
245
// The result is scaled to stay just inside [-1,1]
246
return 32.0*(n0 + n1 + n2 + n3);
253
#define PRIME_LEVELS 4
254
//static uint64_t _low_primes[PRIME_LEVELS] ={ 12503,14029,15649, 11369 };
255
//uint64_t _mid_primes[PRIME_LEVELS] ={ 784697,875783, 536461,639259};
257
/*static double __value_noise(uint32_t level,uint32_t x,uint32_t y)
259
//uint32_t lvl=level%PRIME_LEVELS;
260
uint32_t n = x + y * 57;
262
return ( 1.0 - (( (n * (n * n * 15731 + 789221) +1376312589) & 0x7fffffff) / 1073741824.0));
265
static double __value_smooth_noise(uint32_t level,double x,double y)
267
double corners = ( __value_noise(level,x-1, y-1)+__value_noise(level,x+1, y-1)+__value_noise(level,x-1, y+1)+__value_noise(level,x+1, y+1) ) / 16;
268
double sides = ( __value_noise(level,x-1, y) +__value_noise(level,x+1, y) +__value_noise(level,x, y-1) +__value_noise(level,x, y+1) ) / 8;
269
double center = __value_noise(level,x, y) / 4;
270
return corners + sides + center;
273
static double __preline_cosine_interpolate(double a,double b,double x)
275
double ft = x * 3.1415927;
276
double f = (1 - cos(ft)) * .5;
277
return a*(1-f) + b*f;
280
static double __value_interpolate(uint32_t level,double x,double y)
282
double fx = x - (uint32_t)x;
283
double fy = y - (uint32_t)y;
285
double v1 = __value_smooth_noise(level,(uint32_t)x, (uint32_t)y);
286
double v2 = __value_smooth_noise(level,(uint32_t)x + 1, (uint32_t)y);
287
double v3 = __value_smooth_noise(level,(uint32_t)x, (uint32_t)y + 1);
288
double v4 = __value_smooth_noise(level,(uint32_t)x + 1, (uint32_t)y + 1);
290
double i1 = __preline_cosine_interpolate(v1 , v2 , fx);
291
double i2 = __preline_cosine_interpolate(v3 , v4 , fx);
293
return __preline_cosine_interpolate(i1 , i2 , fy);
295
static double _perlin_2d_noise(double x,double y,uint32_t octaves,double persistance,double z)
297
double f=1,a=1,total=0;
299
for(int o=0;o<octaves;o++) {
300
total+= (__value_interpolate(o,x*f/z,y*f/z)*a);
307
static double _simplex_2d_noise(double x,double y,uint32_t octaves,double persistance,double z)
309
double f=1,a=1,total=0;
311
for(int o=0; o<octaves; o++)
313
total+= (_simplex_noise(x*f/z,y*f/z,o)*a);
328
return IOP_FLAGS_INCLUDE_IN_STYLES;
334
return IOP_GROUP_EFFECT;
340
void process (struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, void *ivoid, void *ovoid, const dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out)
342
dt_iop_grain_data_t *data = (dt_iop_grain_data_t *)piece->data;
343
const int ch = piece->colors;
344
// Apply grain to image
345
const double strength=(data->strength/100.0);
346
const double octaves=3;
347
// double zoom=1.0+(8*(data->scale/100.0));
348
const double wd = fminf(piece->buf_in.width, piece->buf_in.height);
349
const double zoom=(1.0+8*data->scale/100)/800.0;
350
const int filter = fabsf(roi_out->scale - 1.0) > 0.01;
351
// filter width depends on world space (i.e. reverse wd norm and roi->scale, as well as buffer input to pixelpipe iscale)
352
const double filtermul = piece->iscale/(roi_out->scale*wd);
354
#pragma omp parallel for default(none) shared(roi_out, roi_in, ovoid, ivoid, data)
356
for(int j=0; j<roi_out->height; j++)
358
float *in = ((float *)ivoid) + roi_out->width * j * ch;
359
float *out = ((float *)ovoid) + roi_out->width * j * ch;
360
for(int i=0; i<roi_out->width; i++)
362
// calculate x, y in a resolution independent way:
363
// wx,wy: worldspace in full image pixel coords:
364
double wx = (roi_out->x + i)/roi_out->scale;
365
double wy = (roi_out->y + j)/roi_out->scale;
366
// x, y: normalized to shorter side of image, so with pixel aspect = 1.
367
// printf("scale %f\n", wd);
370
// double noise=_perlin_2d_noise(x, y, octaves,0.25, zoom)*1.5;
374
// if zoomed out a lot, use rank-1 lattice downsampling
375
const float fib1 = 34.0, fib2 = 21.0;
376
for(int l=0; l<fib2; l++)
378
float px = l/fib2, py = l*(fib1/fib2);
380
float dx = px*filtermul, dy = py*filtermul;
381
noise += (1.0/fib2) * _simplex_2d_noise(x+dx, y+dy, octaves, 1.0, zoom);
386
noise = _simplex_2d_noise(x, y, octaves, 1.0, zoom);
389
out[0] = in[0]+((100.0*(noise*(strength)))*GRAIN_LIGHTNESS_STRENGTH_SCALE);
400
scale_callback (GtkDarktableSlider *slider, gpointer user_data)
402
dt_iop_module_t *self = (dt_iop_module_t *)user_data;
403
if(self->dt->gui->reset) return;
404
dt_iop_grain_params_t *p = (dt_iop_grain_params_t *)self->params;
405
p->scale = dtgtk_slider_get_value(slider)/53.3;
406
dt_dev_add_history_item(darktable.develop, self, TRUE);
410
strength_callback (GtkDarktableSlider *slider, gpointer user_data)
412
dt_iop_module_t *self = (dt_iop_module_t *)user_data;
413
if(self->dt->gui->reset) return;
414
dt_iop_grain_params_t *p = (dt_iop_grain_params_t *)self->params;
415
p->strength= dtgtk_slider_get_value(slider);
416
dt_dev_add_history_item(darktable.develop, self, TRUE);
420
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)
422
dt_iop_grain_params_t *p = (dt_iop_grain_params_t *)p1;
424
fprintf(stderr, "[grain] TODO: implement gegl version!\n");
425
// pull in new params to gegl
427
dt_iop_grain_data_t *d = (dt_iop_grain_data_t *)piece->data;
428
d->channel = p->channel;
430
d->strength = p->strength;
434
void init_pipe (struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
437
// create part of the gegl pipeline
440
piece->data = malloc(sizeof(dt_iop_grain_data_t));
441
memset(piece->data,0,sizeof(dt_iop_grain_data_t));
442
self->commit_params(self, self->default_params, pipe, piece);
446
void cleanup_pipe (struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
449
// clean up everything again.
450
(void)gegl_node_remove_child(pipe->gegl, piece->input);
451
// no free necessary, no data is alloc'ed
457
void gui_update(struct dt_iop_module_t *self)
459
dt_iop_module_t *module = (dt_iop_module_t *)self;
460
dt_iop_grain_gui_data_t *g = (dt_iop_grain_gui_data_t *)self->gui_data;
461
dt_iop_grain_params_t *p = (dt_iop_grain_params_t *)module->params;
463
dtgtk_slider_set_value(g->scale1, p->scale*53.3);
464
dtgtk_slider_set_value(g->scale2, p->strength);
467
void init(dt_iop_module_t *module)
469
_simplex_noise_init();
470
module->params = malloc(sizeof(dt_iop_grain_params_t));
471
module->default_params = malloc(sizeof(dt_iop_grain_params_t));
472
module->default_enabled = 0;
473
module->priority = 855;
474
module->params_size = sizeof(dt_iop_grain_params_t);
475
module->gui_data = NULL;
476
dt_iop_grain_params_t tmp = (dt_iop_grain_params_t)
478
DT_GRAIN_CHANNEL_LIGHTNESS, 400.0/53.3, 25.0
480
memcpy(module->params, &tmp, sizeof(dt_iop_grain_params_t));
481
memcpy(module->default_params, &tmp, sizeof(dt_iop_grain_params_t));
484
void cleanup(dt_iop_module_t *module)
486
free(module->gui_data);
487
module->gui_data = NULL;
488
free(module->params);
489
module->params = NULL;
492
void gui_init(struct dt_iop_module_t *self)
494
self->gui_data = malloc(sizeof(dt_iop_grain_gui_data_t));
495
dt_iop_grain_gui_data_t *g = (dt_iop_grain_gui_data_t *)self->gui_data;
496
dt_iop_grain_params_t *p = (dt_iop_grain_params_t *)self->params;
498
self->widget = GTK_WIDGET(gtk_hbox_new(FALSE, 0));
499
g->vbox1 = GTK_VBOX(gtk_vbox_new(FALSE, DT_GUI_IOP_MODULE_CONTROL_SPACING));
500
g->vbox2 = GTK_VBOX(gtk_vbox_new(FALSE, DT_GUI_IOP_MODULE_CONTROL_SPACING));
501
gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(g->vbox1), FALSE, FALSE, 5);
502
gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(g->vbox2), TRUE, TRUE, 5);
504
g->label2 = dtgtk_reset_label_new(_("coarseness"), self, &p->scale, sizeof(float));
505
g->label3 = dtgtk_reset_label_new(_("strength"), self, &p->strength, sizeof(float));
507
gtk_box_pack_start(GTK_BOX(g->vbox1), GTK_WIDGET(g->label2), TRUE, TRUE, 0);
508
gtk_box_pack_start(GTK_BOX(g->vbox1), GTK_WIDGET(g->label3), TRUE, TRUE, 0);
510
g->scale1 = DTGTK_SLIDER(dtgtk_slider_new_with_range(DARKTABLE_SLIDER_BAR, 100.0, 3200.0, 20.0, p->scale*53.3, 0));
511
dtgtk_slider_set_snap(g->scale1, 20);
512
g->scale2 = DTGTK_SLIDER(dtgtk_slider_new_with_range(DARKTABLE_SLIDER_BAR, 0.0, 100.0, 1.0, p->strength, 2));
513
dtgtk_slider_set_format_type(g->scale2,DARKTABLE_SLIDER_FORMAT_PERCENT);
514
gtk_box_pack_start(GTK_BOX(g->vbox2), GTK_WIDGET(g->scale1), TRUE, TRUE, 0);
515
gtk_box_pack_start(GTK_BOX(g->vbox2), GTK_WIDGET(g->scale2), TRUE, TRUE, 0);
516
gtk_object_set(GTK_OBJECT(g->scale1), "tooltip-text", _("the grain size (~iso of the film)"), (char *)NULL);
517
gtk_object_set(GTK_OBJECT(g->scale2), "tooltip-text", _("the strength of applied grain"), (char *)NULL);
519
g_signal_connect (G_OBJECT (g->scale1), "value-changed",
520
G_CALLBACK (scale_callback), self);
521
g_signal_connect (G_OBJECT (g->scale2), "value-changed",
522
G_CALLBACK (strength_callback), self);
526
void gui_cleanup(struct dt_iop_module_t *self)
528
free(self->gui_data);
529
self->gui_data = NULL;