The Basic Image Support API (XForms (Forms Library) - Version 1.2 (Rev. 4) A Graphical User Interface Toolkit for X)

Next: The FL_IMAGE Structure, Up: Part VI Images [Contents][Index]

### 37.1 The Basic Image Support API

Reading and displaying images are quite easy. It can be as simple as a couple of lines of code:

    FL_IMAGE *image;

    if ((image = flimage_load("imagefilename"))
        image->display(image, win);

In this example, an image is created from a file, then the image is displayed in a window, `win`. For most casual uses, this is really what is needed to load and display an image.

As you may have guessed, an image in Forms Library is represented by a structure of type `FL_IMAGE`. In addition to the pixels in the image, it also keeps a variety of information about the image such as its type, dimension, lookup tables etc. Further, if the image can not be displayed directly on the display hardware (for example, the image is 24 bits, while the display is only capable of 8 bits), a separate displayable image is created and displayed. Any manipulation of the image is always performed on the original high-resolution image, and a new displayable image will be created if necessary.

Writing an image is just as simple

    if (flimage_dump(image, "filename", "jpeg") < 0)
        fprintf(stderr,"image write failed");

In this code snippet, an image in memory is written to a file in JPEG format. As you might have noticed by now, all image routines start with flimage. The exact APIs for reading and writing an image are as follows

    FL_IMAGE *flimage_load(const char *filename);
    int flimage_dump(FL_IMAGE *im, const char *filename, const char *fmt);

The function `flimage_load()` takes a filename and attempts to read it. If successful, an image (or multiple images) is created and returned. If for any reason the image can’t be created (no permission to read, unknown file format, out of memory etc), a null pointer is returned. As will be documented later, error reporting and progress report can be configured so these tasks are performed inside the library.

The function `flimage_dump()` takes an image, either returned by `flimage_load()` (possibly after some processing) or created on the fly by the application, attempts to create a file to store the image. The image format written is controlled by the third parameter `fmt`q, which should be either the formal name or the short name of one of the supported formats (such as jpeg, ppm, gif, bmp etc., see section 23.3) or some other formats the application knows how to write. If this parameter is `NULL`, the original format the image was in is used. If the image is successfully written, a non-negative number is returned, otherwise a negative number. Depending on how the image support is configured, error reporting may have already occurred before the function returns.

Given these two routines, a file converter (i.e., changing the image file format) is simple

    if ((image = flimage_load("inputfile"))
        flimage_dump(image, "outfile", "newformat");

See the demo program `iconvert.c` for a flexible and usable image converter.

To free an image, use the following routine

    void flimage_free(FL_IMAGE *image);

The function first frees all memory allocated for the image, then the image structure itself. After the function returns, the image should not be referenced.

The following routines are available to display an image in a window

    int flimage_display(FL_IMAGE *image, FL_WINDOW win);
    int flimage_sdisplay(FL_IMAGE *image, FL_WINDOW win);

where `win` is a window ID. If the image(s) is successfully displayed, a non-negative integer is returned, a negative integer otherwise. The difference between the two display routines is that `flimage_sdisplay()` only displays a single image while `flimage_display()`, built on top of `flimage_sdisplay()`, can display single or multiple images. For typical use, `flimage_display()` or `image->display` should be used. `flimage_sdisplay()` is useful only if you’re coding your own multi-image display routine. For example, `flimage_display()` is built roughly like the following

    int flimage_display(FL_IMAGE *im, FL_WINDOW win) {
        int err;

        for (err = 0; err >=0 && im; im = im->next) {
            err = flimage_sdisplay(im, win);
            fl_update_display(0);
            fl_msleep(im->setup->delay);
        }

        return err;
    }

And you can build your own multi-frame image display routine to suit your application’s needs.

Despite the display routine’s simple look, this function performs tasks that involve the details of dealing with different hardware capabilities, a daunting task for beginners. For PseudoColor displays (i.e., using color maps or color lookup tables), a color quantization or dithering step may be performed by the function to reduce the number of colors in the image (of course, the colorreduced image is kept only for display, the original image is untouched so future processing is carried out on the original full resolution image, rather than the displayed, an approximate of the original image). In general, when the information in an image is reduced in order to display it, the original image is not altered in any way. For example, this function can display a 24bit image on a 1bit display without losing any information on the original 24bit image.

By default, the entire image is displayed at the top-left corner of the window. To display the image at other locations within the window (perhaps to center it), use the `image->wx` and `image->wy` fields of the `FL_IMAGE` structure. These two fields specify where in the window the origin of the image should be. By repeatedly changing `image->wx` and `image->wy` and displaying, image panning can be implemented.

It is also possible to display a subimage by specifying non-zero value for `(image->sx,image->sy)` and `(image->sw, image->sh)`. You can view the image as a 2D space with the origin at the top left corner. The positive y axis of the image space is pointing downward. `(image->sx,image->sy)` specify the subimage offset into the image (they must be non-negative) and `(image->sw,image->sh)` specify the width and height of the subimage. Taken the window offset and the subimage together, the more accurate statement of the functionality of the the function `flimage_display()` is that it displays a subimage specified by `(image->sx,image->sy)` and `(image->sw,image->sh)` starting at `(image->wx, image->wy)`.

You can also use clipping to display a subimage by utilizing the following functions and `image->gc`

    fl_set_gc_clipping(image->gc, x, y, w, h);
    fl_unset_gc_clipping(image->gc);

where the coordinates are window coordinates. Of course, by manipulating `image->gc` directly, more interesting clipping or masking can be achieved. Since the GC is visual dependent, a newly created image before displaying may not yet have a valid GC assoiated with it. If you must set some clipping before displaying, you can set the `image->gc` yourself beforehand. Note that you if you free the GC, make sure you reset it to `None`.

To display an image in a canvas, the following can be used

    flimage_display(image, FL_ObjWin(canvas));

Since this function only knows about window IDs, and writes to the window directly, it may not be sensitive to the status of the form the canvas is on, e.g., a frozen form. In your application, you should check the status of the form before calling this function.

Sometimes it may be useful to find out if a specific file is an image file before attempting to read it (for example, as a file filter). To this end, the following routine exists

    int flimage_is_supported(const char *file);

The function returns true if the specified file is a known image file. If the file is not a known image or not readable for any reason, the function return 0.

Next: The FL_IMAGE Structure, Up: Part VI Images [Contents][Index]