Next: The FL_IMAGE Structure, Up: Part VI Images [Contents][Index]
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]