diff --git a/app/core/gimpimage.c b/app/core/gimpimage.c index 6ff4620220..deb0bc43e3 100644 --- a/app/core/gimpimage.c +++ b/app/core/gimpimage.c @@ -1553,6 +1553,7 @@ gimp_image_get_graph (GimpProjectable *projectable) gegl_node_new_child (private->graph, "operation", "gimp:mask-components", "mask", mask, + "alpha", 1.0, NULL); gegl_node_connect_to (layers_node, "output", diff --git a/app/operations/gimpoperationmaskcomponents.cc b/app/operations/gimpoperationmaskcomponents.cc index 91cdb9ff7e..f3646c985d 100644 --- a/app/operations/gimpoperationmaskcomponents.cc +++ b/app/operations/gimpoperationmaskcomponents.cc @@ -35,7 +35,8 @@ extern "C" enum { PROP_0, - PROP_MASK + PROP_MASK, + PROP_ALPHA }; @@ -99,6 +100,17 @@ gimp_operation_mask_components_class_init (GimpOperationMaskComponentsClass *kla (GParamFlags) ( G_PARAM_READWRITE | G_PARAM_CONSTRUCT))); + + g_object_class_install_property (object_class, PROP_ALPHA, + g_param_spec_double ("alpha", + "Alpha", + "The masked-in alpha value when there's no aux input", + -G_MAXDOUBLE, + G_MAXDOUBLE, + 0.0, + (GParamFlags) ( + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT))); } static void @@ -120,6 +132,10 @@ gimp_operation_mask_components_get_property (GObject *object, g_value_set_flags (value, self->mask); break; + case PROP_ALPHA: + g_value_set_double (value, self->alpha); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -140,30 +156,33 @@ gimp_operation_mask_components_set_property (GObject *object, self->mask = (GimpComponentMask) g_value_get_flags (value); break; - default: + case PROP_ALPHA: + self->alpha = g_value_get_double (value); + break; + + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static guint32 -get_opacity_value (const Babl *format) +get_alpha_value (const Babl *format, + gfloat alpha) { - gfloat src_value = 1.0f; - switch (babl_format_get_bytes_per_pixel (format)) { #define DEF_CASE(bpp, type) \ case bpp: \ { \ - type dst_value; \ + type alpha_value; \ \ babl_process ( \ babl_fish (babl_format_n (babl_type ("float"), 1), \ babl_format_n (babl_format_get_type (format, 0), 1)), \ - &src_value, &dst_value, 1); \ + &alpha, &alpha_value, 1); \ \ - return dst_value; \ + return alpha_value; \ } DEF_CASE ( 4, guint8) @@ -186,7 +205,7 @@ struct ProcessGeneric gpointer out_buf, gint n, GimpComponentMask mask, - T opacity_value) + T alpha_value) { T *out = (T *) out_buf; gint i; @@ -231,7 +250,7 @@ struct ProcessGeneric } if (mask & (1 << 3)) - out[3] = opacity_value; + out[3] = alpha_value; else out[3] = in[3]; @@ -258,7 +277,7 @@ struct Process gpointer out_buf, gint n, GimpComponentMask mask, - guint8 opacity_value) + guint8 alpha_value) { const guint32 *in; guint32 *out; @@ -269,7 +288,7 @@ struct Process if (((guintptr) in_buf | (guintptr) aux_buf | (guintptr) out_buf) % 4) { ProcessGeneric::process (in_buf, aux_buf, out_buf, n, - mask, opacity_value); + mask, alpha_value); return; } @@ -299,7 +318,7 @@ struct Process } else { - if (! (mask & GIMP_COMPONENT_MASK_ALPHA)) + if (! (mask & GIMP_COMPONENT_MASK_ALPHA) || ! alpha_value) { for (i = 0; i < n; i++) { @@ -311,11 +330,11 @@ struct Process } else { - g_return_if_fail (opacity_value == 0xff); + guint32 alpha_mask = alpha_value << 24; for (i = 0; i < n; i++) { - *out = (*in & in_mask) | 0xff000000u; + *out = (*in & in_mask) | alpha_mask; in++; out++; @@ -338,7 +357,7 @@ gimp_operation_mask_components_process (GimpOperationMaskComponents *self, gint level) { Process::process (in_buf, aux_buf, out_buf, samples, - self->mask, self->opacity_value); + self->mask, self->alpha_value); return TRUE; } @@ -360,7 +379,7 @@ gimp_operation_mask_components_prepare (GeglOperation *operation) { self->format = format; - self->opacity_value = get_opacity_value (format); + self->alpha_value = get_alpha_value (format, self->alpha); switch (babl_format_get_bytes_per_pixel (format)) { @@ -407,10 +426,10 @@ gimp_operation_mask_components_parent_process (GeglOperation *operation, GObject *aux = gegl_operation_context_get_object (context, "aux"); /* when there's no aux and the alpha component is masked-in, we set the - * result's alpha component to full opacity, rather than full - * transparency, so we can't just forward an empty aux in this case. + * result's alpha component to the value of the "alpha" property; if it + * doesn't equal 0, we can't forward an empty aux. */ - if (aux) + if (aux || ! self->alpha_value) { gegl_operation_context_set_object (context, "output", aux); @@ -511,28 +530,23 @@ gimp_operation_mask_components_process (const Babl *format, gint n, GimpComponentMask mask) { - guint32 opacity_value = 0; - g_return_if_fail (format != NULL); g_return_if_fail (in != NULL); g_return_if_fail (out != NULL); g_return_if_fail (n >= 0); - if (! aux && (mask & GIMP_COMPONENT_MASK_ALPHA)) - opacity_value = get_opacity_value (format); - switch (babl_format_get_bytes_per_pixel (format)) { case 4: - Process::process (in, aux, out, n, mask, opacity_value); + Process::process (in, aux, out, n, mask, 0); break; case 8: - Process::process (in, aux, out, n, mask, opacity_value); + Process::process (in, aux, out, n, mask, 0); break; case 16: - Process::process (in, aux, out, n, mask, opacity_value); + Process::process (in, aux, out, n, mask, 0); break; default: diff --git a/app/operations/gimpoperationmaskcomponents.h b/app/operations/gimpoperationmaskcomponents.h index 9fa653824a..0919a3876f 100644 --- a/app/operations/gimpoperationmaskcomponents.h +++ b/app/operations/gimpoperationmaskcomponents.h @@ -40,7 +40,9 @@ struct _GimpOperationMaskComponents GeglOperationPointComposer parent_instance; GimpComponentMask mask; - guint32 opacity_value; + gdouble alpha; + + guint32 alpha_value; gpointer process; const Babl *format; };