32#define DT_BLENDIF_RGB_CH 4
33#define DT_BLENDIF_RGB_BCH 3
37 float *
const restrict
out,
const float *
const restrict mask,
const size_t stride);
42 const
float *const restrict parameters)
45 if(
value <= parameters[0])
50 else if(
value < parameters[1])
55 else if(
value <= parameters[2])
60 else if(
value < parameters[3])
63 factor = 1.0f - (
value - parameters[2]) * parameters[5];
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,
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);
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)
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)
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)
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,
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);
139 dt_JzAzBz_2_JzCzhz(
JzAzBz, JzCzhz);
142 for(
size_t i = 0;
i < 3;
i++)
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,
159 invert_mask, profile);
172 _blendif_rgb_green(pixels, mask, stride,
191 invert_mask, profile);
197 const float *
const restrict a,
198 const float *
const restrict b,
float *
const restrict mask)
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;
222 const size_t buffsize = (size_t)owidth * oheight;
225 const float global_opacity =
clamp_simd(
d->opacity / 100.0f);
233 for(
size_t x = 0;
x < buffsize;
x++) mask[
x] = global_opacity * (1.0f - mask[
x]);
240 else if(canceling_channel || !any_channel_active)
245 const float opac = ((mask_inversed == 0) ^ (mask_inclusive == 0)) ? global_opacity : 0.0f;
273 for(
size_t x = 0;
x < buffsize;
x++) temp_mask[
x] = 1.0f;
277 for(
size_t y = 0; y < oheight; y++)
280 _blendif_combine_channels(a + start, temp_mask + (y * owidth), owidth, blendif, parameters, profile);
283 for(
size_t y = 0; y < oheight; y++)
297 for(
size_t x = 0;
x < buffsize;
x++) mask[
x] = global_opacity * (1.0f - mask[
x]) * temp_mask[
x];
302 for(
size_t x = 0;
x < buffsize;
x++) mask[
x] = global_opacity * (1.0f - (1.0f - mask[
x]) * temp_mask[
x]);
310 for(
size_t x = 0;
x < buffsize;
x++) mask[
x] = global_opacity * (1.0f - mask[
x] * temp_mask[
x]);
315 for(
size_t x = 0;
x < buffsize;
x++) mask[
x] = global_opacity * mask[
x] * temp_mask[
x];
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)
332 const float local_opacity = mask[
i];
335 out[j +
k] = a[j +
k] * (1.0f - local_opacity) + b[j +
k] * local_opacity;
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)
348 const float local_opacity =
mask[
i];
351 out[j +
k] = a[j +
k] * (1.0f - local_opacity) + (a[j +
k] * b[j +
k] *
p) * local_opacity;
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)
364 const float local_opacity =
mask[
i];
367 out[j +
k] = a[j +
k] * (1.0f - local_opacity) + (a[j +
k] +
p * b[j +
k]) * local_opacity;
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)
380 const float local_opacity =
mask[
i];
383 out[j +
k] = a[j +
k] * (1.0f - local_opacity) + fmaxf(a[j +
k] -
p * b[j +
k], 0.0f) * local_opacity;
385 out[j + 3] = local_opacity;
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,
397 const float local_opacity =
mask[
i];
400 out[j +
k] = a[j +
k] * (1.0f - local_opacity) + fmaxf(b[j +
k] -
p * a[j +
k], 0.0f) * local_opacity;
402 out[j + 3] = local_opacity;
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)
413 const float local_opacity =
mask[
i];
416 out[j +
k] = a[j +
k] * (1.0f - local_opacity) + fabsf(a[j +
k] - b[j +
k]) * local_opacity;
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)
429 const float local_opacity =
mask[
i];
432 out[j +
k] = a[j +
k] * (1.0f - local_opacity) + a[j +
k] / fmaxf(
p * b[j +
k], 1e-6f) * local_opacity;
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)
445 const float local_opacity =
mask[
i];
448 out[j +
k] = a[j +
k] * (1.0f - local_opacity) + b[j +
k] / fmaxf(
p * a[j +
k], 1e-6f) * local_opacity;
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)
461 const float local_opacity =
mask[
i];
464 out[j +
k] = a[j +
k] * (1.0f - local_opacity) + (a[j +
k] + b[j +
k]) / 2.0f * local_opacity;
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)
477 const float local_opacity =
mask[
i];
480 out[j +
k] = a[j +
k] * (1.0f - local_opacity) + sqrtf(fmax(a[j +
k] * b[j +
k], 0.0f)) * local_opacity;
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)
493 const float local_opacity =
mask[
i];
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;
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)
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);
516 out[j +
k] = a[j +
k] * (1.0f - local_opacity) + b[j +
k] * norm_a / norm_b * local_opacity;
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)
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);
534 out[j +
k] = a[j +
k] * (1.0f - local_opacity) + a[j +
k] * norm_b / norm_a * local_opacity;
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)
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;
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)
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;
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)
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;
594 blend = _blend_multiply;
597 blend = _blend_average;
603 blend = _blend_subtract;
606 blend = _blend_subtract_inverse;
610 blend = _blend_difference;
613 blend = _blend_divide;
616 blend = _blend_divide_inverse;
619 blend = _blend_luminance;
622 blend = _blend_chromaticity;
625 blend = _blend_RGB_R;
628 blend = _blend_RGB_G;
631 blend = _blend_RGB_B;
634 blend = _blend_geometric_mean;
637 blend = _blend_harmonic_mean;
642 blend = _blend_normal;
651static inline float _rgb_luminance(const float *const restrict
rgb,
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);
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);
685 dt_JzAzBz_2_JzCzhz(
JzAzBz, JzCzhz);
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,
791 _rgb_to_JzCzhz(a + j, JzCzhz, profile);
804 _rgb_to_JzCzhz(b + j, JzCzhz, profile);
817 _rgb_to_JzCzhz(a + j, JzCzhz, profile);
830 _rgb_to_JzCzhz(b + j, JzCzhz, profile);
842 _rgb_to_JzCzhz(a + j, JzCzhz, profile);
853 _rgb_to_JzCzhz(b + j, JzCzhz, profile);
871static inline
void _copy_mask(const float *const restrict a, float *const restrict b, const size_t stride)
879 const float *
const restrict a,
float *
const restrict b,
880 const float *
const restrict mask,
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;
905 const float *
const restrict boost_factors =
d->blendif_boost_factors;
908 for(
size_t y = 0; y < oheight; y++)
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);
918 const float p = exp2f(
d->blend_parameter);
928 for(
size_t y = 0; y < oheight; y++)
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);
939 for(
size_t y = 0; y < oheight; y++)
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);
955 for(
size_t y = 0; y < oheight; y++)
958 const size_t b_start = y * stride;
959 _copy_mask(a + a_start, b + b_start, stride);
void dt_develop_blendif_process_parameters(float *const restrict parameters, const dt_develop_blend_params_t *const params)
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)
@ DEVELOP_BLEND_CS_RGB_SCENE
@ DEVELOP_BLENDIF_GRAY_out
@ DEVELOP_BLENDIF_GREEN_in
@ DEVELOP_BLENDIF_RED_out
@ DEVELOP_BLENDIF_BLUE_in
@ DEVELOP_BLENDIF_BLUE_out
@ DEVELOP_BLENDIF_RGB_MASK
@ DEVELOP_BLENDIF_GRAY_in
@ DEVELOP_BLENDIF_GREEN_out
#define DEVELOP_BLENDIF_PARAMETER_ITEMS
@ DEVELOP_BLEND_CHROMATICITY
@ DEVELOP_BLEND_DIFFERENCE
@ DEVELOP_BLEND_LIGHTNESS
@ DEVELOP_BLEND_MODE_MASK
@ DEVELOP_BLEND_DIVIDE_INVERSE
@ DEVELOP_BLEND_HARMONIC_MEAN
@ DEVELOP_BLEND_GEOMETRIC_MEAN
@ DEVELOP_BLEND_DIFFERENCE2
@ DEVELOP_BLEND_SUBTRACT_INVERSE
@ DEVELOP_MASK_PARAMETRIC
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 __OMP_SIMD__(...)
#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id)
#define __OMP_DECLARE_SIMD__(...)
#define __OMP_PARALLEL__(...)
#define dt_pixelpipe_cache_free_align(mem)
#define __OMP_PARALLEL_FOR__(...)
static const dt_aligned_pixel_simd_t value
#define __OMP_FOR_SIMD__(...)
#define __OMP_PARALLEL_FOR_SIMD__(...)
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
dt_dev_pixelpipe_display_mask_t
@ DT_DEV_PIXELPIPE_DISPLAY_OUTPUT
@ DT_DEV_PIXELPIPE_DISPLAY_G
@ DT_DEV_PIXELPIPE_DISPLAY_ANY
@ DT_DEV_PIXELPIPE_DISPLAY_JzCzhz_hz
@ DT_DEV_PIXELPIPE_DISPLAY_JzCzhz_Cz
@ DT_DEV_PIXELPIPE_DISPLAY_MASK
@ DT_DEV_PIXELPIPE_DISPLAY_JzCzhz_Jz
@ DT_DEV_PIXELPIPE_DISPLAY_GRAY
@ DT_DEV_PIXELPIPE_DISPLAY_B
@ DT_DEV_PIXELPIPE_DISPLAY_R
__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)
__DT_CLONE_TARGETS__ void dt_iop_image_copy(float *const __restrict__ out, const float *const __restrict__ in, const size_t nfloats)
__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)
#define DEVELOP_BLENDIF_SIZE
float *const restrict const size_t k
float dt_aligned_pixel_t[4]
static float clamp_simd(const float x)
dt_iop_buffer_dsc_t dsc_in
Region of interest passed through the pixelpipe.