Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
blendif_rgb_jzczhz.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2020-2021 Harold le Clément de Saint-Marcq.
4 Copyright (C) 2020-2021 Hubert Kowalski.
5 Copyright (C) 2020-2021 Ralf Brown.
6 Copyright (C) 2021 Chris Elston.
7 Copyright (C) 2021 Pascal Obry.
8 Copyright (C) 2022 Martin Bařinka.
9 Copyright (C) 2026 Aurélien PIERRE.
10
11 darktable is free software: you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
15
16 darktable is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with darktable. If not, see <http://www.gnu.org/licenses/>.
23*/
24
26#include "common/imagebuf.h"
27#include "develop/blend.h"
28#include "develop/imageop.h"
30#include <math.h>
31
32#define DT_BLENDIF_RGB_CH 4
33#define DT_BLENDIF_RGB_BCH 3
34
35
36typedef void(_blend_row_func)(const float *const restrict a, const float *const restrict b, const float p,
37 float *const restrict out, const float *const restrict mask, const size_t stride);
38
39
40__OMP_DECLARE_SIMD__(uniform(parameters, invert_mask))
41static inline float _blendif_compute_factor(const float value, const unsigned int invert_mask,
42 const float *const restrict parameters)
43{
44 float factor = 0.0f;
45 if(value <= parameters[0])
46 {
47 // we are below the keyframe
48 factor = 0.0f;
49 }
50 else if(value < parameters[1])
51 {
52 // we are on the bottom slope of the keyframe
53 factor = (value - parameters[0]) * parameters[4];
54 }
55 else if(value <= parameters[2])
56 {
57 // we are on the ramp - constant part - of the keyframe
58 factor = 1.0f;
59 }
60 else if(value < parameters[3])
61 {
62 // we are on the top slope of the keyframe
63 factor = 1.0f - (value - parameters[2]) * parameters[5];
64 }
65 else
66 {
67 // we are above the keyframe
68 factor = 0.0f;
69 }
70 return invert_mask ? 1.0f - factor : factor; // inverted channel?
71}
72
73__OMP_DECLARE_SIMD__(aligned(pixels: 16) uniform(parameters, invert_mask, stride, profile))
74static inline void _blendif_gray(const float *const restrict pixels, float *const restrict mask,
75 const size_t stride, const float *const restrict parameters,
76 const unsigned int invert_mask,
77 const dt_iop_order_iccprofile_info_t *const restrict profile)
78{
79 for(size_t x = 0, j = 0; x < stride; x++, j += DT_BLENDIF_RGB_CH)
80 {
81 const float value = dt_ioppr_get_rgb_matrix_luminance(pixels + j, profile->matrix_in, profile->lut_in,
82 profile->unbounded_coeffs_in, profile->lutsize,
83 profile->nonlinearlut);
84 mask[x] *= _blendif_compute_factor(value, invert_mask, parameters);
85 }
86}
87
88__OMP_DECLARE_SIMD__(aligned(pixels: 16) uniform(parameters, invert_mask, stride))
89static inline void _blendif_rgb_red(const float *const restrict pixels, float *const restrict mask,
90 const size_t stride, const float *const restrict parameters,
91 const unsigned int invert_mask)
92{
93 for(size_t x = 0, j = 0; x < stride; x++, j += DT_BLENDIF_RGB_CH)
94 {
95 mask[x] *= _blendif_compute_factor(pixels[j + 0], invert_mask, parameters);
96 }
97}
98
99__OMP_DECLARE_SIMD__(aligned(pixels: 16) uniform(parameters, invert_mask, stride))
100static inline void _blendif_rgb_green(const float *const restrict pixels, float *const restrict mask,
101 const size_t stride, const float *const restrict parameters,
102 const unsigned int invert_mask)
103{
104 for(size_t x = 0, j = 0; x < stride; x++, j += DT_BLENDIF_RGB_CH)
105 {
106 mask[x] *= _blendif_compute_factor(pixels[j + 1], invert_mask, parameters);
107 }
108}
109
110__OMP_DECLARE_SIMD__(aligned(pixels: 16) uniform(parameters, invert_mask, stride))
111static inline void _blendif_rgb_blue(const float *const restrict pixels, float *const restrict mask,
112 const size_t stride, const float *const restrict parameters,
113 const unsigned int invert_mask)
114{
115 for(size_t x = 0, j = 0; x < stride; x++, j += DT_BLENDIF_RGB_CH)
116 {
117 mask[x] *= _blendif_compute_factor(pixels[j + 2], invert_mask, parameters);
118 }
119}
120
121__OMP_DECLARE_SIMD__(aligned(pixels, invert_mask: 16) uniform(parameters, invert_mask, stride, profile))
122static inline void _blendif_jzczhz(const float *const restrict pixels, float *const restrict mask,
123 const size_t stride, const float *const restrict parameters,
124 const unsigned int *const restrict invert_mask,
125 const dt_iop_order_iccprofile_info_t *const restrict profile)
126{
127 for(size_t x = 0, j = 0; x < stride; x++, j += DT_BLENDIF_RGB_CH)
128 {
131 dt_aligned_pixel_t JzCzhz;
132
133 // use the matrix_out of the hacked profile for blending to use the
134 // conversion from RGB to XYZ D65 (instead of XYZ D50)
135 dt_ioppr_rgb_matrix_to_xyz(pixels + j, XYZ_D65, profile->matrix_out_transposed, profile->lut_in,
136 profile->unbounded_coeffs_in, profile->lutsize, profile->nonlinearlut);
137
138 dt_XYZ_2_JzAzBz(XYZ_D65, JzAzBz);
139 dt_JzAzBz_2_JzCzhz(JzAzBz, JzCzhz);
140
141 float factor = 1.0f;
142 for(size_t i = 0; i < 3; i++)
143 factor *= _blendif_compute_factor(JzCzhz[i], invert_mask[i],
144 parameters + DEVELOP_BLENDIF_PARAMETER_ITEMS * i);
145 mask[x] *= factor;
146 }
147}
148
149__OMP_DECLARE_SIMD__(aligned(pixels: 16) uniform(stride, blendif, parameters, profile))
150static void _blendif_combine_channels(const float *const restrict pixels, float *const restrict mask,
151 const size_t stride, const unsigned int blendif,
152 const float *const restrict parameters,
153 const dt_iop_order_iccprofile_info_t *const restrict profile)
154{
155 if(blendif & (1 << DEVELOP_BLENDIF_GRAY_in))
156 {
157 const unsigned int invert_mask = (blendif >> 16) & (1 << DEVELOP_BLENDIF_GRAY_in);
158 _blendif_gray(pixels, mask, stride, parameters + DEVELOP_BLENDIF_PARAMETER_ITEMS * DEVELOP_BLENDIF_GRAY_in,
159 invert_mask, profile);
160 }
161
162 if(blendif & (1 << DEVELOP_BLENDIF_RED_in))
163 {
164 const unsigned int invert_mask = (blendif >> 16) & (1 << DEVELOP_BLENDIF_RED_in);
165 _blendif_rgb_red(pixels, mask, stride, parameters + DEVELOP_BLENDIF_PARAMETER_ITEMS * DEVELOP_BLENDIF_RED_in,
166 invert_mask);
167 }
168
169 if(blendif & (1 << DEVELOP_BLENDIF_GREEN_in))
170 {
171 const unsigned int invert_mask = (blendif >> 16) & (1 << DEVELOP_BLENDIF_GREEN_in);
172 _blendif_rgb_green(pixels, mask, stride,
174 }
175
176 if(blendif & (1 << DEVELOP_BLENDIF_BLUE_in))
177 {
178 const unsigned int invert_mask = (blendif >> 16) & (1 << DEVELOP_BLENDIF_BLUE_in);
179 _blendif_rgb_blue(pixels, mask, stride, parameters + DEVELOP_BLENDIF_PARAMETER_ITEMS * DEVELOP_BLENDIF_BLUE_in,
180 invert_mask);
181 }
182
183 if(blendif & ((1 << DEVELOP_BLENDIF_Jz_in) | (1 << DEVELOP_BLENDIF_Cz_in) | (1 << DEVELOP_BLENDIF_hz_in)))
184 {
185 const unsigned int invert_mask[3] DT_ALIGNED_PIXEL = {
186 (blendif >> 16) & (1 << DEVELOP_BLENDIF_Jz_in),
187 (blendif >> 16) & (1 << DEVELOP_BLENDIF_Cz_in),
188 (blendif >> 16) & (1 << DEVELOP_BLENDIF_hz_in),
189 };
190 _blendif_jzczhz(pixels, mask, stride, parameters + DEVELOP_BLENDIF_PARAMETER_ITEMS * DEVELOP_BLENDIF_Jz_in,
191 invert_mask, profile);
192 }
193}
194
196 const struct dt_dev_pixelpipe_iop_t *piece,
197 const float *const restrict a,
198 const float *const restrict b, float *const restrict mask)
199{
200 const dt_iop_roi_t *const roi_in = &piece->roi_in;
201 const dt_iop_roi_t *const roi_out = &piece->roi_out;
202 const dt_develop_blend_params_t *const d = (const dt_develop_blend_params_t *const)piece->blendop_data;
203
204 if(piece->dsc_in.channels != DT_BLENDIF_RGB_CH) return;
205
206 const int xoffs = roi_out->x - roi_in->x;
207 const int yoffs = roi_out->y - roi_in->y;
208 const int iwidth = roi_in->width;
209 const int owidth = roi_out->width;
210 const int oheight = roi_out->height;
211
212 const unsigned int any_channel_active = d->blendif & DEVELOP_BLENDIF_RGB_MASK;
213 const unsigned int mask_inclusive = d->mask_combine & DEVELOP_COMBINE_INCL;
214 const unsigned int mask_inversed = d->mask_combine & DEVELOP_COMBINE_INV;
215
216 // invert the individual channels if the combine mode is inclusive
217 const unsigned int blendif = d->blendif ^ (mask_inclusive ? DEVELOP_BLENDIF_RGB_MASK << 16 : 0);
218
219 // a channel cancels the mask if the whole span is selected and the channel is inverted
220 const unsigned int canceling_channel = (blendif >> 16) & ~blendif & DEVELOP_BLENDIF_RGB_MASK;
221
222 const size_t buffsize = (size_t)owidth * oheight;
223
224 // get the clipped opacity value 0 - 1
225 const float global_opacity = clamp_simd(d->opacity / 100.0f);
226
227 if(!(d->mask_mode & DEVELOP_MASK_PARAMETRIC) || (!canceling_channel && !any_channel_active))
228 {
229 // mask is not conditional, invert the mask if required
230 if(mask_inversed)
231 {
233 for(size_t x = 0; x < buffsize; x++) mask[x] = global_opacity * (1.0f - mask[x]);
234 }
235 else
236 {
237 dt_iop_image_mul_const(mask,global_opacity,owidth,oheight,1); // mask[k] *= global_opacity;
238 }
239 }
240 else if(canceling_channel || !any_channel_active)
241 {
242 // one of the conditional channel selects nothing
243 // this means that the conditional opacity of all pixels is the same
244 // and depends on whether the mask combination is inclusive and whether the mask is inverted
245 const float opac = ((mask_inversed == 0) ^ (mask_inclusive == 0)) ? global_opacity : 0.0f;
246 dt_iop_image_fill(mask,opac,owidth,oheight,1); // mask[k] = opac;
247 }
248 else
249 {
250 // we need to process all conditional channels
251
252 // parameters, for every channel the 4 limits + pre-computed increasing slope and decreasing slope
255
256 dt_iop_order_iccprofile_info_t blend_profile;
258 {
259 return;
260 }
261 const dt_iop_order_iccprofile_info_t *profile = &blend_profile;
262
263 // allocate space for a temporary mask buffer to split the computation of every channel
264 float *const restrict temp_mask = dt_pixelpipe_cache_alloc_align_float_cache(buffsize, 0);
265 if(IS_NULL_PTR(temp_mask))
266 {
267 return;
268 }
270 {
271 // initialize the parametric mask
272 __OMP_FOR_SIMD__(aligned(temp_mask:64))
273 for(size_t x = 0; x < buffsize; x++) temp_mask[x] = 1.0f;
274
275 // combine channels
277 for(size_t y = 0; y < oheight; y++)
278 {
279 const size_t start = ((y + yoffs) * iwidth + xoffs) * DT_BLENDIF_RGB_CH;
280 _blendif_combine_channels(a + start, temp_mask + (y * owidth), owidth, blendif, parameters, profile);
281 }
283 for(size_t y = 0; y < oheight; y++)
284 {
285 const size_t start = (y * owidth) * DT_BLENDIF_RGB_CH;
286 _blendif_combine_channels(b + start, temp_mask + (y * owidth), owidth, blendif >> DEVELOP_BLENDIF_GRAY_out,
288 profile);
289 }
290
291 // apply global opacity
292 if(mask_inclusive)
293 {
294 if(mask_inversed)
295 {
296 __OMP_FOR_SIMD__(aligned(mask, temp_mask:64))
297 for(size_t x = 0; x < buffsize; x++) mask[x] = global_opacity * (1.0f - mask[x]) * temp_mask[x];
298 }
299 else
300 {
301 __OMP_FOR_SIMD__(aligned(mask, temp_mask:64))
302 for(size_t x = 0; x < buffsize; x++) mask[x] = global_opacity * (1.0f - (1.0f - mask[x]) * temp_mask[x]);
303 }
304 }
305 else
306 {
307 if(mask_inversed)
308 {
309 __OMP_FOR_SIMD__(aligned(mask, temp_mask:64))
310 for(size_t x = 0; x < buffsize; x++) mask[x] = global_opacity * (1.0f - mask[x] * temp_mask[x]);
311 }
312 else
313 {
314 __OMP_FOR_SIMD__(aligned(mask, temp_mask:64))
315 for(size_t x = 0; x < buffsize; x++) mask[x] = global_opacity * mask[x] * temp_mask[x];
316 }
317 }
318 }
319
321 }
322}
323
324
325/* normal blend without any clamping */
326__OMP_DECLARE_SIMD__(aligned(a, b, out:16) uniform(p, stride))
327static void _blend_normal(const float *const restrict a, const float *const restrict b, const float p,
328 float *const restrict out, const float *const restrict mask, const size_t stride)
329{
330 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
331 {
332 const float local_opacity = mask[i];
333 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++)
334 {
335 out[j + k] = a[j + k] * (1.0f - local_opacity) + b[j + k] * local_opacity;
336 }
337 out[j + DT_BLENDIF_RGB_BCH] = local_opacity;
338 }
339}
340
341/* multiply */
342__OMP_DECLARE_SIMD__(aligned(a, b, out:16) uniform(p, stride))
343static void _blend_multiply(const float *const restrict a, const float *const restrict b, const float p,
344 float *const restrict out, const float *const restrict mask, const size_t stride)
345{
346 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
347 {
348 const float local_opacity = mask[i];
349 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++)
350 {
351 out[j + k] = a[j + k] * (1.0f - local_opacity) + (a[j + k] * b[j + k] * p) * local_opacity;
352 }
353 out[j + DT_BLENDIF_RGB_BCH] = local_opacity;
354 }
355}
356
357/* add */
358__OMP_DECLARE_SIMD__(aligned(a, b, out:16) uniform(p, stride))
359static void _blend_add(const float *const restrict a, const float *const restrict b, const float p,
360 float *const restrict out, const float *const restrict mask, const size_t stride)
361{
362 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
363 {
364 const float local_opacity = mask[i];
365 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++)
366 {
367 out[j + k] = a[j + k] * (1.0f - local_opacity) + (a[j + k] + p * b[j + k]) * local_opacity;
368 }
369 out[j + DT_BLENDIF_RGB_BCH] = local_opacity;
370 }
371}
372
373/* subtract */
374__OMP_DECLARE_SIMD__(aligned(a, b, out:16) uniform(p, stride))
375static void _blend_subtract(const float *const restrict a, const float *const restrict b, const float p,
376 float *const restrict out, const float *const restrict mask, const size_t stride)
377{
378 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
379 {
380 const float local_opacity = mask[i];
381 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++)
382 {
383 out[j + k] = a[j + k] * (1.0f - local_opacity) + fmaxf(a[j + k] - p * b[j + k], 0.0f) * local_opacity;
384 }
385 out[j + 3] = local_opacity;
386 }
387}
388
389/* subtract inverse */
390__OMP_DECLARE_SIMD__(aligned(a, b, out:16) uniform(p, stride))
391static void _blend_subtract_inverse(const float *const restrict a, const float *const restrict b, const float p,
392 float *const restrict out, const float *const restrict mask,
393 const size_t stride)
394{
395 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
396 {
397 const float local_opacity = mask[i];
398 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++)
399 {
400 out[j + k] = a[j + k] * (1.0f - local_opacity) + fmaxf(b[j + k] - p * a[j + k], 0.0f) * local_opacity;
401 }
402 out[j + 3] = local_opacity;
403 }
404}
405
406/* difference */
407__OMP_DECLARE_SIMD__(aligned(a, b, out:16) uniform(p, stride))
408static void _blend_difference(const float *const restrict a, const float *const restrict b, const float p,
409 float *const restrict out, const float *const restrict mask, const size_t stride)
410{
411 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
412 {
413 const float local_opacity = mask[i];
414 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++)
415 {
416 out[j + k] = a[j + k] * (1.0f - local_opacity) + fabsf(a[j + k] - b[j + k]) * local_opacity;
417 }
418 out[j + DT_BLENDIF_RGB_BCH] = local_opacity;
419 }
420}
421
422/* divide */
423__OMP_DECLARE_SIMD__(aligned(a, b, out:16) uniform(p, stride))
424static void _blend_divide(const float *const restrict a, const float *const restrict b, const float p,
425 float *const restrict out, const float *const restrict mask, const size_t stride)
426{
427 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
428 {
429 const float local_opacity = mask[i];
430 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++)
431 {
432 out[j + k] = a[j + k] * (1.0f - local_opacity) + a[j + k] / fmaxf(p * b[j + k], 1e-6f) * local_opacity;
433 }
434 out[j + DT_BLENDIF_RGB_BCH] = local_opacity;
435 }
436}
437
438/* divide inverse */
439__OMP_DECLARE_SIMD__(aligned(a, b, out:16) uniform(p, stride))
440static void _blend_divide_inverse(const float *const restrict a, const float *const restrict b, const float p,
441 float *const restrict out, const float *const restrict mask, const size_t stride)
442{
443 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
444 {
445 const float local_opacity = mask[i];
446 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++)
447 {
448 out[j + k] = a[j + k] * (1.0f - local_opacity) + b[j + k] / fmaxf(p * a[j + k], 1e-6f) * local_opacity;
449 }
450 out[j + DT_BLENDIF_RGB_BCH] = local_opacity;
451 }
452}
453
454/* average */
455__OMP_DECLARE_SIMD__(aligned(a, b, out:16) uniform(p, stride))
456static void _blend_average(const float *const restrict a, const float *const restrict b, const float p,
457 float *const restrict out, const float *const restrict mask, const size_t stride)
458{
459 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
460 {
461 const float local_opacity = mask[i];
462 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++)
463 {
464 out[j + k] = a[j + k] * (1.0f - local_opacity) + (a[j + k] + b[j + k]) / 2.0f * local_opacity;
465 }
466 out[j + DT_BLENDIF_RGB_BCH] = local_opacity;
467 }
468}
469
470/* geometric mean */
471__OMP_DECLARE_SIMD__(aligned(a, b, out:16) uniform(p, stride))
472static void _blend_geometric_mean(const float *const restrict a, const float *const restrict b, const float p,
473 float *const restrict out, const float *const restrict mask, const size_t stride)
474{
475 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
476 {
477 const float local_opacity = mask[i];
478 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++)
479 {
480 out[j + k] = a[j + k] * (1.0f - local_opacity) + sqrtf(fmax(a[j + k] * b[j + k], 0.0f)) * local_opacity;
481 }
482 out[j + DT_BLENDIF_RGB_BCH] = local_opacity;
483 }
484}
485
486/* harmonic mean */
487__OMP_DECLARE_SIMD__(aligned(a, b, out:16) uniform(p, stride))
488static void _blend_harmonic_mean(const float *const restrict a, const float *const restrict b, const float p,
489 float *const restrict out, const float *const restrict mask, const size_t stride)
490{
491 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
492 {
493 const float local_opacity = mask[i];
494 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++)
495 {
496 // consider that pixel values should be positive
497 out[j + k] = a[j + k] * (1.0f - local_opacity)
498 + 2.0f * a[j + k] * b[j + k] / (fmaxf(a[j + k], 5e-7f) + fmaxf(b[j + k], 5e-7f)) * local_opacity;
499 }
500 out[j + DT_BLENDIF_RGB_BCH] = local_opacity;
501 }
502}
503
504/* chromaticity */
505__OMP_DECLARE_SIMD__(aligned(a, b, out:16) uniform(p, stride))
506static void _blend_chromaticity(const float *const restrict a, const float *const restrict b, const float p,
507 float *const restrict out, const float *const restrict mask, const size_t stride)
508{
509 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
510 {
511 const float local_opacity = mask[i];
512 const float norm_a = fmax(sqrtf(sqf(a[j]) + sqf(a[j + 1]) + sqf(a[j + 2])), 1e-6f);
513 const float norm_b = fmax(sqrtf(sqf(b[j]) + sqf(b[j + 1]) + sqf(b[j + 2])), 1e-6f);
514 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++)
515 {
516 out[j + k] = a[j + k] * (1.0f - local_opacity) + b[j + k] * norm_a / norm_b * local_opacity;
517 }
518 out[j + DT_BLENDIF_RGB_BCH] = local_opacity;
519 }
520}
521
522/* luminance */
523__OMP_DECLARE_SIMD__(aligned(a, b, out:16) uniform(p, stride))
524static void _blend_luminance(const float *const restrict a, const float *const restrict b, const float p,
525 float *const restrict out, const float *const restrict mask, const size_t stride)
526{
527 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
528 {
529 const float local_opacity = mask[i];
530 const float norm_a = fmax(sqrtf(sqf(a[j]) + sqf(a[j + 1]) + sqf(a[j + 2])), 1e-6f);
531 const float norm_b = fmax(sqrtf(sqf(b[j]) + sqf(b[j + 1]) + sqf(b[j + 2])), 1e-6f);
532 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++)
533 {
534 out[j + k] = a[j + k] * (1.0f - local_opacity) + a[j + k] * norm_b / norm_a * local_opacity;
535 }
536 out[j + DT_BLENDIF_RGB_BCH] = local_opacity;
537 }
538}
539
540/* blend only R-channel in RGB color space without any clamping */
541__OMP_DECLARE_SIMD__(aligned(a, b, out:16) uniform(p, stride))
542static void _blend_RGB_R(const float *const restrict a, const float *const restrict b, const float p,
543 float *const restrict out, const float *const restrict mask, const size_t stride)
544{
545 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
546 {
547 const float local_opacity = mask[i];
548 out[j + 0] = a[j + 0] * (1.0f - local_opacity) + p * b[j + 0] * local_opacity;
549 out[j + 1] = a[j + 1];
550 out[j + 2] = a[j + 2];
551 out[j + 3] = local_opacity;
552 }
553}
554
555/* blend only R-channel in RGB color space without any clamping */
556__OMP_DECLARE_SIMD__(aligned(a, b, out:16) uniform(p, stride))
557static void _blend_RGB_G(const float *const restrict a, const float *const restrict b, const float p,
558 float *const restrict out, const float *const restrict mask, const size_t stride)
559{
560 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
561 {
562 const float local_opacity = mask[i];
563 out[j + 0] = a[j + 0];
564 out[j + 1] = a[j + 1] * (1.0f - local_opacity) + p * b[j + 1] * local_opacity;
565 out[j + 2] = a[j + 2];
566 out[j + 3] = local_opacity;
567 }
568}
569
570/* blend only R-channel in RGB color space without any clamping */
571__OMP_DECLARE_SIMD__(aligned(a, b, out:16) uniform(p, stride))
572static void _blend_RGB_B(const float *const restrict a, const float *const restrict b, const float p,
573 float *const restrict out, const float *const restrict mask, const size_t stride)
574{
575 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
576 {
577 const float local_opacity = mask[i];
578 out[j + 0] = a[j + 0];
579 out[j + 1] = a[j + 1];
580 out[j + 2] = a[j + 2] * (1.0f - local_opacity) + p * b[j + 2] * local_opacity;
581 out[j + 3] = local_opacity;
582 }
583}
584
585
586static _blend_row_func *_choose_blend_func(const unsigned int blend_mode)
587{
588 _blend_row_func *blend = NULL;
589
590 /* select the blend operator */
591 switch(blend_mode & DEVELOP_BLEND_MODE_MASK)
592 {
594 blend = _blend_multiply;
595 break;
597 blend = _blend_average;
598 break;
600 blend = _blend_add;
601 break;
603 blend = _blend_subtract;
604 break;
606 blend = _blend_subtract_inverse;
607 break;
610 blend = _blend_difference;
611 break;
613 blend = _blend_divide;
614 break;
616 blend = _blend_divide_inverse;
617 break;
619 blend = _blend_luminance;
620 break;
622 blend = _blend_chromaticity;
623 break;
625 blend = _blend_RGB_R;
626 break;
628 blend = _blend_RGB_G;
629 break;
631 blend = _blend_RGB_B;
632 break;
634 blend = _blend_geometric_mean;
635 break;
637 blend = _blend_harmonic_mean;
638 break;
639
640 /* fallback to normal blend */
641 default:
642 blend = _blend_normal;
643 break;
644 }
645
646 return blend;
647}
648
649
650__OMP_DECLARE_SIMD__(aligned(rgb: 16) uniform(profile))
651static inline float _rgb_luminance(const float *const restrict rgb,
652 const dt_iop_order_iccprofile_info_t *const restrict profile)
653{
654 float value = 0.0f;
655 if(!IS_NULL_PTR(profile))
656 value = dt_ioppr_get_rgb_matrix_luminance(rgb, profile->matrix_in, profile->lut_in,
657 profile->unbounded_coeffs_in, profile->lutsize,
658 profile->nonlinearlut);
659 else
660 value = 0.3f * rgb[0] + 0.59f * rgb[1] + 0.11f * rgb[2];
661 return value;
662}
663
664__OMP_DECLARE_SIMD__(aligned(rgb, JzCzhz: 16) uniform(profile))
665static inline void _rgb_to_JzCzhz(const dt_aligned_pixel_t rgb, dt_aligned_pixel_t JzCzhz,
666 const dt_iop_order_iccprofile_info_t *const restrict profile)
667{
668 dt_aligned_pixel_t JzAzBz = { 0.0f, 0.0f, 0.0f };
669
670 if(!IS_NULL_PTR(profile))
671 {
672 dt_aligned_pixel_t XYZ_D65 = { 0.0f, 0.0f, 0.0f };
673 // use the matrix_out of the hacked profile for blending to use the
674 // conversion from RGB to XYZ D65 (instead of XYZ D50)
675 dt_ioppr_rgb_matrix_to_xyz(rgb, XYZ_D65, profile->matrix_out_transposed, profile->lut_in, profile->unbounded_coeffs_in,
676 profile->lutsize, profile->nonlinearlut);
677 dt_XYZ_2_JzAzBz(XYZ_D65, JzAzBz);
678 }
679 else
680 {
681 // This should not happen (we don't know what RGB is), but use this when profile is not defined
682 dt_XYZ_2_JzAzBz(rgb, JzAzBz);
683 }
684
685 dt_JzAzBz_2_JzCzhz(JzAzBz, JzCzhz);
686}
687
688
689__OMP_DECLARE_SIMD__(aligned(a, b:16) uniform(channel, profile, stride))
690static void _display_channel(const float *const restrict a, float *const restrict b,
691 const float *const restrict mask, const size_t stride, const int channel,
692 const float *const restrict boost_factors,
693 const dt_iop_order_iccprofile_info_t *const profile)
694{
695 switch(channel)
696 {
698 {
699 const float factor = 1.0f / exp2f(boost_factors[DEVELOP_BLENDIF_RED_in]);
700 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
701 {
702 const float c = clamp_simd(a[j + 0] * factor);
703 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++) b[j + k] = c;
704 b[j + DT_BLENDIF_RGB_BCH] = mask[i];
705 }
706 break;
707 }
709 {
710 const float factor = 1.0f / exp2f(boost_factors[DEVELOP_BLENDIF_RED_out]);
711 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
712 {
713 const float c = clamp_simd(b[j + 0] * factor);
714 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++) b[j + k] = c;
715 b[j + DT_BLENDIF_RGB_BCH] = mask[i];
716 }
717 break;
718 }
720 {
721 const float factor = 1.0f / exp2f(boost_factors[DEVELOP_BLENDIF_GREEN_in]);
722 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
723 {
724 const float c = clamp_simd(a[j + 1] * factor);
725 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++) b[j + k] = c;
726 b[j + DT_BLENDIF_RGB_BCH] = mask[i];
727 }
728 break;
729 }
731 {
732 const float factor = 1.0f / exp2f(boost_factors[DEVELOP_BLENDIF_GREEN_out]);
733 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
734 {
735 const float c = clamp_simd(b[j + 1] * factor);
736 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++) b[j + k] = c;
737 b[j + DT_BLENDIF_RGB_BCH] = mask[i];
738 }
739 break;
740 }
742 {
743 const float factor = 1.0f / exp2f(boost_factors[DEVELOP_BLENDIF_BLUE_in]);
744 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
745 {
746 const float c = clamp_simd(a[j + 2] * factor);
747 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++) b[j + k] = c;
748 b[j + DT_BLENDIF_RGB_BCH] = mask[i];
749 }
750 break;
751 }
753 {
754 const float factor = 1.0f / exp2f(boost_factors[DEVELOP_BLENDIF_BLUE_out]);
755 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
756 {
757 const float c = clamp_simd(b[j + 2] * factor);
758 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++) b[j + k] = c;
759 b[j + DT_BLENDIF_RGB_BCH] = mask[i];
760 }
761 break;
762 }
764 {
765 const float factor = 1.0f / exp2f(boost_factors[DEVELOP_BLENDIF_GRAY_in]);
766 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
767 {
768 const float c = clamp_simd(_rgb_luminance(a + j, profile) * factor);
769 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++) b[j + k] = c;
770 b[j + DT_BLENDIF_RGB_BCH] = mask[i];
771 }
772 break;
773 }
775 {
776 const float factor = 1.0f / exp2f(boost_factors[DEVELOP_BLENDIF_GRAY_out]);
777 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
778 {
779 const float c = clamp_simd(_rgb_luminance(b + j, profile) * factor);
780 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++) b[j + k] = c;
781 b[j + DT_BLENDIF_RGB_BCH] = mask[i];
782 }
783 break;
784 }
786 {
787 const float factor = 1.0f / exp2f(boost_factors[DEVELOP_BLENDIF_Jz_in]);
788 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
789 {
790 dt_aligned_pixel_t JzCzhz;
791 _rgb_to_JzCzhz(a + j, JzCzhz, profile);
792 const float c = clamp_simd(JzCzhz[0] * factor);
793 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++) b[j + k] = c;
794 b[j + DT_BLENDIF_RGB_BCH] = mask[i];
795 }
796 break;
797 }
799 {
800 const float factor = 1.0f / exp2f(boost_factors[DEVELOP_BLENDIF_Jz_out]);
801 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
802 {
803 dt_aligned_pixel_t JzCzhz;
804 _rgb_to_JzCzhz(b + j, JzCzhz, profile);
805 const float c = clamp_simd(JzCzhz[0] * factor);
806 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++) b[j + k] = c;
807 b[j + DT_BLENDIF_RGB_BCH] = mask[i];
808 }
809 break;
810 }
812 {
813 const float factor = 1.0f / exp2f(boost_factors[DEVELOP_BLENDIF_Cz_in]);
814 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
815 {
816 dt_aligned_pixel_t JzCzhz;
817 _rgb_to_JzCzhz(a + j, JzCzhz, profile);
818 const float c = clamp_simd(JzCzhz[1] * factor);
819 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++) b[j + k] = c;
820 b[j + DT_BLENDIF_RGB_BCH] = mask[i];
821 }
822 break;
823 }
825 {
826 const float factor = 1.0f / exp2f(boost_factors[DEVELOP_BLENDIF_Cz_out]);
827 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
828 {
829 dt_aligned_pixel_t JzCzhz;
830 _rgb_to_JzCzhz(b + j, JzCzhz, profile);
831 const float c = clamp_simd(JzCzhz[1] * factor);
832 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++) b[j + k] = c;
833 b[j + DT_BLENDIF_RGB_BCH] = mask[i];
834 }
835 break;
836 }
838 // no boost factor for hues
839 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
840 {
841 dt_aligned_pixel_t JzCzhz;
842 _rgb_to_JzCzhz(a + j, JzCzhz, profile);
843 const float c = clamp_simd(JzCzhz[2]);
844 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++) b[j + k] = c;
845 b[j + DT_BLENDIF_RGB_BCH] = mask[i];
846 }
847 break;
849 // no boost factor for hues
850 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
851 {
852 dt_aligned_pixel_t JzCzhz;
853 _rgb_to_JzCzhz(b + j, JzCzhz, profile);
854 const float c = clamp_simd(JzCzhz[2]);
855 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++) b[j + k] = c;
856 b[j + DT_BLENDIF_RGB_BCH] = mask[i];
857 }
858 break;
859 default:
860 for(size_t i = 0, j = 0; i < stride; i++, j += DT_BLENDIF_RGB_CH)
861 {
862 for(int k = 0; k < DT_BLENDIF_RGB_BCH; k++) b[j + k] = 0.0f;
863 b[j + DT_BLENDIF_RGB_BCH] = mask[i];
864 }
865 break;
866 }
867}
868
869
870__OMP_DECLARE_SIMD__(aligned(a, b:16) uniform(stride))
871static inline void _copy_mask(const float *const restrict a, float *const restrict b, const size_t stride)
872{
873 __OMP_SIMD__(aligned(a, b: 16))
874 for(size_t x = DT_BLENDIF_RGB_BCH; x < stride; x += DT_BLENDIF_RGB_CH) b[x] = a[x];
875}
876
878 const struct dt_dev_pixelpipe_iop_t *piece,
879 const float *const restrict a, float *const restrict b,
880 const float *const restrict mask,
881 const dt_dev_pixelpipe_display_mask_t request_mask_display)
882{
883 const dt_iop_roi_t *const roi_in = &piece->roi_in;
884 const dt_iop_roi_t *const roi_out = &piece->roi_out;
885 const dt_develop_blend_params_t *const d = (const dt_develop_blend_params_t *const)piece->blendop_data;
886
887 if(piece->dsc_in.channels != DT_BLENDIF_RGB_CH) return;
888
889 const int xoffs = roi_out->x - roi_in->x;
890 const int yoffs = roi_out->y - roi_in->y;
891 const int iwidth = roi_in->width;
892 const int owidth = roi_out->width;
893 const int oheight = roi_out->height;
894
895 // only non-zero if mask_display was set by an _earlier_ module
896 const dt_dev_pixelpipe_display_mask_t mask_display = pipe->mask_display;
897
898 // process the blending operator
899 if(request_mask_display & DT_DEV_PIXELPIPE_DISPLAY_ANY)
900 {
901 dt_iop_order_iccprofile_info_t blend_profile;
902 const int use_profile = dt_develop_blendif_init_masking_profile(pipe, piece, &blend_profile,
904 const dt_iop_order_iccprofile_info_t *profile = use_profile ? &blend_profile : NULL;
905 const float *const restrict boost_factors = d->blendif_boost_factors;
906 const dt_dev_pixelpipe_display_mask_t channel = request_mask_display & DT_DEV_PIXELPIPE_DISPLAY_ANY;
908 for(size_t y = 0; y < oheight; y++)
909 {
910 const size_t a_start = ((y + yoffs) * iwidth + xoffs) * DT_BLENDIF_RGB_CH;
911 const size_t b_start = y * owidth * DT_BLENDIF_RGB_CH;
912 const size_t m_start = y * owidth;
913 _display_channel(a + a_start, b + b_start, mask + m_start, owidth, channel, boost_factors, profile);
914 }
915 }
916 else
917 {
918 const float p = exp2f(d->blend_parameter);
919 _blend_row_func *const blend = _choose_blend_func(d->blend_mode);
920
921 float *tmp_buffer = dt_pixelpipe_cache_alloc_align_float_cache((size_t)owidth * oheight * DT_BLENDIF_RGB_CH, 0);
922 if (!IS_NULL_PTR(tmp_buffer))
923 {
924 dt_iop_image_copy(tmp_buffer, b, (size_t)owidth * oheight * DT_BLENDIF_RGB_CH);
925 if((d->blend_mode & DEVELOP_BLEND_REVERSE) == DEVELOP_BLEND_REVERSE)
926 {
928 for(size_t y = 0; y < oheight; y++)
929 {
930 const size_t a_start = ((y + yoffs) * iwidth + xoffs) * DT_BLENDIF_RGB_CH;
931 const size_t b_start = y * owidth * DT_BLENDIF_RGB_CH;
932 const size_t m_start = y * owidth;
933 blend(tmp_buffer + b_start, a + a_start, p, b + b_start, mask + m_start, owidth);
934 }
935 }
936 else
937 {
939 for(size_t y = 0; y < oheight; y++)
940 {
941 const size_t a_start = ((y + yoffs) * iwidth + xoffs) * DT_BLENDIF_RGB_CH;
942 const size_t b_start = y * owidth * DT_BLENDIF_RGB_CH;
943 const size_t m_start = y * owidth;
944 blend(a + a_start, tmp_buffer + b_start, p, b + b_start, mask + m_start, owidth);
945 }
946 }
948 }
949 }
950
951 if(mask_display & DT_DEV_PIXELPIPE_DISPLAY_MASK)
952 {
953 const size_t stride = owidth * DT_BLENDIF_RGB_CH;
955 for(size_t y = 0; y < oheight; y++)
956 {
957 const size_t a_start = ((y + yoffs) * iwidth + xoffs) * DT_BLENDIF_RGB_CH;
958 const size_t b_start = y * stride;
959 _copy_mask(a + a_start, b + b_start, stride);
960 }
961 }
962}
963
964// tools/update_modelines.sh
965// remove-trailing-space on;
966// clang-format off
967// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
968// vim: shiftwidth=2 expandtab tabstop=2 cindent
969// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
970// clang-format on
void dt_develop_blendif_process_parameters(float *const restrict parameters, const dt_develop_blend_params_t *const params)
Definition blend.c:198
int dt_develop_blendif_init_masking_profile(const struct dt_dev_pixelpipe_t *pipe, const struct dt_dev_pixelpipe_iop_t *piece, dt_iop_order_iccprofile_info_t *blending_profile, dt_develop_blend_colorspace_t cst)
Definition blend.c:306
@ DEVELOP_BLEND_CS_RGB_SCENE
Definition blend.h:60
@ DEVELOP_COMBINE_INV
Definition blend.h:125
@ DEVELOP_COMBINE_INCL
Definition blend.h:127
@ DEVELOP_BLENDIF_GRAY_out
Definition blend.h:158
@ DEVELOP_BLENDIF_hz_in
Definition blend.h:179
@ DEVELOP_BLENDIF_Cz_in
Definition blend.h:178
@ DEVELOP_BLENDIF_RED_in
Definition blend.h:154
@ DEVELOP_BLENDIF_GREEN_in
Definition blend.h:155
@ DEVELOP_BLENDIF_RED_out
Definition blend.h:159
@ DEVELOP_BLENDIF_Jz_out
Definition blend.h:181
@ DEVELOP_BLENDIF_Cz_out
Definition blend.h:182
@ DEVELOP_BLENDIF_Jz_in
Definition blend.h:177
@ DEVELOP_BLENDIF_BLUE_in
Definition blend.h:156
@ DEVELOP_BLENDIF_BLUE_out
Definition blend.h:161
@ DEVELOP_BLENDIF_RGB_MASK
Definition blend.h:193
@ DEVELOP_BLENDIF_GRAY_in
Definition blend.h:153
@ DEVELOP_BLENDIF_GREEN_out
Definition blend.h:160
#define DEVELOP_BLENDIF_PARAMETER_ITEMS
Definition blend.h:451
@ DEVELOP_BLEND_CHROMATICITY
Definition blend.h:82
@ DEVELOP_BLEND_DIFFERENCE
Definition blend.h:73
@ DEVELOP_BLEND_RGB_B
Definition blend.h:100
@ DEVELOP_BLEND_LIGHTNESS
Definition blend.h:81
@ DEVELOP_BLEND_SUBTRACT
Definition blend.h:72
@ DEVELOP_BLEND_MODE_MASK
Definition blend.h:109
@ DEVELOP_BLEND_DIVIDE_INVERSE
Definition blend.h:104
@ DEVELOP_BLEND_RGB_R
Definition blend.h:98
@ DEVELOP_BLEND_REVERSE
Definition blend.h:108
@ DEVELOP_BLEND_AVERAGE
Definition blend.h:70
@ DEVELOP_BLEND_DIVIDE
Definition blend.h:103
@ DEVELOP_BLEND_MULTIPLY
Definition blend.h:69
@ DEVELOP_BLEND_HARMONIC_MEAN
Definition blend.h:106
@ DEVELOP_BLEND_ADD
Definition blend.h:71
@ DEVELOP_BLEND_GEOMETRIC_MEAN
Definition blend.h:105
@ DEVELOP_BLEND_DIFFERENCE2
Definition blend.h:88
@ DEVELOP_BLEND_SUBTRACT_INVERSE
Definition blend.h:102
@ DEVELOP_BLEND_RGB_G
Definition blend.h:99
@ DEVELOP_MASK_PARAMETRIC
Definition blend.h:117
static _blend_row_func * _choose_blend_func(const unsigned int blend_mode)
static float _blendif_compute_factor(const float value, const unsigned int invert_mask, const float *const restrict parameters)
void dt_develop_blendif_rgb_jzczhz_blend(const struct dt_dev_pixelpipe_t *pipe, const struct dt_dev_pixelpipe_iop_t *piece, const float *const restrict a, float *const restrict b, const float *const restrict mask, const dt_dev_pixelpipe_display_mask_t request_mask_display)
void dt_develop_blendif_rgb_jzczhz_make_mask(const struct dt_dev_pixelpipe_t *pipe, const struct dt_dev_pixelpipe_iop_t *piece, const float *const restrict a, const float *const restrict b, float *const restrict mask)
void() _blend_row_func(const float *const restrict a, const float *const restrict b, const float p, float *const restrict out, const float *const restrict mask, const size_t stride)
#define DT_BLENDIF_RGB_BCH
#define DT_BLENDIF_RGB_CH
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
static dt_aligned_pixel_t rgb
static dt_aligned_pixel_t XYZ_D65
const dt_colormatrix_t dt_aligned_pixel_t out
static dt_aligned_pixel_t JzAzBz
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
#define DT_ALIGNED_PIXEL
Definition darktable.h:389
#define __OMP_SIMD__(...)
Definition darktable.h:262
#define DT_ALIGNED_ARRAY
Definition darktable.h:388
#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id)
Definition darktable.h:447
#define __OMP_FOR__(...)
Definition darktable.h:261
#define __OMP_DECLARE_SIMD__(...)
Definition darktable.h:263
#define __OMP_PARALLEL__(...)
Definition darktable.h:257
#define dt_pixelpipe_cache_free_align(mem)
Definition darktable.h:453
#define __OMP_PARALLEL_FOR__(...)
Definition darktable.h:258
static const dt_aligned_pixel_simd_t value
Definition darktable.h:577
#define __OMP_FOR_SIMD__(...)
Definition darktable.h:260
#define __OMP_PARALLEL_FOR_SIMD__(...)
Definition darktable.h:259
#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
dt_dev_pixelpipe_display_mask_t
Definition develop.h:116
@ DT_DEV_PIXELPIPE_DISPLAY_OUTPUT
Definition develop.h:120
@ DT_DEV_PIXELPIPE_DISPLAY_G
Definition develop.h:125
@ DT_DEV_PIXELPIPE_DISPLAY_ANY
Definition develop.h:138
@ DT_DEV_PIXELPIPE_DISPLAY_JzCzhz_hz
Definition develop.h:135
@ DT_DEV_PIXELPIPE_DISPLAY_JzCzhz_Cz
Definition develop.h:134
@ DT_DEV_PIXELPIPE_DISPLAY_MASK
Definition develop.h:118
@ DT_DEV_PIXELPIPE_DISPLAY_JzCzhz_Jz
Definition develop.h:133
@ DT_DEV_PIXELPIPE_DISPLAY_GRAY
Definition develop.h:127
@ DT_DEV_PIXELPIPE_DISPLAY_B
Definition develop.h:126
@ DT_DEV_PIXELPIPE_DISPLAY_R
Definition develop.h:124
__DT_CLONE_TARGETS__ void dt_iop_image_mul_const(float *const buf, const float mul_value, const size_t width, const size_t height, const size_t ch)
Definition imagebuf.c:351
__DT_CLONE_TARGETS__ void dt_iop_image_copy(float *const __restrict__ out, const float *const __restrict__ in, const size_t nfloats)
Definition imagebuf.c:138
__DT_CLONE_TARGETS__ void dt_iop_image_fill(float *const buf, const float fill_value, const size_t width, const size_t height, const size_t ch)
Definition imagebuf.c:214
static const float x
#define DEVELOP_BLENDIF_SIZE
Definition lightroom.c:235
float *const restrict const size_t k
float dt_aligned_pixel_t[4]
static float clamp_simd(const float x)
const float factor
Definition pdf.h:90
dt_iop_buffer_dsc_t dsc_in
unsigned int channels
Definition format.h:54
Region of interest passed through the pixelpipe.
Definition imageop.h:72