[gimp] app: fix toggling-off of alpha channel



commit 6419ed32460fcad47464cd97980a5a61eb86d297
Author: Ell <ell_se yahoo com>
Date:   Fri Mar 1 14:07:03 2019 -0500

    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.

 app/operations/gimpoperationmaskcomponents.cc | 123 ++++++++++++++++++++------
 app/operations/gimpoperationmaskcomponents.h  |   2 +
 2 files changed, 97 insertions(+), 28 deletions(-)
---
diff --git a/app/operations/gimpoperationmaskcomponents.cc b/app/operations/gimpoperationmaskcomponents.cc
index 44fbb7d68e..4b6af65005 100644
--- a/app/operations/gimpoperationmaskcomponents.cc
+++ b/app/operations/gimpoperationmaskcomponents.cc
@@ -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>
 struct ProcessGeneric
 {
@@ -154,7 +185,8 @@ struct ProcessGeneric
            gconstpointer     aux_buf,
            gpointer          out_buf,
            gint              n,
-           GimpComponentMask mask)
+           GimpComponentMask mask,
+           T                 opacity_value)
   {
     T    *out = (T *) out_buf;
     gint  i;
@@ -190,7 +222,7 @@ struct ProcessGeneric
 
         for (i = 0; i < n; i++)
           {
-            for (c = 0; c < 4; c++)
+            for (c = 0; c < 3; c++)
               {
                 if (mask & (1 << c))
                   out[c] = 0;
@@ -198,6 +230,11 @@ struct ProcessGeneric
                   out[c] = in[c];
               }
 
+            if (mask & (1 << 3))
+              out[3] = opacity_value;
+            else
+              out[3] = in[3];
+
             in  += 4;
             out += 4;
           }
@@ -220,7 +257,8 @@ struct Process<guint8>
            gconstpointer     aux_buf,
            gpointer          out_buf,
            gint              n,
-           GimpComponentMask mask)
+           GimpComponentMask mask,
+           guint8            opacity_value)
   {
     const guint32 *in;
     guint32       *out;
@@ -230,7 +268,8 @@ struct Process<guint8>
 
     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;
       }
@@ -260,12 +299,27 @@ struct Process<guint8>
       }
     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++;
-            out++;
+                in++;
+                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,
                                         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;
 }
@@ -301,25 +356,32 @@ gimp_operation_mask_components_prepare (GeglOperation *operation)
   gegl_operation_set_format (operation, "aux",    format);
   gegl_operation_set_format (operation, "output", format);
 
-  switch (babl_format_get_bytes_per_pixel (format))
+  if (format != self->format)
     {
-    case 4:
-      self->process = (gpointer)
-                        gimp_operation_mask_components_process<guint8>;
-      break;
-
-    case 8:
-      self->process = (gpointer)
-                        gimp_operation_mask_components_process<guint16>;
-      break;
+      self->format = format;
 
-    case 16:
-      self->process = (gpointer)
-                        gimp_operation_mask_components_process<guint32>;
-      break;
+      self->opacity_value = get_opacity_value (format);
 
-    default:
-      g_return_if_reached ();
+      switch (babl_format_get_bytes_per_pixel (format))
+        {
+        case 4:
+          self->process = (gpointer)
+                            gimp_operation_mask_components_process<guint8>;
+          break;
+
+        case 8:
+          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 ();
+        }
     }
 }
 
@@ -442,23 +504,28 @@ 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<guint8>::process (in, aux, out, n, mask);
+      Process<guint8>::process (in, aux, out, n, mask, opacity_value);
       break;
 
     case 8:
-      Process<guint16>::process (in, aux, out, n, mask);
+      Process<guint16>::process (in, aux, out, n, mask, opacity_value);
       break;
 
     case 16:
-      Process<guint32>::process (in, aux, out, n, mask);
+      Process<guint32>::process (in, aux, out, n, mask, opacity_value);
       break;
 
     default:
diff --git a/app/operations/gimpoperationmaskcomponents.h b/app/operations/gimpoperationmaskcomponents.h
index e04a21b948..9fa653824a 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;
   gpointer                    process;
+  const Babl                 *format;
 };
 
 struct _GimpOperationMaskComponentsClass


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]