Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
detailmask.c
Go to the documentation of this file.
1/*
2 This file is part of Ansel,
3 Copyright (C) 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#ifdef HAVE_CONFIG_H
20#include "config.h"
22#endif
23
24#include "common/imagebuf.h"
25#include "pixel/interpolation.h"
26#include "common/opencl.h"
27#include "develop/blend.h"
28#include "develop/develop.h"
29#include "system/macros.h"
30#include "system/mem_alloc.h"
31#include "system/simd.h"
32#include "common/logging.h"
34#include "develop/imageop.h"
36#include "develop/pixelpipe.h"
37#include "iop/iop_api.h"
38#include <glib/gi18n.h>
39
41
46
48
49const char *name()
50{
51 return _("detail mask");
52}
53
55{
57}
58
63
68
71{
72 default_input_format(self, pipe, piece, dsc);
73 dsc->channels = 4;
74 dsc->datatype = TYPE_FLOAT;
76}
77
80{
81 default_output_format(self, pipe, piece, dsc);
82 dsc->channels = 4;
83 dsc->datatype = TYPE_FLOAT;
85}
86
87void distort_mask(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe,
88 struct dt_dev_pixelpipe_iop_t *piece, const float *const in, float *const out,
89 const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out)
90{
91 if((roi_in->scale == roi_out->scale)
92 && (roi_in->width == roi_out->width)
93 && (roi_in->height == roi_out->height)
94 && (roi_in->x == roi_out->x)
95 && (roi_in->y == roi_out->y))
96 {
97 dt_iop_copy_image_roi(out, in, 1, roi_in, roi_out, TRUE);
98 return;
99 }
100
102 dt_interpolation_resample_roi_1c(itor, out, roi_out, in, roi_in);
103}
104
105int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece,
106 const void *const ivoid, void *const ovoid)
107{
108 dt_dev_pixelpipe_t *const mutable_pipe = (dt_dev_pixelpipe_t *)pipe;
109 const dt_iop_roi_t *const roi_out = &piece->roi_out;
110 const uint64_t mask_hash = dt_dev_pixelpipe_rawdetail_mask_hash(piece);
111 const int width = roi_out->width;
112 const int height = roi_out->height;
113 dt_pixel_cache_entry_t *entry = NULL;
114 void *cache_data = NULL;
115 float *mask = NULL;
116 float *tmp = NULL;
117 int created = 0;
118
120 dt_dev_clear_rawdetail_mask(mutable_pipe);
121
122 created = dt_dev_pixelpipe_cache_get(mask_hash, sizeof(float) * (size_t)width * height,
123 "detailmask rawdetail", pipe->type, TRUE, &cache_data, &entry);
124 mask = (float *)cache_data;
125 if(IS_NULL_PTR(mask) || IS_NULL_PTR(entry)) goto error;
126
127 mutable_pipe->rawdetail_mask_hash = mask_hash;
128 memcpy(&mutable_pipe->rawdetail_mask_roi, roi_out, sizeof(dt_iop_roi_t));
129 if(!created) return 0;
130
132 if(IS_NULL_PTR(tmp)) goto error;
133
134 dt_aligned_pixel_t wb = { 1.0f, 1.0f, 1.0f };
135 if(piece->dsc_in.temperature.enabled)
136 {
137 wb[0] = piece->dsc_in.temperature.coeffs[0];
138 wb[1] = piece->dsc_in.temperature.coeffs[1];
139 wb[2] = piece->dsc_in.temperature.coeffs[2];
140 }
141
142 /* This stage always sees tightly-packed RGBA float pixels, so the luminance
143 * input uses an explicit 4-float stride while the Scharr operator runs on the
144 * 1-float-per-pixel temporary buffer. No CFA layout survives past demosaic. */
145 dt_masks_calc_rawdetail_mask((float *const)ovoid, mask, tmp, width, height, wb);
148 dt_print(DT_DEBUG_MASKS, "[detailmask process] (%ix%i)\n", width, height);
149
150 return 0;
151
152error:
153 fprintf(stderr, "[detailmask process] couldn't write detail mask\n");
154 if(created && !IS_NULL_PTR(entry))
156 dt_dev_clear_rawdetail_mask(mutable_pipe);
157 if(!IS_NULL_PTR(entry))
158 {
159 if(created) dt_dev_pixelpipe_cache_remove(TRUE, entry);
160 }
162 return 1;
163}
164
165#ifdef HAVE_OPENCL
166int process_cl(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece,
167 cl_mem dev_in, cl_mem dev_out)
168{
169 dt_dev_pixelpipe_t *const mutable_pipe = (dt_dev_pixelpipe_t *)pipe;
170 const dt_iop_roi_t *const roi_out = &piece->roi_out;
171 const int devid = pipe->devid;
172 const uint64_t mask_hash = dt_dev_pixelpipe_rawdetail_mask_hash(piece);
173 const int width = roi_out->width;
174 const int height = roi_out->height;
175 dt_pixel_cache_entry_t *entry = NULL;
176 void *cache_data = NULL;
177 cl_mem detail = NULL;
178 cl_mem mask_dev = NULL;
179 float *mask = NULL;
180 cl_int err = CL_SUCCESS;
181 int created = 0;
182
183 size_t origin[3] = { 0, 0, 0 };
184 size_t region[3] = { (size_t)width, (size_t)height, 1 };
185 if(dt_opencl_enqueue_copy_image(devid, dev_in, dev_out, origin, origin, region) != CL_SUCCESS)
186 return FALSE;
187
188 dt_dev_clear_rawdetail_mask(mutable_pipe);
189 created = dt_dev_pixelpipe_cache_get(mask_hash, sizeof(float) * (size_t)width * height,
190 "detailmask rawdetail", pipe->type, TRUE, &cache_data, &entry);
191 mask = (float *)cache_data;
192 if(IS_NULL_PTR(mask) || IS_NULL_PTR(entry)) goto error;
193
194 mutable_pipe->rawdetail_mask_hash = mask_hash;
195 memcpy(&mutable_pipe->rawdetail_mask_roi, roi_out, sizeof(dt_iop_roi_t));
196 if(!created) return TRUE;
197
198 detail = dt_opencl_alloc_device_buffer(devid, sizeof(float) * width * height);
199 if(IS_NULL_PTR(detail)) goto error;
200 mask_dev = dt_opencl_alloc_device_buffer(devid, sizeof(float) * width * height);
201 if(IS_NULL_PTR(mask_dev)) goto error;
202
203 {
205 dt_aligned_pixel_t wb = { 1.0f, 1.0f, 1.0f };
206 if(piece->dsc_in.temperature.enabled)
207 {
208 wb[0] = piece->dsc_in.temperature.coeffs[0];
209 wb[1] = piece->dsc_in.temperature.coeffs[1];
210 wb[2] = piece->dsc_in.temperature.coeffs[2];
211 }
212
213 size_t sizes[3] = { ROUNDUPDWD(width, devid), ROUNDUPDHT(height, devid), 1 };
214 dt_opencl_set_kernel_arg(devid, kernel, 0, sizeof(cl_mem), &detail);
215 dt_opencl_set_kernel_arg(devid, kernel, 1, sizeof(cl_mem), &dev_out);
216 dt_opencl_set_kernel_arg(devid, kernel, 2, sizeof(int), &width);
217 dt_opencl_set_kernel_arg(devid, kernel, 3, sizeof(int), &height);
218 dt_opencl_set_kernel_arg(devid, kernel, 4, sizeof(float), &wb[0]);
219 dt_opencl_set_kernel_arg(devid, kernel, 5, sizeof(float), &wb[1]);
220 dt_opencl_set_kernel_arg(devid, kernel, 6, sizeof(float), &wb[2]);
221 err = dt_opencl_enqueue_kernel_2d(devid, kernel, sizes);
222 if(err != CL_SUCCESS) goto error;
223 }
224
225 {
227 size_t sizes[3] = { ROUNDUPDWD(width, devid), ROUNDUPDHT(height, devid), 1 };
228 dt_opencl_set_kernel_arg(devid, kernel, 0, sizeof(cl_mem), &detail);
229 dt_opencl_set_kernel_arg(devid, kernel, 1, sizeof(cl_mem), &mask_dev);
230 dt_opencl_set_kernel_arg(devid, kernel, 2, sizeof(int), &width);
231 dt_opencl_set_kernel_arg(devid, kernel, 3, sizeof(int), &height);
232 err = dt_opencl_enqueue_kernel_2d(devid, kernel, sizes);
233 if(err != CL_SUCCESS) goto error;
234 }
235
236 err = dt_opencl_read_buffer_from_device(devid, mask, mask_dev, 0, sizeof(float) * (size_t)width * height, CL_TRUE);
237 if(err != CL_SUCCESS) goto error;
238
242 dt_print(DT_DEBUG_MASKS, "[detailmask process_cl] (%ix%i)\n", width, height);
243
244 return TRUE;
245
246error:
247 fprintf(stderr, "[detailmask process_cl] couldn't write detail mask: %i\n", err);
248 if(created && !IS_NULL_PTR(entry))
250 dt_dev_clear_rawdetail_mask(mutable_pipe);
251 if(!IS_NULL_PTR(entry))
252 {
253 if(created) dt_dev_pixelpipe_cache_remove(TRUE, entry);
254 }
257 return FALSE;
258}
259#endif
260
263{
264 memcpy(piece->data, params, sizeof(dt_iop_detailmask_params_t));
265 piece->process_tiling_ready = 0;
266}
267
269{
271 piece->data_size = sizeof(dt_iop_detailmask_data_t);
272 piece->enabled = FALSE;
273}
274
276{
277 dt_free_align(piece->data);
278 piece->data = NULL;
279}
280
282{
283 dt_iop_default_init(module);
284 module->default_enabled = 0;
285}
286
287
288// clang-format off
289// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
290// vim: shiftwidth=2 expandtab tabstop=2 cindent
291// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
292// 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
dt_blendop_cl_global_t * dt_develop_blend_get_cl_global(void)
Definition blend.c:72
@ IOP_CS_RGB
const dt_colormatrix_t dt_aligned_pixel_t out
__DT_CLONE_TARGETS__ void dt_masks_calc_rawdetail_mask(float *const restrict src, float *const restrict mask, float *const restrict tmp, const int width, const int height, const dt_aligned_pixel_t wb)
Definition detail.c:289
void init(dt_iop_module_t *module)
Definition detailmask.c:281
void distort_mask(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, struct dt_dev_pixelpipe_iop_t *piece, const float *const in, float *const out, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out)
Definition detailmask.c:87
int default_group()
Definition detailmask.c:54
struct dt_iop_detailmask_params_t dt_iop_detailmask_data_t
Definition detailmask.c:47
const char * name()
Definition detailmask.c:49
void output_format(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_iop_buffer_dsc_t *dsc)
Definition detailmask.c:78
void cleanup_pipe(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition detailmask.c:275
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
Definition detailmask.c:64
void input_format(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_iop_buffer_dsc_t *dsc)
Definition detailmask.c:69
int flags()
Definition detailmask.c:59
void commit_params(dt_iop_module_t *self, dt_iop_params_t *params, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition detailmask.c:261
int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid, void *const ovoid)
Definition detailmask.c:105
void init_pipe(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
Definition detailmask.c:268
int process_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)
Definition detailmask.c:166
void dt_iop_params_t
Definition dev_history.h:43
void default_output_format(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_iop_buffer_dsc_t *dsc)
void default_input_format(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_iop_buffer_dsc_t *dsc)
@ TYPE_FLOAT
Definition format.h:56
void dt_iop_copy_image_roi(float *const __restrict__ out, const float *const __restrict__ in, const size_t ch, const dt_iop_roi_t *const __restrict__ roi_in, const dt_iop_roi_t *const __restrict__ roi_out, const int zero_pad)
Definition imagebuf.c:163
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:91
void dt_iop_default_init(dt_iop_module_t *module)
Definition imageop.c:308
@ IOP_FLAGS_HIDDEN
Definition imageop.h:189
@ IOP_FLAGS_ONE_INSTANCE
Definition imageop.h:191
@ IOP_FLAGS_NO_HISTORY_STACK
Definition imageop.h:193
@ IOP_GROUP_TECHNICAL
Definition imageop.h:162
void *const ovoid
const struct dt_interpolation * dt_interpolation_new(enum dt_interpolation_type type)
void dt_interpolation_resample_roi_1c(const struct dt_interpolation *itor, float *out, const dt_iop_roi_t *const roi_out, const float *const in, const dt_iop_roi_t *const roi_in)
@ DT_INTERPOLATION_USERPREF_WARP
static float kernel(const float *x, const float *y)
@ DT_DEBUG_MASKS
Definition logging.h:62
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
#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 macros.h:96
The detail-mask pixel math: a Scharr-style detail estimate over a raw or scene-referred buffer,...
#define dt_free_align(ptr)
Release memory from dt_alloc_align() and set ptr to NULL.
Definition mem_alloc.h:214
static void * dt_calloc_align(size_t size)
dt_alloc_align() followed by a zero fill.
Definition mem_alloc.h:225
uint32_t width
Definition mipmap_cache.c:0
uint32_t height
Definition mipmap_cache.c:1
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
DT_MODULE() for a module whose params struct is introspected.
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
Definition opencl.c:2554
void * dt_opencl_alloc_device_buffer(const int devid, const size_t size)
Definition opencl.c:2970
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:2679
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:2727
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:2545
void dt_opencl_release_mem_object(cl_mem mem)
Definition opencl.c:2805
#define ROUNDUPDHT(a, b)
Definition opencl.h:86
#define ROUNDUPDWD(a, b)
Definition opencl.h:85
void dt_iop_buffer_dsc_update_bpp(dt_iop_buffer_dsc_t *dsc)
uint64_t dt_dev_pixelpipe_rawdetail_mask_hash(const dt_dev_pixelpipe_iop_t *piece)
Definition pixelpipe.c:45
void dt_dev_clear_rawdetail_mask(dt_dev_pixelpipe_t *pipe)
Release the side-band detail mask cache reference currently owned by the pipeline.
Definition pixelpipe.c:64
void dt_dev_pixelpipe_cache_wrlock_entry(gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Lock or release the write lock on the entry.
int dt_dev_pixelpipe_cache_get(const uint64_t hash, const size_t size, const char *name, const int id, const gboolean alloc, void **data, dt_pixel_cache_entry_t **entry)
Get a cache line from the cache.
int dt_dev_pixelpipe_cache_remove(const gboolean force, dt_pixel_cache_entry_t *cache_entry)
Arbitrarily remove the cache entry matching hash. Entries having a reference count > 0 (inter-thread ...
#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id)
#define dt_pixelpipe_cache_free_align(mem)
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
Definition simd.h:53
unsigned __int64 uint64_t
Definition strptime.c:75
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
dt_dev_pixelpipe_type_t type
uint64_t rawdetail_mask_hash
struct dt_iop_roi_t rawdetail_mask_roi
dt_aligned_pixel_t coeffs
Definition format.h:110
unsigned int channels
Definition format.h:83
dt_iop_buffer_type_t datatype
Definition format.h:85
struct dt_iop_buffer_dsc_t::@56 temperature
Region of interest passed through the pixelpipe.
Definition format.h:49
double scale
Definition format.h:51
int width
Definition format.h:50
int height
Definition format.h:50