4. Loading image data into a texture

4.1. Problem

You want to display an image inside a Clutter application.

4.2. Solution

Create a ClutterTexture directly from an image file:

ClutterActor *texture;
GError *error = NULL;
gchar *image_path = "/path/to/image";

texture = clutter_texture_new_from_file (image_path, &error);

if (error != NULL)
  {
    // handle error
  }

Or create a texture and set its source to an image file:

ClutterActor *texture;
GError *error = NULL;
gchar *image_path = "/path/to/image";
gboolean loaded;

texture = clutter_texture_new ();

/*
 * returns FALSE if file could not be loaded or texture
 * could not be set from image data in the file
 */
loaded = clutter_texture_set_from_file (CLUTTER_TEXTURE (texture),
                                        image_path,
                                        &error);

if (error != NULL)
  {
    // handle error
  }

4.3. Discussion

Bear the following in mind when loading images into a texture:

  • An image load may fail if:

    • The file does not exist.

    • The image format is unsupported: most of the common bitmap formats (PNG, JPEG, BMP, GIF, TIFF, XPM) are supported, but more exotic ones may not be.

  • Whether you're creating a texture from an image file, or loading an image from a file into an existing texture, you should specify the filesystem path to the file, rather than a URI.

4.3.1. Synchronous vs. asynchronous image loading

The code examples above show the simplest approach: loading an image into a texture synchronously. This means that the application waits for each image to be loaded before continuing; which is acceptable in this case, but may not be when loading images into multiple textures.

Another approach is to load data into textures asynchronously. This requires some extra set up in your code:

  • Call g_thread_init() (from the GLib library) prior to calling clutter_init(), so that a local thread is used to load the file, rather than the main loop. (Note that this is not necessary if you're using GLib version >= 2.24, since GObject initializes threading with the type system.)

  • Set the texture to load data asynchronously.

  • Connect a callback to the texture's load-finished signal to handle any errors which occur during loading, and/or to do extra work if data loads successfully.

The code below shows how to put these together:

/* callback to invoke when a texture finishes loading image data */
static void
_load_finished_cb (ClutterTexture *texture,
                 gpointer        error,
                 gpointer        user_data)
{
  GError *err = error;
  const gchar *image_path = user_data;

  if (err != NULL)
    g_warning ("Could not load image from file %s; message: %s",
               image_path,
               err->message);
  else
    g_debug ("Image loaded from %s", image_path);
}

int
main (int argc, char *argv[])
{
  /* initialize GLib's default threading implementation */
  g_thread_init (NULL);

  if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
    return 1;

  /* ... get stage etc. */

  ClutterActor *texture;
  GError *error = NULL;

  texture = clutter_texture_new ();

  /* load data asynchronously */
  clutter_texture_set_load_async (CLUTTER_TEXTURE (texture), TRUE);

  /* connect a callback to the "load-finished" signal */
  g_signal_connect (texture,
                    "load-finished",
                     G_CALLBACK (_load_finished_cb),
                    image_path);

  /* load the image from a file */
  clutter_texture_set_from_file (CLUTTER_TEXTURE (texture),
                                 image_path,
                                 &error);

  /* ... clutter_main () etc. */
}

4.3.2. Other ways to load image data into a texture

While it's useful to load image data into a texture directly from a file, there are occasions where you may have image data in some other (non-file) format:

  • Various GNOME libraries provide image data in GdkPixbuf structures; clutter-gtk has functions for creating or setting a texture from a GdkPixbuf: gtk_clutter_texture_new_from_pixbuf() and gtk_clutter_texture_set_from_pixbuf() respectively.

  • If you have raw RGB pixel data, ClutterTexture also has a clutter_texture_set_from_rgb_data() function for loading it.