33#define DT_BLENDIF_RGB_CH 4
34#define DT_BLENDIF_RGB_BCH 3
38 float *
const restrict
out,
const float *
const restrict mask,
const size_t stride);
48static inline
void _PX_COPY(const float *const restrict src, float *const restrict dst)
50 for(
size_t i = 0;
i < 3;
i++) dst[
i] = src[
i];
56 const
float *const restrict parameters)
59 if(
value <= parameters[0])
64 else if(
value < parameters[1])
69 else if(
value <= parameters[2])
74 else if(
value < parameters[3])
77 factor = 1.0f - (
value - parameters[2]) * parameters[5];
88static inline
void _blendif_gray(const float *const restrict pixels, float *const restrict mask,
89 const size_t stride, const float *const restrict parameters,
90 const unsigned int invert_mask,
95 const float value = dt_ioppr_get_rgb_matrix_luminance(pixels + j, profile->matrix_in, profile->lut_in,
96 profile->unbounded_coeffs_in, profile->lutsize,
97 profile->nonlinearlut);
103static inline
void _blendif_gray_fb(const float *const restrict pixels, float *const restrict mask,
104 const size_t stride, const float *const restrict parameters,
105 const unsigned int invert_mask)
109 const float value = 0.3f * pixels[j + 0] + 0.59f * pixels[j + 1] + 0.11f * pixels[j + 2];
115static inline
void _blendif_rgb_red(const float *const restrict pixels, float *const restrict
mask,
116 const size_t stride, const float *const restrict parameters,
117 const unsigned int invert_mask)
126static inline
void _blendif_rgb_green(const float *const restrict pixels, float *const restrict
mask,
127 const size_t stride, const float *const restrict parameters,
128 const unsigned int invert_mask)
137static inline
void _blendif_rgb_blue(const float *const restrict pixels, float *const restrict
mask,
138 const size_t stride, const float *const restrict parameters,
139 const unsigned int invert_mask)
148static inline
void _blendif_hsl(const float *const restrict pixels, float *const restrict mask,
149 const size_t stride, const float *const restrict parameters,
150 const unsigned int *const restrict invert_mask)
155 dt_RGB_2_HSL(pixels + j,
HSL);
157 for(
size_t i = 0;
i < 3;
i++)
164static
void _blendif_combine_channels(const float *const restrict pixels, float *const restrict mask,
165 const size_t stride, const unsigned int blendif,
166 const float *const restrict parameters,
175 invert_mask, profile);
179 _blendif_gray_fb(pixels, mask, stride,
194 _blendif_rgb_green(pixels, mask, stride,
219 const float *
const restrict a,
220 const float *
const restrict b,
float *
const restrict mask)
228 const int xoffs = roi_out->
x - roi_in->
x;
229 const int yoffs = roi_out->
y - roi_in->
y;
230 const int iwidth = roi_in->
width;
231 const int owidth = roi_out->
width;
232 const int oheight = roi_out->
height;
244 const size_t buffsize = (size_t)owidth * oheight;
247 const float global_opacity =
clamp_simd(
d->opacity / 100.0f);
255 for(
size_t x = 0;
x < buffsize;
x++) mask[
x] = global_opacity * (1.0f - mask[
x]);
262 else if(canceling_channel || !any_channel_active)
267 const float opac = ((mask_inversed == 0) ^ (mask_inclusive == 0)) ? global_opacity : 0.0f;
293 for(
size_t x = 0;
x < buffsize;
x++) temp_mask[
x] = 1.0f;
297 for(
size_t y = 0; y < oheight; y++)
300 _blendif_combine_channels(a + start, temp_mask + (y * owidth), owidth, blendif, parameters, profile);
303 for(
size_t y = 0; y < oheight; y++)
317 for(
size_t x = 0;
x < buffsize;
x++) mask[
x] = global_opacity * (1.0f - mask[
x]) * temp_mask[
x];
322 for(
size_t x = 0;
x < buffsize;
x++) mask[
x] = global_opacity * (1.0f - (1.0f - mask[
x]) * temp_mask[
x]);
330 for(
size_t x = 0;
x < buffsize;
x++) mask[
x] = global_opacity * (1.0f - mask[
x] * temp_mask[
x]);
335 for(
size_t x = 0;
x < buffsize;
x++) mask[
x] = global_opacity * mask[
x] * temp_mask[
x];
347static
void _blend_normal_bounded(const float *const restrict a, const float *const restrict b,
348 float *const restrict
out, const float *const restrict mask, const size_t stride)
352 const float local_opacity = mask[
i];
355 out[j +
k] =
clamp_simd(a[j +
k] * (1.0f - local_opacity) + b[j +
k] * local_opacity);
363static
void _blend_normal_unbounded(const float *const restrict a, const float *const restrict
b,
364 float *const restrict
out, const float *const restrict
mask,
369 const float local_opacity =
mask[
i];
372 out[j +
k] = a[j +
k] * (1.0f - local_opacity) + b[j +
k] * local_opacity;
380static
void _blend_lighten(const float *const restrict a, const float *const restrict
b,
381 float *const restrict
out, const float *const restrict
mask, const size_t stride)
385 const float local_opacity =
mask[
i];
388 out[j +
k] =
clamp_simd(a[j +
k] * (1.0f - local_opacity) + fmaxf(a[j +
k], b[j +
k]) * local_opacity);
396static
void _blend_darken(const float *const restrict a, const float *const restrict
b,
397 float *const restrict
out, const float *const restrict
mask, const size_t stride)
401 const float local_opacity =
mask[
i];
404 out[j +
k] =
clamp_simd(a[j +
k] * (1.0f - local_opacity) + fminf(a[j +
k], b[j +
k]) * local_opacity);
412static
void _blend_multiply(const float *const restrict a, const float *const restrict
b,
413 float *const restrict
out, const float *const restrict
mask, const size_t stride)
417 const float local_opacity =
mask[
i];
420 out[j +
k] =
clamp_simd(a[j +
k] * (1.0f - local_opacity) + (a[j +
k] * b[j +
k]) * local_opacity);
428static
void _blend_average(const float *const restrict a, const float *const restrict
b,
429 float *const restrict
out, const float *const restrict
mask, const size_t stride)
433 const float local_opacity =
mask[
i];
436 out[j +
k] =
clamp_simd(a[j +
k] * (1.0f - local_opacity) + (a[j +
k] + b[j +
k]) / 2.0f * local_opacity);
444static
void _blend_add(const float *const restrict a, const float *const restrict
b,
445 float *const restrict
out, const float *const restrict
mask, const size_t stride)
449 const float local_opacity =
mask[
i];
452 out[j +
k] =
clamp_simd(a[j +
k] * (1.0f - local_opacity) + (a[j +
k] + b[j +
k]) * local_opacity);
460static
void _blend_subtract(const float *const restrict a, const float *const restrict
b,
461 float *const restrict
out, const float *const restrict
mask, const size_t stride)
465 const float local_opacity =
mask[
i];
468 out[j +
k] =
clamp_simd(a[j +
k] * (1.0f - local_opacity) + ((b[j +
k] + a[j +
k]) - 1.0f) * local_opacity);
476static
void _blend_difference(const float *const restrict a, const float *const restrict
b,
477 float *const restrict
out, const float *const restrict
mask, const size_t stride)
481 const float local_opacity =
mask[
i];
484 out[j +
k] =
clamp_simd(a[j +
k] * (1.0f - local_opacity) + fabsf(a[j +
k] - b[j +
k]) * local_opacity);
492static
void _blend_screen(const float *const restrict a, const float *const restrict
b,
493 float *const restrict
out, const float *const restrict
mask, const size_t stride)
497 const float local_opacity =
mask[
i];
502 out[j +
k] =
clamp_simd(la * (1.0f - local_opacity) + (1.0f - (1.0f - la) * (1.0f - lb)) * local_opacity);
510static
void _blend_overlay(const float *const restrict a, const float *const restrict
b,
511 float *const restrict
out, const float *const restrict
mask, const size_t stride)
515 const float local_opacity =
mask[
i];
516 const float local_opacity2 = local_opacity * local_opacity;
522 la * (1.0f - local_opacity2)
523 + (la > 0.5f ? 1.0f - (1.0f - 2.0f * (la - 0.5f)) * (1.0f - lb)
533static
void _blend_softlight(const float *const restrict a, const float *const restrict
b,
534 float *const restrict
out, const float *const restrict
mask, const size_t stride)
538 const float local_opacity =
mask[
i];
539 const float local_opacity2 = local_opacity * local_opacity;
545 la * (1.0f - local_opacity2)
546 + (lb > 0.5f ? 1.0f - (1.0f - la) * (1.0f - (lb - 0.5f))
556static
void _blend_hardlight(const float *const restrict a, const float *const restrict
b,
557 float *const restrict
out, const float *const restrict
mask, const size_t stride)
561 const float local_opacity =
mask[
i];
562 const float local_opacity2 = local_opacity * local_opacity;
568 la * (1.0f - local_opacity2)
569 + (lb > 0.5f ? 1.0f - (1.0f - 2.0f * (la - 0.5f)) * (1.0f - lb)
579static
void _blend_vividlight(const float *const restrict a, const float *const restrict
b,
580 float *const restrict
out, const float *const restrict
mask, const size_t stride)
584 float local_opacity =
mask[
i];
585 float local_opacity2 = local_opacity * local_opacity;
591 la * (1.0f - local_opacity2)
592 + (lb > 0.5f ? (lb >= 1.0f ? 1.0f : la / (2.0f * (1.0f - lb)))
593 : (lb <= 0.0f ? 0.0f : 1.0f - (1.0f - la) / (2.0f * lb)))
602static
void _blend_linearlight(const float *const restrict a, const float *const restrict
b,
603 float *const restrict
out, const float *const restrict
mask, const size_t stride)
607 const float local_opacity =
mask[
i];
608 const float local_opacity2 = local_opacity * local_opacity;
613 out[j +
k] =
clamp_simd(la * (1.0f - local_opacity2) + (la + 2.0f * lb - 1.0f) * local_opacity2);
621static
void _blend_pinlight(const float *const restrict a, const float *const restrict
b,
622 float *const restrict
out, const float *const restrict
mask, const size_t stride)
626 const float local_opacity =
mask[
i];
627 const float local_opacity2 = local_opacity * local_opacity;
633 la * (1.0f - local_opacity2)
634 + (lb > 0.5f ? fmaxf(la, 2.0f * (lb - 0.5f))
635 : fminf(la, 2.0f * lb))
644static
void _blend_lightness(const float *const restrict a, const float *const restrict
b,
645 float *const restrict
out, const float *const restrict
mask, const size_t stride)
649 const float local_opacity =
mask[
i];
659 dt_RGB_2_HSL(ta, tta);
660 dt_RGB_2_HSL(tb, ttb);
664 ttb[2] = (tta[2] * (1.0f - local_opacity)) + ttb[2] * local_opacity;
666 dt_HSL_2_RGB(ttb,
out + j);
675static
void _blend_chromaticity(const float *const restrict a, const float *const restrict
b,
676 float *const restrict
out, const float *const restrict
mask, const size_t stride)
680 const float local_opacity =
mask[
i];
690 dt_RGB_2_HSL(ta, tta);
691 dt_RGB_2_HSL(tb, ttb);
694 ttb[1] = (tta[1] * (1.0f - local_opacity)) + ttb[1] * local_opacity;
697 dt_HSL_2_RGB(ttb,
out + j);
706static
void _blend_hue(const float *const restrict a, const float *const restrict
b,
707 float *const restrict
out, const float *const restrict
mask, const size_t stride)
711 const float local_opacity =
mask[
i];
721 dt_RGB_2_HSL(ta, tta);
722 dt_RGB_2_HSL(tb, ttb);
725 float d = fabsf(tta[0] - ttb[0]);
726 float s =
d > 0.5f ? -local_opacity * (1.0f -
d) /
d : local_opacity;
727 ttb[0] = fmodf((tta[0] * (1.0f - s)) + ttb[0] * s + 1.0f, 1.0f);
731 dt_HSL_2_RGB(ttb,
out + j);
740static
void _blend_color(const float *const restrict a, const float *const restrict
b,
741 float *const restrict
out, const float *const restrict
mask, const size_t stride)
745 float local_opacity =
mask[
i];
755 dt_RGB_2_HSL(ta, tta);
756 dt_RGB_2_HSL(tb, ttb);
759 float d = fabsf(tta[0] - ttb[0]);
760 float s =
d > 0.5f ? -local_opacity * (1.0f -
d) /
d : local_opacity;
761 ttb[0] = fmodf((tta[0] * (1.0f - s)) + ttb[0] * s + 1.0f, 1.0f);
763 ttb[1] = (tta[1] * (1.0f - local_opacity)) + ttb[1] * local_opacity;
766 dt_HSL_2_RGB(ttb,
out + j);
775static
void _blend_coloradjust(const float *const restrict a, const float *const restrict
b,
776 float *const restrict
out, const float *const restrict
mask, const size_t stride)
780 const float local_opacity =
mask[
i];
790 dt_RGB_2_HSL(ta, tta);
791 dt_RGB_2_HSL(tb, ttb);
794 const float d = fabsf(tta[0] - ttb[0]);
795 const float s =
d > 0.5f ? -local_opacity * (1.0f -
d) /
d : local_opacity;
796 ttb[0] = fmodf((tta[0] * (1.0f - s)) + ttb[0] * s + 1.0f, 1.0f);
798 ttb[1] = (tta[1] * (1.0f - local_opacity)) + ttb[1] * local_opacity;
801 dt_HSL_2_RGB(ttb,
out + j);
810static
void _blend_HSV_value(const float *const restrict a, const float *const restrict
b,
811 float *const restrict
out, const float *const restrict
mask, const size_t stride)
815 const float local_opacity =
mask[
i];
818 dt_RGB_2_HSV(a + j, ta);
819 dt_RGB_2_HSV(b + j, tb);
826 tb[2] = ta[2] * (1.0f - local_opacity) + tb[2] * local_opacity;
828 dt_HSV_2_RGB(tb,
out + j);
835static
void _blend_HSV_color(const float *const restrict a, const float *const restrict b,
836 float *const restrict
out, const float *const restrict mask, const size_t stride)
840 const float local_opacity = mask[
i];
843 dt_RGB_2_HSV(a + j, ta);
844 dt_RGB_2_HSV(b + j, tb);
847 const float xa = ta[1] * cosf(2.0f *
DT_M_PI_F * ta[0]);
848 const float ya = ta[1] * sinf(2.0f *
DT_M_PI_F * ta[0]);
849 const float xb = tb[1] * cosf(2.0f *
DT_M_PI_F * tb[0]);
850 const float yb = tb[1] * sinf(2.0f *
DT_M_PI_F * tb[0]);
853 const float xc = xa * (1.0f - local_opacity) + xb * local_opacity;
854 const float yc = ya * (1.0f - local_opacity) + yb * local_opacity;
856 tb[0] = atan2f(yc, xc) / (2.0f *
DT_M_PI_F);
857 if(tb[0] < 0.0f) tb[0] += 1.0f;
858 tb[1] = sqrtf(xc * xc + yc * yc);
863 dt_HSV_2_RGB(tb,
out + j);
870static
void _blend_RGB_R(const float *const restrict a, const float *const restrict
b,
871 float *const restrict
out, const float *const restrict
mask, const size_t stride)
875 const float local_opacity =
mask[
i];
876 out[j + 0] = a[j + 0] * (1.0f - local_opacity) + b[j + 0] * local_opacity;
877 out[j + 1] = a[j + 1];
878 out[j + 2] = a[j + 2];
879 out[j + 3] = local_opacity;
885static
void _blend_RGB_G(const float *const restrict a, const float *const restrict
b,
886 float *const restrict
out, const float *const restrict
mask, const size_t stride)
890 const float local_opacity =
mask[
i];
891 out[j + 0] = a[j + 0];
892 out[j + 1] = a[j + 1] * (1.0f - local_opacity) + b[j + 1] * local_opacity;
893 out[j + 2] = a[j + 2];
894 out[j + 3] = local_opacity;
900static
void _blend_RGB_B(const float *const restrict a, const float *const restrict
b,
901 float *const restrict
out, const float *const restrict
mask, const size_t stride)
905 const float local_opacity =
mask[
i];
906 out[j + 0] = a[j + 0];
907 out[j + 1] = a[j + 1];
908 out[j + 2] = a[j + 2] * (1.0f - local_opacity) + b[j + 2] * local_opacity;
909 out[j + 3] = local_opacity;
922 blend = _blend_lighten;
925 blend = _blend_darken;
928 blend = _blend_multiply;
931 blend = _blend_average;
937 blend = _blend_subtract;
941 blend = _blend_difference;
944 blend = _blend_screen;
947 blend = _blend_overlay;
950 blend = _blend_softlight;
953 blend = _blend_hardlight;
956 blend = _blend_vividlight;
959 blend = _blend_linearlight;
962 blend = _blend_pinlight;
965 blend = _blend_lightness;
968 blend = _blend_chromaticity;
974 blend = _blend_color;
977 blend = _blend_normal_bounded;
980 blend = _blend_coloradjust;
983 blend = _blend_HSV_value;
986 blend = _blend_HSV_color;
989 blend = _blend_RGB_R;
992 blend = _blend_RGB_G;
995 blend = _blend_RGB_B;
1001 blend = _blend_normal_unbounded;
1010static inline float _rgb_luminance(const float *const restrict
rgb,
1015 value = dt_ioppr_get_rgb_matrix_luminance(
rgb, profile->matrix_in, profile->lut_in,
1016 profile->unbounded_coeffs_in, profile->lutsize,
1017 profile->nonlinearlut);
1024static
void _display_channel(const float *const restrict a, float *const restrict b,
1025 const float *const restrict mask, const size_t stride, const int channel,
1026 const float *const restrict boost_factors,
1124 dt_RGB_2_HSL(a + j,
HSL);
1135 dt_RGB_2_HSL(b + j,
HSL);
1146 dt_RGB_2_HSL(a + j,
HSL);
1157 dt_RGB_2_HSL(b + j,
HSL);
1168 dt_RGB_2_HSL(a + j,
HSL);
1179 dt_RGB_2_HSL(b + j,
HSL);
1197static inline
void _copy_mask(const float *const restrict a, float *const restrict
b, const size_t stride)
1205 const float *
const restrict a,
float *
const restrict b,
1206 const float *
const restrict mask,
1215 const int xoffs = roi_out->
x - roi_in->
x;
1216 const int yoffs = roi_out->
y - roi_in->
y;
1217 const int iwidth = roi_in->
width;
1218 const int owidth = roi_out->
width;
1219 const int oheight = roi_out->
height;
1231 const float *
const restrict boost_factors =
d->blendif_boost_factors;
1234 for(
size_t y = 0; y < oheight; y++)
1238 const size_t m_start = y * owidth;
1239 _display_channel(a + a_start, b + b_start, mask + m_start, owidth, channel, boost_factors, profile);
1253 for(
size_t y = 0; y < oheight; y++)
1257 const size_t m_start = y * owidth;
1258 blend(tmp_buffer + b_start, a + a_start, b + b_start, mask + m_start, owidth);
1264 for(
size_t y = 0; y < oheight; y++)
1268 const size_t m_start = y * owidth;
1269 blend(a + a_start, tmp_buffer + b_start, b + b_start, mask + m_start, owidth);
1280 for(
size_t y = 0; y < oheight; y++)
1283 const size_t b_start = y * stride;
1284 _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_DISPLAY
@ 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_HARDLIGHT
@ DEVELOP_BLEND_HSV_COLOR
@ DEVELOP_BLEND_HSV_VALUE
@ DEVELOP_BLEND_LINEARLIGHT
@ DEVELOP_BLEND_VIVIDLIGHT
@ DEVELOP_BLEND_SOFTLIGHT
@ DEVELOP_BLEND_COLORADJUST
@ DEVELOP_BLEND_DIFFERENCE2
@ 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)
static void _CLAMP_XYZ(float *const restrict XYZ)
static void _PX_COPY(const float *const restrict src, float *const restrict dst)
void dt_develop_blendif_rgb_hsl_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 dt_develop_blendif_rgb_hsl_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() _blend_row_func(const float *const restrict a, const float *const restrict b, float *const restrict out, const float *const restrict mask, const size_t stride)
#define DT_BLENDIF_RGB_BCH
#define DT_BLENDIF_RGB_CH
static dt_aligned_pixel_t rgb
static dt_aligned_pixel_t HSL
static dt_aligned_pixel_t XYZ
const dt_colormatrix_t dt_aligned_pixel_t out
for(size_t c=0;c< 3;c++) sRGB[c]
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_HSL_H
@ DT_DEV_PIXELPIPE_DISPLAY_HSL_S
@ DT_DEV_PIXELPIPE_DISPLAY_MASK
@ DT_DEV_PIXELPIPE_DISPLAY_HSL_l
@ 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.