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