Commit 435df29d authored by Michael Natterer's avatar Michael Natterer 😴

app: add utility functions for applying specific operations to buffers

so gimp_gegl_apply_foo() will run "gegl:foo" with the required
properties on a buffer and write the result to another buffer.
parent 819ad3b4
......@@ -30,8 +30,6 @@
#include "paint/gimppaintcore-stroke.h"
#include "paint/gimppaintoptions.h"
#include "gegl/gimp-gegl-nodes.h"
#include "gegl/gimp-gegl-apply-operation.h"
#include "gegl/gimp-gegl-utils.h"
......@@ -463,7 +461,6 @@ gimp_channel_convert (GimpItem *item,
if (gimp_drawable_has_alpha (drawable))
{
GeglBuffer *new_buffer;
GeglNode *flatten;
const Babl *format;
GimpRGB background;
......@@ -476,14 +473,10 @@ gimp_channel_convert (GimpItem *item,
format);
gimp_rgba_set (&background, 0.0, 0.0, 0.0, 0.0);
flatten = gimp_gegl_create_flatten_node (&background);
gimp_gegl_apply_operation (gimp_drawable_get_buffer (drawable),
NULL, NULL,
flatten,
new_buffer, NULL);
g_object_unref (flatten);
gimp_gegl_apply_flatten (gimp_drawable_get_buffer (drawable),
NULL, NULL,
new_buffer, &background);
gimp_drawable_set_buffer_full (drawable, FALSE, NULL,
new_buffer,
......@@ -822,26 +815,14 @@ gimp_channel_convert_type (GimpDrawable *drawable,
}
else
{
GeglNode *dither;
gint bits;
gint bits;
bits = (babl_format_get_bytes_per_pixel (new_format) * 8 /
babl_format_get_n_components (new_format));
dither = gegl_node_new_child (NULL,
"operation", "gegl:color-reduction",
"red-bits", bits,
"green-bits", bits,
"blue-bits", bits,
"alpha-bits", bits,
"dither-strategy", mask_dither_type,
NULL);
gimp_gegl_apply_operation (gimp_drawable_get_buffer (drawable),
NULL, NULL,
dither,
dest_buffer, NULL);
g_object_unref (dither);
gimp_gegl_apply_color_reduction (gimp_drawable_get_buffer (drawable),
NULL, NULL,
dest_buffer, bits, mask_dither_type);
}
gimp_drawable_set_buffer (drawable, push_undo, NULL, dest_buffer);
......@@ -1282,7 +1263,6 @@ gimp_channel_real_feather (GimpChannel *channel,
gboolean push_undo)
{
GimpDrawable *drawable = GIMP_DRAWABLE (channel);
GeglNode *node;
if (push_undo)
gimp_channel_push_undo (channel,
......@@ -1293,18 +1273,11 @@ gimp_channel_real_feather (GimpChannel *channel,
/* 3.5 is completely magic and picked to visually match the old
* gaussian_blur_region() on a crappy laptop display
*/
node = gegl_node_new_child (NULL,
"operation", "gegl:gaussian-blur",
"std-dev-x", radius_x / 3.5,
"std-dev-y", radius_y / 3.5,
NULL);
gimp_gegl_apply_operation (gimp_drawable_get_buffer (drawable),
NULL, NULL,
node,
gimp_drawable_get_buffer (drawable), NULL);
g_object_unref (node);
gimp_gegl_apply_gaussian_blur (gimp_drawable_get_buffer (drawable),
NULL, NULL,
gimp_drawable_get_buffer (drawable),
radius_x / 3.5,
radius_y / 3.5);
channel->bounds_known = FALSE;
......@@ -1318,7 +1291,6 @@ gimp_channel_real_sharpen (GimpChannel *channel,
gboolean push_undo)
{
GimpDrawable *drawable = GIMP_DRAWABLE (channel);
GeglNode *node;
if (push_undo)
gimp_channel_push_undo (channel,
......@@ -1326,17 +1298,10 @@ gimp_channel_real_sharpen (GimpChannel *channel,
else
gimp_drawable_invalidate_boundary (drawable);
node = gegl_node_new_child (NULL,
"operation", "gegl:threshold",
"value", 0.5,
NULL);
gimp_gegl_apply_operation (gimp_drawable_get_buffer (drawable),
gimp_gegl_apply_threshold (gimp_drawable_get_buffer (drawable),
NULL, NULL,
node,
gimp_drawable_get_buffer (drawable), NULL);
g_object_unref (node);
gimp_drawable_get_buffer (drawable),
0.5);
channel->bounds_known = FALSE;
......@@ -1437,16 +1402,9 @@ gimp_channel_real_invert (GimpChannel *channel,
}
else
{
GeglNode *node = g_object_new (GEGL_TYPE_NODE,
"operation", "gegl:invert",
NULL);
gimp_gegl_apply_operation (gimp_drawable_get_buffer (drawable),
NULL, NULL,
node,
gimp_drawable_get_buffer (drawable), NULL);
g_object_unref (node);
gimp_gegl_apply_invert (gimp_drawable_get_buffer (drawable),
NULL, NULL,
gimp_drawable_get_buffer (drawable));
channel->bounds_known = FALSE;
......
......@@ -28,7 +28,6 @@
#include "core-types.h"
#include "gegl/gimp-gegl-apply-operation.h"
#include "gegl/gimp-gegl-nodes.h"
#include "gegl/gimp-gegl-utils.h"
#include "gimp.h"
......@@ -140,7 +139,6 @@ gimp_drawable_bucket_fill_internal (GimpDrawable *drawable,
GimpChannel *mask;
GeglBuffer *buffer;
GeglBuffer *mask_buffer;
GeglNode *apply_opacity;
gint x1, y1, x2, y2;
gint mask_offset_x = 0;
gint mask_offset_y = 0;
......@@ -246,16 +244,11 @@ gimp_drawable_bucket_fill_internal (GimpDrawable *drawable,
break;
}
apply_opacity = gimp_gegl_create_apply_opacity_node (mask_buffer,
-mask_offset_x,
-mask_offset_y,
1.0);
gimp_gegl_apply_operation (buffer, NULL, NULL,
apply_opacity,
buffer, NULL);
g_object_unref (apply_opacity);
gimp_gegl_apply_opacity (buffer, NULL, NULL, buffer,
mask_buffer,
-mask_offset_x,
-mask_offset_y,
1.0);
g_object_unref (mask);
/* Apply it to the image */
......
......@@ -31,7 +31,6 @@
#include "core-types.h"
#include "gegl/gimp-gegl-apply-operation.h"
#include "gegl/gimp-gegl-nodes.h"
#include "gegl/gimp-gegl-utils.h"
#include "gimp.h"
......@@ -286,7 +285,6 @@ gimp_drawable_stroke_scan_convert (GimpDrawable *drawable,
GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable));
GeglBuffer *base_buffer;
GeglBuffer *mask_buffer;
GeglNode *apply_opacity;
gint x, y, w, h;
gint off_x;
gint off_y;
......@@ -379,14 +377,8 @@ gimp_drawable_stroke_scan_convert (GimpDrawable *drawable,
break;
}
apply_opacity = gimp_gegl_create_apply_opacity_node (mask_buffer, 0, 0, 1.0);
gimp_gegl_apply_operation (base_buffer, NULL, NULL,
apply_opacity,
base_buffer, NULL);
g_object_unref (apply_opacity);
gimp_gegl_apply_opacity (base_buffer, NULL, NULL, base_buffer,
mask_buffer, 0, 0, 1.0);
g_object_unref (mask_buffer);
/* Apply to drawable */
......
......@@ -31,7 +31,6 @@
#include "core-types.h"
#include "gegl/gimp-gegl-apply-operation.h"
#include "gegl/gimp-gegl-nodes.h"
#include "gegl/gimp-gegl-utils.h"
#include "gimp.h"
......@@ -84,7 +83,6 @@ gimp_drawable_transform_buffer_affine (GimpDrawable *drawable,
GimpMatrix3 inv;
gint u1, v1, u2, v2; /* source bounding box */
gint x1, y1, x2, y2; /* target bounding box */
GeglNode *affine;
GimpMatrix3 gegl_matrix;
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
......@@ -136,19 +134,10 @@ gimp_drawable_transform_buffer_affine (GimpDrawable *drawable,
gimp_matrix3_mult (&inv, &gegl_matrix);
gimp_matrix3_translate (&gegl_matrix, -x1, -y1);
affine = gegl_node_new_child (NULL,
"operation", "gegl:transform",
"filter", gimp_interpolation_to_gegl_filter (interpolation_type),
"hard-edges", TRUE,
NULL);
gimp_gegl_node_set_matrix (affine, &gegl_matrix);
gimp_gegl_apply_operation (orig_buffer, progress, NULL,
affine,
new_buffer, NULL);
g_object_unref (affine);
gimp_gegl_apply_transform (orig_buffer, progress, NULL,
new_buffer,
interpolation_type,
&gegl_matrix);
*new_offset_x = x1;
*new_offset_y = y1;
......
......@@ -410,32 +410,19 @@ gimp_drawable_scale (GimpItem *item,
{
GimpDrawable *drawable = GIMP_DRAWABLE (item);
GeglBuffer *new_buffer;
GeglNode *scale;
new_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
new_width, new_height),
gimp_drawable_get_format (drawable));
scale = g_object_new (GEGL_TYPE_NODE,
"operation", "gegl:scale",
NULL);
gegl_node_set (scale,
"origin-x", 0.0,
"origin-y", 0.0,
"filter", gimp_interpolation_to_gegl_filter (interpolation_type),
"hard-edges", TRUE,
"x", ((gdouble) new_width /
gimp_item_get_width (item)),
"y", ((gdouble) new_height /
gimp_item_get_height (item)),
NULL);
gimp_gegl_apply_operation (gimp_drawable_get_buffer (drawable),
progress, C_("undo-type", "Scale"),
scale,
new_buffer, NULL);
g_object_unref (scale);
gimp_gegl_apply_scale (gimp_drawable_get_buffer (drawable),
progress, C_("undo-type", "Scale"),
new_buffer,
interpolation_type,
((gdouble) new_width /
gimp_item_get_width (item)),
((gdouble) new_height /
gimp_item_get_height (item)));
gimp_drawable_set_buffer_full (drawable, gimp_item_is_attached (item), NULL,
new_buffer,
......
......@@ -32,7 +32,6 @@
#include "gegl/gimp-gegl-apply-operation.h"
#include "gegl/gimp-gegl-nodes.h"
#include "gegl/gimp-gegl-utils.h"
#include "gimpboundary.h"
#include "gimpchannel-select.h"
......@@ -974,26 +973,14 @@ gimp_layer_convert_type (GimpDrawable *drawable,
}
else
{
GeglNode *dither;
gint bits;
gint bits;
bits = (babl_format_get_bytes_per_pixel (new_format) * 8 /
babl_format_get_n_components (new_format));
dither = gegl_node_new_child (NULL,
"operation", "gegl:color-reduction",
"red-bits", bits,
"green-bits", bits,
"blue-bits", bits,
"alpha-bits", bits,
"dither-strategy", layer_dither_type,
NULL);
gimp_gegl_apply_operation (gimp_drawable_get_buffer (drawable),
NULL, NULL,
dither,
dest_buffer, NULL);
g_object_unref (dither);
gimp_gegl_apply_color_reduction (gimp_drawable_get_buffer (drawable),
NULL, NULL,
dest_buffer, bits, layer_dither_type);
}
gimp_drawable_set_buffer (drawable, push_undo, NULL, dest_buffer);
......@@ -1416,8 +1403,6 @@ gimp_layer_create_mask (const GimpLayer *layer,
if (add_mask_type == GIMP_ADD_ALPHA_TRANSFER_MASK)
{
GeglNode *set_alpha;
gimp_drawable_push_undo (drawable,
C_("undo-type", "Transfer Alpha to Mask"),
NULL,
......@@ -1425,18 +1410,10 @@ gimp_layer_create_mask (const GimpLayer *layer,
gimp_item_get_width (item),
gimp_item_get_height (item));
set_alpha = gegl_node_new_child (NULL,
"operation", "gimp:set-alpha",
"value", 1.0,
NULL);
gimp_gegl_apply_operation (gimp_drawable_get_buffer (drawable),
gimp_gegl_apply_set_alpha (gimp_drawable_get_buffer (drawable),
NULL, NULL,
set_alpha,
gimp_drawable_get_buffer (drawable),
NULL);
g_object_unref (set_alpha);
1.0);
}
}
break;
......@@ -1521,17 +1498,12 @@ gimp_layer_create_mask (const GimpLayer *layer,
if (gimp_drawable_has_alpha (drawable))
{
GeglNode *flatten;
GimpRGB background;
GimpRGB background;
gimp_rgba_set (&background, 0.0, 0.0, 0.0, 0.0);
flatten = gimp_gegl_create_flatten_node (&background);
gimp_gegl_apply_operation (src_buffer, NULL, NULL,
flatten,
dest_buffer, NULL);
g_object_unref (flatten);
gimp_gegl_apply_flatten (src_buffer, NULL, NULL,
dest_buffer, &background);
}
else
{
......@@ -1605,7 +1577,6 @@ gimp_layer_apply_mask (GimpLayer *layer,
{
GeglBuffer *mask_buffer;
GeglBuffer *dest_buffer;
GeglNode *apply_opacity;
if (push_undo)
gimp_drawable_push_undo (GIMP_DRAWABLE (layer), NULL,
......@@ -1618,15 +1589,9 @@ gimp_layer_apply_mask (GimpLayer *layer,
mask_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (mask));
dest_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer));
apply_opacity = gimp_gegl_create_apply_opacity_node (mask_buffer, 0, 0,
1.0);
gimp_gegl_apply_operation (gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)),
NULL, NULL,
apply_opacity,
dest_buffer, NULL);
g_object_unref (apply_opacity);
gimp_gegl_apply_opacity (gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)),
NULL, NULL, dest_buffer,
mask_buffer, 0, 0, 1.0);
}
g_signal_handlers_disconnect_by_func (mask,
......@@ -1853,7 +1818,6 @@ void
gimp_layer_flatten (GimpLayer *layer,
GimpContext *context)
{
GeglNode *flatten;
GeglBuffer *new_buffer;
GimpRGB background;
......@@ -1870,14 +1834,10 @@ gimp_layer_flatten (GimpLayer *layer,
gimp_drawable_get_format_without_alpha (GIMP_DRAWABLE (layer)));
gimp_context_get_background (context, &background);
flatten = gimp_gegl_create_flatten_node (&background);
gimp_gegl_apply_operation (gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)),
NULL, NULL,
flatten,
new_buffer, NULL);
g_object_unref (flatten);
gimp_gegl_apply_flatten (gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)),
NULL, NULL,
new_buffer, &background);
gimp_drawable_set_buffer (GIMP_DRAWABLE (layer),
gimp_item_is_attached (GIMP_ITEM (layer)),
......
......@@ -25,8 +25,6 @@
#include "gegl/gimp-babl.h"
#include "gegl/gimp-gegl-apply-operation.h"
#include "gegl/gimp-gegl-nodes.h"
#include "gegl/gimp-gegl-utils.h"
#include "gimp.h"
#include "gimp-edit.h"
......@@ -748,20 +746,14 @@ gimp_selection_extract (GimpSelection *selection,
/* If there is a selection, mask the dest_buffer with it */
GeglBuffer *mask_buffer;
GeglNode *apply_opacity;
mask_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (selection));
apply_opacity = gimp_gegl_create_apply_opacity_node (mask_buffer,
- (off_x + x1),
- (off_y + y1),
1.0);
gimp_gegl_apply_operation (dest_buffer, NULL, NULL,
apply_opacity,
dest_buffer, NULL);
g_object_unref (apply_opacity);
gimp_gegl_apply_opacity (dest_buffer, NULL, NULL, dest_buffer,
mask_buffer,
- (off_x + x1),
- (off_y + y1),
1.0);
if (cut_image && GIMP_IS_DRAWABLE (pickable))
{
......
......@@ -30,6 +30,8 @@
#include "core/gimpprogress.h"
#include "gimp-gegl-apply-operation.h"
#include "gimp-gegl-nodes.h"
#include "gegl/gimp-gegl-utils.h"
void
......@@ -106,3 +108,229 @@ gimp_gegl_apply_operation (GeglBuffer *src_buffer,
if (progress && ! progress_active)
gimp_progress_end (progress);
}
void
gimp_gegl_apply_color_reduction (GeglBuffer *src_buffer,
GimpProgress *progress,
const gchar *undo_desc,
GeglBuffer *dest_buffer,
gint bits,
gint dither_type)
{
GeglNode *node;
g_return_if_fail (GEGL_IS_BUFFER (src_buffer));
g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));
g_return_if_fail (GEGL_IS_BUFFER (dest_buffer));
node = gegl_node_new_child (NULL,
"operation", "gegl:color-reduction",
"red-bits", bits,
"green-bits", bits,
"blue-bits", bits,
"alpha-bits", bits,
"dither-strategy", dither_type,
NULL);
gimp_gegl_apply_operation (src_buffer, progress, undo_desc,
node, dest_buffer, NULL);
g_object_unref (node);
}
void
gimp_gegl_apply_flatten (GeglBuffer *src_buffer,
GimpProgress *progress,
const gchar *undo_desc,
GeglBuffer *dest_buffer,
const GimpRGB *background)
{
GeglNode *node;
g_return_if_fail (GEGL_IS_BUFFER (src_buffer));
g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));
g_return_if_fail (GEGL_IS_BUFFER (dest_buffer));
g_return_if_fail (background != NULL);
node = gimp_gegl_create_flatten_node (background);
gimp_gegl_apply_operation (src_buffer, progress, undo_desc,
node, dest_buffer, NULL);
g_object_unref (node);
}
void
gimp_gegl_apply_gaussian_blur (GeglBuffer *src_buffer,
GimpProgress *progress,
const gchar *undo_desc,
GeglBuffer *dest_buffer,
gdouble std_dev_x,
gdouble std_dev_y)
{
GeglNode *node;
g_return_if_fail (GEGL_IS_BUFFER (src_buffer));
g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));
g_return_if_fail (GEGL_IS_BUFFER (dest_buffer));
node = gegl_node_new_child (NULL,
"operation", "gegl:gaussian-blur",
"std-dev-x", std_dev_x,
"std-dev-y", std_dev_y,
NULL);
gimp_gegl_apply_operation (src_buffer, progress, undo_desc,
node, dest_buffer, NULL);
g_object_unref (node);
}
void
gimp_gegl_apply_invert (GeglBuffer *src_buffer,
GimpProgress *progress,
const gchar *undo_desc,
GeglBuffer *dest_buffer)
{
GeglNode *node;
g_return_if_fail (GEGL_IS_BUFFER (src_buffer));
g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));
g_return_if_fail (GEGL_IS_BUFFER (dest_buffer));
node = gegl_node_new_child (NULL,
"operation", "gegl:invert",
NULL);
gimp_gegl_apply_operation (src_buffer, progress, undo_desc,
node, dest_buffer, NULL);
g_object_unref (node);
}
void
gimp_gegl_apply_opacity (GeglBuffer *src_buffer,
GimpProgress *progress,
const gchar *undo_desc,
GeglBuffer *dest_buffer,
GeglBuffer *mask,
gint mask_offset_x,
gint mask_offset_y,
gdouble opacity)
{
GeglNode *node;
g_return_if_fail (GEGL_IS_BUFFER (src_buffer));
g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));
g_return_if_fail (GEGL_IS_BUFFER (dest_buffer));
g_return_if_fail (mask == NULL || GEGL_IS_BUFFER (mask));
node = gimp_gegl_create_apply_opacity_node (mask,
mask_offset_x,
mask_offset_y,
opacity);
gimp_gegl_apply_operation (src_buffer, progress, undo_desc,
node, dest_buffer, NULL);
g_object_unref (node);
}
void
gimp_gegl_apply_scale (GeglBuffer *src_buffer,
GimpProgress *progress,
const gchar *undo_desc,
GeglBuffer *dest_buffer,
GimpInterpolationType interpolation_type,
gdouble x,
gdouble y)
{
GeglNode *node;
g_return_if_fail (GEGL_IS_BUFFER (src_buffer));
g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));
g_return_if_fail (GEGL_IS_BUFFER (dest_buffer));
node = gegl_node_new_child (NULL,
"operation", "gegl:scale",
"origin-x", 0.0,
"origin-y", 0.0,
"filter", gimp_interpolation_to_gegl_filter (interpolation_type),
"hard-edges", TRUE,
"x", x,
"y", y,
NULL);
gimp_gegl_apply_operation (src_buffer, progress, undo_desc,
node, dest_buffer, NULL);
g_object_unref (node);
}
void
gimp_gegl_apply_set_alpha (GeglBuffer *src_buffer,
GimpProgress *progress,
const gchar *undo_desc,
GeglBuffer *dest_buffer,
gdouble value)
{
GeglNode *node;
g_return_if_fail (GEGL_IS_BUFFER (src_buffer));
g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));
g_return_if_fail (GEGL_IS_BUFFER (dest_buffer));
node = gegl_node_new_child (NULL,
"operation", "gimp:set-alpha",
"value", value,
NULL);
gimp_gegl_apply_operation (src_buffer, progress, undo_desc,
node, dest_buffer, NULL);
g_object_unref (node);
}
void
gimp_gegl_apply_threshold (GeglBuffer *src_buffer,
GimpProgress *progress,
const gchar *undo_desc,
GeglBuffer *dest_buffer,
gdouble value)
{
GeglNode *node;
g_return_if_fail (GEGL_IS_BUFFER (src_buffer));
g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));
g_return_if_fail (GEGL_IS_BUFFER (dest_buffer));
node = gegl_node_new_child (NULL,
"operation", "gegl:threshold",
"value", value,
NULL);
gimp_gegl_apply_operation (src_buffer, progress, undo_desc,
node, dest_buffer, NULL);
g_object_unref (node);
}
void
gimp_gegl_apply_transform (GeglBuffer *src_buffer,
GimpProgress *progress,
const gchar *undo_desc,
GeglBuffer *dest_buffer,
GimpInterpolationType interpolation_type,
GimpMatrix3 *transform)
{
GeglNode *node;
g_return_if_fail (GEGL_IS_BUFFER (src_buffer));
g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));
g_return_if_fail (GEGL_IS_BUFFER (dest_buffer));
node = gegl_node_new_child (NULL,
"operation", "gegl:transform",
"filter", gimp_interpolation_to_gegl_filter (interpolation_type),
"hard-edges", TRUE,
NULL);
gimp_gegl_node_set_matrix (node, transform);
gimp_gegl_apply_operation (src_buffer, progress, undo_desc,
node, dest_buffer, NULL);
g_object_unref (node);
}
......@@ -24,12 +24,78 @@
#define __GIMP_GEGL_APPLY_OPERATION_H__
void gimp_gegl_apply_operation (GeglBuffer *src_buffer,
GimpProgress *progress,
const gchar *undo_desc,
GeglNode *operation,
GeglBuffer *dest_buffer,
const GeglRectangle *dest_rect);
/* generic function, also used by the specific ones below */
void gimp_gegl_apply_operation (GeglBuffer *src_buffer,
GimpProgress *progress,
const gchar *undo_desc,
GeglNode *operation,
GeglBuffer *dest_buffer,
const GeglRectangle *dest_rect);
/* apply specific operations */
void gimp_gegl_apply_color_reduction (GeglBuffer *src_buffer,
GimpProgress *progress,
const gchar *undo_desc,
GeglBuffer *dest_buffer,
gint bits,
gint dither_type);
void gimp_gegl_apply_flatten (GeglBuffer *src_buffer,
GimpProgress *progress,