Next: , Previous: , Up: Part VI Images   [Contents][Index]


37.4 Creating Images

With the basic fields in the image structure and image types explained, we’re now in a position to tackle the problem of creating images on the fly. The data may have come from some simulations or some other means, the task now is to create an image from the data and try to display/visualize it.

The first task involved in creating an image is to create an image structure that is properly initialized. To this end, the following routine is available

FL_IMAGE *flimage_alloc(void);

The function returns a pointer to a piece of dynamically allocated memory that’s properly initialized.

The task next is to put the existing data into the structure. This involves several steps. The first step is to figure out what type of image to create. For scalar data, there are two logical choices, either a gray-scale intensity image or a color index image with the data being interpreted as indices into some lookup table. Both of these may be useful. Gray-scale imagse are straight forward to create and the meaning of the pixel values is well defined and understood. On the other hand with color-mapped image you can selectively enhance the data range you want to visualize by choosing appropriate color-maps. For vector data, RGB image probably makes most sense. In any case it’s strictly application’s decision. All that is needed to make it work with Forms Library is to set the image->type field to a valid value. Of course the image dimension (width and height) also needs to be set. Once this is done, we need to copy the data into the image structure.

Before we copy the data we create the destination storage using one of the following routines

void *fl_get_matrix(int nrows, int ncols, unsigned int elem_size);
int flimage_getmem(FL_IMAGE *image);

The fl_get_matrix() function creates a 2-dimensional array of entities of size elem_size. The array is of nrows by ncols in size. The 2D array can be passed as a pointer to pointer and indexed as a real 2D arrays. The flimage_getmem() routine allocates the proper amount of memory appropriate for the image type, including colormaps when needed.

After the destination storage is allocated, copying the data into it is simple

image->type = FL_IMAGE_GRAY;
image->w    = data_columns;
image->h    = data_row;
flimage_getmem(image);
/* or you can use the instead
  im->gray = fl_get_matrix(im->h, im->w, sizeof **im->gray);
*/

for (row = 0; row < image->h; row++)
    for (col = 0; col < image->w; col++)
        image->gray[row][col] = data_at_row_and_col;

Of course, if data is stored row-by-row, a memcpy(3) instead of a loop over columns may be more efficient. Also if your data are stored in a single array, fl_make_matrix() might be a lot faster as it does not copy the data.

If the created image is a color index image, in addition to copying the data to image->ci, you also need to set the lookup table length image->map_len, which should reflect the dynamic range of the data:

image->type    = FL_IMAGE_CI;
image->w       = A;
image->h       = B;
image->map_len = X;
flimage_getmem(image);  /* this will allocate ci and lut */

for (row = 0; row < image->h; row++)
    for (col = 0; col < image->w; col++)
        image->ci[row][col] = data;

for (i = 0; i < image->map_len; i++) {
   image->red_lut[i]   = some_value_less_than_FL_PCMAX;
   image->green_lut[i] = some_value_less_than_FL_PCMAX;
   image->blue_lut[i]  = some_value_less_than_FL_PCMAX;
}

If the type is FL_IMAGE_GRAY16, you also need to set image->gray_maxval to the maximum value in the data.

Now we’re ready to display the image

flimage_display(image, win);

As mentioned before, the display routine may create a buffered, display hardware specific and potentially lower-resolution image than the original image. If for any reason, you need to modify the image, either the pixels or the lookup tables, you need to inform the library to invalidate the buffered image:

image->modified = 1;

Next: , Previous: , Up: Part VI Images   [Contents][Index]