/** * return number of frames per second and duration in msec */ gint pgpug_pixbuf_animation_get_detail (GdkPixbufAnimation *anim, gint *frames_count, gint *duration) { //FIXME: there should be a better way to get frames count from animation *frames_count = 0; *duration = 0; if (gdk_pixbuf_animation_is_static_image (anim)){ (*frames_count)++; return; } GTimeVal start_time = {0, 0}; GdkPixbufAnimationIter *iter = gdk_pixbuf_animation_get_iter (anim, &start_time); GdkPixbuf *cur_frame, *first_frame = gdk_pixbuf_animation_iter_get_pixbuf (iter); int delay_time = gdk_pixbuf_animation_iter_get_delay_time (iter); while (delay_time > 0){ g_time_val_add (&start_time, delay_time*1000); gboolean need_upd = gdk_pixbuf_animation_iter_advance (iter, &start_time); if (need_upd){ (*frames_count)++; *duration += delay_time; } cur_frame = gdk_pixbuf_animation_iter_get_pixbuf (iter); if (!need_upd || cur_frame == first_frame) { delay_time = -1; } } g_object_unref (iter); }
static void img_cell_renderer_anim_render( GtkCellRenderer *cell, GdkDrawable *window, GtkWidget *widget, GdkRectangle *background_a, GdkRectangle *cell_a, GdkRectangle *expose_a, GtkCellRendererState state ) { ImgCellRendererAnimPrivate *priv; GdkPixbufAnimationIter *iter; GdkPixbuf *pixbuf; cairo_t *cr; GdkRectangle rect, draw_rect; priv = IMG_CELL_RENDERER_ANIM_GET_PRIVATE ( cell ); /* Get image size */ img_cell_renderer_anim_get_size( cell, widget, cell_a, &rect.x, &rect.y, &rect.width, &rect.height ); rect.x += cell_a->x + cell->xpad; rect.y += cell_a->y + cell->ypad; rect.width -= 2 * cell->xpad; rect.height -= 2 * cell->ypad; /* Check for overlaping */ if( ! gdk_rectangle_intersect( cell_a, &rect, &draw_rect ) || ! gdk_rectangle_intersect( expose_a, &draw_rect, &draw_rect ) ) return; /* Draw indicators */ cr = gdk_cairo_create( window ); /* Draw the current frame of the GdkPixbufAnimation */ iter = g_object_get_data( G_OBJECT( priv->anim ), "iter" ); if( ! iter ) { gint delay; /* Initialiize iter */ iter = gdk_pixbuf_animation_get_iter( priv->anim, NULL ); g_object_set_data_full( G_OBJECT( priv->anim ), "iter", iter, (GDestroyNotify)g_object_unref ); /* Install timeout */ delay = gdk_pixbuf_animation_iter_get_delay_time( iter ); gdk_threads_add_timeout( delay, (GSourceFunc)cb_timeout, iter ); } g_object_set_data( G_OBJECT( iter ), "widget", widget ); pixbuf = gdk_pixbuf_animation_iter_get_pixbuf( iter ); gdk_cairo_set_source_pixbuf( cr, pixbuf, rect.x, rect.y ); gdk_cairo_rectangle( cr, &draw_rect ); cairo_fill( cr ); cairo_destroy( cr ); }
/* TODO: have image_fetcher tell us if it was a 404 and handle that image here rather than there. */ void Image::on_image(const Glib::RefPtr<Gdk::PixbufLoader> &loader) { if (loader) { unscaled_image.reset(); if (post->is_gif()) { unscaled_animation = loader->get_animation(); if (unscaled_animation->is_static_image()) { unscaled_image = unscaled_animation->get_static_image(); unscaled_animation.reset(); } else { if (!animation_iter) { animation_time.assign_current_time(); animation_iter = Glib::wrap(gdk_pixbuf_animation_get_iter(unscaled_animation->gobj(), &animation_time)); animation_timeout = Glib::signal_timeout().connect(sigc::mem_fun(*this, &Image::on_animation_timeout), animation_iter->get_delay_time()); } unscaled_image.reset(); unscaled_image = animation_iter->get_pixbuf(); } } else { unscaled_image = loader->get_pixbuf(); } if (G_UNLIKELY(!unscaled_image)) { g_error("Received pixbuf image is null"); } image->set(unscaled_image); image->show(); show_all(); image->queue_draw(); refresh_size_request(); if (is_changing_state) { is_changing_state = false; set_expand_state(); } if (image_state == NONE) set_thumb_state(); } else { std::cerr << "Warning: Horizon::Image got invalid PixbufLoader for" << " image" << std::endl; } am_fetching_image = false; }
bool Image::on_image_draw(const Cairo::RefPtr< Cairo::Context > &) { if (unscaled_animation) { if (!animation_iter) { animation_time.assign_current_time(); animation_iter = Glib::wrap(gdk_pixbuf_animation_get_iter(unscaled_animation->gobj(), &animation_time)); unscaled_image.reset(); unscaled_image = animation_iter->get_pixbuf(); animation_timeout = Glib::signal_timeout().connect(sigc::mem_fun(*this, &Image::on_animation_timeout), animation_iter->get_delay_time()); } } return false; }
static gboolean ygtk_image_advance_frame_cb (gpointer data) { YGtkImage *image = (YGtkImage *) data; struct _YGtkImageAnimation *animation = image->animation; if (!animation->frame) // no frame yet loaded animation->frame = gdk_pixbuf_animation_get_iter (animation->pixbuf, NULL); else if (gdk_pixbuf_animation_iter_advance (animation->frame, NULL)) gtk_widget_queue_draw (GTK_WIDGET (image)); // shedule next frame int delay = gdk_pixbuf_animation_iter_get_delay_time (animation->frame); if (delay != -1) animation->timeout_id = g_timeout_add (delay, ygtk_image_advance_frame_cb, data); return FALSE; }
bool wxAnimationCtrl::Play() { if (m_anim == NULL) return false; // init the iterator and start a one-shot timer ResetIter(); m_iter = gdk_pixbuf_animation_get_iter (m_anim, NULL); m_bPlaying = true; // gdk_pixbuf_animation_iter_get_delay_time() may return -1 which means // that the timer should not start int n = gdk_pixbuf_animation_iter_get_delay_time(m_iter); if (n >= 0) m_timer.Start(n, true); return true; }
/* prepare frame information and register other callbacks */ static void callback_area_prepared_anim (GdkPixbufLoader* loader) { GdkPixbufAnimation *anim; FrameData* frame_copy = g_new (FrameData, 1); g_signal_connect (loader, "area-updated", (GCallback) callback_area_updated_anim, (gpointer) frame_copy); g_signal_connect (loader, "closed", (GCallback) callback_closed_anim, (gpointer) frame_copy); frame_copy->time.tv_sec = frame_copy->time.tv_usec = 0; /* some time */ anim = gdk_pixbuf_loader_get_animation (loader); frame_copy->iter = gdk_pixbuf_animation_get_iter (anim, &frame_copy->time); frame_copy->pixbuf = gdk_pixbuf_copy (gdk_pixbuf_animation_iter_get_pixbuf (frame_copy->iter)); update_currently_loaded_frame (frame_copy); }
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); }
static GdkPixbuf * _gdk_pixbuf_new_from_uri_at_scale (const char *uri, gint size, GError **error) { gboolean result; guchar buffer[LOAD_BUFFER_SIZE]; gssize bytes_read; GdkPixbufLoader *loader = NULL; GdkPixbuf *pixbuf; GdkPixbufAnimation *animation; GdkPixbufAnimationIter *iter; gboolean has_frame; SizePrepareContext info; GFile *file; GInputStream *input_stream; g_return_val_if_fail (uri != NULL, NULL); file = g_file_new_for_uri (uri); input_stream = G_INPUT_STREAM (g_file_read (file, NULL, error)); if (input_stream == NULL) { g_object_unref (file); return NULL; } has_frame = FALSE; result = FALSE; while (!has_frame) { bytes_read = g_input_stream_read (input_stream, buffer, sizeof (buffer), NULL, error); if (bytes_read == -1) { break; } result = TRUE; if (bytes_read == 0) { break; } if (loader == NULL) { loader = create_loader (file, buffer, bytes_read); if (1 <= size) { info.size = size; info.input_width = info.input_height = 0; g_signal_connect (loader, "size-prepared", G_CALLBACK (size_prepared_cb), &info); } g_assert (loader != NULL); } if (!gdk_pixbuf_loader_write (loader, (unsigned char *)buffer, bytes_read, error)) { result = FALSE; break; } animation = gdk_pixbuf_loader_get_animation (loader); if (animation) { iter = gdk_pixbuf_animation_get_iter (animation, NULL); if (!gdk_pixbuf_animation_iter_on_currently_loading_frame (iter)) { has_frame = TRUE; } g_object_unref (iter); } } if (loader == NULL) { /* This can happen if the above loop was exited due to the * g_input_stream_read() call failing. */ result = FALSE; } else if (*error != NULL) { gdk_pixbuf_loader_close (loader, NULL); result = FALSE; } else if (gdk_pixbuf_loader_close (loader, error) == FALSE) { if (!g_error_matches (*error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INCOMPLETE_ANIMATION)) result = FALSE; else g_clear_error (error); } if (!result) { g_clear_object (&loader); g_input_stream_close (input_stream, NULL, NULL); g_object_unref (input_stream); g_object_unref (file); return NULL; } g_input_stream_close (input_stream, NULL, NULL); g_object_unref (input_stream); g_object_unref (file); pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); if (pixbuf != NULL) { g_object_ref (G_OBJECT (pixbuf)); g_object_set_data (G_OBJECT (pixbuf), "gnome-original-width", GINT_TO_POINTER (info.input_width)); g_object_set_data (G_OBJECT (pixbuf), "gnome-original-height", GINT_TO_POINTER (info.input_height)); } g_object_unref (G_OBJECT (loader)); return pixbuf; }
int main (int argc, char *argv[]) { if(argc > 1 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "-H"))) { printf("Ponies for Linux/GTK+ by rabbit\n"); printf("Command list:\n"); printf("No Parameters: Run with the settings used from last run\n"); printf("-h: Display this help\n"); printf("file path: Set new file path to look for pony gif files\n"); printf("ponyname: Sets to run one of the pony type listed\n"); return 0; } for(int i = 1; i < argc; i++) if(*argv[i] == '/') setPonyDirectory(argv[i]); char* ponyDirectory = NULL; char* ponyHomeFile = NULL; ponyHomeFile = malloc((strlen(getenv("HOME"))+ 9) * sizeof(char)); if(!ponyHomeFile) { printf("Could not allocate memory for ponyHomeFile\n"); return 0; } strcpy(ponyHomeFile, getenv("HOME")); strcat(ponyHomeFile,"/.ponies"); ponyDirectory = getPonyDirectory(); if(!ponyDirectory) { free(ponyHomeFile); printf("Error locating pony directory\n"); return 0; } //Initialize GTK+ and set up loggers GError* error = NULL; g_log_set_handler ("Gtk", G_LOG_LEVEL_WARNING, (GLogFunc) gtk_false, NULL); gtk_init (&argc, &argv); g_log_set_handler ("Gtk", G_LOG_LEVEL_WARNING, g_log_default_handler, NULL); //For command line commands later, require input on inital load //Normally would close, but hard coded in for easier testing int numberOfPonies = 0; if(argc == 1) { //Read in from ~/.ponies file to find saved settings FILE* ifp = NULL; char buffer[256]; ifp = fopen(ponyHomeFile,"r"); if(!ifp) { free(ponyHomeFile); free(ponyDirectory); printf("Could not open file for reading\n"); return 0; } //fread(buffer, sizeof(char), 256, ifp); while(fgets(buffer, 256, ifp)) if(buffer[0] != '\n') numberOfPonies++; fclose(ifp); numberOfPonies--;//First line is directory } //Not default arguments else { for(int i = 1; i < argc; i++) { if(*argv[i] == '/') continue; numberOfPonies++; } } //Seed the randomizer srand(time(0)); //Number of ponies pony ponyArray[numberOfPonies]; char buffer[256]; FILE* ifp = NULL; ifp = fopen(ponyHomeFile,"r"); if(!ifp) { printf("Could not open ~/.ponies\n"); free(ponyDirectory); free(ponyHomeFile); return 0; } fgets(buffer, 256, ifp);//throw away first line //0 Ponies if(!numberOfPonies) { free(ponyDirectory); free(ponyHomeFile); printf("No ponies in the ~/.ponies file! Add some ponies!\n"); printf("allowable ponies are: "); for(int i = 0; i <= Zecora; i++) printf("%s ", getDirectoryName(i)); return 0; } //Make pony windows for( int i = 0; i < numberOfPonies; i++) { fgets(buffer, 256, ifp); char* temp = NULL; temp = strchr(buffer, '\n'); if(temp) buffer[temp - buffer] = '\0'; ponyArray[i].name = ponyNameFromString(buffer); ponyArray[i].direction = DirNone; ponyArray[i].dragActive = 0; ponyArray[i].speed = SpeedStopped; ponyArray[i].animation = AnimIdle; ponyArray[i].active = 1; ponyArray[i].facing = FaceLeft; //Create animation from file, default is idle_left char* initialPicturePath; initialPicturePath = malloc((strlen(ponyDirectory) + strlen(getDirectoryName(ponyArray[i].name)) + 14) * sizeof(char)); if(!initialPicturePath) { printf("Unable to allocate memory for directory"); continue; } strcpy(initialPicturePath, ponyDirectory); strcat(initialPicturePath, getDirectoryName(ponyArray[i].name)); strcat(initialPicturePath, "/idle_left.gif"); ponyArray[i].pictureanim = gdk_pixbuf_animation_new_from_file (initialPicturePath, &error); free(initialPicturePath); ponyArray[i].image = gtk_image_new_from_animation(ponyArray[i].pictureanim); ponyArray[i].pictureanimit = gdk_pixbuf_animation_get_iter (ponyArray[i].pictureanim, NULL); ponyArray[i].win = gtk_window_new(GTK_WINDOW_TOPLEVEL); //Resize everytime the gif updates g_timeout_add(gdk_pixbuf_animation_iter_get_delay_time(ponyArray[i]. pictureanimit),(GSourceFunc)updateWinSize, &ponyArray[i]); //Name the window the name of the pony being animated gtk_window_set_title(GTK_WINDOW(ponyArray[i].win), getPonyName(ponyArray[i].name)); //Size down the window before showing it gtk_window_set_default_size(GTK_WINDOW(ponyArray[i].win), gdk_pixbuf_animation_get_width(ponyArray[i]. pictureanim), gdk_pixbuf_animation_get_height (ponyArray[i].pictureanim)); //Remove the titlebar gtk_window_set_decorated(GTK_WINDOW(ponyArray[i].win), FALSE); //Set up the signals ponyArray[i].clickEventID = g_signal_connect(G_OBJECT(ponyArray[i].win), "button_press_event", G_CALLBACK(click_event), &ponyArray[i]); ponyArray[i].enterEventID = g_signal_connect(G_OBJECT(ponyArray[i].win), "enter-notify-event", G_CALLBACK(enter_event), &ponyArray[i]); ponyArray[i].leaveEventID = g_signal_connect(G_OBJECT(ponyArray[i].win), "leave-notify-event", G_CALLBACK(enter_event), &ponyArray[i]); gtk_widget_add_events(ponyArray[i].win, GDK_BUTTON_PRESS_MASK); gtk_container_add(GTK_CONTAINER(ponyArray[i].win), GTK_WIDGET(ponyArray[i]. image)); //Get rid of taskbar item gtk_window_set_skip_taskbar_hint(GTK_WINDOW(ponyArray[i].win), TRUE); //Make it so it can't be selected gtk_window_set_accept_focus(GTK_WINDOW(ponyArray[i].win), FALSE); gtk_widget_realize(ponyArray[i].win); //Always on top gtk_window_set_keep_above(GTK_WINDOW(ponyArray[i].win), TRUE); updateWinSize(&ponyArray[i]); if(error != NULL) break; } free(ponyDirectory); free(ponyHomeFile); //Quit out if there were any errors and give a message if( error != NULL) { printf("%s\n",error->message); return 0; } //Make it transparent? /*cr = gdk_cairo_create(win->window); cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0); cairo_set_operator( cr, CAIRO_OPERATOR_SOURCE); cairo_paint(cr); gtk_container_add(GTK_CONTAINER(win), GTK_WIDGET(image));*/ //Main loop for( int i = 0; i < numberOfPonies; i++) gtk_widget_show_all(ponyArray[i].win); gtk_main(); return 0; }
void gaym_gtkconv_update_thumbnail(GaimConversation * conv, struct fetch_thumbnail_data *thumbnail_data) { GaimGtkConversation *gtkconv; char filename[256]; FILE *file; GError *err = NULL; size_t len; GdkPixbuf *buf; GdkPixbuf *scale; GdkPixmap *pm; GdkBitmap *bm; int scale_width, scale_height; GaimAccount *account; GaimPluginProtocolInfo *prpl_info = NULL; g_return_if_fail(conv != NULL); g_return_if_fail(GAIM_IS_GTK_CONVERSATION(conv)); g_return_if_fail(gaim_conversation_get_type(conv) == GAIM_CONV_CHAT); gtkconv = GAIM_GTK_CONVERSATION(conv); GaymChatIcon *icon_data = g_hash_table_lookup(icons, conv); if (!thumbnail_data) return; if (!icon_data->show_icon) return; const char *data = thumbnail_data->pic_data; len = thumbnail_data->pic_data_len; account = gaim_conversation_get_account(conv); if (account && account->gc) prpl_info = GAIM_PLUGIN_PROTOCOL_INFO(account->gc->prpl); if (icon_data->anim != NULL) g_object_unref(G_OBJECT(icon_data->anim)); icon_data->anim = NULL; if (icon_data->icon_timer != 0) g_source_remove(icon_data->icon_timer); icon_data->icon_timer = 0; if (icon_data->iter != NULL) g_object_unref(G_OBJECT(icon_data->iter)); icon_data->iter = NULL; if (!gaim_prefs_get_bool ("/gaim/gtk/conversations/im/show_buddy_icons")) return; if (gaim_conversation_get_gc(conv) == NULL) return; /* this is such an evil hack, i don't know why i'm even considering it. we'll do it differently when gdk-pixbuf-loader isn't leaky anymore. */ /* gdk-pixbuf-loader was leaky? is it still? */ g_snprintf(filename, sizeof(filename), "%s" G_DIR_SEPARATOR_S "gaimicon-%s.%d", g_get_tmp_dir(), thumbnail_data->who, getpid()); if (!(file = g_fopen(filename, "wb"))) return; fwrite(data, 1, len, file); fclose(file); icon_data->anim = gdk_pixbuf_animation_new_from_file(filename, &err); /* make sure we remove the file as soon as possible */ g_unlink(filename); if (err) { gaim_debug(GAIM_DEBUG_ERROR, "gtkconv", "Buddy icon error: %s\n", err->message); g_error_free(err); } if (!icon_data->anim) return; if (gdk_pixbuf_animation_is_static_image(icon_data->anim)) { icon_data->iter = NULL; buf = gdk_pixbuf_animation_get_static_image(icon_data->anim); } else { icon_data->iter = gdk_pixbuf_animation_get_iter(icon_data->anim, NULL); /* LEAK */ buf = gdk_pixbuf_animation_iter_get_pixbuf(icon_data->iter); } get_icon_scale_size(icon_data->anim, prpl_info ? &prpl_info->icon_spec : NULL, &scale_width, &scale_height); scale = gdk_pixbuf_scale_simple(buf, MAX(gdk_pixbuf_get_width(buf) * scale_width / gdk_pixbuf_animation_get_width (icon_data->anim), 1), MAX(gdk_pixbuf_get_height(buf) * scale_height / gdk_pixbuf_animation_get_height (icon_data->anim), 1), GDK_INTERP_NEAREST); gdk_pixbuf_render_pixmap_and_mask(scale, &pm, &bm, 100); g_object_unref(G_OBJECT(scale)); icon_data->event = gtk_event_box_new(); gtk_container_add(GTK_CONTAINER(icon_data->frame), icon_data->event); gtk_widget_set_size_request(GTK_WIDGET(icon_data->frame), scale_width, scale_height); // g_signal_connect(G_OBJECT(icon_data->event), "button-press-event", // G_CALLBACK(icon_menu), conv); gtk_widget_show(icon_data->event); icon_data->icon = gtk_image_new_from_pixmap(pm, bm); gtk_container_add(GTK_CONTAINER(icon_data->event), icon_data->icon); gtk_widget_show(icon_data->icon); g_object_unref(G_OBJECT(pm)); if (bm) g_object_unref(G_OBJECT(bm)); }
/** * gnome_gdk_pixbuf_new_from_uri: * @uri: the uri of an image * @width: The width the image should have or -1 to not constrain the width * @height: The height the image should have or -1 to not constrain the height * @preserve_aspect_ratio: %TRUE to preserve the image's aspect ratio * * Loads a GdkPixbuf from the image file @uri points to, scaling it to the * desired size. If you pass -1 for @width or @height then the value * specified in the file will be used. * * When preserving aspect ratio, if both height and width are set the size * is picked such that the scaled image fits in a width * height rectangle. * * Return value: The loaded pixbuf, or NULL on error * * Since: 2.14 **/ GdkPixbuf * gnome_gdk_pixbuf_new_from_uri_at_scale (const char *uri, gint width, gint height, gboolean preserve_aspect_ratio) { GnomeVFSResult result; char buffer[LOAD_BUFFER_SIZE]; GnomeVFSFileSize bytes_read; GdkPixbufLoader *loader; GdkPixbuf *pixbuf; GdkPixbufAnimation *animation; GdkPixbufAnimationIter *iter; gboolean has_frame; SizePrepareContext info; GFile *file; GFileInputStream *file_input_stream; g_return_val_if_fail (uri != NULL, NULL); file = g_file_new_for_uri (uri); file_input_stream = g_file_read (file, NULL, NULL); if (file_input_stream == NULL) { g_object_unref (file); return NULL; } loader = gdk_pixbuf_loader_new (); if (1 <= width || 1 <= height) { info.width = width; info.height = height; info.input_width = info.input_height = 0; info.preserve_aspect_ratio = preserve_aspect_ratio; g_signal_connect (loader, "size-prepared", G_CALLBACK (size_prepared_cb), &info); } has_frame = FALSE; result = GNOME_VFS_ERROR_GENERIC; while (!has_frame) { bytes_read = g_input_stream_read (G_INPUT_STREAM (file_input_stream), buffer, sizeof (buffer), NULL, NULL); if (bytes_read == -1) { break; } result = GNOME_VFS_OK; if (bytes_read == 0) { break; } if (!gdk_pixbuf_loader_write (loader, (unsigned char *)buffer, bytes_read, NULL)) { result = GNOME_VFS_ERROR_WRONG_FORMAT; break; } animation = gdk_pixbuf_loader_get_animation (loader); if (animation) { iter = gdk_pixbuf_animation_get_iter (animation, NULL); if (!gdk_pixbuf_animation_iter_on_currently_loading_frame (iter)) { has_frame = TRUE; } g_object_unref (iter); } } gdk_pixbuf_loader_close (loader, NULL); if (result != GNOME_VFS_OK) { g_object_unref (G_OBJECT (loader)); g_input_stream_close (G_INPUT_STREAM (file_input_stream), NULL, NULL); g_object_unref (file_input_stream); g_object_unref (file); return NULL; } g_input_stream_close (G_INPUT_STREAM (file_input_stream), NULL, NULL); g_object_unref (file_input_stream); g_object_unref (file); pixbuf = gdk_pixbuf_loader_get_pixbuf (loader); if (pixbuf != NULL) { g_object_ref (G_OBJECT (pixbuf)); g_object_set_data (G_OBJECT (pixbuf), "gnome-original-width", GINT_TO_POINTER (info.input_width)); g_object_set_data (G_OBJECT (pixbuf), "gnome-original-height", GINT_TO_POINTER (info.input_height)); } g_object_unref (G_OBJECT (loader)); return pixbuf; }