void vnr_tools_apply_embedded_orientation (GdkPixbufAnimation **anim) { GdkPixbuf *pixbuf; GdkPixbuf *original; if(!gdk_pixbuf_animation_is_static_image (*anim)) return; pixbuf = gdk_pixbuf_animation_get_static_image (*anim); original = pixbuf; pixbuf = gdk_pixbuf_apply_embedded_orientation(pixbuf); if(original == pixbuf) { g_object_unref(pixbuf); return; } GdkPixbufSimpleAnim *s_anim; s_anim = gdk_pixbuf_simple_anim_new (gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf), -1); gdk_pixbuf_simple_anim_add_frame(s_anim, pixbuf); g_object_unref(pixbuf); g_object_unref(*anim); *anim = GDK_PIXBUF_ANIMATION(s_anim); }
gboolean tilem_animation_save(TilemAnimation *anim, const char *fname, const char *type, char **option_keys, char **option_values, GError **err) { FILE *fp; char *dname; int errnum; GdkPixbuf *pb; gboolean status; byte palette[768]; int i; g_return_val_if_fail(TILEM_IS_ANIMATION(anim), FALSE); g_return_val_if_fail(fname != NULL, FALSE); g_return_val_if_fail(type != NULL, FALSE); g_return_val_if_fail(err == NULL || *err == NULL, FALSE); if (strcmp(type, "gif") != 0) { pb = gdk_pixbuf_animation_get_static_image (GDK_PIXBUF_ANIMATION(anim)); status = gdk_pixbuf_savev(pb, fname, type, option_keys, option_values, err); return status; } fp = g_fopen(fname, "wb"); if (!fp) { errnum = errno; dname = g_filename_display_name(fname); g_set_error(err, G_FILE_ERROR, g_file_error_from_errno(errnum), _("Failed to open '%s' for writing: %s"), dname, g_strerror(errnum)); g_free(dname); return FALSE; } for (i = 0; i < 256; i++) { palette[3 * i] = anim->palette[i] >> 16; palette[3 * i + 1] = anim->palette[i] >> 8; palette[3 * i + 2] = anim->palette[i]; } tilem_animation_write_gif(anim, palette, 256, fp); if (fclose(fp)) { errnum = errno; dname = g_filename_display_name(fname); g_set_error(err, G_FILE_ERROR, g_file_error_from_errno(errnum), _("Error while closing '%s': %s"), dname, g_strerror(errnum)); g_free(dname); return FALSE; } return TRUE; }
static void prepared_callback (GdkPixbufLoader *loader, gpointer data) { AniLoaderContext *context = (AniLoaderContext*)data; #ifdef DEBUG_ANI g_print ("%d pixbuf prepared\n", context->pos); #endif GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); if (!pixbuf) return; if (gdk_pixbuf_get_width (pixbuf) > context->animation->width) context->animation->width = gdk_pixbuf_get_width (pixbuf); if (gdk_pixbuf_get_height (pixbuf) > context->animation->height) context->animation->height = gdk_pixbuf_get_height (pixbuf); if (context->title != NULL) gdk_pixbuf_set_option (pixbuf, "Title", context->title); if (context->author != NULL) gdk_pixbuf_set_option (pixbuf, "Author", context->author); g_object_ref (pixbuf); context->animation->pixbufs[context->pos] = pixbuf; if (context->pos == 0) { if (context->prepared_func) (* context->prepared_func) (pixbuf, GDK_PIXBUF_ANIMATION (context->animation), context->user_data); } else { /* FIXME - this is necessary for nice display of loading animations because GtkImage ignores gdk_pixbuf_animation_iter_on_currently_loading_frame() and always exposes the full frame */ GdkPixbuf *last = context->animation->pixbufs[context->pos - 1]; gint width = MIN (gdk_pixbuf_get_width (last), gdk_pixbuf_get_width (pixbuf)); gint height = MIN (gdk_pixbuf_get_height (last), gdk_pixbuf_get_height (pixbuf)); gdk_pixbuf_copy_area (last, 0, 0, width, height, pixbuf, 0, 0); } context->pos++; }
GdkPixbufAnimation* pgpug_animated_icon_compose_from_anim_list (GdkPixbufAnimation * anim, ...) { g_return_val_if_fail (anim != NULL, NULL); g_return_val_if_fail (GDK_IS_PIXBUF_ANIMATION (anim), NULL); int width, height; width = gdk_pixbuf_animation_get_width (anim); height = gdk_pixbuf_animation_get_height (anim); g_return_val_if_fail (height == width, NULL); va_list anim_p; va_start (anim_p, anim); //get all animation into an array GPtrArray *anim_array = g_ptr_array_new (); animation_param_entry* p_entry = g_malloc0 (sizeof (animation_param_entry)); p_entry->anim = anim; g_ptr_array_add (anim_array, p_entry); gint anim_pos, param_num = 0; anim_pos = va_arg (anim_p, gint); while (anim_pos >= 0){ gpointer ptr = va_arg (anim_p, gpointer); p_entry = g_malloc (sizeof (animation_param_entry)); param_num += 2; if (!GDK_IS_PIXBUF_ANIMATION (ptr)) { WARN_MSG ("pgpug_animated_icon_compose_from_anim_list: var_arg parameter %d expected GdkPixbufAnimation*", param_num); break; } p_entry->anim = GDK_PIXBUF_ANIMATION (ptr); p_entry->pos = anim_pos; g_ptr_array_add (anim_array, p_entry); anim_pos = va_arg (anim_p, gint); } va_end (anim_p); GdkPixbufAnimation *result; result = compose_animation_from_array ((animation_param_entry**)anim_array->pdata, anim_array->len, width); g_ptr_array_foreach (anim_array, (GFunc)g_free, NULL); g_ptr_array_free (anim_array, TRUE); return result; }
static GdkPixbufAnimation* compose_animation_from_array (animation_param_entry **anim_array, gint array_len, gint pix_size) { GdkPixbufSimpleAnim *result = NULL; gint frames = 1, duration = 0, duration_p, frames_p; /* calculate frames count as multiplication of all frames and duration as max */ gint i; GTimeVal start_time = {0, 0}; for (i = 0; i<array_len; i++){ /* initialize iterators for each animation*/ animation_param_entry *p_entry = anim_array[i]; p_entry->iter = gdk_pixbuf_animation_get_iter (p_entry->anim, &start_time); frames_p = duration_p = 0; pgpug_pixbuf_animation_get_detail (p_entry->anim, &frames_p, &duration_p); duration = duration < duration_p ? duration_p : duration; frames *= frames_p; } float fps = duration > 0 ? frames * 1000 / duration : 1; gint frame_change_time = duration / frames; DEBG_MSG ("Fps: %f. frame change time :%dmsec", fps,frame_change_time); result = gdk_pixbuf_simple_anim_new (pix_size, pix_size, fps); gint elapsed_time = 0, frames_counter = 1; while (elapsed_time <= duration && frames_counter++ <= frames){ animation_param_entry *p_entry = anim_array[0]; GdkPixbuf *base_pixbuf = gdk_pixbuf_copy (gdk_pixbuf_animation_iter_get_pixbuf (p_entry->iter)); g_time_val_add (&start_time, frame_change_time * 1000); gdk_pixbuf_animation_iter_advance (p_entry->iter, &start_time); for (i = 1; i < array_len; i++) { p_entry = anim_array[i]; GdkPixbuf *src_pixbuf = gdk_pixbuf_animation_iter_get_pixbuf (p_entry->iter); gint x_offset, y_offset, src_size; src_size = gdk_pixbuf_get_width (src_pixbuf); pgpug_pixbuf_calculate_composition_offset (pix_size, src_size, p_entry->pos, &x_offset, &y_offset); gdk_pixbuf_composite (src_pixbuf, base_pixbuf, x_offset, y_offset, src_size, src_size, x_offset, y_offset, 1.0f, 1.0f, GDK_INTERP_BILINEAR, 255); gboolean res; res = gdk_pixbuf_animation_iter_advance (p_entry->iter, &start_time); } gdk_pixbuf_simple_anim_add_frame (result, base_pixbuf); elapsed_time += frame_change_time; } gdk_pixbuf_simple_anim_set_loop (result, TRUE); for (i=0;i<array_len;i++){ g_object_unref (anim_array[i]->iter); } return GDK_PIXBUF_ANIMATION (result); }
GdkPixbufAnimation* pgpug_animated_icon (PgpugPixEnum icon_id, gint size) { g_return_val_if_fail (icon_id < PIX_NUMBER, NULL); GdkPixbufSimpleAnim *result = NULL; PgpugPixEntry entry = icon_entries_array [icon_id]; /* assert that ids are in order */ g_return_val_if_fail (entry.id == icon_id, NULL); GPtrArray *frames_array = g_ptr_array_new (); GtkIconTheme* theme; GdkPixbuf *pixbuf; GError *error = NULL, *error_anim = NULL; theme = gtk_icon_theme_get_default (); pixbuf = gtk_icon_theme_load_icon (theme, entry.name, size, GTK_ICON_LOOKUP_FORCE_SIZE, &error); if (error == NULL && pixbuf != NULL) { DEBG_MSG ("Loaded icon with name %s", entry.name); //it's a static image g_ptr_array_add (frames_array, (gpointer)pixbuf); }else{ //else try to get frame sequence gchar *name_template = g_strconcat (entry.name, "%02d", NULL); int i = 1; do { gchar *name = g_strdup_printf (name_template, i++); pixbuf = gtk_icon_theme_load_icon (theme, name, size, GTK_ICON_LOOKUP_FORCE_SIZE, &error_anim); if (pixbuf != NULL){ DEBG_MSG ("Loaded animation frame with name %s, address %p", name, pixbuf); g_ptr_array_add (frames_array, (gpointer)pixbuf); } g_free (name); } while (error_anim == NULL && i < 100); g_free (name_template); } if (frames_array->len != 0){ //construct animation result = gdk_pixbuf_simple_anim_new (size, size, frames_array->len); guint i; for (i = 0;i < frames_array->len; i++) gdk_pixbuf_simple_anim_add_frame (result, frames_array->pdata[i]); } else{ //we didn't find any images gchar **search_paths; gint index; gchar *search_path_str; gtk_icon_theme_get_search_path (theme, &search_paths, &index); search_path_str = g_strjoinv ("\n", search_paths); WARN_MSG ("Icon with name \"%s\" can not be loaded.\n" "Icon search paths are: \n%s\n" "Error message: %s", entry.name, search_path_str, error->message); g_strfreev (search_paths); g_free (search_path_str); } g_ptr_array_foreach (frames_array, (GFunc)g_object_unref, NULL); g_ptr_array_free (frames_array, TRUE); if (error != NULL) g_error_free (error); if (error_anim != NULL) g_error_free (error_anim); return GDK_PIXBUF_ANIMATION (result); }
static gboolean stop_load (GpBitmap *bitmap, GdipContext *context, GError **error) { guint n_frames = 1, i; GdkPixbufGdipAnim *animation = NULL; gdip_bitmap_get_n_frames (bitmap, &n_frames, TRUE); for (i = 0; i < n_frames; i++) { GdkPixbuf *pixbuf = NULL; GdkPixbufFrame *frame; guint frame_delay = 0; gdip_bitmap_select_frame (bitmap, i, TRUE); pixbuf = gdip_bitmap_to_pixbuf (bitmap, error); if (!pixbuf) { if (animation != NULL) g_object_unref (G_OBJECT (animation)); GdipDisposeImage ((GpImage *)bitmap); destroy_gdipcontext (context); return FALSE; } if (animation == NULL) { guint n_loops = 1; animation = g_object_new (GDK_TYPE_PIXBUF_GDIP_ANIM, NULL); gdip_bitmap_get_n_loops (bitmap, &n_loops); animation->loop = n_loops; } frame = g_new (GdkPixbufFrame, 1); frame->pixbuf = pixbuf; gdip_bitmap_get_frame_delay (bitmap, &frame_delay); animation->n_frames++; animation->frames = g_list_append (animation->frames, frame); animation->width = gdk_pixbuf_get_width (pixbuf); animation->height = gdk_pixbuf_get_height (pixbuf); /* GIF delay is in hundredths, we want thousandths */ frame->delay_time = frame_delay * 10; frame->elapsed = animation->total_time; /* Some GIFs apparently have delay time of 0, * that crashes everything so set it to "fast". * Also, timeouts less than 20 or so just lock up * the app or make the animation choppy, so fix them. */ if (frame->delay_time < 20) frame->delay_time = 20; /* 20 = "fast" */ animation->total_time += frame->delay_time; if (i == 0) emit_prepared (context, pixbuf, GDK_PIXBUF_ANIMATION (animation)); emit_updated (context, pixbuf); } if (animation != NULL) g_object_unref (G_OBJECT (animation)); GdipDisposeImage ((GpImage *)bitmap); destroy_gdipcontext (context); return TRUE; }