[gimp/soc-2011-seamless-clone2] plug-ins: the animated frames are generated at initialization, ready for render.



commit 7f5132f3c7820a9dcab5c47db66b0912bc6e48b6
Author: Jehan <jehan girinstud io>
Date:   Thu Nov 15 19:34:21 2012 +0900

    plug-ins: the animated frames are generated at initialization, ready for render.
    
    Additionaly a bug on shaping the window around moving non-alpha pixel is fixed.

 plug-ins/common/animation-play.c |  380 +++++++++++++-------------------------
 1 files changed, 127 insertions(+), 253 deletions(-)
---
diff --git a/plug-ins/common/animation-play.c b/plug-ins/common/animation-play.c
index e2f72de..65946f0 100644
--- a/plug-ins/common/animation-play.c
+++ b/plug-ins/common/animation-play.c
@@ -84,6 +84,8 @@ static gboolean    repaint_da                (GtkWidget       *darea,
                                               GdkEventExpose  *event,
                                               gpointer         data);
 
+static void        init_frames               (void);
+static void        generate_frames           (void);
 static void        render_frame              (gint32           whichframe);
 static void        show_frame                (void);
 static void        total_alpha_preview       (guchar          *ptr);
@@ -128,9 +130,12 @@ static guint              width, height;
 static guchar            *preview_alpha1_data;
 static guchar            *preview_alpha2_data;
 static gint32             image_id;
+static guchar            *rawframe                = NULL;
+static gint32            *frames                  = NULL;
 static gint32             total_frames;
 static guint              frame_number;
 static gint32            *layers;
+static gint32             total_layers;
 static gboolean           playing = FALSE;
 static guint              timer   = 0;
 static GimpImageBaseType  imagetype;
@@ -298,16 +303,6 @@ shape_pressed (GtkWidget      *widget,
 }
 
 static gboolean
-maybeblocked_expose (GtkWidget      *widget,
-                     GdkEventExpose *event)
-{
-  if (playing)
-    return TRUE;
-
-  return repaint_sda (widget, event, NULL);
-}
-
-static gboolean
 shape_released (GtkWidget *widget)
 {
   gtk_grab_remove (widget);
@@ -750,7 +745,7 @@ build_dialog (GimpImageBaseType  basetype,
                     NULL);
 
   g_signal_connect (shape_drawing_area, "expose-event",
-                    G_CALLBACK (maybeblocked_expose),
+                    G_CALLBACK (repaint_sda),
                     NULL);
 
   root_win = gdk_get_default_root_window ();
@@ -761,7 +756,7 @@ do_playback (void)
 {
   width     = gimp_image_width (image_id);
   height    = gimp_image_height (image_id);
-  layers    = gimp_image_get_layers (image_id, &total_frames);
+  layers    = gimp_image_get_layers (image_id, &total_layers);
   imagetype = gimp_image_base_type (image_id);
 
   if (imagetype == GIMP_INDEXED)
@@ -787,8 +782,7 @@ do_playback (void)
   build_dialog (gimp_image_base_type (image_id),
                 gimp_image_get_name (image_id));
 
-  /* Make sure that whole preview is dirtied with pure-alpha */
-  total_alpha_preview (preview_data);
+  init_frames ();
 
   render_frame (0);
   show_frame ();
@@ -806,13 +800,9 @@ render_frame (gint32 whichframe)
   GtkStyle      *drawing_style = gtk_widget_get_style (drawing_area);
   GeglBuffer    *buffer;
   gint           drawable_id;
-  static guchar *rawframe = NULL;
-  static gint    rawwidth = 0, rawheight = 0, rawbpp = 0;
-  gint           rawx = 0, rawy = 0;
+  gint i, j, k;
   guchar        *srcptr;
   guchar        *destptr;
-  gint           i, j, k; /* imaginative loop variables */
-  DisposeType    dispose;
 
   if (whichframe >= total_frames)
     {
@@ -821,8 +811,7 @@ render_frame (gint32 whichframe)
       gimp_quit ();
     }
 
-  drawable_id = layers[total_frames - (whichframe + 1)];
-
+  drawable_id = frames[whichframe];
   buffer = gimp_drawable_get_buffer (drawable_id);
 
   /* Lame attempt to catch the case that a user has closed the image. */
@@ -833,260 +822,66 @@ render_frame (gint32 whichframe)
       return;
     }
 
-  dispose = get_frame_disposal (frame_number);
-
-  if (((dispose == DISPOSE_REPLACE) || (whichframe == 0)) &&
-      gimp_drawable_has_alpha (drawable_id))
-    {
-      total_alpha_preview (preview_data);
-    }
-
-
-  /* only get a new 'raw' drawable-data buffer if this and
-     the previous raw buffer were different sizes */
-
-  if ((rawwidth * rawheight * rawbpp) !=
-      ((gimp_drawable_width (drawable_id) *
-        gimp_drawable_height (drawable_id) *
-        gimp_drawable_has_alpha (drawable_id) ? 4 : 3)))
-    {
-      if (rawframe != NULL)
-        g_free (rawframe);
-
-      rawwidth  = gimp_drawable_width (drawable_id);
-      rawheight = gimp_drawable_height (drawable_id);
-      rawbpp    = gimp_drawable_has_alpha (drawable_id) ? 4 : 3;
-
-      rawframe = g_malloc (rawwidth * rawheight * rawbpp);
-    }
+  /* Initialize the rawframe only once. */
+  if (rawframe == NULL)
+    rawframe = g_malloc (width * height * 4);
 
   /* Initialise and fetch the whole raw new frame */
-
-  gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, rawwidth, rawheight), 1.0,
-                   gimp_drawable_has_alpha (drawable_id) ?
-                   babl_format ("R'G'B'A u8") :
-                   babl_format ("R'G'B' u8"),
+  gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, width, height), 1.0,
+                   babl_format ("R'G'B'A u8"),
                    rawframe, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
 
-  gimp_drawable_offsets (drawable_id, &rawx, &rawy);
-
-
   /* render... */
+  total_alpha_preview (preview_data);
 
-  if ((rawwidth == width) &&
-      (rawheight == height) &&
-      (rawx == 0) &&
-      (rawy == 0))
+  i = width * height;
+  destptr = preview_data;
+  srcptr  = rawframe;
+  while (i--)
     {
-      /* --- These cases are for the best cases,  in        --- */
-      /* --- which this frame is the same size and position --- */
-      /* --- as the preview buffer itself                   --- */
-
-      if (gimp_drawable_has_alpha (drawable_id))
+      if (! (srcptr[3] & 128))
         {
-          destptr = preview_data;
-          srcptr  = rawframe;
-
-          i = rawwidth * rawheight;
-          while (i--)
-            {
-              if (! (srcptr[3] & 128))
-                {
-                  srcptr  += 4;
-                  destptr += 3;
-                  continue;
-                }
-
-              *(destptr++) = *(srcptr++);
-              *(destptr++) = *(srcptr++);
-              *(destptr++) = *(srcptr++);
-
-              srcptr++;
-            }
-
-          /* calculate the shape mask */
-          if (detached)
-            {
-              srcptr = rawframe + 3;
-
-              for (j = 0; j < rawheight; j++)
-                {
-                  k = j * ((7 + rawwidth) / 8);
-
-                  for (i = 0; i < rawwidth; i++)
-                    {
-                      if ((*srcptr) & 128)
-                        shape_preview_mask[k + i/8] |= (1 << (i&7));
-
-                      srcptr += 4;
-                    }
-                }
-            }
+          srcptr  += 4;
+          destptr += 3;
+          continue;
         }
-      else /* no alpha */
-        {
-          if ((rawwidth == width) && (rawheight == height))
-            memcpy (preview_data, rawframe, width * height * 3);
 
-          if (detached)
-            {
-              /* opacify the shape mask */
-              memset (shape_preview_mask, 255,
-                      (rawwidth * rawheight) / 8 + rawheight);
-            }
-        }
+      *(destptr++) = *(srcptr++);
+      *(destptr++) = *(srcptr++);
+      *(destptr++) = *(srcptr++);
 
-      /* Display the preview buffer... finally. */
-      if (detached)
-        {
-          reshape_from_bitmap (shape_preview_mask);
-          gdk_draw_rgb_image (gtk_widget_get_window (shape_drawing_area),
-                              shape_style->white_gc,
-                              0, 0, width, height,
-                              (total_frames == 1 ?
-                               GDK_RGB_DITHER_MAX : DITHERTYPE),
-                              preview_data, width * 3);
-        }
-      else
-        {
-          reshape_from_bitmap (shape_preview_mask);
-          gdk_draw_rgb_image (gtk_widget_get_window (drawing_area),
-                              drawing_style->white_gc,
-                              0, 0, width, height,
-                              (total_frames == 1 ?
-                               GDK_RGB_DITHER_MAX : DITHERTYPE),
-                              preview_data, width * 3);
-        }
+      srcptr++;
     }
-  else
-    {
-      /* --- These are suboptimal catch-all cases for when  --- */
-      /* --- this frame is bigger/smaller than the preview  --- */
-      /* --- buffer, and/or offset within it.               --- */
 
-      if (gimp_drawable_has_alpha (drawable_id))
-        {
-          srcptr = rawframe;
-
-          for (j = rawy; j < rawheight + rawy; j++)
-            {
-              for (i = rawx; i < rawwidth + rawx; i++)
-                {
-                  if ((i >= 0 && i < width) &&
-                      (j >= 0 && j < height))
-                    {
-                      if (srcptr[3] & 128)
-                        {
-                          preview_data[(j * width + i) * 3    ] = *(srcptr);
-                          preview_data[(j * width + i) * 3 + 1] = *(srcptr + 1);
-                          preview_data[(j * width + i) * 3 + 2] = *(srcptr + 2);
-                        }
-                    }
-
-                  srcptr += 4;
-                }
-            }
+  /* calculate the shape mask */
+  if (detached)
+    {
+      memset (shape_preview_mask, 0, (width * height) / 8 + height);
+      srcptr = rawframe + 3;
 
-          if (detached)
-            {
-              srcptr = rawframe + 3;
-
-              for (j = rawy; j < rawheight + rawy; j++)
-                {
-                  k = j * ((width + 7) / 8);
-
-                  for (i = rawx; i < rawwidth + rawx; i++)
-                    {
-                      if ((i>=0 && i<width) &&
-                          (j>=0 && j<height))
-                        {
-                          if ((*srcptr) & 128)
-                            shape_preview_mask[k + i/8] |= (1 << (i&7));
-                        }
-
-                      srcptr += 4;
-                    }
-                }
-            }
-        }
-      else
+      for (j = 0; j < height; j++)
         {
-          /* noalpha */
-
-          srcptr = rawframe;
+          k = j * ((7 + width) / 8);
 
-          for (j = rawy; j < rawheight + rawy; j++)
+          for (i = 0; i < width; i++)
             {
-              for (i = rawx; i < rawwidth + rawx; i++)
-                {
-                  if ((i >= 0 && i < width) &&
-                      (j >= 0 && j < height))
-                    {
-                      preview_data[(j * width + i) * 3    ] = *(srcptr);
-                      preview_data[(j * width + i) * 3 + 1] = *(srcptr + 1);
-                      preview_data[(j * width + i) * 3 + 2] = *(srcptr + 2);
-                    }
-
-                  srcptr += 3;
-                }
-            }
-        }
+              if ((*srcptr) & 128)
+                shape_preview_mask[k + i/8] |= (1 << (i&7));
 
-      /* Display the preview buffer... finally. */
-      if (detached)
-        {
-          if ((dispose != DISPOSE_REPLACE) && (whichframe != 0))
-            {
-              gint top    = MAX (rawy, 0);
-              gint bottom = MIN (rawy + rawheight, height);
-
-              reshape_from_bitmap (shape_preview_mask);
-              gdk_draw_rgb_image (gtk_widget_get_window (shape_drawing_area),
-                                  shape_style->white_gc,
-                                  0, top, width, bottom - top,
-                                  (total_frames == 1 ?
-                                   GDK_RGB_DITHER_MAX : DITHERTYPE),
-                                  preview_data + 3 * top * width,
-                                  width * 3);
-            }
-          else
-            {
-              reshape_from_bitmap (shape_preview_mask);
-              gdk_draw_rgb_image (gtk_widget_get_window (shape_drawing_area),
-                                  shape_style->white_gc,
-                                  0, 0, width, height,
-                                  (total_frames == 1 ?
-                                   GDK_RGB_DITHER_MAX : DITHERTYPE),
-                                  preview_data, width * 3);
-            }
-        }
-      else
-        {
-          if ((dispose != DISPOSE_REPLACE) && (whichframe != 0))
-            {
-              gint top    = MAX (rawy, 0);
-              gint bottom = MIN (rawy + rawheight, height);
-
-              gdk_draw_rgb_image (gtk_widget_get_window (drawing_area),
-                                  drawing_style->white_gc,
-                                  0, top, width, bottom - top,
-                                  (total_frames == 1 ?
-                                   GDK_RGB_DITHER_MAX : DITHERTYPE),
-                                  preview_data + 3 * top * width,
-                                  width * 3);
-            }
-          else
-            {
-              gdk_draw_rgb_image (gtk_widget_get_window (drawing_area),
-                                  drawing_style->white_gc,
-                                  0, 0, width, height,
-                                  (total_frames == 1 ?
-                                   GDK_RGB_DITHER_MAX : DITHERTYPE),
-                                  preview_data, width * 3);
+              srcptr += 4;
             }
         }
+      reshape_from_bitmap (shape_preview_mask);
     }
 
+  /* Display the preview buffer. */
+  gdk_draw_rgb_image (gtk_widget_get_window (detached? shape_drawing_area : drawing_area),
+                      detached? shape_style->white_gc : drawing_style->white_gc,
+                      0, 0, width, height,
+                      (total_frames == 1 ?
+                       GDK_RGB_DITHER_MAX : DITHERTYPE),
+                      preview_data, width * 3);
+
   /* clean up */
   g_object_unref (buffer);
 }
@@ -1551,3 +1346,82 @@ parse_disposal_tag (const gchar *str)
 
   return DISPOSE_UNDEFINED; /* FIXME */
 }
+
+static void
+init_frames (void)
+{
+  GtkAction   *action;
+  total_frames = total_layers;
+  generate_frames();
+  if (total_frames < 2)
+    {
+      action = gtk_ui_manager_get_action (ui_manager,
+                                          "/ui/anim-play-toolbar/play");
+      gtk_action_set_sensitive (action, FALSE);
+
+      action = gtk_ui_manager_get_action (ui_manager,
+                                          "/ui/anim-play-toolbar/step");
+      gtk_action_set_sensitive (action, FALSE);
+
+      action = gtk_ui_manager_get_action (ui_manager,
+                                          "/ui/anim-play-toolbar/rewind");
+      gtk_action_set_sensitive (action, FALSE);
+    }
+  else
+    {
+      action = gtk_ui_manager_get_action (ui_manager,
+                                          "/ui/anim-play-toolbar/play");
+      gtk_action_set_sensitive (action, TRUE);
+
+      action = gtk_ui_manager_get_action (ui_manager,
+                                          "/ui/anim-play-toolbar/step");
+      gtk_action_set_sensitive (action, TRUE);
+
+      action = gtk_ui_manager_get_action (ui_manager,
+                                          "/ui/anim-play-toolbar/rewind");
+      gtk_action_set_sensitive (action, TRUE);
+    }
+}
+
+static void
+generate_frames (void)
+{
+  /* Frames are associated to an unused image. */
+  static gint32 frames_image_id;
+  gint          i;
+  gint32        new_frame, previous_frame, new_layer;
+
+  /* Cleanup before re-generation. */
+  if (frames != NULL)
+    {
+      for (i = 0; i < total_frames; i++)
+        gimp_image_remove_layer (frames_image_id, frames[i]);
+      gimp_image_delete (frames_image_id);
+      g_free (frames);
+    }
+  frames = g_try_malloc0_n (total_frames, sizeof (gint32));
+
+  if (frames == NULL)
+    {
+      gimp_message (_("Memory could not be allocated to the frame container."));
+      gtk_main_quit ();
+      return;
+    }
+  frames_image_id = gimp_image_new (width, height, imagetype);
+
+  for (i = 0; i < total_frames; i++)
+    {
+      if (i > 0 && get_frame_disposal (i) != DISPOSE_REPLACE)
+        {
+          previous_frame = gimp_layer_copy (frames[i - 1]);
+          gimp_image_insert_layer (frames_image_id, previous_frame, 0, -1);
+          gimp_item_set_visible (previous_frame, TRUE);
+        }
+      new_layer = gimp_layer_new_from_drawable (layers[total_layers - (i + 1)], frames_image_id);
+      gimp_item_set_visible (new_layer, TRUE);
+      gimp_image_insert_layer (frames_image_id, new_layer, 0, -1);
+      new_frame = gimp_image_merge_visible_layers (frames_image_id, GIMP_CLIP_TO_IMAGE);
+      frames[i] = new_frame;
+      gimp_item_set_visible (new_frame, FALSE);
+    }
+}


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