~ubuntu-branches/ubuntu/saucy/darktable/saucy

« back to all changes in this revision

Viewing changes to src/iop/sharpen.c

  • Committer: Bazaar Package Importer
  • Author(s): David Bremner
  • Date: 2011-07-12 09:36:46 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20110712093646-yp9dbxan44dmw15h
Tags: 0.9-1
* New upstream release.
* Remove all patches now upstream; only patch for
  -Wno-error=unused-but-set-variable remains.
* Bump Standards-Version to 3.9.2 (no changes)

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
 
35
35
DT_MODULE(1)
36
36
 
37
 
#define MAXR 8
 
37
#define MAXR 12
38
38
 
39
39
typedef struct dt_iop_sharpen_params_t
40
40
{
44
44
 
45
45
typedef struct dt_iop_sharpen_gui_data_t
46
46
{
47
 
  GtkVBox   *vbox1,  *vbox2;
 
47
  GtkVBox   *vbox;
48
48
  GtkDarktableSlider *scale1, *scale2, *scale3;
49
49
}
50
50
dt_iop_sharpen_gui_data_t;
64
64
 
65
65
const char *name()
66
66
{
67
 
  return _("sharpen");
 
67
  return C_("sharpen", "sharpen");
68
68
}
69
69
 
70
70
 
74
74
  return IOP_GROUP_CORRECT;
75
75
}
76
76
 
 
77
int
 
78
flags ()
 
79
{
 
80
  return IOP_FLAGS_SUPPORTS_BLENDING;
 
81
}
 
82
 
77
83
#ifdef HAVE_OPENCL
78
 
void
 
84
int
79
85
process_cl (struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, cl_mem dev_in, cl_mem dev_out, const dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out)
80
86
{
81
87
  dt_iop_sharpen_data_t *d = (dt_iop_sharpen_data_t *)piece->data;
82
88
  dt_iop_sharpen_global_data_t *gd = (dt_iop_sharpen_global_data_t *)self->data;
 
89
  cl_mem dev_m = NULL;
 
90
  cl_int err = -999;
83
91
 
84
 
  cl_int err;
85
92
  const int devid = piece->pipe->devid;
86
93
  const int rad = MIN(MAXR, ceilf(d->radius * roi_in->scale / piece->iscale));
 
94
 
87
95
  if(rad == 0)
88
96
  {
89
97
    size_t origin[] = {0, 0, 0};
90
98
    size_t region[] = {roi_in->width, roi_in->height, 1};
91
 
    err = clEnqueueCopyImage(darktable.opencl->dev[devid].cmd_queue, dev_in, dev_out, origin, origin, region, 0, NULL, NULL);
92
 
    return;
 
99
    err = dt_opencl_enqueue_copy_image(darktable.opencl->dev[devid].cmd_queue, dev_in, dev_out, origin, origin, region, 0, NULL, NULL);
 
100
    if (err != CL_SUCCESS) goto error;
 
101
    return TRUE;
93
102
  }
 
103
  // init gaussian kernel
94
104
  float mat[2*(MAXR+1)];
95
105
  const int wd = 2*rad+1;
96
106
  float *m = mat + rad;
97
 
  const float sigma2 = (2.5*2.5)*(d->radius*roi_in->scale/piece->iscale)*(d->radius*roi_in->scale/piece->iscale);
 
107
  const float sigma2 = (1.0f/(2.5*2.5))*(d->radius*roi_in->scale/piece->iscale)*(d->radius*roi_in->scale/piece->iscale);
98
108
  float weight = 0.0f;
99
 
  // init gaussian kernel
100
109
  for(int l=-rad; l<=rad; l++) weight += m[l] = expf(- (l*l)/(2.f*sigma2));
101
110
  for(int l=-rad; l<=rad; l++) m[l] /= weight;
102
111
  size_t sizes[] = {roi_in->width, roi_in->height, 1};
103
 
  cl_mem dev_m = dt_opencl_copy_host_to_device_constant(sizeof(float)*wd, devid, mat);
 
112
  dev_m = dt_opencl_copy_host_to_device_constant(sizeof(float)*wd, devid, mat);
 
113
  if (dev_m == NULL) goto error;
104
114
  dt_opencl_set_kernel_arg(darktable.opencl, devid, gd->kernel_sharpen, 0, sizeof(cl_mem), (void *)&dev_in);
105
115
  dt_opencl_set_kernel_arg(darktable.opencl, devid, gd->kernel_sharpen, 1, sizeof(cl_mem), (void *)&dev_out);
106
116
  dt_opencl_set_kernel_arg(darktable.opencl, devid, gd->kernel_sharpen, 2, sizeof(cl_mem), (void *)&dev_m);
108
118
  dt_opencl_set_kernel_arg(darktable.opencl, devid, gd->kernel_sharpen, 4, sizeof(float), (void *)&d->amount);
109
119
  dt_opencl_set_kernel_arg(darktable.opencl, devid, gd->kernel_sharpen, 5, sizeof(float), (void *)&d->threshold);
110
120
  err = dt_opencl_enqueue_kernel_2d(darktable.opencl, devid, gd->kernel_sharpen, sizes);
111
 
  if(err != CL_SUCCESS) fprintf(stderr, "couldn't enqueue sharpen kernel! %d\n", err);
112
 
  clReleaseMemObject(dev_m);
 
121
  if(err != CL_SUCCESS) goto error;
 
122
  dt_opencl_release_mem_object(dev_m);
 
123
  return TRUE;
 
124
 
 
125
error:
 
126
  if (dev_m != NULL) dt_opencl_release_mem_object(dev_m);
 
127
  dt_print(DT_DEBUG_OPENCL, "[opencl_sharpen] couldn't enqueue kernel! %d\n", err);
 
128
  return FALSE;
113
129
}
114
130
#endif
115
131
 
124
140
    return;
125
141
  }
126
142
 
 
143
  float *const tmp = dt_alloc_align(16, sizeof(float)*ch*roi_out->width*roi_out->height);
 
144
 
127
145
  const int wd = 2*rad+1;
128
 
  float mat[wd*wd];
129
 
  float *m;
130
 
  const float sigma2 = (2.5*2.5)*(data->radius*roi_in->scale/piece->iscale)*(data->radius*roi_in->scale/piece->iscale);
 
146
  float mat[wd];
 
147
  const float sigma2 = (1.0f/(2.5*2.5))*(data->radius*roi_in->scale/piece->iscale)*(data->radius*roi_in->scale/piece->iscale);
131
148
  float weight = 0.0f;
 
149
 
132
150
  // init gaussian kernel
133
 
  m = mat;
134
 
  for(int l=-rad; l<=rad; l++) for(int k=-rad; k<=rad; k++,m++)
135
 
      weight += *m = expf(- (l*l + k*k)/(2.f*sigma2));
136
 
  m = mat;
137
 
  for(int l=-rad; l<=rad; l++) for(int k=-rad; k<=rad; k++,m++)
138
 
      *m /= weight;
139
 
 
140
 
  // gauss blur the image
141
 
#ifdef _OPENMP
142
 
#pragma omp parallel for default(none) shared(mat, ivoid, ovoid, roi_out, roi_in) schedule(static)
 
151
  for(int l=-rad; l<=rad; l++)
 
152
    weight += mat[l+rad] = expf(- l*l/(2.f*sigma2));
 
153
  for(int l=0; l<wd; l++)
 
154
    mat[l] /= weight;
 
155
 
 
156
  // gauss blur the image horizontally
 
157
#ifdef _OPENMP
 
158
  #pragma omp parallel for default(none) shared(mat, ivoid, ovoid, roi_out, roi_in) schedule(static)
 
159
#endif
 
160
  for(int j=0; j<roi_out->height; j++)
 
161
  {
 
162
    const float *in = ((float *)ivoid) + ch*(j*roi_in->width + rad);
 
163
    float *out = tmp + ch*(j*roi_out->width + rad);
 
164
    for(int i=rad; i<roi_out->width-rad; i++)
 
165
    {
 
166
      const float *inp = in - ch*rad;
 
167
      const float *m = mat;
 
168
      float sum = 0.0f;
 
169
      for(int k=-rad; k<=rad; k++,m++,inp+=ch)
 
170
        sum += *m * *inp;
 
171
      *out = sum;
 
172
      out += ch;
 
173
      in += ch;
 
174
    }
 
175
  }
 
176
 
 
177
  // gauss blur the image horizontally
 
178
#ifdef _OPENMP
 
179
  #pragma omp parallel for default(none) shared(mat, ivoid, ovoid, roi_out, roi_in) schedule(static)
143
180
#endif
144
181
  for(int j=rad; j<roi_out->height-rad; j++)
145
182
  {
146
 
    float *in = ((float *)ivoid) + ch*(j*roi_in->width + rad);
 
183
    const float *in = tmp + ch*(j*roi_in->width + rad);
147
184
    float *out = ((float *)ovoid) + ch*(j*roi_out->width + rad);
148
185
    for(int i=rad; i<roi_out->width-rad; i++)
149
186
    {
150
 
      float *m = mat;
 
187
      const int step = ch*roi_in->width;
 
188
      const float *inp = in - step*rad;
 
189
      const float *m = mat;
151
190
      float sum = 0.0f;
152
 
      for(int l=-rad; l<=rad; l++)
153
 
      {
154
 
        float *inp = in + ch*(l*roi_in->width-rad);
155
 
        for(int k=-rad; k<=rad; k++,m++,inp+=ch)
156
 
          sum += *m * *inp;
157
 
      }
 
191
      for(int k=-rad; k<=rad; k++,m++,inp+=step)
 
192
        sum += *m * *inp;
158
193
      *out = sum;
159
194
      out += ch;
160
195
      in += ch;
166
201
    memcpy(((float*)ovoid) + ch*j*roi_out->width, ((float*)ivoid) + ch*j*roi_in->width, ch*sizeof(float)*roi_out->width);
167
202
  for(int j=roi_out->height-rad; j<roi_out->height; j++)
168
203
    memcpy(((float*)ovoid) + ch*j*roi_out->width, ((float*)ivoid) + ch*j*roi_in->width, ch*sizeof(float)*roi_out->width);
 
204
 
 
205
  free(tmp);
 
206
 
169
207
#ifdef _OPENMP
170
 
#pragma omp parallel for default(none) shared(ivoid, ovoid, roi_out, roi_in) schedule(static)
 
208
  #pragma omp parallel for default(none) shared(ivoid, ovoid, roi_out, roi_in) schedule(static)
171
209
#endif
172
210
  for(int j=rad; j<roi_out->height-rad; j++)
173
211
  {
179
217
      out[ch*i] = in[ch*i];
180
218
  }
181
219
#ifdef _OPENMP
182
 
#pragma omp parallel for default(none) shared(data, ivoid, ovoid, roi_out, roi_in) schedule(static)
 
220
  #pragma omp parallel for default(none) shared(data, ivoid, ovoid, roi_out, roi_in) schedule(static)
183
221
#endif
184
222
  // subtract blurred image, if diff > thrs, add *amount to orginal image
185
223
  for(int j=0; j<roi_out->height; j++)
242
280
  // pull in new params to gegl
243
281
#else
244
282
  dt_iop_sharpen_data_t *d = (dt_iop_sharpen_data_t *)piece->data;
245
 
  d->radius = p->radius;
 
283
  // actually need to increase the mask to fit 2.5 sigma inside
 
284
  d->radius = 2.5f*p->radius;
246
285
  d->amount = p->amount;
247
286
  d->threshold = p->threshold;
248
287
#endif
286
325
  module->params = malloc(sizeof(dt_iop_sharpen_params_t));
287
326
  module->default_params = malloc(sizeof(dt_iop_sharpen_params_t));
288
327
  module->default_enabled = 1;
289
 
  module->priority = 850;
 
328
  module->priority = 644; // module order created by iop_dependencies.py, do not edit!
290
329
  module->params_size = sizeof(dt_iop_sharpen_params_t);
291
330
  module->gui_data = NULL;
292
331
  dt_iop_sharpen_params_t tmp = (dt_iop_sharpen_params_t)
328
367
  dt_iop_sharpen_params_t *p = (dt_iop_sharpen_params_t *)self->params;
329
368
 
330
369
  self->widget = GTK_WIDGET(gtk_hbox_new(FALSE, 0));
331
 
  g->vbox1 = GTK_VBOX(gtk_vbox_new(FALSE, DT_GUI_IOP_MODULE_CONTROL_SPACING));
332
 
  g->vbox2 = GTK_VBOX(gtk_vbox_new(FALSE, DT_GUI_IOP_MODULE_CONTROL_SPACING));
333
 
  gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(g->vbox1), FALSE, FALSE, 5);
334
 
  gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(g->vbox2), TRUE, TRUE, 5);
335
 
 
336
 
 
337
 
  GtkWidget *widget;
338
 
  widget = dtgtk_reset_label_new(_("radius"), self, &p->radius, sizeof(float));
339
 
  gtk_box_pack_start(GTK_BOX(g->vbox1), widget, TRUE, TRUE, 0);
340
 
  widget = dtgtk_reset_label_new(_("amount"), self, &p->amount, sizeof(float));
341
 
  gtk_box_pack_start(GTK_BOX(g->vbox1), widget, TRUE, TRUE, 0);
342
 
  widget = dtgtk_reset_label_new(_("threshold"), self, &p->threshold, sizeof(float));
343
 
  gtk_box_pack_start(GTK_BOX(g->vbox1), widget, TRUE, TRUE, 0);
 
370
  g->vbox = GTK_VBOX(gtk_vbox_new(FALSE, DT_GUI_IOP_MODULE_CONTROL_SPACING));
 
371
  gtk_box_pack_start(GTK_BOX(self->widget), GTK_WIDGET(g->vbox), TRUE, TRUE, 5);
344
372
 
345
373
  g->scale1 = DTGTK_SLIDER(dtgtk_slider_new_with_range(DARKTABLE_SLIDER_BAR,0.0, 8.0000, 0.100, p->radius, 3));
 
374
  g_object_set (GTK_OBJECT(g->scale1), "tooltip-text", _("spatial extent of the unblurring"), (char *)NULL);
 
375
  dtgtk_slider_set_label(g->scale1,_("radius"));
346
376
  g->scale2 = DTGTK_SLIDER(dtgtk_slider_new_with_range(DARKTABLE_SLIDER_BAR,0.0, 2.0000, 0.010, p->amount, 3));
 
377
  g_object_set (GTK_OBJECT(g->scale2), "tooltip-text", _("strength of the sharpen"), (char *)NULL);
 
378
  dtgtk_slider_set_label(g->scale2,_("amount"));
347
379
  g->scale3 = DTGTK_SLIDER(dtgtk_slider_new_with_range(DARKTABLE_SLIDER_BAR,0.0, 1.0000, 0.001, p->threshold, 3));
348
 
  gtk_box_pack_start(GTK_BOX(g->vbox2), GTK_WIDGET(g->scale1), TRUE, TRUE, 0);
349
 
  gtk_box_pack_start(GTK_BOX(g->vbox2), GTK_WIDGET(g->scale2), TRUE, TRUE, 0);
350
 
  gtk_box_pack_start(GTK_BOX(g->vbox2), GTK_WIDGET(g->scale3), TRUE, TRUE, 0);
 
380
  g_object_set (GTK_OBJECT(g->scale3), "tooltip-text", _("threshold to activate sharpen"), (char *)NULL);
 
381
  dtgtk_slider_set_label(g->scale3,_("threshold"));
 
382
  gtk_box_pack_start(GTK_BOX(g->vbox), GTK_WIDGET(g->scale1), TRUE, TRUE, 0);
 
383
  gtk_box_pack_start(GTK_BOX(g->vbox), GTK_WIDGET(g->scale2), TRUE, TRUE, 0);
 
384
  gtk_box_pack_start(GTK_BOX(g->vbox), GTK_WIDGET(g->scale3), TRUE, TRUE, 0);
351
385
 
352
386
  g_signal_connect (G_OBJECT (g->scale1), "value-changed",
353
387
                    G_CALLBACK (radius_callback), self);
364
398
}
365
399
 
366
400
#undef MAXR
 
401
 
 
402
// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-space on;