[gegl] operations: make generated point composers handle more pixel formats



commit 8f6103462dfd19637a3d19352d6139623816e53e
Author: Øyvind Kolås <pippin gimp org>
Date:   Sun Oct 28 15:51:59 2018 +0100

    operations: make generated point composers handle more pixel formats
    
    Make the innerloops able to work with any number of components with or without
    alpha, a possible performance enhancement would be to implement separate code
    paths for formats with and without alpha, while still keeping the number of
    components dynamic.
    
    This makes the math and generated operations have code paths dealing with
    grayscale and grayscale with alpha versions - reducing the needed memory
    bandwidth, while also preparing for spectral or other multi-channel uses with
    or without alpha channels.

 operations/generated/add.c                 |  79 +++++++++++----
 operations/generated/clear.c               |  82 ++++++++++++----
 operations/generated/color-burn.c          |  80 ++++++++++++----
 operations/generated/color-dodge.c         |  80 ++++++++++++----
 operations/generated/darken.c              |  80 ++++++++++++----
 operations/generated/difference.c          |  80 ++++++++++++----
 operations/generated/divide.c              |  79 +++++++++++----
 operations/generated/dst-atop.c            |  82 ++++++++++++----
 operations/generated/dst-in.c              |  82 ++++++++++++----
 operations/generated/dst-out.c             |  93 +++++++++++++-----
 operations/generated/dst-over.c            |  93 +++++++++++++-----
 operations/generated/dst.c                 |  93 +++++++++++++-----
 operations/generated/exclusion.c           |  80 ++++++++++++----
 operations/generated/gamma.c               |  79 +++++++++++----
 operations/generated/hard-light.c          |  80 ++++++++++++----
 operations/generated/lighten.c             |  80 ++++++++++++----
 operations/generated/math.rb               |  79 +++++++++++----
 operations/generated/multiply.c            |  79 +++++++++++----
 operations/generated/overlay.c             |  80 ++++++++++++----
 operations/generated/plus.c                |  80 ++++++++++++----
 operations/generated/screen.c              |  80 ++++++++++++----
 operations/generated/soft-light.c          |  82 ++++++++++++----
 operations/generated/src-atop.c            |  93 +++++++++++++-----
 operations/generated/src-in.c              |  82 ++++++++++++----
 operations/generated/src-out.c             |  82 ++++++++++++----
 operations/generated/src.c                 |  82 ++++++++++++----
 operations/generated/subtract.c            |  79 +++++++++++----
 operations/generated/svg-12-blend.rb       | 148 +++++++++++++++++++++--------
 operations/generated/svg-12-porter-duff.rb | 115 ++++++++++++++++------
 operations/generated/xor.c                 |  93 +++++++++++++-----
 tests/mipmap/unsharp-crop-reference.png    | Bin 14777 -> 14972 bytes
 31 files changed, 2026 insertions(+), 550 deletions(-)
---
diff --git a/operations/generated/add.c b/operations/generated/add.c
index 06ef89407..1fb671653 100644
--- a/operations/generated/add.c
+++ b/operations/generated/add.c
@@ -46,14 +46,56 @@ property_double (value, _("Value"), 0.0)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-     space = gegl_operation_get_source_space (operation, "aux");
-  format  = babl_format_with_space ("RGBA float", space);
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
+
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space ("Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space ("YA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space ("RGB float", space);
+  }
+#if 0
+  else if (babl_model_is (model, "RGBA") ||
+           babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~") ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space ("RGBA float", space);
+  }
+#endif
+  else
+  {
+    format  = babl_format_with_space ("RGBA float", space);
+  }
 
   gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", babl_format_with_space ("RGB float", space));
+  gegl_operation_set_format (operation, "aux", format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -69,6 +111,9 @@ process (GeglOperation       *op,
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
   gint    i;
 
   if (aux == NULL)
@@ -77,16 +122,17 @@ process (GeglOperation       *op,
       for (i=0; i<n_pixels; i++)
         {
           gint   j;
-          for (j=0; j<3; j++)
+          for (j=0; j<components-alpha; j++)
             {
               gfloat result;
               gfloat input=in[j];
               result = input + value;
               out[j]=result;
             }
-          out[3]=in[3];
-          in += 4;
-          out+= 4;
+          if (alpha)
+            out[components-1]=in[components-1];
+          in += components;
+          out+= components;
         }
     }
   else
@@ -95,7 +141,7 @@ process (GeglOperation       *op,
         {
           gint   j;
           gfloat value;
-          for (j=0; j<3; j++)
+          for (j=0; j<components-alpha; j++)
             {
               gfloat input =in[j];
               gfloat result;
@@ -103,13 +149,14 @@ process (GeglOperation       *op,
               result = input + value;
               out[j]=result;
             }
-          out[3]=in[3];
-          in += 4;
-          aux += 3;
-          out+= 4;
+          if (alpha)
+            out[components-1]=in[components-1];
+
+          in  += components;
+          aux += components;
+          out += components;
         }
     }
-
   return TRUE;
 }
 
diff --git a/operations/generated/clear.c b/operations/generated/clear.c
index bc56ae601..37f6b7a81 100644
--- a/operations/generated/clear.c
+++ b/operations/generated/clear.c
@@ -48,18 +48,55 @@ property_boolean (srgb, _("sRGB"), FALSE)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-    space = gegl_operation_get_source_space (operation, "aux");
-
-  if (GEGL_PROPERTIES (operation)->srgb)
-    format = babl_format_with_space ("R~aG~aB~aA float", space);
+  int use_srgb = GEGL_PROPERTIES (operation)->srgb?1:0;
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
+
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~ float":"Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~aA float":"YaA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~G~B~ float":"RGB float", space);
+  }
+  else if (babl_model_is (model, "RGBA")    ||
+           babl_model_is (model, "RGB")     ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'")  ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~")  ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
   else
-    format = babl_format_with_space ("RaGaBaA float", space);
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
 
-  gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", format);
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -76,6 +113,9 @@ process (GeglOperation        *op,
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
 
   if (!aux)
     return TRUE;
@@ -86,11 +126,18 @@ process (GeglOperation        *op,
           gint   j;
           gfloat aA G_GNUC_UNUSED, aB G_GNUC_UNUSED, aD G_GNUC_UNUSED;
 
-          aB = in[3];
-          aA = aux[3];
+          if (alpha)
+          {
+            aB = in[components-1];
+            aA = aux[components-1];
+          }
+          else
+          {
+            aB = aA = 1.0f;
+          }
           aD = 0.0f;
 
-          for (j = 0; j < 3; j++)
+          for (j = 0; j < components-alpha; j++)
             {
               gfloat cA G_GNUC_UNUSED, cB G_GNUC_UNUSED;
 
@@ -98,10 +145,11 @@ process (GeglOperation        *op,
               cA = aux[j];
               out[j] = 0.0f;
             }
-          out[3] = aD;
-          in  += 4;
-          aux += 4;
-          out += 4;
+          if (alpha)
+            out[components-alpha] = aD;
+          in  += components;
+          aux += components;
+          out += components;
         }
     }
   return TRUE;
diff --git a/operations/generated/color-burn.c b/operations/generated/color-burn.c
index 605b43afd..fc06f3a1b 100644
--- a/operations/generated/color-burn.c
+++ b/operations/generated/color-burn.c
@@ -48,18 +48,55 @@ property_boolean (srgb, _("sRGB"), FALSE)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-    space = gegl_operation_get_source_space (operation, "aux");
+  int use_srgb = GEGL_PROPERTIES (operation)->srgb?1:0;
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
 
-  if (GEGL_PROPERTIES (operation)->srgb)
-    format = babl_format_with_space ("R~aG~aB~aA float", space);
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~ float":"Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~aA float":"YaA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~G~B~ float":"RGB float", space);
+  }
+  else if (babl_model_is (model, "RGBA")    ||
+           babl_model_is (model, "RGB")     ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'")  ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~")  ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
   else
-    format = babl_format_with_space ("RaGaBaA float", space);
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
 
-  gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", format);
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -119,6 +156,9 @@ process (GeglOperation       *op,
          const GeglRectangle *roi,
          gint                 level)
 {
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
@@ -132,11 +172,18 @@ process (GeglOperation       *op,
       gfloat aA, aB, aD;
       gint   j;
 
-      aB = in[3];
-      aA = aux[3];
+      if (alpha)
+      {
+        aB = in[components-1];
+        aA = aux[components-1];
+      }
+      else
+      {
+        aB = aA = 1.0f;
+      }
       aD = aA + aB - aA * aB;
 
-      for (j = 0; j < 3; j++)
+      for (j = 0; j < components-alpha; j++)
         {
           gfloat cA, cB;
 
@@ -147,10 +194,11 @@ process (GeglOperation       *op,
           else
             out[j] = CLAMP ((cA == 0 ? 1 : (aA * (cA * aB + cB * aA - aA * aB) / cA) + cA * (1 - aB) + cB * 
(1 - aA)), 0, aD);
         }
-      out[3] = aD;
-      in  += 4;
-      aux += 4;
-      out += 4;
+      if (alpha)
+        out[components-1] = aD;
+      in  += components;
+      aux += components;
+      out += components;
     }
 
   return TRUE;
diff --git a/operations/generated/color-dodge.c b/operations/generated/color-dodge.c
index ad3ddb40d..dd5c4d6b9 100644
--- a/operations/generated/color-dodge.c
+++ b/operations/generated/color-dodge.c
@@ -48,18 +48,55 @@ property_boolean (srgb, _("sRGB"), FALSE)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-    space = gegl_operation_get_source_space (operation, "aux");
+  int use_srgb = GEGL_PROPERTIES (operation)->srgb?1:0;
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
 
-  if (GEGL_PROPERTIES (operation)->srgb)
-    format = babl_format_with_space ("R~aG~aB~aA float", space);
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~ float":"Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~aA float":"YaA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~G~B~ float":"RGB float", space);
+  }
+  else if (babl_model_is (model, "RGBA")    ||
+           babl_model_is (model, "RGB")     ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'")  ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~")  ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
   else
-    format = babl_format_with_space ("RaGaBaA float", space);
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
 
-  gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", format);
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -119,6 +156,9 @@ process (GeglOperation       *op,
          const GeglRectangle *roi,
          gint                 level)
 {
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
@@ -132,11 +172,18 @@ process (GeglOperation       *op,
       gfloat aA, aB, aD;
       gint   j;
 
-      aB = in[3];
-      aA = aux[3];
+      if (alpha)
+      {
+        aB = in[components-1];
+        aA = aux[components-1];
+      }
+      else
+      {
+        aB = aA = 1.0f;
+      }
       aD = aA + aB - aA * aB;
 
-      for (j = 0; j < 3; j++)
+      for (j = 0; j < components-alpha; j++)
         {
           gfloat cA, cB;
 
@@ -147,10 +194,11 @@ process (GeglOperation       *op,
           else
             out[j] = CLAMP ((cA == aA ? 1 : cB * aA / (aA == 0 ? 1 : 1 - cA / aA)) + cA * (1 - aB) + cB * (1 
- aA), 0, aD);
         }
-      out[3] = aD;
-      in  += 4;
-      aux += 4;
-      out += 4;
+      if (alpha)
+        out[components-1] = aD;
+      in  += components;
+      aux += components;
+      out += components;
     }
 
   return TRUE;
diff --git a/operations/generated/darken.c b/operations/generated/darken.c
index 14f82febf..22dffa6dd 100644
--- a/operations/generated/darken.c
+++ b/operations/generated/darken.c
@@ -48,18 +48,55 @@ property_boolean (srgb, _("sRGB"), FALSE)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-    space = gegl_operation_get_source_space (operation, "aux");
+  int use_srgb = GEGL_PROPERTIES (operation)->srgb?1:0;
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
 
-  if (GEGL_PROPERTIES (operation)->srgb)
-    format = babl_format_with_space ("R~aG~aB~aA float", space);
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~ float":"Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~aA float":"YaA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~G~B~ float":"RGB float", space);
+  }
+  else if (babl_model_is (model, "RGBA")    ||
+           babl_model_is (model, "RGB")     ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'")  ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~")  ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
   else
-    format = babl_format_with_space ("RaGaBaA float", space);
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
 
-  gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", format);
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -119,6 +156,9 @@ process (GeglOperation       *op,
          const GeglRectangle *roi,
          gint                 level)
 {
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
@@ -132,11 +172,18 @@ process (GeglOperation       *op,
       gfloat aA, aB, aD;
       gint   j;
 
-      aB = in[3];
-      aA = aux[3];
+      if (alpha)
+      {
+        aB = in[components-1];
+        aA = aux[components-1];
+      }
+      else
+      {
+        aB = aA = 1.0f;
+      }
       aD = aA + aB - aA * aB;
 
-      for (j = 0; j < 3; j++)
+      for (j = 0; j < components-alpha; j++)
         {
           gfloat cA, cB;
 
@@ -144,10 +191,11 @@ process (GeglOperation       *op,
           cA = aux[j];
           out[j] = CLAMP (MIN (cA * aB, cB * aA) + cA * (1 - aB) + cB * (1 - aA), 0, aD);
         }
-      out[3] = aD;
-      in  += 4;
-      aux += 4;
-      out += 4;
+      if (alpha)
+        out[components-1] = aD;
+      in  += components;
+      aux += components;
+      out += components;
     }
 
   return TRUE;
diff --git a/operations/generated/difference.c b/operations/generated/difference.c
index 3402ffa09..10158ca1e 100644
--- a/operations/generated/difference.c
+++ b/operations/generated/difference.c
@@ -48,18 +48,55 @@ property_boolean (srgb, _("sRGB"), FALSE)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-    space = gegl_operation_get_source_space (operation, "aux");
+  int use_srgb = GEGL_PROPERTIES (operation)->srgb?1:0;
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
 
-  if (GEGL_PROPERTIES (operation)->srgb)
-    format = babl_format_with_space ("R~aG~aB~aA float", space);
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~ float":"Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~aA float":"YaA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~G~B~ float":"RGB float", space);
+  }
+  else if (babl_model_is (model, "RGBA")    ||
+           babl_model_is (model, "RGB")     ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'")  ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~")  ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
   else
-    format = babl_format_with_space ("RaGaBaA float", space);
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
 
-  gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", format);
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -119,6 +156,9 @@ process (GeglOperation       *op,
          const GeglRectangle *roi,
          gint                 level)
 {
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
@@ -132,11 +172,18 @@ process (GeglOperation       *op,
       gfloat aA, aB, aD;
       gint   j;
 
-      aB = in[3];
-      aA = aux[3];
+      if (alpha)
+      {
+        aB = in[components-1];
+        aA = aux[components-1];
+      }
+      else
+      {
+        aB = aA = 1.0f;
+      }
       aD = aA + aB - aA * aB;
 
-      for (j = 0; j < 3; j++)
+      for (j = 0; j < components-alpha; j++)
         {
           gfloat cA, cB;
 
@@ -144,10 +191,11 @@ process (GeglOperation       *op,
           cA = aux[j];
           out[j] = CLAMP (cA + cB - 2 * (MIN (cA * aB, cB * aA)), 0, aD);
         }
-      out[3] = aD;
-      in  += 4;
-      aux += 4;
-      out += 4;
+      if (alpha)
+        out[components-1] = aD;
+      in  += components;
+      aux += components;
+      out += components;
     }
 
   return TRUE;
diff --git a/operations/generated/divide.c b/operations/generated/divide.c
index 55db52e8d..c52d67d54 100644
--- a/operations/generated/divide.c
+++ b/operations/generated/divide.c
@@ -46,14 +46,56 @@ property_double (value, _("Value"), 1.0)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-     space = gegl_operation_get_source_space (operation, "aux");
-  format  = babl_format_with_space ("RGBA float", space);
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
+
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space ("Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space ("YA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space ("RGB float", space);
+  }
+#if 0
+  else if (babl_model_is (model, "RGBA") ||
+           babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~") ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space ("RGBA float", space);
+  }
+#endif
+  else
+  {
+    format  = babl_format_with_space ("RGBA float", space);
+  }
 
   gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", babl_format_with_space ("RGB float", space));
+  gegl_operation_set_format (operation, "aux", format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -69,6 +111,9 @@ process (GeglOperation       *op,
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
   gint    i;
 
   if (aux == NULL)
@@ -77,16 +122,17 @@ process (GeglOperation       *op,
       for (i=0; i<n_pixels; i++)
         {
           gint   j;
-          for (j=0; j<3; j++)
+          for (j=0; j<components-alpha; j++)
             {
               gfloat result;
               gfloat input=in[j];
               result = value==0.0f?0.0f:input/value;
               out[j]=result;
             }
-          out[3]=in[3];
-          in += 4;
-          out+= 4;
+          if (alpha)
+            out[components-1]=in[components-1];
+          in += components;
+          out+= components;
         }
     }
   else
@@ -95,7 +141,7 @@ process (GeglOperation       *op,
         {
           gint   j;
           gfloat value;
-          for (j=0; j<3; j++)
+          for (j=0; j<components-alpha; j++)
             {
               gfloat input =in[j];
               gfloat result;
@@ -103,13 +149,14 @@ process (GeglOperation       *op,
               result = value==0.0f?0.0f:input/value;
               out[j]=result;
             }
-          out[3]=in[3];
-          in += 4;
-          aux += 3;
-          out+= 4;
+          if (alpha)
+            out[components-1]=in[components-1];
+
+          in  += components;
+          aux += components;
+          out += components;
         }
     }
-
   return TRUE;
 }
 
diff --git a/operations/generated/dst-atop.c b/operations/generated/dst-atop.c
index 97451c2a5..15f8e2437 100644
--- a/operations/generated/dst-atop.c
+++ b/operations/generated/dst-atop.c
@@ -48,18 +48,55 @@ property_boolean (srgb, _("sRGB"), FALSE)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-    space = gegl_operation_get_source_space (operation, "aux");
-
-  if (GEGL_PROPERTIES (operation)->srgb)
-    format = babl_format_with_space ("R~aG~aB~aA float", space);
+  int use_srgb = GEGL_PROPERTIES (operation)->srgb?1:0;
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
+
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~ float":"Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~aA float":"YaA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~G~B~ float":"RGB float", space);
+  }
+  else if (babl_model_is (model, "RGBA")    ||
+           babl_model_is (model, "RGB")     ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'")  ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~")  ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
   else
-    format = babl_format_with_space ("RaGaBaA float", space);
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
 
-  gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", format);
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -76,6 +113,9 @@ process (GeglOperation        *op,
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
 
   if (!aux)
     return TRUE;
@@ -86,11 +126,18 @@ process (GeglOperation        *op,
           gint   j;
           gfloat aA G_GNUC_UNUSED, aB G_GNUC_UNUSED, aD G_GNUC_UNUSED;
 
-          aB = in[3];
-          aA = aux[3];
+          if (alpha)
+          {
+            aB = in[components-1];
+            aA = aux[components-1];
+          }
+          else
+          {
+            aB = aA = 1.0f;
+          }
           aD = aA;
 
-          for (j = 0; j < 3; j++)
+          for (j = 0; j < components-alpha; j++)
             {
               gfloat cA G_GNUC_UNUSED, cB G_GNUC_UNUSED;
 
@@ -98,10 +145,11 @@ process (GeglOperation        *op,
               cA = aux[j];
               out[j] = cB * aA + cA * (1.0f - aB);
             }
-          out[3] = aD;
-          in  += 4;
-          aux += 4;
-          out += 4;
+          if (alpha)
+            out[components-alpha] = aD;
+          in  += components;
+          aux += components;
+          out += components;
         }
     }
   return TRUE;
diff --git a/operations/generated/dst-in.c b/operations/generated/dst-in.c
index 446607736..6a7ec145c 100644
--- a/operations/generated/dst-in.c
+++ b/operations/generated/dst-in.c
@@ -48,18 +48,55 @@ property_boolean (srgb, _("sRGB"), FALSE)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-    space = gegl_operation_get_source_space (operation, "aux");
-
-  if (GEGL_PROPERTIES (operation)->srgb)
-    format = babl_format_with_space ("R~aG~aB~aA float", space);
+  int use_srgb = GEGL_PROPERTIES (operation)->srgb?1:0;
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
+
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~ float":"Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~aA float":"YaA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~G~B~ float":"RGB float", space);
+  }
+  else if (babl_model_is (model, "RGBA")    ||
+           babl_model_is (model, "RGB")     ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'")  ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~")  ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
   else
-    format = babl_format_with_space ("RaGaBaA float", space);
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
 
-  gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", format);
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -76,6 +113,9 @@ process (GeglOperation        *op,
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
 
   if (!aux)
     return TRUE;
@@ -86,11 +126,18 @@ process (GeglOperation        *op,
           gint   j;
           gfloat aA G_GNUC_UNUSED, aB G_GNUC_UNUSED, aD G_GNUC_UNUSED;
 
-          aB = in[3];
-          aA = aux[3];
+          if (alpha)
+          {
+            aB = in[components-1];
+            aA = aux[components-1];
+          }
+          else
+          {
+            aB = aA = 1.0f;
+          }
           aD = aA * aB;
 
-          for (j = 0; j < 3; j++)
+          for (j = 0; j < components-alpha; j++)
             {
               gfloat cA G_GNUC_UNUSED, cB G_GNUC_UNUSED;
 
@@ -98,10 +145,11 @@ process (GeglOperation        *op,
               cA = aux[j];
               out[j] = cB * aA;
             }
-          out[3] = aD;
-          in  += 4;
-          aux += 4;
-          out += 4;
+          if (alpha)
+            out[components-alpha] = aD;
+          in  += components;
+          aux += components;
+          out += components;
         }
     }
   return TRUE;
diff --git a/operations/generated/dst-out.c b/operations/generated/dst-out.c
index d8998d1ac..7cc90033f 100644
--- a/operations/generated/dst-out.c
+++ b/operations/generated/dst-out.c
@@ -48,18 +48,55 @@ property_boolean (srgb, _("sRGB"), FALSE)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-    space = gegl_operation_get_source_space (operation, "aux");
-
-  if (GEGL_PROPERTIES (operation)->srgb)
-    format = babl_format_with_space ("R~aG~aB~aA float", space);
+  int use_srgb = GEGL_PROPERTIES (operation)->srgb?1:0;
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
+
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~ float":"Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~aA float":"YaA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~G~B~ float":"RGB float", space);
+  }
+  else if (babl_model_is (model, "RGBA")    ||
+           babl_model_is (model, "RGB")     ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'")  ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~")  ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
   else
-    format = babl_format_with_space ("RaGaBaA float", space);
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
 
-  gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", format);
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -76,6 +113,9 @@ process (GeglOperation        *op,
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
 
   if (!aux)
     {
@@ -84,11 +124,11 @@ process (GeglOperation        *op,
           gint   j;
           gfloat aA G_GNUC_UNUSED, aB G_GNUC_UNUSED, aD G_GNUC_UNUSED;
 
-          aB = in[3];
+          aB = alpha?in[components-alpha]:1.0f;
           aA = 0.0f;
           aD = aB * (1.0f - aA);
 
-          for (j = 0; j < 3; j++)
+          for (j = 0; j < components-alpha; j++)
             {
               gfloat cA G_GNUC_UNUSED, cB G_GNUC_UNUSED;
 
@@ -96,9 +136,10 @@ process (GeglOperation        *op,
               cA = 0.0f;
               out[j] = cB * (1.0f - aA);
             }
-          out[3] = aD;
-          in  += 4;
-          out += 4;
+          if (alpha)
+            out[components-1] = aD;
+          in  += components;
+          out += components;
         }
     }
   else
@@ -108,11 +149,18 @@ process (GeglOperation        *op,
           gint   j;
           gfloat aA G_GNUC_UNUSED, aB G_GNUC_UNUSED, aD G_GNUC_UNUSED;
 
-          aB = in[3];
-          aA = aux[3];
+          if (alpha)
+          {
+            aB = in[components-1];
+            aA = aux[components-1];
+          }
+          else
+          {
+            aB = aA = 1.0f;
+          }
           aD = aB * (1.0f - aA);
 
-          for (j = 0; j < 3; j++)
+          for (j = 0; j < components-alpha; j++)
             {
               gfloat cA G_GNUC_UNUSED, cB G_GNUC_UNUSED;
 
@@ -120,10 +168,11 @@ process (GeglOperation        *op,
               cA = aux[j];
               out[j] = cB * (1.0f - aA);
             }
-          out[3] = aD;
-          in  += 4;
-          aux += 4;
-          out += 4;
+          if (alpha)
+            out[components-alpha] = aD;
+          in  += components;
+          aux += components;
+          out += components;
         }
     }
   return TRUE;
diff --git a/operations/generated/dst-over.c b/operations/generated/dst-over.c
index f69d15d7a..22a3c0b71 100644
--- a/operations/generated/dst-over.c
+++ b/operations/generated/dst-over.c
@@ -48,18 +48,55 @@ property_boolean (srgb, _("sRGB"), FALSE)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-    space = gegl_operation_get_source_space (operation, "aux");
-
-  if (GEGL_PROPERTIES (operation)->srgb)
-    format = babl_format_with_space ("R~aG~aB~aA float", space);
+  int use_srgb = GEGL_PROPERTIES (operation)->srgb?1:0;
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
+
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~ float":"Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~aA float":"YaA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~G~B~ float":"RGB float", space);
+  }
+  else if (babl_model_is (model, "RGBA")    ||
+           babl_model_is (model, "RGB")     ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'")  ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~")  ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
   else
-    format = babl_format_with_space ("RaGaBaA float", space);
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
 
-  gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", format);
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -76,6 +113,9 @@ process (GeglOperation        *op,
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
 
   if (!aux)
     {
@@ -84,11 +124,11 @@ process (GeglOperation        *op,
           gint   j;
           gfloat aA G_GNUC_UNUSED, aB G_GNUC_UNUSED, aD G_GNUC_UNUSED;
 
-          aB = in[3];
+          aB = alpha?in[components-alpha]:1.0f;
           aA = 0.0f;
           aD = aA + aB - aA * aB;
 
-          for (j = 0; j < 3; j++)
+          for (j = 0; j < components-alpha; j++)
             {
               gfloat cA G_GNUC_UNUSED, cB G_GNUC_UNUSED;
 
@@ -96,9 +136,10 @@ process (GeglOperation        *op,
               cA = 0.0f;
               out[j] = cB + cA * (1.0f - aB);
             }
-          out[3] = aD;
-          in  += 4;
-          out += 4;
+          if (alpha)
+            out[components-1] = aD;
+          in  += components;
+          out += components;
         }
     }
   else
@@ -108,11 +149,18 @@ process (GeglOperation        *op,
           gint   j;
           gfloat aA G_GNUC_UNUSED, aB G_GNUC_UNUSED, aD G_GNUC_UNUSED;
 
-          aB = in[3];
-          aA = aux[3];
+          if (alpha)
+          {
+            aB = in[components-1];
+            aA = aux[components-1];
+          }
+          else
+          {
+            aB = aA = 1.0f;
+          }
           aD = aA + aB - aA * aB;
 
-          for (j = 0; j < 3; j++)
+          for (j = 0; j < components-alpha; j++)
             {
               gfloat cA G_GNUC_UNUSED, cB G_GNUC_UNUSED;
 
@@ -120,10 +168,11 @@ process (GeglOperation        *op,
               cA = aux[j];
               out[j] = cB + cA * (1.0f - aB);
             }
-          out[3] = aD;
-          in  += 4;
-          aux += 4;
-          out += 4;
+          if (alpha)
+            out[components-alpha] = aD;
+          in  += components;
+          aux += components;
+          out += components;
         }
     }
   return TRUE;
diff --git a/operations/generated/dst.c b/operations/generated/dst.c
index fb1396e99..56d33759f 100644
--- a/operations/generated/dst.c
+++ b/operations/generated/dst.c
@@ -48,18 +48,55 @@ property_boolean (srgb, _("sRGB"), FALSE)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-    space = gegl_operation_get_source_space (operation, "aux");
-
-  if (GEGL_PROPERTIES (operation)->srgb)
-    format = babl_format_with_space ("R~aG~aB~aA float", space);
+  int use_srgb = GEGL_PROPERTIES (operation)->srgb?1:0;
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
+
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~ float":"Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~aA float":"YaA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~G~B~ float":"RGB float", space);
+  }
+  else if (babl_model_is (model, "RGBA")    ||
+           babl_model_is (model, "RGB")     ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'")  ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~")  ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
   else
-    format = babl_format_with_space ("RaGaBaA float", space);
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
 
-  gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", format);
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -76,6 +113,9 @@ process (GeglOperation        *op,
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
 
   if (!aux)
     {
@@ -84,11 +124,11 @@ process (GeglOperation        *op,
           gint   j;
           gfloat aA G_GNUC_UNUSED, aB G_GNUC_UNUSED, aD G_GNUC_UNUSED;
 
-          aB = in[3];
+          aB = alpha?in[components-alpha]:1.0f;
           aA = 0.0f;
           aD = aB;
 
-          for (j = 0; j < 3; j++)
+          for (j = 0; j < components-alpha; j++)
             {
               gfloat cA G_GNUC_UNUSED, cB G_GNUC_UNUSED;
 
@@ -96,9 +136,10 @@ process (GeglOperation        *op,
               cA = 0.0f;
               out[j] = cB;
             }
-          out[3] = aD;
-          in  += 4;
-          out += 4;
+          if (alpha)
+            out[components-1] = aD;
+          in  += components;
+          out += components;
         }
     }
   else
@@ -108,11 +149,18 @@ process (GeglOperation        *op,
           gint   j;
           gfloat aA G_GNUC_UNUSED, aB G_GNUC_UNUSED, aD G_GNUC_UNUSED;
 
-          aB = in[3];
-          aA = aux[3];
+          if (alpha)
+          {
+            aB = in[components-1];
+            aA = aux[components-1];
+          }
+          else
+          {
+            aB = aA = 1.0f;
+          }
           aD = aB;
 
-          for (j = 0; j < 3; j++)
+          for (j = 0; j < components-alpha; j++)
             {
               gfloat cA G_GNUC_UNUSED, cB G_GNUC_UNUSED;
 
@@ -120,10 +168,11 @@ process (GeglOperation        *op,
               cA = aux[j];
               out[j] = cB;
             }
-          out[3] = aD;
-          in  += 4;
-          aux += 4;
-          out += 4;
+          if (alpha)
+            out[components-alpha] = aD;
+          in  += components;
+          aux += components;
+          out += components;
         }
     }
   return TRUE;
diff --git a/operations/generated/exclusion.c b/operations/generated/exclusion.c
index 109c6e761..c8022991e 100644
--- a/operations/generated/exclusion.c
+++ b/operations/generated/exclusion.c
@@ -48,18 +48,55 @@ property_boolean (srgb, _("sRGB"), FALSE)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-    space = gegl_operation_get_source_space (operation, "aux");
+  int use_srgb = GEGL_PROPERTIES (operation)->srgb?1:0;
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
 
-  if (GEGL_PROPERTIES (operation)->srgb)
-    format = babl_format_with_space ("R~aG~aB~aA float", space);
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~ float":"Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~aA float":"YaA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~G~B~ float":"RGB float", space);
+  }
+  else if (babl_model_is (model, "RGBA")    ||
+           babl_model_is (model, "RGB")     ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'")  ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~")  ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
   else
-    format = babl_format_with_space ("RaGaBaA float", space);
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
 
-  gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", format);
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -119,6 +156,9 @@ process (GeglOperation       *op,
          const GeglRectangle *roi,
          gint                 level)
 {
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
@@ -132,11 +172,18 @@ process (GeglOperation       *op,
       gfloat aA, aB, aD;
       gint   j;
 
-      aB = in[3];
-      aA = aux[3];
+      if (alpha)
+      {
+        aB = in[components-1];
+        aA = aux[components-1];
+      }
+      else
+      {
+        aB = aA = 1.0f;
+      }
       aD = aA + aB - aA * aB;
 
-      for (j = 0; j < 3; j++)
+      for (j = 0; j < components-alpha; j++)
         {
           gfloat cA, cB;
 
@@ -144,10 +191,11 @@ process (GeglOperation       *op,
           cA = aux[j];
           out[j] = CLAMP ((cA * aB + cB * aA - 2 * cA * cB) + cA * (1 - aB) + cB * (1 - aA), 0, aD);
         }
-      out[3] = aD;
-      in  += 4;
-      aux += 4;
-      out += 4;
+      if (alpha)
+        out[components-1] = aD;
+      in  += components;
+      aux += components;
+      out += components;
     }
 
   return TRUE;
diff --git a/operations/generated/gamma.c b/operations/generated/gamma.c
index df9ca042c..3594dfad5 100644
--- a/operations/generated/gamma.c
+++ b/operations/generated/gamma.c
@@ -46,14 +46,56 @@ property_double (value, _("Value"), 1.0)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-     space = gegl_operation_get_source_space (operation, "aux");
-  format  = babl_format_with_space ("RGBA float", space);
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
+
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space ("Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space ("YA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space ("RGB float", space);
+  }
+#if 0
+  else if (babl_model_is (model, "RGBA") ||
+           babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~") ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space ("RGBA float", space);
+  }
+#endif
+  else
+  {
+    format  = babl_format_with_space ("RGBA float", space);
+  }
 
   gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", babl_format_with_space ("RGB float", space));
+  gegl_operation_set_format (operation, "aux", format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -69,6 +111,9 @@ process (GeglOperation       *op,
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
   gint    i;
 
   if (aux == NULL)
@@ -77,16 +122,17 @@ process (GeglOperation       *op,
       for (i=0; i<n_pixels; i++)
         {
           gint   j;
-          for (j=0; j<3; j++)
+          for (j=0; j<components-alpha; j++)
             {
               gfloat result;
               gfloat input=in[j];
               result = powf (input, value);
               out[j]=result;
             }
-          out[3]=in[3];
-          in += 4;
-          out+= 4;
+          if (alpha)
+            out[components-1]=in[components-1];
+          in += components;
+          out+= components;
         }
     }
   else
@@ -95,7 +141,7 @@ process (GeglOperation       *op,
         {
           gint   j;
           gfloat value;
-          for (j=0; j<3; j++)
+          for (j=0; j<components-alpha; j++)
             {
               gfloat input =in[j];
               gfloat result;
@@ -103,13 +149,14 @@ process (GeglOperation       *op,
               result = powf (input, value);
               out[j]=result;
             }
-          out[3]=in[3];
-          in += 4;
-          aux += 3;
-          out+= 4;
+          if (alpha)
+            out[components-1]=in[components-1];
+
+          in  += components;
+          aux += components;
+          out += components;
         }
     }
-
   return TRUE;
 }
 
diff --git a/operations/generated/hard-light.c b/operations/generated/hard-light.c
index f5724cfbb..1f2c078f7 100644
--- a/operations/generated/hard-light.c
+++ b/operations/generated/hard-light.c
@@ -48,18 +48,55 @@ property_boolean (srgb, _("sRGB"), FALSE)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-    space = gegl_operation_get_source_space (operation, "aux");
+  int use_srgb = GEGL_PROPERTIES (operation)->srgb?1:0;
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
 
-  if (GEGL_PROPERTIES (operation)->srgb)
-    format = babl_format_with_space ("R~aG~aB~aA float", space);
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~ float":"Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~aA float":"YaA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~G~B~ float":"RGB float", space);
+  }
+  else if (babl_model_is (model, "RGBA")    ||
+           babl_model_is (model, "RGB")     ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'")  ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~")  ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
   else
-    format = babl_format_with_space ("RaGaBaA float", space);
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
 
-  gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", format);
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -119,6 +156,9 @@ process (GeglOperation       *op,
          const GeglRectangle *roi,
          gint                 level)
 {
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
@@ -132,11 +172,18 @@ process (GeglOperation       *op,
       gfloat aA, aB, aD;
       gint   j;
 
-      aB = in[3];
-      aA = aux[3];
+      if (alpha)
+      {
+        aB = in[components-1];
+        aA = aux[components-1];
+      }
+      else
+      {
+        aB = aA = 1.0f;
+      }
       aD = aA + aB - aA * aB;
 
-      for (j = 0; j < 3; j++)
+      for (j = 0; j < components-alpha; j++)
         {
           gfloat cA, cB;
 
@@ -147,10 +194,11 @@ process (GeglOperation       *op,
           else
             out[j] = CLAMP (aA * aB - 2 * (aB - cB) * (aA - cA) + cA * (1 - aB) + cB * (1 - aA), 0, aD);
         }
-      out[3] = aD;
-      in  += 4;
-      aux += 4;
-      out += 4;
+      if (alpha)
+        out[components-1] = aD;
+      in  += components;
+      aux += components;
+      out += components;
     }
 
   return TRUE;
diff --git a/operations/generated/lighten.c b/operations/generated/lighten.c
index 267a2b283..6c37389f7 100644
--- a/operations/generated/lighten.c
+++ b/operations/generated/lighten.c
@@ -48,18 +48,55 @@ property_boolean (srgb, _("sRGB"), FALSE)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-    space = gegl_operation_get_source_space (operation, "aux");
+  int use_srgb = GEGL_PROPERTIES (operation)->srgb?1:0;
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
 
-  if (GEGL_PROPERTIES (operation)->srgb)
-    format = babl_format_with_space ("R~aG~aB~aA float", space);
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~ float":"Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~aA float":"YaA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~G~B~ float":"RGB float", space);
+  }
+  else if (babl_model_is (model, "RGBA")    ||
+           babl_model_is (model, "RGB")     ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'")  ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~")  ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
   else
-    format = babl_format_with_space ("RaGaBaA float", space);
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
 
-  gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", format);
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -119,6 +156,9 @@ process (GeglOperation       *op,
          const GeglRectangle *roi,
          gint                 level)
 {
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
@@ -132,11 +172,18 @@ process (GeglOperation       *op,
       gfloat aA, aB, aD;
       gint   j;
 
-      aB = in[3];
-      aA = aux[3];
+      if (alpha)
+      {
+        aB = in[components-1];
+        aA = aux[components-1];
+      }
+      else
+      {
+        aB = aA = 1.0f;
+      }
       aD = aA + aB - aA * aB;
 
-      for (j = 0; j < 3; j++)
+      for (j = 0; j < components-alpha; j++)
         {
           gfloat cA, cB;
 
@@ -144,10 +191,11 @@ process (GeglOperation       *op,
           cA = aux[j];
           out[j] = CLAMP (MAX (cA * aB, cB * aA) + cA * (1 - aB) + cB * (1 - aA), 0, aD);
         }
-      out[3] = aD;
-      in  += 4;
-      aux += 4;
-      out += 4;
+      if (alpha)
+        out[components-1] = aD;
+      in  += components;
+      aux += components;
+      out += components;
     }
 
   return TRUE;
diff --git a/operations/generated/math.rb b/operations/generated/math.rb
index d75aa11f4..0bb124caa 100755
--- a/operations/generated/math.rb
+++ b/operations/generated/math.rb
@@ -76,14 +76,56 @@ property_double (value, _(\"Value\"), #{item[2]})
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, \"input\");
-  const Babl *format;
-  if (!space)
-     space = gegl_operation_get_source_space (operation, \"aux\");
-  format  = babl_format_with_space (\"RGBA float\", space);
+  const Babl *format = gegl_operation_get_source_format (operation, \"input\");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, \"aux\");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
+
+  if (babl_model_is (model, \"Y\") ||
+      babl_model_is (model, \"Y'\") ||
+      babl_model_is (model, \"Y~\"))
+  {
+    format  = babl_format_with_space (\"Y float\", space);
+  }
+  else if (babl_model_is (model, \"YA\") ||
+           babl_model_is (model, \"Y'A\") ||
+           babl_model_is (model, \"Y~A\") ||
+           babl_model_is (model, \"YaA\") ||
+           babl_model_is (model, \"Y'aA\"))
+  {
+    format  = babl_format_with_space (\"YA float\", space);
+  }
+  else if (babl_model_is (model, \"RGB\") ||
+           babl_model_is (model, \"R'G'B'\") ||
+           babl_model_is (model, \"R~G~B~\"))
+  {
+    format  = babl_format_with_space (\"RGB float\", space);
+  }
+#if 0
+  else if (babl_model_is (model, \"RGBA\") ||
+           babl_model_is (model, \"RGB\") ||
+           babl_model_is (model, \"R'G'B'A\") ||
+           babl_model_is (model, \"R'G'B'\") ||
+           babl_model_is (model, \"R~G~B~A\") ||
+           babl_model_is (model, \"R~G~B~\") ||
+           babl_model_is (model, \"RaGaBaA\") ||
+           babl_model_is (model, \"R'aG'aB'aA\"))
+  {
+    format  = babl_format_with_space (\"RGBA float\", space);
+  }
+#endif
+  else
+  {
+    format  = babl_format_with_space (\"RGBA float\", space);
+  }
 
   gegl_operation_set_format (operation, \"input\", format);
-  gegl_operation_set_format (operation, \"aux\", babl_format_with_space (\"RGB float\", space));
+  gegl_operation_set_format (operation, \"aux\", format);
   gegl_operation_set_format (operation, \"output\", format);
 }
 
@@ -99,6 +141,9 @@ process (GeglOperation       *op,
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
+  const Babl *format = gegl_operation_get_format (op, \"output\");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
   gint    i;
 
   if (aux == NULL)
@@ -107,16 +152,17 @@ process (GeglOperation       *op,
       for (i=0; i<n_pixels; i++)
         {
           gint   j;
-          for (j=0; j<3; j++)
+          for (j=0; j<components-alpha; j++)
             {
               gfloat result;
               gfloat input=in[j];
               #{formula};
               out[j]=result;
             }
-          out[3]=in[3];
-          in += 4;
-          out+= 4;
+          if (alpha)
+            out[components-1]=in[components-1];
+          in += components;
+          out+= components;
         }
     }
   else
@@ -125,7 +171,7 @@ process (GeglOperation       *op,
         {
           gint   j;
           gfloat value;
-          for (j=0; j<3; j++)
+          for (j=0; j<components-alpha; j++)
             {
               gfloat input =in[j];
               gfloat result;
@@ -133,13 +179,14 @@ process (GeglOperation       *op,
               #{formula};
               out[j]=result;
             }
-          out[3]=in[3];
-          in += 4;
-          aux += 3;
-          out+= 4;
+          if (alpha)
+            out[components-1]=in[components-1];
+
+          in  += components;
+          aux += components;
+          out += components;
         }
     }
-
   return TRUE;
 }
 
diff --git a/operations/generated/multiply.c b/operations/generated/multiply.c
index 87fcb5242..b603b647d 100644
--- a/operations/generated/multiply.c
+++ b/operations/generated/multiply.c
@@ -46,14 +46,56 @@ property_double (value, _("Value"), 1.0)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-     space = gegl_operation_get_source_space (operation, "aux");
-  format  = babl_format_with_space ("RGBA float", space);
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
+
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space ("Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space ("YA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space ("RGB float", space);
+  }
+#if 0
+  else if (babl_model_is (model, "RGBA") ||
+           babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~") ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space ("RGBA float", space);
+  }
+#endif
+  else
+  {
+    format  = babl_format_with_space ("RGBA float", space);
+  }
 
   gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", babl_format_with_space ("RGB float", space));
+  gegl_operation_set_format (operation, "aux", format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -69,6 +111,9 @@ process (GeglOperation       *op,
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
   gint    i;
 
   if (aux == NULL)
@@ -77,16 +122,17 @@ process (GeglOperation       *op,
       for (i=0; i<n_pixels; i++)
         {
           gint   j;
-          for (j=0; j<3; j++)
+          for (j=0; j<components-alpha; j++)
             {
               gfloat result;
               gfloat input=in[j];
               result = input * value;
               out[j]=result;
             }
-          out[3]=in[3];
-          in += 4;
-          out+= 4;
+          if (alpha)
+            out[components-1]=in[components-1];
+          in += components;
+          out+= components;
         }
     }
   else
@@ -95,7 +141,7 @@ process (GeglOperation       *op,
         {
           gint   j;
           gfloat value;
-          for (j=0; j<3; j++)
+          for (j=0; j<components-alpha; j++)
             {
               gfloat input =in[j];
               gfloat result;
@@ -103,13 +149,14 @@ process (GeglOperation       *op,
               result = input * value;
               out[j]=result;
             }
-          out[3]=in[3];
-          in += 4;
-          aux += 3;
-          out+= 4;
+          if (alpha)
+            out[components-1]=in[components-1];
+
+          in  += components;
+          aux += components;
+          out += components;
         }
     }
-
   return TRUE;
 }
 
diff --git a/operations/generated/overlay.c b/operations/generated/overlay.c
index 50697dd1f..12aab208d 100644
--- a/operations/generated/overlay.c
+++ b/operations/generated/overlay.c
@@ -48,18 +48,55 @@ property_boolean (srgb, _("sRGB"), FALSE)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-    space = gegl_operation_get_source_space (operation, "aux");
+  int use_srgb = GEGL_PROPERTIES (operation)->srgb?1:0;
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
 
-  if (GEGL_PROPERTIES (operation)->srgb)
-    format = babl_format_with_space ("R~aG~aB~aA float", space);
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~ float":"Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~aA float":"YaA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~G~B~ float":"RGB float", space);
+  }
+  else if (babl_model_is (model, "RGBA")    ||
+           babl_model_is (model, "RGB")     ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'")  ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~")  ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
   else
-    format = babl_format_with_space ("RaGaBaA float", space);
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
 
-  gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", format);
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -119,6 +156,9 @@ process (GeglOperation       *op,
          const GeglRectangle *roi,
          gint                 level)
 {
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
@@ -132,11 +172,18 @@ process (GeglOperation       *op,
       gfloat aA, aB, aD;
       gint   j;
 
-      aB = in[3];
-      aA = aux[3];
+      if (alpha)
+      {
+        aB = in[components-1];
+        aA = aux[components-1];
+      }
+      else
+      {
+        aB = aA = 1.0f;
+      }
       aD = aA + aB - aA * aB;
 
-      for (j = 0; j < 3; j++)
+      for (j = 0; j < components-alpha; j++)
         {
           gfloat cA, cB;
 
@@ -147,10 +194,11 @@ process (GeglOperation       *op,
           else
             out[j] = CLAMP (aA * aB - 2 * (aB - cB) * (aA - cA) + cA * (1 - aB) + cB * (1 - aA), 0, aD);
         }
-      out[3] = aD;
-      in  += 4;
-      aux += 4;
-      out += 4;
+      if (alpha)
+        out[components-1] = aD;
+      in  += components;
+      aux += components;
+      out += components;
     }
 
   return TRUE;
diff --git a/operations/generated/plus.c b/operations/generated/plus.c
index 35928497c..6e8ece5a7 100644
--- a/operations/generated/plus.c
+++ b/operations/generated/plus.c
@@ -48,18 +48,55 @@ property_boolean (srgb, _("sRGB"), FALSE)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-    space = gegl_operation_get_source_space (operation, "aux");
+  int use_srgb = GEGL_PROPERTIES (operation)->srgb?1:0;
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
 
-  if (GEGL_PROPERTIES (operation)->srgb)
-    format = babl_format_with_space ("R~aG~aB~aA float", space);
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~ float":"Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~aA float":"YaA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~G~B~ float":"RGB float", space);
+  }
+  else if (babl_model_is (model, "RGBA")    ||
+           babl_model_is (model, "RGB")     ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'")  ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~")  ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
   else
-    format = babl_format_with_space ("RaGaBaA float", space);
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
 
-  gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", format);
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -119,6 +156,9 @@ process (GeglOperation       *op,
          const GeglRectangle *roi,
          gint                 level)
 {
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
@@ -132,11 +172,18 @@ process (GeglOperation       *op,
       gfloat aA, aB, aD;
       gint   j;
 
-      aB = in[3];
-      aA = aux[3];
+      if (alpha)
+      {
+        aB = in[components-1];
+        aA = aux[components-1];
+      }
+      else
+      {
+        aA = aB = 1.0f;
+      }
       aD = MIN (aA + aB, 1);
 
-      for (j = 0; j < 3; j++)
+      for (j = 0; j < components-alpha; j++)
         {
           gfloat cA, cB;
 
@@ -144,10 +191,11 @@ process (GeglOperation       *op,
           cA = aux[j];
           out[j] = CLAMP (cA + cB, 0, aD);
         }
-      out[3] = aD;
-      in  += 4;
-      aux += 4;
-      out += 4;
+      if (alpha)
+        out[components-1] = aD;
+      in  += components;
+      aux += components;
+      out += components;
     }
 
   return TRUE;
diff --git a/operations/generated/screen.c b/operations/generated/screen.c
index 64a0d6e16..0cee8cf8c 100644
--- a/operations/generated/screen.c
+++ b/operations/generated/screen.c
@@ -48,18 +48,55 @@ property_boolean (srgb, _("sRGB"), FALSE)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-    space = gegl_operation_get_source_space (operation, "aux");
+  int use_srgb = GEGL_PROPERTIES (operation)->srgb?1:0;
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
 
-  if (GEGL_PROPERTIES (operation)->srgb)
-    format = babl_format_with_space ("R~aG~aB~aA float", space);
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~ float":"Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~aA float":"YaA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~G~B~ float":"RGB float", space);
+  }
+  else if (babl_model_is (model, "RGBA")    ||
+           babl_model_is (model, "RGB")     ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'")  ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~")  ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
   else
-    format = babl_format_with_space ("RaGaBaA float", space);
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
 
-  gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", format);
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -119,6 +156,9 @@ process (GeglOperation       *op,
          const GeglRectangle *roi,
          gint                 level)
 {
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
@@ -132,11 +172,18 @@ process (GeglOperation       *op,
       gfloat aA, aB, aD;
       gint   j;
 
-      aB = in[3];
-      aA = aux[3];
+      if (alpha)
+      {
+        aB = in[components-1];
+        aA = aux[components-1];
+      }
+      else
+      {
+        aB = aA = 1.0f;
+      }
       aD = aA + aB - aA * aB;
 
-      for (j = 0; j < 3; j++)
+      for (j = 0; j < components-alpha; j++)
         {
           gfloat cA, cB;
 
@@ -144,10 +191,11 @@ process (GeglOperation       *op,
           cA = aux[j];
           out[j] = CLAMP (cA + cB - cA * cB, 0, aD);
         }
-      out[3] = aD;
-      in  += 4;
-      aux += 4;
-      out += 4;
+      if (alpha)
+        out[components-1] = aD;
+      in  += components;
+      aux += components;
+      out += components;
     }
 
   return TRUE;
diff --git a/operations/generated/soft-light.c b/operations/generated/soft-light.c
index 0a2be72dd..5822468dd 100644
--- a/operations/generated/soft-light.c
+++ b/operations/generated/soft-light.c
@@ -49,18 +49,55 @@ property_boolean (srgb, _("sRGB"), FALSE)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-    space = gegl_operation_get_source_space (operation, "aux");
+  int use_srgb = GEGL_PROPERTIES (operation)->srgb?1:0;
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
 
-  if (GEGL_PROPERTIES (operation)->srgb)
-    format = babl_format_with_space ("R~aG~aB~aA float", space);
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~ float":"Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~aA float":"YaA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~G~B~ float":"RGB float", space);
+  }
+  else if (babl_model_is (model, "RGBA")    ||
+           babl_model_is (model, "RGB")     ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'")  ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~")  ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
   else
-    format = babl_format_with_space ("RaGaBaA float", space);
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
 
-  gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", format);
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -120,6 +157,9 @@ process (GeglOperation       *op,
          const GeglRectangle *roi,
          gint                 level)
 {
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
@@ -133,11 +173,18 @@ process (GeglOperation       *op,
       gfloat aA, aB, aD;
       gint   j;
 
-      aB = in[3];
-      aA = aux[3];
+      if (alpha)
+      {
+        aB = in[components-1];
+        aA = aux[components-1];
+      }
+      else
+      {
+        aB = aA = 1.0f;
+      }
       aD = aA + aB - aA * aB;
 
-      for (j = 0; j < 3; j++)
+      for (j = 0; j < components-alpha; j++)
         {
           gfloat cA, cB;
 
@@ -150,10 +197,13 @@ process (GeglOperation       *op,
           else
             out[j] = CLAMP ((aA * cB + (aB == 0 ? 0 : sqrt (cB / aB) * aB - cB) * (2 * cA - aA)) + cA * (1 - 
aB) + cB * (1 - aA), 0, aD);
         }
-      out[3] = aD;
-      in  += 4;
-      aux += 4;
-      out += 4;
+      if (alpha)
+      {
+        out[components-1] = aD;
+      }
+      in  += components;
+      aux += components;
+      out += components;
     }
 
   return TRUE;
diff --git a/operations/generated/src-atop.c b/operations/generated/src-atop.c
index 22f8f6fd1..376d9d520 100644
--- a/operations/generated/src-atop.c
+++ b/operations/generated/src-atop.c
@@ -48,18 +48,55 @@ property_boolean (srgb, _("sRGB"), FALSE)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-    space = gegl_operation_get_source_space (operation, "aux");
-
-  if (GEGL_PROPERTIES (operation)->srgb)
-    format = babl_format_with_space ("R~aG~aB~aA float", space);
+  int use_srgb = GEGL_PROPERTIES (operation)->srgb?1:0;
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
+
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~ float":"Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~aA float":"YaA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~G~B~ float":"RGB float", space);
+  }
+  else if (babl_model_is (model, "RGBA")    ||
+           babl_model_is (model, "RGB")     ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'")  ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~")  ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
   else
-    format = babl_format_with_space ("RaGaBaA float", space);
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
 
-  gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", format);
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -76,6 +113,9 @@ process (GeglOperation        *op,
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
 
   if (!aux)
     {
@@ -84,11 +124,11 @@ process (GeglOperation        *op,
           gint   j;
           gfloat aA G_GNUC_UNUSED, aB G_GNUC_UNUSED, aD G_GNUC_UNUSED;
 
-          aB = in[3];
+          aB = alpha?in[components-alpha]:1.0f;
           aA = 0.0f;
           aD = aB;
 
-          for (j = 0; j < 3; j++)
+          for (j = 0; j < components-alpha; j++)
             {
               gfloat cA G_GNUC_UNUSED, cB G_GNUC_UNUSED;
 
@@ -96,9 +136,10 @@ process (GeglOperation        *op,
               cA = 0.0f;
               out[j] = cA * aB + cB * (1.0f - aA);
             }
-          out[3] = aD;
-          in  += 4;
-          out += 4;
+          if (alpha)
+            out[components-1] = aD;
+          in  += components;
+          out += components;
         }
     }
   else
@@ -108,11 +149,18 @@ process (GeglOperation        *op,
           gint   j;
           gfloat aA G_GNUC_UNUSED, aB G_GNUC_UNUSED, aD G_GNUC_UNUSED;
 
-          aB = in[3];
-          aA = aux[3];
+          if (alpha)
+          {
+            aB = in[components-1];
+            aA = aux[components-1];
+          }
+          else
+          {
+            aB = aA = 1.0f;
+          }
           aD = aB;
 
-          for (j = 0; j < 3; j++)
+          for (j = 0; j < components-alpha; j++)
             {
               gfloat cA G_GNUC_UNUSED, cB G_GNUC_UNUSED;
 
@@ -120,10 +168,11 @@ process (GeglOperation        *op,
               cA = aux[j];
               out[j] = cA * aB + cB * (1.0f - aA);
             }
-          out[3] = aD;
-          in  += 4;
-          aux += 4;
-          out += 4;
+          if (alpha)
+            out[components-alpha] = aD;
+          in  += components;
+          aux += components;
+          out += components;
         }
     }
   return TRUE;
diff --git a/operations/generated/src-in.c b/operations/generated/src-in.c
index e11aa1c63..fc0d0c031 100644
--- a/operations/generated/src-in.c
+++ b/operations/generated/src-in.c
@@ -48,18 +48,55 @@ property_boolean (srgb, _("sRGB"), FALSE)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-    space = gegl_operation_get_source_space (operation, "aux");
-
-  if (GEGL_PROPERTIES (operation)->srgb)
-    format = babl_format_with_space ("R~aG~aB~aA float", space);
+  int use_srgb = GEGL_PROPERTIES (operation)->srgb?1:0;
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
+
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~ float":"Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~aA float":"YaA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~G~B~ float":"RGB float", space);
+  }
+  else if (babl_model_is (model, "RGBA")    ||
+           babl_model_is (model, "RGB")     ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'")  ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~")  ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
   else
-    format = babl_format_with_space ("RaGaBaA float", space);
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
 
-  gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", format);
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -76,6 +113,9 @@ process (GeglOperation        *op,
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
 
   if (!aux)
     return TRUE;
@@ -85,11 +125,18 @@ process (GeglOperation        *op,
       gint   j;
       gfloat aA G_GNUC_UNUSED, aB G_GNUC_UNUSED, aD G_GNUC_UNUSED;
 
-      aB = in[3];
-      aA = aux[3];
+      if (alpha)
+        {
+          aB = in[components-1];
+          aA = aux[components-1];
+        }
+      else
+        {
+          aB = aA = 1.0f;
+        }
       aD = aA * aB;
 
-      for (j = 0; j < 3; j++)
+      for (j = 0; j < components-alpha; j++)
         {
           gfloat cA G_GNUC_UNUSED, cB G_GNUC_UNUSED;
 
@@ -97,10 +144,11 @@ process (GeglOperation        *op,
           cA = aux[j];
           out[j] = cA * aB;
         }
-      out[3] = aD;
-      in  += 4;
-      aux += 4;
-      out += 4;
+      if (alpha)
+        out[components-alpha] = aD;
+      in  += components;
+      aux += components;
+      out += components;
     }
   return TRUE;
 }
diff --git a/operations/generated/src-out.c b/operations/generated/src-out.c
index 02d871ecc..452bfafe1 100644
--- a/operations/generated/src-out.c
+++ b/operations/generated/src-out.c
@@ -48,18 +48,55 @@ property_boolean (srgb, _("sRGB"), FALSE)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-    space = gegl_operation_get_source_space (operation, "aux");
-
-  if (GEGL_PROPERTIES (operation)->srgb)
-    format = babl_format_with_space ("R~aG~aB~aA float", space);
+  int use_srgb = GEGL_PROPERTIES (operation)->srgb?1:0;
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
+
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~ float":"Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~aA float":"YaA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~G~B~ float":"RGB float", space);
+  }
+  else if (babl_model_is (model, "RGBA")    ||
+           babl_model_is (model, "RGB")     ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'")  ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~")  ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
   else
-    format = babl_format_with_space ("RaGaBaA float", space);
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
 
-  gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", format);
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -76,6 +113,9 @@ process (GeglOperation        *op,
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
 
   if (!aux)
     return TRUE;
@@ -86,11 +126,18 @@ process (GeglOperation        *op,
           gint   j;
           gfloat aA G_GNUC_UNUSED, aB G_GNUC_UNUSED, aD G_GNUC_UNUSED;
 
-          aB = in[3];
-          aA = aux[3];
+          if (alpha)
+          {
+            aB = in[components-1];
+            aA = aux[components-1];
+          }
+          else
+          {
+            aB = aA = 1.0f;
+          }
           aD = aA * (1.0f - aB);
 
-          for (j = 0; j < 3; j++)
+          for (j = 0; j < components-alpha; j++)
             {
               gfloat cA G_GNUC_UNUSED, cB G_GNUC_UNUSED;
 
@@ -98,10 +145,11 @@ process (GeglOperation        *op,
               cA = aux[j];
               out[j] = cA * (1.0f - aB);
             }
-          out[3] = aD;
-          in  += 4;
-          aux += 4;
-          out += 4;
+          if (alpha)
+            out[components-alpha] = aD;
+          in  += components;
+          aux += components;
+          out += components;
         }
     }
   return TRUE;
diff --git a/operations/generated/src.c b/operations/generated/src.c
index 8fcb3acc1..c03cc0b93 100644
--- a/operations/generated/src.c
+++ b/operations/generated/src.c
@@ -48,18 +48,55 @@ property_boolean (srgb, _("sRGB"), FALSE)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-    space = gegl_operation_get_source_space (operation, "aux");
-
-  if (GEGL_PROPERTIES (operation)->srgb)
-    format = babl_format_with_space ("R~aG~aB~aA float", space);
+  int use_srgb = GEGL_PROPERTIES (operation)->srgb?1:0;
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
+
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~ float":"Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~aA float":"YaA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~G~B~ float":"RGB float", space);
+  }
+  else if (babl_model_is (model, "RGBA")    ||
+           babl_model_is (model, "RGB")     ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'")  ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~")  ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
   else
-    format = babl_format_with_space ("RaGaBaA float", space);
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
 
-  gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", format);
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -76,6 +113,9 @@ process (GeglOperation        *op,
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
 
   if (!aux)
     return TRUE;
@@ -86,11 +126,18 @@ process (GeglOperation        *op,
           gint   j;
           gfloat aA G_GNUC_UNUSED, aB G_GNUC_UNUSED, aD G_GNUC_UNUSED;
 
-          aB = in[3];
-          aA = aux[3];
+          if (alpha)
+          {
+            aB = in[components-1];
+            aA = aux[components-1];
+          }
+          else
+          {
+            aB = aA = 1.0f;
+          }
           aD = aA;
 
-          for (j = 0; j < 3; j++)
+          for (j = 0; j < components-alpha; j++)
             {
               gfloat cA G_GNUC_UNUSED, cB G_GNUC_UNUSED;
 
@@ -98,10 +145,11 @@ process (GeglOperation        *op,
               cA = aux[j];
               out[j] = cA;
             }
-          out[3] = aD;
-          in  += 4;
-          aux += 4;
-          out += 4;
+          if (alpha)
+            out[components-alpha] = aD;
+          in  += components;
+          aux += components;
+          out += components;
         }
     }
   return TRUE;
diff --git a/operations/generated/subtract.c b/operations/generated/subtract.c
index e83b622e2..f99c763a4 100644
--- a/operations/generated/subtract.c
+++ b/operations/generated/subtract.c
@@ -46,14 +46,56 @@ property_double (value, _("Value"), 0.0)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-     space = gegl_operation_get_source_space (operation, "aux");
-  format  = babl_format_with_space ("RGBA float", space);
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
+
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space ("Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space ("YA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space ("RGB float", space);
+  }
+#if 0
+  else if (babl_model_is (model, "RGBA") ||
+           babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~") ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space ("RGBA float", space);
+  }
+#endif
+  else
+  {
+    format  = babl_format_with_space ("RGBA float", space);
+  }
 
   gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", babl_format_with_space ("RGB float", space));
+  gegl_operation_set_format (operation, "aux", format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -69,6 +111,9 @@ process (GeglOperation       *op,
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
   gint    i;
 
   if (aux == NULL)
@@ -77,16 +122,17 @@ process (GeglOperation       *op,
       for (i=0; i<n_pixels; i++)
         {
           gint   j;
-          for (j=0; j<3; j++)
+          for (j=0; j<components-alpha; j++)
             {
               gfloat result;
               gfloat input=in[j];
               result = input - value;
               out[j]=result;
             }
-          out[3]=in[3];
-          in += 4;
-          out+= 4;
+          if (alpha)
+            out[components-1]=in[components-1];
+          in += components;
+          out+= components;
         }
     }
   else
@@ -95,7 +141,7 @@ process (GeglOperation       *op,
         {
           gint   j;
           gfloat value;
-          for (j=0; j<3; j++)
+          for (j=0; j<components-alpha; j++)
             {
               gfloat input =in[j];
               gfloat result;
@@ -103,13 +149,14 @@ process (GeglOperation       *op,
               result = input - value;
               out[j]=result;
             }
-          out[3]=in[3];
-          in += 4;
-          aux += 3;
-          out+= 4;
+          if (alpha)
+            out[components-1]=in[components-1];
+
+          in  += components;
+          aux += components;
+          out += components;
         }
     }
-
   return TRUE;
 }
 
diff --git a/operations/generated/svg-12-blend.rb b/operations/generated/svg-12-blend.rb
index d53807e29..1600bb5e2 100755
--- a/operations/generated/svg-12-blend.rb
+++ b/operations/generated/svg-12-blend.rb
@@ -93,18 +93,55 @@ property_boolean (srgb, _("sRGB"), FALSE)
 file_head2 = '
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-    space = gegl_operation_get_source_space (operation, "aux");
+  int use_srgb = GEGL_PROPERTIES (operation)->srgb?1:0;
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
 
-  if (GEGL_PROPERTIES (operation)->srgb)
-    format = babl_format_with_space ("R~aG~aB~aA float", space);
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y\'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~ float":"Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y\'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y\'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~aA float":"YaA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R\'G\'B\'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~G~B~ float":"RGB float", space);
+  }
+  else if (babl_model_is (model, "RGBA")    ||
+           babl_model_is (model, "RGB")     ||
+           babl_model_is (model, "R\'G\'B\'A") ||
+           babl_model_is (model, "R\'G\'B\'")  ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~")  ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R\'aG\'aB\'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
   else
-    format = babl_format_with_space ("RaGaBaA float", space);
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
 
-  gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", format);
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -164,6 +201,9 @@ process (GeglOperation       *op,
          const GeglRectangle *roi,
          gint                 level)
 {
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
@@ -229,11 +269,18 @@ a.each do
       gfloat aA, aB, aD;
       gint   j;
 
-      aB = in[3];
-      aA = aux[3];
+      if (alpha)
+      {
+        aB = in[components-1];
+        aA = aux[components-1];
+      }
+      else
+      {
+        aB = aA = 1.0f;
+      }
       aD = aA + aB - aA * aB;
 
-      for (j = 0; j < 3; j++)
+      for (j = 0; j < components-alpha; j++)
         {
           gfloat cA, cB;
 
@@ -241,10 +288,11 @@ a.each do
           cA = aux[j];
           out[j] = CLAMP (#{formula1}, 0, aD);
         }
-      out[3] = aD;
-      in  += 4;
-      aux += 4;
-      out += 4;
+      if (alpha)
+        out[components-1] = aD;
+      in  += components;
+      aux += components;
+      out += components;
     }
 "
   file.write file_tail1
@@ -293,11 +341,18 @@ b.each do
       gfloat aA, aB, aD;
       gint   j;
 
-      aB = in[3];
-      aA = aux[3];
+      if (alpha)
+      {
+        aB = in[components-1];
+        aA = aux[components-1];
+      }
+      else
+      {
+        aB = aA = 1.0f;
+      }
       aD = aA + aB - aA * aB;
 
-      for (j = 0; j < 3; j++)
+      for (j = 0; j < components-alpha; j++)
         {
           gfloat cA, cB;
 
@@ -308,10 +363,11 @@ b.each do
           else
             out[j] = CLAMP (#{formula2}, 0, aD);
         }
-      out[3] = aD;
-      in  += 4;
-      aux += 4;
-      out += 4;
+      if (alpha)
+        out[components-1] = aD;
+      in  += components;
+      aux += components;
+      out += components;
     }
 "
   file.write file_tail1
@@ -364,11 +420,18 @@ c.each do
       gfloat aA, aB, aD;
       gint   j;
 
-      aB = in[3];
-      aA = aux[3];
+      if (alpha)
+      {
+        aB = in[components-1];
+        aA = aux[components-1];
+      }
+      else
+      {
+        aB = aA = 1.0f;
+      }
       aD = aA + aB - aA * aB;
 
-      for (j = 0; j < 3; j++)
+      for (j = 0; j < components-alpha; j++)
         {
           gfloat cA, cB;
 
@@ -381,10 +444,13 @@ c.each do
           else
             out[j] = CLAMP (#{formula3}, 0, aD);
         }
-      out[3] = aD;
-      in  += 4;
-      aux += 4;
-      out += 4;
+      if (alpha)
+      {
+        out[components-1] = aD;
+      }
+      in  += components;
+      aux += components;
+      out += components;
     }
 "
   file.write file_tail1
@@ -432,11 +498,18 @@ d.each do
       gfloat aA, aB, aD;
       gint   j;
 
-      aB = in[3];
-      aA = aux[3];
+      if (alpha)
+      {
+        aB = in[components-1];
+        aA = aux[components-1];
+      }
+      else
+      {
+        aA = aB = 1.0f;
+      }
       aD = #{formula2};
 
-      for (j = 0; j < 3; j++)
+      for (j = 0; j < components-alpha; j++)
         {
           gfloat cA, cB;
 
@@ -444,10 +517,11 @@ d.each do
           cA = aux[j];
           out[j] = CLAMP (#{formula1}, 0, aD);
         }
-      out[3] = aD;
-      in  += 4;
-      aux += 4;
-      out += 4;
+      if (alpha)
+        out[components-1] = aD;
+      in  += components;
+      aux += components;
+      out += components;
     }
 "
   file.write file_tail1
diff --git a/operations/generated/svg-12-porter-duff.rb b/operations/generated/svg-12-porter-duff.rb
index 976ef31da..97bd39bb4 100755
--- a/operations/generated/svg-12-porter-duff.rb
+++ b/operations/generated/svg-12-porter-duff.rb
@@ -90,18 +90,55 @@ property_boolean (srgb, _("sRGB"), FALSE)
 file_head2 = '
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-    space = gegl_operation_get_source_space (operation, "aux");
-
-  if (GEGL_PROPERTIES (operation)->srgb)
-    format = babl_format_with_space ("R~aG~aB~aA float", space);
+  int use_srgb = GEGL_PROPERTIES (operation)->srgb?1:0;
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
+
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y\'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~ float":"Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y\'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y\'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~aA float":"YaA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R\'G\'B\'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~G~B~ float":"RGB float", space);
+  }
+  else if (babl_model_is (model, "RGBA")    ||
+           babl_model_is (model, "RGB")     ||
+           babl_model_is (model, "R\'G\'B\'A") ||
+           babl_model_is (model, "R\'G\'B\'")  ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~")  ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R\'aG\'aB\'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
   else
-    format = babl_format_with_space ("RaGaBaA float", space);
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
 
-  gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", format);
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -118,6 +155,9 @@ process (GeglOperation        *op,
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
 '
 
 file_tail1 = '
@@ -178,11 +218,11 @@ a.each do
           gint   j;
           gfloat aA G_GNUC_UNUSED, aB G_GNUC_UNUSED, aD G_GNUC_UNUSED;
 
-          aB = in[3];
+          aB = alpha?in[components-alpha]:1.0f;
           aA = 0.0f;
           aD = #{a_formula};
 
-          for (j = 0; j < 3; j++)
+          for (j = 0; j < components-alpha; j++)
             {
               gfloat cA G_GNUC_UNUSED, cB G_GNUC_UNUSED;
 
@@ -190,9 +230,10 @@ a.each do
               cA = 0.0f;
               out[j] = #{c_formula};
             }
-          out[3] = aD;
-          in  += 4;
-          out += 4;
+          if (alpha)
+            out[components-1] = aD;
+          in  += components;
+          out += components;
         }
     }
   else"
@@ -210,11 +251,18 @@ a.each do
           gint   j;
           gfloat aA G_GNUC_UNUSED, aB G_GNUC_UNUSED, aD G_GNUC_UNUSED;
 
-          aB = in[3];
-          aA = aux[3];
+          if (alpha)
+          {
+            aB = in[components-1];
+            aA = aux[components-1];
+          }
+          else
+          {
+            aB = aA = 1.0f;
+          }
           aD = #{a_formula};
 
-          for (j = 0; j < 3; j++)
+          for (j = 0; j < components-alpha; j++)
             {
               gfloat cA G_GNUC_UNUSED, cB G_GNUC_UNUSED;
 
@@ -222,10 +270,11 @@ a.each do
               cA = aux[j];
               out[j] = #{c_formula};
             }
-          out[3] = aD;
-          in  += 4;
-          aux += 4;
-          out += 4;
+          if (alpha)
+            out[components-alpha] = aD;
+          in  += components;
+          aux += components;
+          out += components;
         }
     }
   return TRUE;
@@ -285,11 +334,18 @@ b.each do
       gint   j;
       gfloat aA G_GNUC_UNUSED, aB G_GNUC_UNUSED, aD G_GNUC_UNUSED;
 
-      aB = in[3];
-      aA = aux[3];
+      if (alpha)
+        {
+          aB = in[components-1];
+          aA = aux[components-1];
+        }
+      else
+        {
+          aB = aA = 1.0f;
+        }
       aD = #{a_formula};
 
-      for (j = 0; j < 3; j++)
+      for (j = 0; j < components-alpha; j++)
         {
           gfloat cA G_GNUC_UNUSED, cB G_GNUC_UNUSED;
 
@@ -297,10 +353,11 @@ b.each do
           cA = aux[j];
           out[j] = #{c_formula};
         }
-      out[3] = aD;
-      in  += 4;
-      aux += 4;
-      out += 4;
+      if (alpha)
+        out[components-alpha] = aD;
+      in  += components;
+      aux += components;
+      out += components;
     }
   return TRUE;
 }
diff --git a/operations/generated/xor.c b/operations/generated/xor.c
index ffc3f6276..fd983eb6b 100644
--- a/operations/generated/xor.c
+++ b/operations/generated/xor.c
@@ -48,18 +48,55 @@ property_boolean (srgb, _("sRGB"), FALSE)
 
 static void prepare (GeglOperation *operation)
 {
-  const Babl *space = gegl_operation_get_source_space (operation, "input");
-  const Babl *format;
-  if (!space)
-    space = gegl_operation_get_source_space (operation, "aux");
-
-  if (GEGL_PROPERTIES (operation)->srgb)
-    format = babl_format_with_space ("R~aG~aB~aA float", space);
+  int use_srgb = GEGL_PROPERTIES (operation)->srgb?1:0;
+  const Babl *format = gegl_operation_get_source_format (operation, "input");
+  const Babl *space = NULL;
+  const Babl *model = NULL;
+  if (!format)
+    format = gegl_operation_get_source_format (operation, "aux");
+  if (format)
+  {
+    model = babl_format_get_model (format);
+  }
+
+  if (babl_model_is (model, "Y") ||
+      babl_model_is (model, "Y'") ||
+      babl_model_is (model, "Y~"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~ float":"Y float", space);
+  }
+  else if (babl_model_is (model, "YA") ||
+           babl_model_is (model, "Y'A") ||
+           babl_model_is (model, "Y~A") ||
+           babl_model_is (model, "YaA") ||
+           babl_model_is (model, "Y'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"Y~aA float":"YaA float", space);
+  }
+  else if (babl_model_is (model, "RGB") ||
+           babl_model_is (model, "R'G'B'") ||
+           babl_model_is (model, "R~G~B~"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~G~B~ float":"RGB float", space);
+  }
+  else if (babl_model_is (model, "RGBA")    ||
+           babl_model_is (model, "RGB")     ||
+           babl_model_is (model, "R'G'B'A") ||
+           babl_model_is (model, "R'G'B'")  ||
+           babl_model_is (model, "R~G~B~A") ||
+           babl_model_is (model, "R~G~B~")  ||
+           babl_model_is (model, "RaGaBaA") ||
+           babl_model_is (model, "R'aG'aB'aA"))
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
   else
-    format = babl_format_with_space ("RaGaBaA float", space);
+  {
+    format  = babl_format_with_space (use_srgb?"R~aG~aB~a float":"RaGaBaA float", space);
+  }
 
-  gegl_operation_set_format (operation, "input", format);
-  gegl_operation_set_format (operation, "aux", format);
+  gegl_operation_set_format (operation, "input",  format);
+  gegl_operation_set_format (operation, "aux",    format);
   gegl_operation_set_format (operation, "output", format);
 }
 
@@ -76,6 +113,9 @@ process (GeglOperation        *op,
   gfloat * GEGL_ALIGNED in = in_buf;
   gfloat * GEGL_ALIGNED aux = aux_buf;
   gfloat * GEGL_ALIGNED out = out_buf;
+  const Babl *format = gegl_operation_get_format (op, "output");
+  gint    components = babl_format_get_n_components (format);
+  gint    alpha      = babl_format_has_alpha (format);
 
   if (!aux)
     {
@@ -84,11 +124,11 @@ process (GeglOperation        *op,
           gint   j;
           gfloat aA G_GNUC_UNUSED, aB G_GNUC_UNUSED, aD G_GNUC_UNUSED;
 
-          aB = in[3];
+          aB = alpha?in[components-alpha]:1.0f;
           aA = 0.0f;
           aD = aA + aB - 2.0f * aA * aB;
 
-          for (j = 0; j < 3; j++)
+          for (j = 0; j < components-alpha; j++)
             {
               gfloat cA G_GNUC_UNUSED, cB G_GNUC_UNUSED;
 
@@ -96,9 +136,10 @@ process (GeglOperation        *op,
               cA = 0.0f;
               out[j] = cA * (1.0f - aB)+ cB * (1.0f - aA);
             }
-          out[3] = aD;
-          in  += 4;
-          out += 4;
+          if (alpha)
+            out[components-1] = aD;
+          in  += components;
+          out += components;
         }
     }
   else
@@ -108,11 +149,18 @@ process (GeglOperation        *op,
           gint   j;
           gfloat aA G_GNUC_UNUSED, aB G_GNUC_UNUSED, aD G_GNUC_UNUSED;
 
-          aB = in[3];
-          aA = aux[3];
+          if (alpha)
+          {
+            aB = in[components-1];
+            aA = aux[components-1];
+          }
+          else
+          {
+            aB = aA = 1.0f;
+          }
           aD = aA + aB - 2.0f * aA * aB;
 
-          for (j = 0; j < 3; j++)
+          for (j = 0; j < components-alpha; j++)
             {
               gfloat cA G_GNUC_UNUSED, cB G_GNUC_UNUSED;
 
@@ -120,10 +168,11 @@ process (GeglOperation        *op,
               cA = aux[j];
               out[j] = cA * (1.0f - aB)+ cB * (1.0f - aA);
             }
-          out[3] = aD;
-          in  += 4;
-          aux += 4;
-          out += 4;
+          if (alpha)
+            out[components-alpha] = aD;
+          in  += components;
+          aux += components;
+          out += components;
         }
     }
   return TRUE;
diff --git a/tests/mipmap/unsharp-crop-reference.png b/tests/mipmap/unsharp-crop-reference.png
index bc4d1f173..efae526a6 100644
Binary files a/tests/mipmap/unsharp-crop-reference.png and b/tests/mipmap/unsharp-crop-reference.png differ


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