app: fix toggling-off of alpha channel

Fix gimp:mask-components to use full-oapcity value for the alpha
component when it's masked-in and there's no "aux" input, so that
the image is rendered with full opacity when the alpha channel's
visiblity is toggled off, as per bug #143315.

(cherry picked from commit 6419ed3246)
This commit is contained in:
Ell
2019-03-01 14:07:03 -05:00
parent 1d05c286c5
commit 37797f9de4
2 changed files with 96 additions and 27 deletions

View File

@ -146,6 +146,37 @@ gimp_operation_mask_components_set_property (GObject *object,
} }
} }
static guint32
get_opacity_value (const Babl *format)
{
gfloat src_value = 1.0f;
switch (babl_format_get_bytes_per_pixel (format))
{
#define DEF_CASE(bpp, type) \
case bpp: \
{ \
type dst_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); \
\
return dst_value; \
}
DEF_CASE ( 4, guint8)
DEF_CASE ( 8, guint16)
DEF_CASE (16, guint32)
#undef DEF_CASE
default:
g_return_val_if_reached (0);
}
}
template <class T> template <class T>
struct ProcessGeneric struct ProcessGeneric
{ {
@ -154,7 +185,8 @@ struct ProcessGeneric
gconstpointer aux_buf, gconstpointer aux_buf,
gpointer out_buf, gpointer out_buf,
gint n, gint n,
GimpComponentMask mask) GimpComponentMask mask,
T opacity_value)
{ {
T *out = (T *) out_buf; T *out = (T *) out_buf;
gint i; gint i;
@ -190,7 +222,7 @@ struct ProcessGeneric
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
{ {
for (c = 0; c < 4; c++) for (c = 0; c < 3; c++)
{ {
if (mask & (1 << c)) if (mask & (1 << c))
out[c] = 0; out[c] = 0;
@ -198,6 +230,11 @@ struct ProcessGeneric
out[c] = in[c]; out[c] = in[c];
} }
if (mask & (1 << 3))
out[3] = opacity_value;
else
out[3] = in[3];
in += 4; in += 4;
out += 4; out += 4;
} }
@ -220,7 +257,8 @@ struct Process<guint8>
gconstpointer aux_buf, gconstpointer aux_buf,
gpointer out_buf, gpointer out_buf,
gint n, gint n,
GimpComponentMask mask) GimpComponentMask mask,
guint8 opacity_value)
{ {
const guint32 *in; const guint32 *in;
guint32 *out; guint32 *out;
@ -230,7 +268,8 @@ struct Process<guint8>
if (((guintptr) in_buf | (guintptr) aux_buf | (guintptr) out_buf) % 4) if (((guintptr) in_buf | (guintptr) aux_buf | (guintptr) out_buf) % 4)
{ {
ProcessGeneric<guint8>::process (in_buf, aux_buf, out_buf, n, mask); ProcessGeneric<guint8>::process (in_buf, aux_buf, out_buf, n,
mask, opacity_value);
return; return;
} }
@ -260,12 +299,27 @@ struct Process<guint8>
} }
else else
{ {
for (i = 0; i < n; i++) if (! (mask & GIMP_COMPONENT_MASK_ALPHA))
{ {
*out = *in & in_mask; for (i = 0; i < n; i++)
{
*out = *in & in_mask;
in++; in++;
out++; out++;
}
}
else
{
g_return_if_fail (opacity_value == 0xff);
for (i = 0; i < n; i++)
{
*out = (*in & in_mask) | 0xff000000u;
in++;
out++;
}
} }
} }
} }
@ -283,7 +337,8 @@ gimp_operation_mask_components_process (GimpOperationMaskComponents *self,
const GeglRectangle *roi, const GeglRectangle *roi,
gint level) gint level)
{ {
Process<T>::process (in_buf, aux_buf, out_buf, samples, self->mask); Process<T>::process (in_buf, aux_buf, out_buf, samples,
self->mask, self->opacity_value);
return TRUE; return TRUE;
} }
@ -301,25 +356,32 @@ gimp_operation_mask_components_prepare (GeglOperation *operation)
gegl_operation_set_format (operation, "aux", format); gegl_operation_set_format (operation, "aux", format);
gegl_operation_set_format (operation, "output", format); gegl_operation_set_format (operation, "output", format);
switch (babl_format_get_bytes_per_pixel (format)) if (format != self->format)
{ {
case 4: self->format = format;
self->process = (gpointer)
gimp_operation_mask_components_process<guint8>;
break;
case 8: self->opacity_value = get_opacity_value (format);
self->process = (gpointer)
gimp_operation_mask_components_process<guint16>;
break;
case 16: switch (babl_format_get_bytes_per_pixel (format))
self->process = (gpointer) {
gimp_operation_mask_components_process<guint32>; case 4:
break; self->process = (gpointer)
gimp_operation_mask_components_process<guint8>;
break;
default: case 8:
g_return_if_reached (); self->process = (gpointer)
gimp_operation_mask_components_process<guint16>;
break;
case 16:
self->process = (gpointer)
gimp_operation_mask_components_process<guint32>;
break;
default:
g_return_if_reached ();
}
} }
} }
@ -439,23 +501,28 @@ gimp_operation_mask_components_process (const Babl *format,
gint n, gint n,
GimpComponentMask mask) GimpComponentMask mask)
{ {
guint32 opacity_value = 0;
g_return_if_fail (format != NULL); g_return_if_fail (format != NULL);
g_return_if_fail (in != NULL); g_return_if_fail (in != NULL);
g_return_if_fail (out != NULL); g_return_if_fail (out != NULL);
g_return_if_fail (n >= 0); 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)) switch (babl_format_get_bytes_per_pixel (format))
{ {
case 4: case 4:
Process<guint8>::process (in, aux, out, n, mask); Process<guint8>::process (in, aux, out, n, mask, opacity_value);
break; break;
case 8: case 8:
Process<guint16>::process (in, aux, out, n, mask); Process<guint16>::process (in, aux, out, n, mask, opacity_value);
break; break;
case 16: case 16:
Process<guint32>::process (in, aux, out, n, mask); Process<guint32>::process (in, aux, out, n, mask, opacity_value);
break; break;
default: default:

View File

@ -40,7 +40,9 @@ struct _GimpOperationMaskComponents
GeglOperationPointComposer parent_instance; GeglOperationPointComposer parent_instance;
GimpComponentMask mask; GimpComponentMask mask;
guint32 opacity_value;
gpointer process; gpointer process;
const Babl *format;
}; };
struct _GimpOperationMaskComponentsClass struct _GimpOperationMaskComponentsClass