Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
basic.c
Go to the documentation of this file.
1
2/* taken from dcraw and demosaic_ppg below */
3
4static void lin_interpolate(float *out, const float *const in, const dt_iop_roi_t *const roi_out,
5 const dt_iop_roi_t *const roi_in, const uint32_t filters,
6 const uint8_t (*const xtrans)[6])
7{
8 const int colors = (filters == 9) ? 3 : 4;
9
10// border interpolate
11#ifdef _OPENMP
12#pragma omp parallel for default(none) \
13 dt_omp_firstprivate(colors, filters, in, roi_in, roi_out, xtrans) \
14 shared(out) \
15 schedule(static)
16#endif
17 for(int row = 0; row < roi_out->height; row++)
18 for(int col = 0; col < roi_out->width; col++)
19 {
20 dt_aligned_pixel_t sum = { 0.0f };
21 uint8_t count[4] = { 0 };
22 if(col == 1 && row >= 1 && row < roi_out->height - 1) col = roi_out->width - 1;
23 // average all the adjoining pixels inside image by color
24 for(int y = row - 1; y != row + 2; y++)
25 for(int x = col - 1; x != col + 2; x++)
26 if(y >= 0 && x >= 0 && y < roi_in->height && x < roi_in->width)
27 {
28 const int f = fcol(y + roi_in->y, x + roi_in->x, filters, xtrans);
29 sum[f] += in[y * roi_in->width + x];
30 count[f]++;
31 }
32 const int f = fcol(row + roi_in->y, col + roi_in->x, filters, xtrans);
33 // for current cell, copy the current sensor's color data,
34 // interpolate the other two colors from surrounding pixels of
35 // their color
36 for(int c = 0; c < colors; c++)
37 {
38 if(c != f && count[c] != 0)
39 out[4 * (row * roi_out->width + col) + c] = sum[c] / count[c];
40 else
41 out[4 * (row * roi_out->width + col) + c] = in[row * roi_in->width + col];
42 }
43 }
44
45 // build interpolation lookup table which for a given offset in the sensor
46 // lists neighboring pixels from which to interpolate:
47 // NUM_PIXELS # of neighboring pixels to read
48 // for (1..NUM_PIXELS):
49 // OFFSET # in bytes from current pixel
50 // WEIGHT # how much weight to give this neighbor
51 // COLOR # sensor color
52 // # weights of adjoining pixels not of this pixel's color
53 // COLORA TOT_WEIGHT
54 // COLORB TOT_WEIGHT
55 // COLORPIX # color of center pixel
56
57 int(*const lookup)[16][32] = malloc(sizeof(int) * 16 * 16 * 32);
58
59 const int size = (filters == 9) ? 6 : 16;
60 for(int row = 0; row < size; row++)
61 for(int col = 0; col < size; col++)
62 {
63 int *ip = &(lookup[row][col][1]);
64 int sum[4] = { 0 };
65 const int f = fcol(row + roi_in->y, col + roi_in->x, filters, xtrans);
66 // make list of adjoining pixel offsets by weight & color
67 for(int y = -1; y <= 1; y++)
68 for(int x = -1; x <= 1; x++)
69 {
70 const int weight = 1 << ((y == 0) + (x == 0));
71 const int color = fcol(row + y + roi_in->y, col + x + roi_in->x, filters, xtrans);
72 if(color == f) continue;
73 *ip++ = (roi_in->width * y + x);
74 *ip++ = weight;
75 *ip++ = color;
76 sum[color] += weight;
77 }
78 lookup[row][col][0] = (ip - &(lookup[row][col][0])) / 3; /* # of neighboring pixels found */
79 for(int c = 0; c < colors; c++)
80 if(c != f)
81 {
82 *ip++ = c;
83 *ip++ = sum[c];
84 }
85 *ip = f;
86 }
87
88#ifdef _OPENMP
89#pragma omp parallel for default(none) \
90 dt_omp_firstprivate(colors, in, lookup, roi_in, roi_out, size) \
91 shared(out) \
92 schedule(static)
93#endif
94 for(int row = 1; row < roi_out->height - 1; row++)
95 {
96 float *buf = out + 4 * roi_out->width * row + 4;
97 const float *buf_in = in + roi_in->width * row + 1;
98 for(int col = 1; col < roi_out->width - 1; col++)
99 {
100 dt_aligned_pixel_t sum = { 0.0f };
101 int *ip = &(lookup[row % size][col % size][0]);
102 // for each adjoining pixel not of this pixel's color, sum up its weighted values
103 for(int i = *ip++; i--; ip += 3) sum[ip[2]] += buf_in[ip[0]] * ip[1];
104 // for each interpolated color, load it into the pixel
105 for(int i = colors; --i; ip += 2) buf[*ip] = sum[ip[0]] / ip[1];
106 buf[*ip] = *buf_in;
107 buf += 4;
108 buf_in++;
109 }
110 }
111
112 free(lookup);
113}
114
115
116
117#define SWAP(a, b) \
118 { \
119 const float tmp = (b); \
120 (b) = (a); \
121 (a) = tmp; \
122 }
123
124#ifdef _OPENMP
125 #pragma omp declare simd aligned(in, out)
126#endif
127static void pre_median_b(float *out, const float *const in, const dt_iop_roi_t *const roi, const uint32_t filters,
128 const int num_passes, const float threshold)
129{
130 dt_iop_image_copy_by_size(out, in, roi->width, roi->height, 1);
131
132 // now green:
133 const int lim[5] = { 0, 1, 2, 1, 0 };
134 for(int pass = 0; pass < num_passes; pass++)
135 {
136#ifdef _OPENMP
137#pragma omp parallel for default(none) \
138 dt_omp_firstprivate(filters, in, lim, roi, threshold) \
139 shared(out) \
140 schedule(static)
141#endif
142 for(int row = 3; row < roi->height - 3; row++)
143 {
144 float med[9];
145 int col = 3;
146 if(FC(row, col, filters) != 1 && FC(row, col, filters) != 3) col++;
147 float *pixo = out + (size_t)roi->width * row + col;
148 const float *pixi = in + (size_t)roi->width * row + col;
149 for(; col < roi->width - 3; col += 2)
150 {
151 int cnt = 0;
152 for(int k = 0, i = 0; i < 5; i++)
153 {
154 for(int j = -lim[i]; j <= lim[i]; j += 2)
155 {
156 if(fabsf(pixi[roi->width * (i - 2) + j] - pixi[0]) < threshold)
157 {
158 med[k++] = pixi[roi->width * (i - 2) + j];
159 cnt++;
160 }
161 else
162 med[k++] = 64.0f + pixi[roi->width * (i - 2) + j];
163 }
164 }
165 for(int i = 0; i < 8; i++)
166 for(int ii = i + 1; ii < 9; ii++)
167 if(med[i] > med[ii]) SWAP(med[i], med[ii]);
168 pixo[0] = (cnt == 1 ? med[4] - 64.0f : med[(cnt - 1) / 2]);
169 // pixo[0] = med[(cnt-1)/2];
170 pixo += 2;
171 pixi += 2;
172 }
173 }
174 }
175}
176
177static void pre_median(float *out, const float *const in, const dt_iop_roi_t *const roi, const uint32_t filters,
178 const int num_passes, const float threshold)
179{
180 pre_median_b(out, in, roi, filters, num_passes, threshold);
181}
182
183#define SWAPmed(I, J) \
184 if(med[I] > med[J]) SWAP(med[I], med[J])
185
186static void color_smoothing(float *out, const dt_iop_roi_t *const roi_out, const int num_passes)
187{
188 const int width4 = 4 * roi_out->width;
189
190 for(int pass = 0; pass < num_passes; pass++)
191 {
192 for(int c = 0; c < 3; c += 2)
193 {
194 {
195 float *outp = out;
196 for(int j = 0; j < roi_out->height; j++)
197 for(int i = 0; i < roi_out->width; i++, outp += 4) outp[3] = outp[c];
198 }
199#ifdef _OPENMP
200#pragma omp parallel for default(none) \
201 dt_omp_firstprivate(roi_out, width4) \
202 shared(out, c) \
203 schedule(static)
204#endif
205 for(int j = 1; j < roi_out->height - 1; j++)
206 {
207 float *outp = out + (size_t)4 * j * roi_out->width + 4;
208 for(int i = 1; i < roi_out->width - 1; i++, outp += 4)
209 {
210 float med[9] = {
211 outp[-width4 - 4 + 3] - outp[-width4 - 4 + 1], outp[-width4 + 0 + 3] - outp[-width4 + 0 + 1],
212 outp[-width4 + 4 + 3] - outp[-width4 + 4 + 1], outp[-4 + 3] - outp[-4 + 1],
213 outp[+0 + 3] - outp[+0 + 1], outp[+4 + 3] - outp[+4 + 1],
214 outp[+width4 - 4 + 3] - outp[+width4 - 4 + 1], outp[+width4 + 0 + 3] - outp[+width4 + 0 + 1],
215 outp[+width4 + 4 + 3] - outp[+width4 + 4 + 1],
216 };
217 /* optimal 9-element median search */
218 SWAPmed(1, 2);
219 SWAPmed(4, 5);
220 SWAPmed(7, 8);
221 SWAPmed(0, 1);
222 SWAPmed(3, 4);
223 SWAPmed(6, 7);
224 SWAPmed(1, 2);
225 SWAPmed(4, 5);
226 SWAPmed(7, 8);
227 SWAPmed(0, 3);
228 SWAPmed(5, 8);
229 SWAPmed(4, 7);
230 SWAPmed(3, 6);
231 SWAPmed(1, 4);
232 SWAPmed(2, 5);
233 SWAPmed(4, 7);
234 SWAPmed(4, 2);
235 SWAPmed(6, 4);
236 SWAPmed(4, 2);
237 outp[c] = fmaxf(med[4] + outp[1], 0.0f);
238 }
239 }
240 }
241 }
242}
243#undef SWAP
244
245static void green_equilibration_lavg(float *out, const float *const in, const int width, const int height,
246 const uint32_t filters, const int x, const int y, const float thr)
247{
248 const float maximum = 1.0f;
249
250 int oj = 2, oi = 2;
251 if(FC(oj + y, oi + x, filters) != 1) oj++;
252 if(FC(oj + y, oi + x, filters) != 1) oi++;
253 if(FC(oj + y, oi + x, filters) != 1) oj--;
254
256
257#ifdef _OPENMP
258#pragma omp parallel for default(none) \
259 dt_omp_firstprivate(height, in, thr, width, maximum) \
260 shared(out, oi, oj) \
261 schedule(static) collapse(2)
262#endif
263 for(size_t j = oj; j < height - 2; j += 2)
264 {
265 for(size_t i = oi; i < width - 2; i += 2)
266 {
267 const float o1_1 = in[(j - 1) * width + i - 1];
268 const float o1_2 = in[(j - 1) * width + i + 1];
269 const float o1_3 = in[(j + 1) * width + i - 1];
270 const float o1_4 = in[(j + 1) * width + i + 1];
271 const float o2_1 = in[(j - 2) * width + i];
272 const float o2_2 = in[(j + 2) * width + i];
273 const float o2_3 = in[j * width + i - 2];
274 const float o2_4 = in[j * width + i + 2];
275
276 const float m1 = (o1_1 + o1_2 + o1_3 + o1_4) / 4.0f;
277 const float m2 = (o2_1 + o2_2 + o2_3 + o2_4) / 4.0f;
278
279 // prevent divide by zero and ...
280 // guard against m1/m2 becoming too large (due to m2 being too small) which results in hot pixels
281 // also m1 must be checked to be positive
282 if((m2 > 0.0f) && (m1 > 0.0f) && (m1 / m2 < maximum * 2.0f))
283 {
284 const float c1 = (fabsf(o1_1 - o1_2) + fabsf(o1_1 - o1_3) + fabsf(o1_1 - o1_4) + fabsf(o1_2 - o1_3)
285 + fabsf(o1_3 - o1_4) + fabsf(o1_2 - o1_4)) / 6.0f;
286 const float c2 = (fabsf(o2_1 - o2_2) + fabsf(o2_1 - o2_3) + fabsf(o2_1 - o2_4) + fabsf(o2_2 - o2_3)
287 + fabsf(o2_3 - o2_4) + fabsf(o2_2 - o2_4)) / 6.0f;
288 if((in[j * width + i] < maximum * 0.95f) && (c1 < maximum * thr) && (c2 < maximum * thr))
289 {
290 out[j * width + i] = in[j * width + i] * m1 / m2;
291 }
292 }
293 }
294 }
295}
296
297static void green_equilibration_favg(float *out, const float *const in, const int width, const int height,
298 const uint32_t filters, const int x, const int y)
299{
300 int oj = 0, oi = 0;
301 // const float ratio_max = 1.1f;
302 double sum1 = 0.0, sum2 = 0.0, gr_ratio;
303
304 if((FC(oj + y, oi + x, filters) & 1) != 1) oi++;
305 const int g2_offset = oi ? -1 : 1;
307#ifdef _OPENMP
308#pragma omp parallel for default(none) \
309 dt_omp_firstprivate(g2_offset, height, in, width) \
310 reduction(+ : sum1, sum2) \
311 shared(oi, oj) \
312 schedule(static) collapse(2)
313#endif
314 for(size_t j = oj; j < (height - 1); j += 2)
315 {
316 for(size_t i = oi; i < (width - 1 - g2_offset); i += 2)
317 {
318 sum1 += in[j * width + i];
319 sum2 += in[(j + 1) * width + i + g2_offset];
320 }
321 }
322
323 if(sum1 > 0.0 && sum2 > 0.0)
324 gr_ratio = sum2 / sum1;
325 else
326 return;
327
328#ifdef _OPENMP
329#pragma omp parallel for default(none) \
330 dt_omp_firstprivate(g2_offset, height, in, width) \
331 shared(out, oi, oj, gr_ratio) \
332 schedule(static) collapse(2)
333#endif
334 for(int j = oj; j < (height - 1); j += 2)
335 {
336 for(int i = oi; i < (width - 1 - g2_offset); i += 2)
337 {
338 out[(size_t)j * width + i] = in[(size_t)j * width + i] * gr_ratio;
339 }
340 }
341}
342
343#ifdef HAVE_OPENCL
344
345// color smoothing step by multiple passes of median filtering
346static int color_smoothing_cl(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, cl_mem dev_in,
347 cl_mem dev_out, const dt_iop_roi_t *const roi_out, const int passes)
348{
350
351 const int devid = piece->pipe->devid;
352 const int width = roi_out->width;
353 const int height = roi_out->height;
354
355 cl_int err = -999;
356
357 cl_mem dev_tmp = dt_opencl_alloc_device(devid, width, height, sizeof(float) * 4);
358 if(dev_tmp == NULL) goto error;
359
360 dt_opencl_local_buffer_t locopt
361 = (dt_opencl_local_buffer_t){ .xoffset = 2*1, .xfactor = 1, .yoffset = 2*1, .yfactor = 1,
362 .cellsize = 4 * sizeof(float), .overhead = 0,
363 .sizex = 1 << 8, .sizey = 1 << 8 };
364
365 if(!dt_opencl_local_buffer_opt(devid, gd->kernel_color_smoothing, &locopt))
366 goto error;
367
368 // two buffer references for our ping-pong
369 cl_mem dev_t1 = dev_out;
370 cl_mem dev_t2 = dev_tmp;
371
372 for(int pass = 0; pass < passes; pass++)
373 {
374 size_t sizes[] = { ROUNDUP(width, locopt.sizex), ROUNDUP(height, locopt.sizey), 1 };
375 size_t local[] = { locopt.sizex, locopt.sizey, 1 };
376 dt_opencl_set_kernel_arg(devid, gd->kernel_color_smoothing, 0, sizeof(cl_mem), &dev_t1);
377 dt_opencl_set_kernel_arg(devid, gd->kernel_color_smoothing, 1, sizeof(cl_mem), &dev_t2);
378 dt_opencl_set_kernel_arg(devid, gd->kernel_color_smoothing, 2, sizeof(int), &width);
379 dt_opencl_set_kernel_arg(devid, gd->kernel_color_smoothing, 3, sizeof(int), &height);
380 dt_opencl_set_kernel_arg(devid, gd->kernel_color_smoothing, 4,
381 sizeof(float) * 4 * (locopt.sizex + 2) * (locopt.sizey + 2), NULL);
382 err = dt_opencl_enqueue_kernel_2d_with_local(devid, gd->kernel_color_smoothing, sizes, local);
383 if(err != CL_SUCCESS) goto error;
384
385 // swap dev_t1 and dev_t2
386 cl_mem t = dev_t1;
387 dev_t1 = dev_t2;
388 dev_t2 = t;
389 }
390
391 // after last step we find final output in dev_t1.
392 // let's see if this is in dev_tmp1 and needs to be copied to dev_out
393 if(dev_t1 == dev_tmp)
394 {
395 // copy data from dev_tmp -> dev_out
396 size_t origin[] = { 0, 0, 0 };
397 size_t region[] = { width, height, 1 };
398 err = dt_opencl_enqueue_copy_image(devid, dev_tmp, dev_out, origin, origin, region);
399 if(err != CL_SUCCESS) goto error;
400 }
401
403 return TRUE;
404
405error:
407 dt_print(DT_DEBUG_OPENCL, "[opencl_demosaic_color_smoothing] couldn't enqueue kernel! %d\n", err);
408 return FALSE;
409}
410
411static int green_equilibration_cl(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, cl_mem dev_in,
412 cl_mem dev_out, const dt_iop_roi_t *const roi_in)
413{
416
417 const int devid = piece->pipe->devid;
418 const int width = roi_in->width;
419 const int height = roi_in->height;
420
421 cl_mem dev_tmp = NULL;
422 cl_mem dev_m = NULL;
423 cl_mem dev_r = NULL;
424 cl_mem dev_in1 = NULL;
425 cl_mem dev_out1 = NULL;
426 cl_mem dev_in2 = NULL;
427 cl_mem dev_out2 = NULL;
428 float *sumsum = NULL;
429
430 cl_int err = -999;
431
432 if(data->green_eq == DT_IOP_GREEN_EQ_BOTH)
433 {
434 dev_tmp = dt_opencl_alloc_device(devid, width, height, sizeof(float));
435 if(dev_tmp == NULL) goto error;
436 }
437
438 switch(data->green_eq)
439 {
441 dev_in1 = dev_in;
442 dev_out1 = dev_out;
443 break;
445 dev_in2 = dev_in;
446 dev_out2 = dev_out;
447 break;
449 dev_in1 = dev_in;
450 dev_out1 = dev_tmp;
451 dev_in2 = dev_tmp;
452 dev_out2 = dev_out;
453 break;
455 default:
456 goto error;
457 }
458
459 if(data->green_eq == DT_IOP_GREEN_EQ_FULL || data->green_eq == DT_IOP_GREEN_EQ_BOTH)
460 {
461 dt_opencl_local_buffer_t flocopt
462 = (dt_opencl_local_buffer_t){ .xoffset = 0, .xfactor = 1, .yoffset = 0, .yfactor = 1,
463 .cellsize = 2 * sizeof(float), .overhead = 0,
464 .sizex = 1 << 4, .sizey = 1 << 4 };
465
466 if(!dt_opencl_local_buffer_opt(devid, gd->kernel_green_eq_favg_reduce_first, &flocopt))
467 goto error;
468
469 const size_t bwidth = ROUNDUP(width, flocopt.sizex);
470 const size_t bheight = ROUNDUP(height, flocopt.sizey);
471
472 const int bufsize = (bwidth / flocopt.sizex) * (bheight / flocopt.sizey);
473
474 dev_m = dt_opencl_alloc_device_buffer(devid, sizeof(float) * 2 * bufsize);
475 if(dev_m == NULL) goto error;
476
477 size_t fsizes[3] = { bwidth, bheight, 1 };
478 size_t flocal[3] = { flocopt.sizex, flocopt.sizey, 1 };
479 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_favg_reduce_first, 0, sizeof(cl_mem), &dev_in1);
480 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_favg_reduce_first, 1, sizeof(int), &width);
481 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_favg_reduce_first, 2, sizeof(int), &height);
482 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_favg_reduce_first, 3, sizeof(cl_mem), &dev_m);
483 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_favg_reduce_first, 4, sizeof(uint32_t), (void *)&piece->pipe->dsc.filters);
484 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_favg_reduce_first, 5, sizeof(int), &roi_in->x);
485 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_favg_reduce_first, 6, sizeof(int), &roi_in->y);
486 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_favg_reduce_first, 7,
487 sizeof(float) * 2 * flocopt.sizex * flocopt.sizey, NULL);
488 err = dt_opencl_enqueue_kernel_2d_with_local(devid, gd->kernel_green_eq_favg_reduce_first, fsizes,
489 flocal);
490 if(err != CL_SUCCESS) goto error;
491
492 dt_opencl_local_buffer_t slocopt
493 = (dt_opencl_local_buffer_t){ .xoffset = 0, .xfactor = 1, .yoffset = 0, .yfactor = 1,
494 .cellsize = sizeof(float) * 2, .overhead = 0,
495 .sizex = 1 << 16, .sizey = 1 };
496
497 if(!dt_opencl_local_buffer_opt(devid, gd->kernel_green_eq_favg_reduce_second, &slocopt))
498 goto error;
499
500 const int reducesize = MIN(REDUCESIZE, ROUNDUP(bufsize, slocopt.sizex) / slocopt.sizex);
501
502 dev_r = dt_opencl_alloc_device_buffer(devid, sizeof(float) * 2 * reducesize);
503 if(dev_r == NULL) goto error;
504
505 size_t ssizes[3] = { (size_t)reducesize * slocopt.sizex, 1, 1 };
506 size_t slocal[3] = { slocopt.sizex, 1, 1 };
507 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_favg_reduce_second, 0, sizeof(cl_mem), &dev_m);
508 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_favg_reduce_second, 1, sizeof(cl_mem), &dev_r);
509 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_favg_reduce_second, 2, sizeof(int), &bufsize);
510 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_favg_reduce_second, 3, sizeof(float) * 2 * slocopt.sizex, NULL);
511 err = dt_opencl_enqueue_kernel_2d_with_local(devid, gd->kernel_green_eq_favg_reduce_second, ssizes,
512 slocal);
513 if(err != CL_SUCCESS) goto error;
514
515 sumsum = dt_alloc_align_float((size_t)2 * reducesize);
516 if(sumsum == NULL) goto error;
517 err = dt_opencl_read_buffer_from_device(devid, (void *)sumsum, dev_r, 0,
518 sizeof(float) * 2 * reducesize, CL_TRUE);
519 if(err != CL_SUCCESS) goto error;
520
521 float sum1 = 0.0f, sum2 = 0.0f;
522 for(int k = 0; k < reducesize; k++)
523 {
524 sum1 += sumsum[2 * k];
525 sum2 += sumsum[2 * k + 1];
526 }
527
528 const float gr_ratio = (sum1 > 0.0f && sum2 > 0.0f) ? sum2 / sum1 : 1.0f;
529
530 size_t asizes[3] = { ROUNDUPDWD(width, devid), ROUNDUPDHT(height, devid), 1 };
531 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_favg_apply, 0, sizeof(cl_mem), &dev_in1);
532 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_favg_apply, 1, sizeof(cl_mem), &dev_out1);
533 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_favg_apply, 2, sizeof(int), &width);
534 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_favg_apply, 3, sizeof(int), &height);
535 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_favg_apply, 4, sizeof(uint32_t), (void *)&piece->pipe->dsc.filters);
536 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_favg_apply, 5, sizeof(int), &roi_in->x);
537 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_favg_apply, 6, sizeof(int), &roi_in->y);
538 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_favg_apply, 7, sizeof(float), &gr_ratio);
539 err = dt_opencl_enqueue_kernel_2d(devid, gd->kernel_green_eq_favg_apply, asizes);
540 if(err != CL_SUCCESS) goto error;
541 }
542
543 if(data->green_eq == DT_IOP_GREEN_EQ_LOCAL || data->green_eq == DT_IOP_GREEN_EQ_BOTH)
544 {
545 const dt_image_t *img = &self->dev->image_storage;
546 const float threshold = 0.0001f * img->exif_iso;
547
548 dt_opencl_local_buffer_t locopt
549 = (dt_opencl_local_buffer_t){ .xoffset = 2*2, .xfactor = 1, .yoffset = 2*2, .yfactor = 1,
550 .cellsize = 1 * sizeof(float), .overhead = 0,
551 .sizex = 1 << 8, .sizey = 1 << 8 };
552
553 if(!dt_opencl_local_buffer_opt(devid, gd->kernel_green_eq_lavg, &locopt))
554 goto error;
555
556 size_t sizes[3] = { ROUNDUP(width, locopt.sizex), ROUNDUP(height, locopt.sizey), 1 };
557 size_t local[3] = { locopt.sizex, locopt.sizey, 1 };
558 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_lavg, 0, sizeof(cl_mem), &dev_in2);
559 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_lavg, 1, sizeof(cl_mem), &dev_out2);
560 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_lavg, 2, sizeof(int), &width);
561 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_lavg, 3, sizeof(int), &height);
562 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_lavg, 4, sizeof(uint32_t), (void *)&piece->pipe->dsc.filters);
563 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_lavg, 5, sizeof(int), &roi_in->x);
564 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_lavg, 6, sizeof(int), &roi_in->y);
565 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_lavg, 7, sizeof(float), (void *)&threshold);
566 dt_opencl_set_kernel_arg(devid, gd->kernel_green_eq_lavg, 8,
567 sizeof(float) * (locopt.sizex + 4) * (locopt.sizey + 4), NULL);
568 err = dt_opencl_enqueue_kernel_2d_with_local(devid, gd->kernel_green_eq_lavg, sizes, local);
569 if(err != CL_SUCCESS) goto error;
570 }
571
575 dt_free_align(sumsum);
576 return TRUE;
577
578error:
582 dt_free_align(sumsum);
583 dt_print(DT_DEBUG_OPENCL, "[opencl_demosaic_green_equilibration] couldn't enqueue kernel! %d\n", err);
584 return FALSE;
585}
586
587#endif // HAVE_OPENCL
588
589// clang-format off
590// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
591// vim: shiftwidth=2 expandtab tabstop=2 cindent
592// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
593// clang-format on
static void error(char *msg)
Definition ashift_lsd.c:191
#define TRUE
Definition ashift_lsd.c:151
#define FALSE
Definition ashift_lsd.c:147
static void lin_interpolate(float *out, const float *const in, const dt_iop_roi_t *const roi_out, const dt_iop_roi_t *const roi_in, const uint32_t filters, const uint8_t(*const xtrans)[6])
Definition basic.c:4
static void green_equilibration_favg(float *out, const float *const in, const int width, const int height, const uint32_t filters, const int x, const int y)
Definition basic.c:297
static void pre_median_b(float *out, const float *const in, const dt_iop_roi_t *const roi, const uint32_t filters, const int num_passes, const float threshold)
Definition basic.c:127
static void green_equilibration_lavg(float *out, const float *const in, const int width, const int height, const uint32_t filters, const int x, const int y, const float thr)
Definition basic.c:245
#define SWAPmed(I, J)
Definition basic.c:183
static void pre_median(float *out, const float *const in, const dt_iop_roi_t *const roi, const uint32_t filters, const int num_passes, const float threshold)
Definition basic.c:177
#define SWAP(a, b)
Definition basic.c:117
static void color_smoothing(float *out, const dt_iop_roi_t *const roi_out, const int num_passes)
Definition basic.c:186
int width
Definition bilateral.h:1
int height
Definition bilateral.h:1
static float lookup(read_only image2d_t lut, const float x)
Definition color_conversion.h:70
void dt_print(dt_debug_thread_t thread, const char *msg,...)
Definition darktable.c:1395
@ DT_DEBUG_OPENCL
Definition darktable.h:478
static float * dt_alloc_align_float(size_t pixels)
Definition darktable.h:345
#define dt_free_align(A)
Definition darktable.h:334
static int FC(const int row, const int col, const unsigned int filters)
Definition data/kernels/common.h:43
#define REDUCESIZE
Definition demosaic.c:62
@ DT_IOP_GREEN_EQ_LOCAL
Definition demosaic.c:94
@ DT_IOP_GREEN_EQ_FULL
Definition demosaic.c:95
@ DT_IOP_GREEN_EQ_BOTH
Definition demosaic.c:96
@ DT_IOP_GREEN_EQ_NO
Definition demosaic.c:93
static void weight(const float *c1, const float *c2, const float sharpen, dt_aligned_pixel_t weight)
Definition eaw.c:29
const dt_collection_filter_flag_t colors[6]
Definition filter.c:274
static float f(const float t, const float c, const float x)
Definition graduatednd.c:173
static void dt_iop_image_copy_by_size(float *const __restrict__ out, const float *const __restrict__ in, const size_t width, const size_t height, const size_t ch)
Definition imagebuf.h:88
static int fcol(const int row, const int col, const uint32_t filters, const uint8_t(*const xtrans)[6])
Definition imageop_math.h:222
size_t size
Definition mipmap_cache.c:3
k
Definition derive_filmic_v6_gamut_mapping.py:43
static int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
Definition opencl.h:560
static int dt_opencl_set_kernel_arg(const int dev, const int kernel, const size_t size, const void *arg)
Definition opencl.h:556
static void dt_opencl_release_mem_object(void *mem)
Definition opencl.h:601
static int dt_opencl_enqueue_kernel_2d_with_local(const int dev, const int kernel, const size_t *sizes, const size_t *local)
Definition opencl.h:564
Definition pixelpipe_hb.h:46
void * data
Definition pixelpipe_hb.h:49
Definition common/image.h:195
float exif_iso
Definition common/image.h:202
Definition demosaic.c:187
Definition demosaic.c:129
Definition imageop.h:182
dt_iop_global_data_t * global_data
Definition imageop.h:245
Definition imageop.h:32
int x
Definition imageop.h:33
int width
Definition imageop.h:33
int height
Definition imageop.h:33
int y
Definition imageop.h:33
#define c2
#define c1
#define MIN(a, b)
Definition thinplate.c:23