Karma Home Page
Next: Intelligent Arrays Up: Karma Programming Manual Previous: Image Editing

# Colourmaps

# Purpose

The dynamic pseudo colourmap control is intended to provide simple, elegant and device independent control of colourmaps. Integrated into the colourmap support is the ability to "share" colourmaps between graphics applications on the same screen and between different screens. For same-screen operation, this allows the user to dynamically change the colourmap in one window, and have that appear in another window at the same time. This is essential for image comparison. With different screen operation, two or more users may be viewing images on different consoles (perhaps across the planet), and yet when one user changes the image colourmap, the other user(s) sees this change as well. Any combination of same-screen and different-screen operation may be employed. To make use of these advanced facilities requires no extra code by the application programmer: all this functionality is gained for free. Other features of the colourmap support include the ability to register functions which are called if a colourmap is resized, simple interfaces to change colourmap parameters and colour palettes and the ability to read and write colourmaps from/ to disc.

A wide variety of standard colourmaps are available through the provision of colourmap functions. These functions compute continuously varying colours, so they work irrespective of the number of colours available on your screen.

The colourmap support provided in the Karma library can save several hundreds of lines of messy, intricate code.

# Related documents

The documentation on image display and communications support are highly recommended.

# Architecture

The colourmap support in Karma is built on a layered approach, as with many other sections of the library. The various packages in the Karma library which provide colourmap support are listed below.

## ``cf'' package

The cf package provides a large number of colourmap types (or palettes) which support the colourmap selection facility at a higher level in the library. These routines have a very simple defined interface, hence writing new colourmap functions is trivial.

## ``xc'' package

The xc package provides X11 colourmap support for higher levels of the library.

## ``vc'' package

The vc package provides colourmap support for the Vicom VX board (a Sun/VME board with an i860 and a 32 bit frame buffer).

## ``conn'' package

The network support for colourmaps utilises the conn communications package. This means that connection management facilities are applicable to the colourmap support.

## ``kcmap'' package

The actual colourmap support is provided by the kcmap package. This package allows the programmer to create and manipulate dynamic pseudo colourmaps using a generic interface. If network connections are set up (using either the conn package or the Connection Management tool), manipulation of colourmaps is automatically transmitted across the network. In addition to these features, colourmaps may be copied to standard Karma data structures, and hence tranferred from/ to disc. New colourmap functions are easily added. A large number of colourmap functions are automatically available by default.

The kcmap package registers support for two comminications protocols: ``colourmap_indices'' for the sharing of colourmaps on the same screen, ``full_colourmap" for the sharing of colourmaps on different screens.

# Tutorial

Although the simple use of colourmaps is shown in the tutorials for the image display support in Karma, it is worthwhile just pointing out the ease with which colourmap support may be migrated from an X11 environment to, say, a VX display.

## Example 1

This example shows how to initialise the colourmap system for X11 support, and then create a colourmap.

    /*----------------------------------------------------------*/
    /*  Colourmap creation sample programme: X11 interface      */
    /*----------------------------------------------------------*/

    #include <karma.h>
    #include <karma_kcmap.h>
    #include <karma_xc.h>
    #include <X11/Xlib.h>
    #include <X11/Xutil.h>

    #define DEFAULT_COLOURMAP_NAME "Greyscale1"
    #define MAX_COLOURS (unsigned int) 200

    Kcolourmap setup_cmap (dpy, window)
    /*  This routine will create a Kcolourmap object from an X11 display.
        The X display must be given by  dpy  .
        The X window must be given by  window  .
        The routine returns a Kcolourmap object.
    */
    Display *display;
    Window window;
    {
        /*  Declare variables  */
        Kdisplay dpy_handle;
        XWindowAttributes window_attributes;
        Kcolourmap cmap;

        /*  Get X colourmap ID  */
        XGetWindowAttributes (display, win, &window_attributes);
        /*  Initialise colourmap system  */
        dpy_handle = xc_get_dpy_handle (display, window_attributes.colormap);
        /*  Create Kcolourmap object  */
        cmap = kcmap_va_create (DEFAULT_COLOURMAP_NAME, MAX_COLOURS, TRUE,
                                dpy_handle, xc_alloc_colours, xc_free_colours,
                                xc_store_colours, xc_get_location,
                                KCMAP_ATT_END);
        return (cmap);
    }   /*  End Function setup_cmap  */

## Example 2

This example shows how to initialise the colourmap system for a VX display, and then create a colourmap.

    /*----------------------------------------------------------*/
    /*  Colourmap creation sample programme: VX interface       */
    /*----------------------------------------------------------*/

    #include <karma.h>
    #include <karma_kcmap.h>
    #include <karma_vc.h>

    #define DEFAULT_COLOURMAP_NAME "Greyscale1"
    #define MAX_COLOURS (unsigned int) 200

    Kcolourmap setup_cmap ()
    /*  This routine will create a Kcolourmap object from a VX display.
        The routine returns a Kcolourmap object.
    */
    {
        /*  Declare variables  */
        Kdisplay dpy_handle;
        Kcolourmap cmap;

        /*  Initialise colourmap system  */
        dpy_handle = vc_get_dpy_handle ();
        /*  Create Kcolourmap object  */
        cmap = kcmap_va_create (DEFAULT_COLOURMAP_NAME, MAX_COLOURS, TRUE,
                                dpy_handle, vc_alloc_colours, vc_free_colours,
                                vc_store_colours, vc_get_location,
                                KCMAP_ATT_END);
        return (cmap);
    }   /*  End Function setup_cmap  */

## Example 3

This example shows how to save a colourmap to a file.

    /*----------------------------------------------------------*/
    /*  Colourmap save routine:                                 */
    /*----------------------------------------------------------*/

    #include <karma.h>
    #include <karma_kcmap.h>
    #include <karma_ds.h>

    flag write_cmap (cmap, file)
    /*  This routine will write a Kcolourmap object to a file.
        The colourmap must be given by  cmap  .
        The filename must be pointed to by  file  .
        The routine returns TRUE on success, else it returns FALSE.
    */
    Kcolourmap cmap;
    char *file;
    {
        flag ok;
        multi_array *multi_desc;

        multi_desc = ds_alloc_multi (1);
        if ( !kcmap_copy_to_struct (cmap, multi_desc->headers,
                                    multi_desc->data) ) return (FALSE);
        ok = dsxfr_put_multi (multi_desc, file);
        multi_desc->headers[0] = NULL;
        multi_desc->data[0] = NULL;
        ds_dealloc_multi (multi_desc);
        return (ok);
    }   /*  End Function write_cmap  */

## Example 4

This example shows how to create a software colourmap (i.e. a colourmap which is not associated with a display device, but still has colours and pixels associated with it). This software colourmap is a convenient way to manage an array of pixel values or colour component values. The advantage of using a software colourmap rather than maintaining your own array of pixel values is that the software colourmap may be used with parts of the Karma graphics library (such as creating a world canvas and displaying images). This example also shows how the pixel values in a colourmap may be modifed and the changes registered. If the Kcolourmap object is used by a world canvas, refresh events are automatically generated when changes to the pixel values are registered. See the tutorial on image display for information on world canvases.

    /*----------------------------------------------------------*/
    /*  Colourmap creation sample programme: software colourmap */
    /*----------------------------------------------------------*/

    #include <karma.h>
    #include <karma_kcmap.h>

    #define MAX_COLOURS (unsigned int) 200

    Kcolourmap setup_cmap ()
    /*  This routine will create a software Kcolourmap object.
        The routine returns a Kcolourmap object.
    */
    {
        /*  Declare variables  */
        Kcolourmap cmap;

        /*  Create Kcolourmap object  */
        cmap = kcmap_va_create (NULL, MAX_COLOURS, TRUE,
                                NULL, ( unsigned int (*) () ) NULL,
                                ( void (*) () ) NULL, ( void (*) () ) NULL,
                                ( void (*) () ) NULL,
                                KCMAP_ATT_END);
        return (cmap);
    }   /*  End Function setup_cmap  */

    void set_pixels (Kcolourmap cmap,
                     unsigned long first_pixel, unsigned long last_pixel)
    /*  [SUMMARY] Change the first and last pixel values in a colourmap.
        <cmap> The Kcolourmap object.
        <first_pixel> The first pixel value.
        <last_pixel> The last pixel value.
        [RETURNS] Nothing.
    */
    {
        unsigned int size;
        unsigned long *pixel_values;

        size = kcmap_get_pixels (cmap, &pixel_values);
        pixel_values[0] = first_pixel;
        pixel_values[size - 1] = last_pixel;
        /*  If any world canvases were created with this colourmap, refresh events
            would be automatically generated for them
            */
        kcmap_notify_pixels_changed (cmap);
    }   /*  End Function set_pixels  */

## Example 5

This example shows how to create your own colourmap function and register it with the kcmap package. The colourmap function shown here is a simple greyscale, and allows the user to vary the way the colours are squeezed, stretched and moved.

The section below shows the colourmap function.

    /*----------------------------------------------------------*/
    /*  Colourmap function example: greyscale                   */
    /*----------------------------------------------------------*/

    #include <karma.h>
    #include <karma_kcmap.h>
    #include <karma_a.h>

    #define MAX_INTENSITY 65535

    void cf_greyscale1 (unsigned int num_cells, unsigned short *reds,
                        unsigned short *greens, unsigned short *blues,
                        unsigned int stride, double x, double y, void *var_param)
    /*  [SUMMARY] Compute a greyscale colourmap.
        <num_cells> The number of colour cells to modify.
        <reds> The array of red intensity values. This may be NULL.
        <greens> The array of green intensity values. This may be NULL.
        <blues> The array of blue intensity values. This may be NULL.
        <stride> The stride (in unsigned shorts) between intensity values in the
        array.
        <x> A parameter used to compute the colour values.
        <y> A parameter used to compute the colour values.
        <var_param> A parameter used to compute the colour values.
        [RETURNS] Nothing.
    */
    {
        unsigned int pixel_count;
        double slope, offset, factor, intensity;
        static char function_name[] = "cf_greyscale1";

        if ( (x < 0.0) || (x > 1.0) || (y < 0.0) || (y > 1.0) )
        {
            fprintf (stderr, "x or y out of range\n");
            a_prog_bug (function_name);
        }
        /*  Invert y  */
        y = 1.0 - y;
        if (y < 1e-3) slope = 1e3;
        else slope = (1.0 - y) / y;
        offset = 0.5 - slope * x;
        factor = 1.0 / (double) (num_cells - 1);
        /*  Now compute the colours  */
        for (pixel_count = 0; pixel_count < num_cells; ++pixel_count)
        {
            intensity = slope * (double) pixel_count * factor + offset;
            if (intensity < 0.0) intensity = 0.0;
            else if (intensity > 1.0) intensity = 1.0;
            intensity *= MAX_INTENSITY;
            if (reds != NULL) reds[pixel_count * stride] = intensity;
            if (greens != NULL) greens[pixel_count * stride] = intensity;
            if (blues != NULL) blues[pixel_count * stride] = intensity;
        }
    }   /*  End Function cf_greyscale1  */

The section below hows how to register the colourmap function.

        kcmap_add_grey_func ("Greyscale1", cf_greyscale1, 0, 0);

You would call the kcmap_add_RGB_func function instead of kcmap_add_grey_func if the colourmap produced an RGB output rather than a greyscale colourmap.

Karma Home Page
Next: Intelligent Arrays Up: Karma Programming Manual Previous: Image Editing