[gimp] Bug 774472 - animated-webp: saved layers are not alpha-composited before compression
- From: Jehan Pagès <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] Bug 774472 - animated-webp: saved layers are not alpha-composited before compression
- Date: Wed, 23 Nov 2016 19:13:28 +0000 (UTC)
commit 4f67b16dad7fa8583ca0314e12b0a6891d270817
Author: Pascal Massimino <pascal massimino gmail com>
Date: Wed Nov 23 17:46:54 2016 +0100
Bug 774472 - animated-webp: saved layers are not alpha-composited before compression
when saving as animated-webp, use Gegl:over to composite current layer
with the previous frame if needed.
plug-ins/file-webp/file-webp-save.c | 103 +++++++++++++++++++++++++++++++++--
1 files changed, 98 insertions(+), 5 deletions(-)
---
diff --git a/plug-ins/file-webp/file-webp-save.c b/plug-ins/file-webp/file-webp-save.c
index 0626615..0b30731 100644
--- a/plug-ins/file-webp/file-webp-save.c
+++ b/plug-ins/file-webp/file-webp-save.c
@@ -387,6 +387,85 @@ get_layer_delay (gint32 layer)
return delay_ms;
}
+static gboolean
+parse_combine (const char* str)
+{
+ gint offset = 0;
+ gint length = strlen (str);
+
+ while ((offset + 9) <= length)
+ {
+ if (strncmp (&str[offset], "(combine)", 9) == 0)
+ return TRUE;
+
+ if (strncmp (&str[offset], "(replace)", 9) == 0)
+ return FALSE;
+
+ offset++;
+ }
+
+ return FALSE;
+}
+
+static gint
+get_layer_needs_combine (gint32 layer)
+{
+ gchar *layer_name;
+ gboolean needs_combine;
+
+ layer_name = gimp_item_get_name (layer);
+ needs_combine = parse_combine (layer_name);
+ g_free (layer_name);
+
+ return needs_combine;
+}
+
+static GeglBuffer*
+combine_buffers (GeglBuffer* layer_buffer, GeglBuffer* prev_frame_buffer)
+{
+ GeglBuffer *buffer;
+ GeglNode *graph;
+ GeglNode *source;
+ GeglNode *backdrop;
+ GeglNode *over;
+ GeglNode *target;
+
+ graph = gegl_node_new ();
+ buffer = gegl_buffer_new (gegl_buffer_get_extent (prev_frame_buffer),
+ gegl_buffer_get_format (prev_frame_buffer));
+
+ source = gegl_node_new_child (graph,
+ "operation", "gegl:buffer-source",
+ "buffer", layer_buffer,
+ NULL);
+ backdrop = gegl_node_new_child (graph,
+ "operation", "gegl:buffer-source",
+ "buffer", prev_frame_buffer,
+ NULL);
+
+ over = gegl_node_new_child (graph,
+ "operation", "gegl:over",
+ NULL);
+ target = gegl_node_new_child (graph,
+ "operation", "gegl:write-buffer",
+ "buffer", buffer,
+ NULL);
+ gegl_node_link_many (backdrop, over, target, NULL);
+ gegl_node_connect_to (source, "output",
+ over, "aux");
+ gegl_node_process (target);
+ g_object_unref (graph);
+
+ /* release resources associated to layer_buffer */
+ gegl_buffer_flush (layer_buffer);
+ g_object_unref (layer_buffer);
+
+ gegl_buffer_flush (prev_frame_buffer);
+ g_object_unref (prev_frame_buffer);
+
+ return buffer;
+}
+
gboolean
save_animation (const gchar *filename,
gint32 nLayers,
@@ -408,6 +487,7 @@ save_animation (const gchar *filename,
WebPData webp_data;
int frame_timestamp = 0;
WebPAnimEncoder *enc = NULL;
+ GeglBuffer *current_frame = NULL;
if (nLayers < 1)
return FALSE;
@@ -460,6 +540,7 @@ save_animation (const gchar *filename,
WebPMemoryWriter mw = { 0 };
gint32 drawable = allLayers[nLayers - 1 - loop];
gint delay = get_layer_delay (drawable);
+ gboolean needs_combine = get_layer_needs_combine (drawable);
/* Obtain the drawable type */
has_alpha = gimp_drawable_has_alpha (drawable);
@@ -518,8 +599,18 @@ save_animation (const gchar *filename,
picture.custom_ptr = &mw;
picture.writer = WebPMemoryWrite;
+ if (loop == 0 || !needs_combine)
+ {
+ if (current_frame != NULL) g_object_unref (current_frame);
+ current_frame = geglbuffer;
+ }
+ else
+ {
+ current_frame = combine_buffers (geglbuffer, current_frame);
+ }
+
/* Read the region into the buffer */
- gegl_buffer_get (geglbuffer, &extent, 1.0, format, buffer,
+ gegl_buffer_get (current_frame, &extent, 1.0, format, buffer,
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
/* Use the appropriate function to import the data from the buffer */
@@ -550,10 +641,6 @@ save_animation (const gchar *filename,
if (status == FALSE)
break;
- /* Flush the drawable and detach */
- gegl_buffer_flush (geglbuffer);
- g_object_unref (geglbuffer);
-
gimp_progress_update ((loop + 1.0) / nLayers);
frame_timestamp += (delay <= 0 || force_delay) ? default_delay : delay;
}
@@ -612,6 +699,12 @@ save_animation (const gchar *filename,
WebPDataClear (&webp_data);
WebPAnimEncoderDelete (enc);
+ if (current_frame != NULL)
+ {
+ gegl_buffer_flush (current_frame);
+ g_object_unref (current_frame);
+ }
+
if (outfile)
fclose (outfile);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]