Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
dual.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2010-2021 darktable developers.
4
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.
9
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.
14
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/>.
17*/
18
19/*
20 Dual demosaicing has been implemented by Ingo Weyrich <heckflosse67@gmx.de> for
21 rawtherapee under GNU General Public License Version 3
22 and has been modified to work for darktable by Hanno Schwalm (hanno@schwalm-bremen.de).
23 Also the code for dt_masks_blur_9x9 has been taken from rawtherapee capturesharpening,
24 implemented also by Ingo Weyrich.
25*/
26
27
28static float slider2contrast(float slider)
29{
30 return 0.005f * powf(slider, 1.1f);
31}
32static void dual_demosaic(dt_dev_pixelpipe_iop_t *piece, float *const restrict rgb_data, const float *const restrict raw_data,
33 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],
34 const gboolean dual_mask, float dual_threshold)
35{
36 const int width = roi_in->width;
37 const int height = roi_in->height;
38 if((width < 16) || (height < 16)) return;
39
40 // If the threshold is zero and we don't want to see the blend mask we don't do anything
41 if(dual_threshold <= 0.0f) return;
42
43 float *blend = dt_alloc_align_float((size_t) width * height);
44 float *tmp = dt_alloc_align_float((size_t) width * height);
45 float *vng_image = dt_alloc_align_float((size_t) 4 * width * height);
46 if(!blend || !tmp || !vng_image)
47 {
48 if(tmp) dt_free_align(tmp);
49 if(blend) dt_free_align(blend);
50 if(vng_image) dt_free_align(vng_image);
51 dt_control_log(_("[dual demosaic] can't allocate internal buffers"));
52 return;
53 }
54 const gboolean info = ((darktable.unmuted & (DT_DEBUG_DEMOSAIC | DT_DEBUG_PERF)) && (piece->pipe->type == DT_DEV_PIXELPIPE_FULL));
55
56 vng_interpolate(vng_image, raw_data, roi_out, roi_in, filters, xtrans, FALSE);
57 color_smoothing(vng_image, roi_out, 2);
58
59 dt_times_t start_blend = { 0 }, end_blend = { 0 };
60 if(info) dt_get_times(&start_blend);
61
62 const float contrastf = slider2contrast(dual_threshold);
63
64 dt_masks_calc_rawdetail_mask(rgb_data, blend, tmp, width, height, piece->pipe->dsc.temperature.coeffs);
65 dt_masks_calc_detail_mask(blend, blend, tmp, width, height, contrastf, TRUE);
66
67 if(dual_mask)
68 {
69 piece->pipe->mask_display = DT_DEV_PIXELPIPE_DISPLAY_PASSTHRU;
70#ifdef _OPENMP
71 #pragma omp parallel for simd default(none) \
72 dt_omp_firstprivate(blend, rgb_data, vng_image, width, height) \
73 schedule(simd:static) aligned(blend, vng_image, rgb_data : 64)
74#endif
75 for(int idx = 0; idx < width * height; idx++)
76 {
77 for(int c = 0; c < 4; c++)
78 rgb_data[idx * 4 + c] = blend[idx];
79 }
80 }
81 else
82 {
83#ifdef _OPENMP
84 #pragma omp parallel for simd default(none) \
85 dt_omp_firstprivate(blend, rgb_data, vng_image, width, height) \
86 schedule(simd:static) aligned(blend, vng_image, rgb_data : 64)
87#endif
88 for(int idx = 0; idx < width * height; idx++)
89 {
90 const int oidx = 4 * idx;
91 for(int c = 0; c < 4; c++)
92 rgb_data[oidx + c] = intp(blend[idx], rgb_data[oidx + c], vng_image[oidx + c]);
93 }
94 }
95 if(info)
96 {
97 dt_get_times(&end_blend);
98 fprintf(stderr," [demosaic] CPU dual blending %.4f secs (%.4f CPU)\n", end_blend.clock - start_blend.clock, end_blend.user - start_blend.user);
99 }
100 dt_free_align(tmp);
101 dt_free_align(blend);
102 dt_free_align(vng_image);
103}
104
105#ifdef HAVE_OPENCL
106gboolean dual_demosaic_cl(struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, cl_mem detail, cl_mem blend, cl_mem high_image, cl_mem low_image, cl_mem out, const int width, const int height, const int showmask)
107{
108 const int devid = piece->pipe->devid;
111
112 const float contrastf = slider2contrast(data->dual_thrs);
113 if(showmask)
114 piece->pipe->mask_display = DT_DEV_PIXELPIPE_DISPLAY_PASSTHRU;
115
116 {
117 size_t sizes[3] = { ROUNDUPDWD(width, devid), ROUNDUPDHT(height, devid), 1 };
118 const dt_aligned_pixel_t wb = { piece->pipe->dsc.temperature.coeffs[0], piece->pipe->dsc.temperature.coeffs[1],
119 piece->pipe->dsc.temperature.coeffs[2] };
120 const int kernel = darktable.opencl->blendop->kernel_calc_Y0_mask;
121 dt_opencl_set_kernel_arg(devid, kernel, 0, sizeof(cl_mem), &detail);
122 dt_opencl_set_kernel_arg(devid, kernel, 1, sizeof(cl_mem), &high_image);
123 dt_opencl_set_kernel_arg(devid, kernel, 2, sizeof(int), &width);
124 dt_opencl_set_kernel_arg(devid, kernel, 3, sizeof(int), &height);
125 dt_opencl_set_kernel_arg(devid, kernel, 4, sizeof(float), &wb[0]);
126 dt_opencl_set_kernel_arg(devid, kernel, 5, sizeof(float), &wb[1]);
127 dt_opencl_set_kernel_arg(devid, kernel, 6, sizeof(float), &wb[2]);
128 const int err = dt_opencl_enqueue_kernel_2d(devid, kernel, sizes);
129 if(err != CL_SUCCESS) return FALSE;
130 }
131
132 {
133 size_t sizes[3] = { ROUNDUPDWD(width, devid), ROUNDUPDHT(height, devid), 1 };
134 const int kernel = darktable.opencl->blendop->kernel_calc_scharr_mask;
135 dt_opencl_set_kernel_arg(devid, kernel, 0, sizeof(cl_mem), &detail);
136 dt_opencl_set_kernel_arg(devid, kernel, 1, sizeof(cl_mem), &blend);
137 dt_opencl_set_kernel_arg(devid, kernel, 2, sizeof(int), &width);
138 dt_opencl_set_kernel_arg(devid, kernel, 3, sizeof(int), &height);
139 const int err = dt_opencl_enqueue_kernel_2d(devid, kernel, sizes);
140 if(err != CL_SUCCESS) return FALSE;
141 }
142
143 {
144 const int flag = 1;
145 size_t sizes[3] = { ROUNDUPDWD(width, devid), ROUNDUPDHT(height, devid), 1 };
146 const int kernel = darktable.opencl->blendop->kernel_calc_blend;
147 dt_opencl_set_kernel_arg(devid, kernel, 0, sizeof(cl_mem), &blend);
148 dt_opencl_set_kernel_arg(devid, kernel, 1, sizeof(cl_mem), &detail);
149 dt_opencl_set_kernel_arg(devid, kernel, 2, sizeof(int), &width);
150 dt_opencl_set_kernel_arg(devid, kernel, 3, sizeof(int), &height);
151 dt_opencl_set_kernel_arg(devid, kernel, 4, sizeof(float), &contrastf);
152 dt_opencl_set_kernel_arg(devid, kernel, 5, sizeof(int), &flag);
153 const int err = dt_opencl_enqueue_kernel_2d(devid, kernel, sizes);
154 if(err != CL_SUCCESS) return FALSE;
155 }
156
157 {
158 float blurmat[13];
159 dt_masks_blur_9x9_coeff(blurmat, 2.0f);
160 cl_mem dev_blurmat = NULL;
161 dev_blurmat = dt_opencl_copy_host_to_device_constant(devid, sizeof(float) * 13, blurmat);
162 if(dev_blurmat != NULL)
163 {
164 size_t sizes[3] = { ROUNDUPDWD(width, devid), ROUNDUPDHT(height, devid), 1 };
165 const int clkernel = darktable.opencl->blendop->kernel_mask_blur;
166 dt_opencl_set_kernel_arg(devid, clkernel, 0, sizeof(cl_mem), &detail);
167 dt_opencl_set_kernel_arg(devid, clkernel, 1, sizeof(cl_mem), &blend);
168 dt_opencl_set_kernel_arg(devid, clkernel, 2, sizeof(int), &width);
169 dt_opencl_set_kernel_arg(devid, clkernel, 3, sizeof(int), &height);
170 dt_opencl_set_kernel_arg(devid, clkernel, 4, sizeof(cl_mem), (void *) &dev_blurmat);
171 const int err = dt_opencl_enqueue_kernel_2d(devid, clkernel, sizes);
172 dt_opencl_release_mem_object(dev_blurmat);
173 if(err != CL_SUCCESS) return FALSE;
174 }
175 else
176 {
177 dt_opencl_release_mem_object(dev_blurmat);
178 return FALSE;
179 }
180 }
181
182 {
183 size_t sizes[3] = { ROUNDUPDWD(width, devid), ROUNDUPDHT(height, devid), 1 };
184 dt_opencl_set_kernel_arg(devid, gd->kernel_write_blended_dual, 0, sizeof(cl_mem), &high_image);
185 dt_opencl_set_kernel_arg(devid, gd->kernel_write_blended_dual, 1, sizeof(cl_mem), &low_image);
186 dt_opencl_set_kernel_arg(devid, gd->kernel_write_blended_dual, 2, sizeof(cl_mem), &out);
187 dt_opencl_set_kernel_arg(devid, gd->kernel_write_blended_dual, 3, sizeof(int), &width);
188 dt_opencl_set_kernel_arg(devid, gd->kernel_write_blended_dual, 4, sizeof(int), &height);
189 dt_opencl_set_kernel_arg(devid, gd->kernel_write_blended_dual, 5, sizeof(cl_mem), &blend);
190 dt_opencl_set_kernel_arg(devid, gd->kernel_write_blended_dual, 6, sizeof(int), &showmask);
191 const int err = dt_opencl_enqueue_kernel_2d(devid, gd->kernel_write_blended_dual, sizes);
192 if(err != CL_SUCCESS) return FALSE;
193 }
194
195 return TRUE;
196}
197#endif
198
199// clang-format off
200// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
201// vim: shiftwidth=2 expandtab tabstop=2 cindent
202// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
203// clang-format on
#define TRUE
Definition ashift_lsd.c:151
#define FALSE
Definition ashift_lsd.c:147
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 intp(const float a, const float b, const float c)
Definition cacorrect.c:141
static float kernel(const float *x, const float *y)
Definition colorchecker.c:435
const char flag
Definition common/image.h:164
void dt_control_log(const char *msg,...)
Definition control.c:424
darktable_t darktable
Definition darktable.c:111
@ DT_DEBUG_DEMOSAIC
Definition darktable.h:493
@ DT_DEBUG_PERF
Definition darktable.h:475
static float * dt_alloc_align_float(size_t pixels)
Definition darktable.h:345
static void dt_get_times(dt_times_t *t)
Definition darktable.h:693
#define dt_free_align(A)
Definition darktable.h:334
@ DT_DEV_PIXELPIPE_DISPLAY_PASSTHRU
Definition develop.h:100
static float slider2contrast(float slider)
Definition dual.c:28
static void dual_demosaic(dt_dev_pixelpipe_iop_t *piece, float *const restrict rgb_data, const float *const restrict raw_data, 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], const gboolean dual_mask, float dual_threshold)
Definition dual.c:32
void dt_masks_calc_detail_mask(float *const src, float *const out, float *const tmp, const int width, const int height, const float threshold, const gboolean detail)
void dt_masks_blur_9x9_coeff(float *coeffs, const float sigma)
Definition detail.c:163
void dt_masks_calc_rawdetail_mask(float *const src, float *const out, float *const tmp, const int width, const int height, const dt_aligned_pixel_t wb)
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
@ DT_DEV_PIXELPIPE_FULL
Definition pixelpipe.h:31
struct dt_opencl_t * opencl
Definition darktable.h:551
int32_t unmuted
Definition darktable.h:526
Definition pixelpipe_hb.h:46
struct dt_iop_module_t *struct dt_dev_pixelpipe_t * pipe
Definition pixelpipe_hb.h:48
void * data
Definition pixelpipe_hb.h:49
Definition demosaic.c:187
Definition demosaic.c:129
Definition imageop.h:182
Definition imageop.h:32
int width
Definition imageop.h:33
int height
Definition imageop.h:33
Definition darktable.h:605
double clock
Definition darktable.h:606
double user
Definition darktable.h:607
static void vng_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], const int only_vng_linear)
Definition vng.c:15