Progressive Loading with the Gdk-pixbuf Library

Gdk-pixbuf's image-loading facilities make it very easy for you to load a variety
of graphics file formats using the same interface. All you have to do is supply
the file name, and gdk-pixbuf will handle the rest. However, the file-loading
system has one potentially limiting flaw: It blocks until it's finished. With
icons and smaller images, this temporary stall is not noticeable enough to matter,
but when the file is particularly large, or is loading from a remote site with
a slow connection, your application may flounder in an input/output loop, unable
to update itself. The resulting slowness gives your application a buggy, unresponsive
appearance, even though it has a good reason for stalling.

To address this problem, the gdk-pixbuf library offers the GdkPixbufLoader
API. GdkPixbufLoader is a derivative of GtkObject that allows the loading process
to be controlled by your application rather than by gdk-pixbuf's image-loading
code. Because it's derived from GtkObject, GdkPixbufLoader can notify you through
GTK+ signals when something interesting happens.

The interface is simple and straightforward. You create a loader object, write
chunks of raw image data to it, and then close it when you're done. As soon
as the loader receives enough of the graphics file to determine what sort of
image it's loading, it creates a GdkPixbuf structure in which to store the image
data. When you close the loader, it unreferences that GdkPixbuf, so if you want
the pixbuf still to exist after you're done with the loader, your application
will need to explicitly call gdk_pixbuf_ref() on it (and, of course, release
it when you're done). The best place to reference the pixbuf is inside an area_prepared
signal callback, which we'll discuss in a moment.

The loader uses the same code to load images into GdkPixbufLoader that gdk-pixbuf
uses inside gdk_pixbuf_new_from_file(). Here's the basic GdkPixbufLoader API:

The aforementioned area_prepared signal indicates that the loader has read
enough of the file to calculate the size and color depth of the image. Until
the loader has this information, it makes no sense to create the target GdkPixbuf.
This first milestone is important enough to merit a special signal emission
because it means that your application can allocate space in the display for
the image. If you connect to the area_prepared signal, you should take the opportunity
in your callback to call gdk_pixbuf_ref() on the supplied pixbuf. Also, you
are guaranteed at this point that the loader has not started writing into the
new pixel buffer, so you can fill it with whatever background you want, whether
it's a solid color or a placeholder image. As image data continues to pour into
the loader, your background image will slowly be written over, line by line,
until the full image arrives.

You'll receive only one area_prepared signal per loader, but altogether you'll
end up receiving several area_updated signals. In fact, each time you call gdk_pixbuf_loader_write(),
the loader will fire off another area_updated signal. If you're displaying the
progressive image to a drawablewhich, after all, is largely the point
of using GdkPixbufLoaderyou should use this opportunity to update the
display. You can do this by copying the currently loaded portion of the image
to a GdkPixmap drawable with gdk_pixbuf_render_to_drawable_alpha() and then
triggering a refresh with gtk_widget_draw().

The final signal, closed, is useful if you want to know when the image is completely
loaded. If other parts of your application, such as a Web browser window, need
to be notified when the image is complete, you can connect them to the loader's
closed signal, rather than blocking until then.

About the Author

John R. Sheets has been following the GNOME project on a day-to-day
basis for more than two years, since GNOME was only six months old. He is a
software developer for CodeWeavers,
Inc., where he works on Wine and GNOME. In his free time, he is helping
the WorldForge Project
to create a free online multiplayer gaming environment. John is the author of
Writing
GNOME Applications (Addison-Wesley,
2001), and the maintainer of the OpenBooks
Web site.