[gimp/soc-2011-seamless-clone2] plug-ins: the animated frames are generated at initialization, ready for render.
- From: Clayton Walker <claytonw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/soc-2011-seamless-clone2] plug-ins: the animated frames are generated at initialization, ready for render.
- Date: Wed, 8 May 2013 15:16:39 +0000 (UTC)
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]