DragonWins Home Page

IMAGE Structure (1v0)

(Last Mod: 27 November 2010 21:37:52 )



IMAGE Version Parameters

IMAGE Color Parameters

IMAGE Composition Parameters

Note on Data Types:

t_image_data => WORD => unsigned 16-bit integer

t_image_size => WORD => unsigned 16-bit integer

 

WORD         IMAGE_version     (int what);

void         IMAGE_report      (IMAGE *p);

IMAGE*       IMAGE_new         (IMAGE *p, t_image_size rows, t_image_size cols, WORD bits);

IMAGE*       IMAGE_delete      (IMAGE *p);

t_image_data IMAGE_get_color   (IMAGE *p, t_image_size row, t_image_size col, WORD color);

t_image_data IMAGE_set_color   (IMAGE *p, t_image_size row, t_image_size col, WORD color, t_image_data value);

t_image_data IMAGE_set_rgb     (IMAGE *p, t_image_size row, t_image_size col,

                                          t_image_data r, t_image_data g, t_image_data b);

WORD         IMAGE_get_bits    (IMAGE *p);

t_image_size IMAGE_get_rows    (IMAGE *p);

t_image_size IMAGE_get_cols    (IMAGE *p);

IMAGE*       IMAGE_fill        (IMAGE *p, t_image_data r, t_image_data g, t_image_data b);

IMAGE*       IMAGE_color2gray  (IMAGE *p);

t_image_data IMAGE_min         (IMAGE *p);

t_image_data IMAGE_max         (IMAGE *p);

t_image_data IMAGE_min_gray    (IMAGE *p);

t_image_data IMAGE_max_gray    (IMAGE *p);

IMAGE*       IMAGE_clip        (IMAGE *p);

IMAGE*       IMAGE_scale       (IMAGE *p, double factor);

IMAGE*       IMAGE_offset      (IMAGE *p, int offset);

IMAGE*       IMAGE_set_depth   (IMAGE *p, WORD bits);

IMAGE*       IMAGE_draw_pixel  (IMAGE *p, t_image_size x, t_image_size y,

                                          t_image_data r, t_image_data g, t_image_data b);

IMAGE*       IMAGE_draw_line   (IMAGE *p, t_image_size x1, t_image_size y1, t_image_size x2, t_image_size y2,

                                          t_image_data r, t_image_data g, t_image_data b);

IMAGE*       IMAGE_draw_box    (IMAGE *p, t_image_size x1, t_image_size y1, t_image_size x2, t_image_size y2,

                                          t_image_data r, t_image_data g, t_image_data b, WORD fill);

IMAGE*       IMAGE_draw_circle (IMAGE *p, t_image_size x, t_image_size y, t_image_size radius,

                                          t_image_data r, t_image_data g, t_image_data b, WORD how);

IMAGE*       IMAGE_compose     (IMAGE *d, IMAGE *s, int x, int y, WORD how,

                                          t_image_data (*func)(t_image_data d, t_image_data s));



Overview

The IMAGE structure is used to contain the data for a three-color 2-D picture. The size (number of rows and columns) of the image is maintained as part of the image structure. The data for each pixel may be accessed and modified individually. This data consists of three values, one each for the red, green, and blue color components.

Gray scale images are implemented by setting all three color components in a pixel to the same value. The gray scale equivalent of a colored pixel is taken to be the RMS (root-mean-square) value of the three components. This is frequently referred to as the luminosity of the pixel.

The maximum size that an image can be is limited by the size of the integer used to represent the number of rows and columns. This data type is defined as t_image_size and, in V1.0, is a WORD (unsigned 16-bit integers). Thus, in theory, images with up to 65,535 rows and an equal number of colums are supported. Similarly, the intensity information for each color component is limited by the size of the data type t_image_data, which, in V1.0, is also a WORD .

However, most images are composed of one-byte color intensities (0 through 255), though some formats of interest use 10-bits (0 through 1023). The ideal way of dealing with these variations would be to store the data as floating point values between 0.0 and 1.0; however, not only would this require more space (not a large concern, here) and probably slow down the functions (again, not a large concern, here), but it would add potential uncertainly in the exact values for each pixel. Because of the nature of some of the applications this structure is intended for, such as steganography, this was considered unacceptable. The consequence is that the user is responsible for knowing what the acceptable range of values is for the image they are working with. To help out with this, the nominal bit depth of the image is maintained within the structure and several functions are provided to help the user translate between bit depths. Furthermore, the function that writes the values to the data structure ensures that the values are clipped to the ranged supported by the present bit depth of the image. The user is cautioned that, since these are unsigned integers, code which produces nominally negative component values will likely end up being clipped at the most positive allowed component value.

One important distinction to be aware of is that the bit-depth of an IMAGE structure is not the same as the bit-depth of a BMP file. In an IMAGE structure, the bit depth is how may bits are in the unsigned integer used to represent each color component. In a BMP file, the bid-depth is how many bits are used to represent the color of each pixel according to the BMP format definitions. These are fundamentally different concepts; aside from the obvious distinction of being per-color versus per-pixel, the bit-depth of a BMP file dictates the encoding scheme used. For instance, in a BMP file, all bit depths of one-byte or less are represented using a color palette. While this limits the total number of distinct colors available to the image as a whole, each color used is still 24-bits total (8 bits per component). Except for 24-bit BMP files, which correspond directly to 8-bit IMAGE structures, there is no simple way to convert back and forth between the two. Of course, reading any of the legitimate BMP file formats and converting them to IMAGE structures is relatively straight forward. But writing an IMAGE structure to a non-24-bit BMP file is much less so. However, since the IMAGE structure is intended to be a generic representation of an image, the task of performing this conversion, in either direction, is properly the responsibility of the BMP (or possibly other) library.


Macro Constants

The following sets of symbolic constants are defined in the image.h header file:

IMAGE Version Parameters

IMAGE_VERSION

IMAGE_MAJOR

IMAGE_MINOR

These are used as arguments to the IMAGE_version().

IMAGE Color Parameters

IMAGE_RED

IMAGE_GREEN

IMAGE_BLUE

IMAGE_GRAY

These are to be used as arguments to those functions calling for a "color" parameter. The purpose is to make indicating the intended color easier and the code more readable. The red, green, and blue constants are self-explanatory. Using a color of 'gray' will either set all three color components to the same value or return the 'gray' equivalent of the pixel color which, here, is taken to be the RMS (root-mean-square) value of the three color components.

IMAGE Composition Parameters

IMAGE_NEW

IMAGE_MIN

IMAGE_MAX

IMAGE_AVG

IMAGE_SUM

IMAGE_SUB

IMAGE_FUN

These are used as arguments to the IMAGE_compose() function to determine how pixels from two images are to be combined.


The Public Functions

IMAGE_version()

WORD IMAGE_report(int what)

Returns the version information for the STRUCT library as a 16-bit unsigned integer according to value passed as the what parameter:

IMAGE_report()

void IMAGE_report(IMAGE *p)

Generates an on screen report giving the address of the structure and the values of all of the members. This is primarily for debugging purposes.

IMAGE_new()

IMAGE* IMAGE_new(IMAGE *p, t_image_size rows, t_image_size cols, WORD bits)

If p is NULL (the usual case), allocates memory for a new IMAGE structure with sufficient memory to store a (rows)x(cols) image and returns a pointer to that structure if successful. If p is a pointer to an existing IMAGE structure, then that structure is reused. Returns NULL if unsuccessful. If either rows or cols is zero, then the structure is still allocated but no memory for the data is allocated.

The bits parameter is the nominal bit depth (per image component, not per pixel) of the image that is stored within the structure. It has no effect on the amount of memory allocated, but is used to ensure that data written to the structure is within the appropriate range. The maximum value of bits is sizeof(t_image_color).

IMAGE_delete()

IMAGE* IMAGE_delete(IMAGE *p)

Deallocates the memory used by the structure, including that allocated for the pixel data. Returns a NULL pointer if successful. If the memory could not be freed, then the original value of the pointer is returned.

IMAGE_get_color()

int IMAGE_get_color(IMAGE *p, t_image_size row, t_image_size col, WORD color)

Gets the value of the color component specified for the pixel in the specificed row and column. If the requested color is gray (IMAGE_GRAY), then the RMS value of the three color components is returned. Note: the data itself is not changed.

IMAGE_set_color()

t_image_data IMAGE_set_color(IMAGE *p, t_image_size row, t_image_size col, WORD color, t_image_data value)

Sets the specified color component of the pixel specified by row and col to value. If the specified component is gray (IMAGE_GRAY), then all three component are set to value. Returns the new value of the specified component (which should be value). 

IMAGE_set_rgb()

t_image_data IMAGE_set_rgb(IMAGE *p, t_image_size row, t_image_size col, t_image_data r, t_image_data g, t_image_data b)

Sets the color of the pixel specified by row and col to that indicated by the r, g, and b parameters. Returns the new grayscale value of the pixel.

IMAGE_get_bits()

WORD IMAGE_get_bits(IMAGE *p)

Returns the nominal bit depth of the image.

IMAGE_get_rows()

t_image_size IMAGE_get_rows(IMAGE *p)

Returns the number of rows in the image.

IMAGE_get_cols()

t_image_size IMAGE_get_cols(IMAGE *p)

Returns the number of columns in the image.

IMAGE_fill()

IMAGE* IMAGE_fill(IMAGE *p, t_image_data r, t_image_data g, t_image_data b)

Fills the entire image with the color indicated by the r, g, and b parameters. Returns p.

IMAGE_color2gray()

IMAGE*       IMAGE_color2gray  (IMAGE *p);

Sets each pixel's color to that pixel's gray scale value. Returns p.

IMAGE_min()

t_image_data IMAGE_min         (IMAGE *p);

Returns the minimum color component in the image.

IMAGE_max()

t_image_data IMAGE_max         (IMAGE *p);

Returns the maximum color component in the image.

IMAGE_min_gray()

t_image_data IMAGE_min_gray    (IMAGE *p);

Returns the minimum gray scale value in the image.

IMAGE_max_gray()

t_image_data IMAGE_max_gray    (IMAGE *p);

Returns the minimum gray scale value in the image.

IMAGE_clip()

IMAGE*       IMAGE_clip        (IMAGE *p);

Clips all component values in the image to the maximum as indicated by the images' present bit depth. Returns p.

IMAGE_scale()

IMAGE*       IMAGE_scale       (IMAGE *p, double factor);

Multiplies all component values within the image by factor, clipping as needed to avoid exceeding the image's bit depth. Returns p.

IMAGE_offset()

IMAGE*       IMAGE_offset      (IMAGE *p, int offset);

Adds factor to all component values within the image, clipping as needed to avoid exceeding the image's bit depth. Returns p.

IMAGE_set_depth()

IMAGE*       IMAGE_set_depth   (IMAGE *p, WORD bits);

Changes the image's bit depth from its present value to bits. The pixel component values are scaled accordinglyt. Returns p.

IMAGE_draw_pixel()

IMAGE*       IMAGE_draw_pixel  (IMAGE *p, t_image_size x, t_image_size y,

                                          t_image_data r, t_image_data g, t_image_data b);

Sets the color of the pixel specified by row and col to that indicated by the r, g, and b parameters. The same as IMAGE_set_rgb() except for the return value. This function is primarily provided to give the a consistent set of drawing functions. Returns p.

IMAGE_draw_line()

IMAGE*       IMAGE_draw_line   (IMAGE *p, t_image_size x1, t_image_size y1, t_image_size x2, t_image_size y2,

                                          t_image_data r, t_image_data g, t_image_data b);

Draws a line from (x1,y1) to (x1,y2). Returns p.

Note, unspecified results if the endpoints are not within the image's bounds.

IMAGE_draw_box()

IMAGE*       IMAGE_draw_box    (IMAGE *p, t_image_size x1, t_image_size y1, t_image_size x2, t_image_size y2,

                                          t_image_data r, t_image_data g, t_image_data b, WORD fill);

Draws a box with corners located at (x1,y1) to (x1,y2). If fill is FALSE then only the outline is draw, otherwise the box is solid. Returns p.

Note, unspecified results if the endpoints are not within the image's bounds.

IMAGE_draw_circle()

IMAGE*       IMAGE_draw_circle (IMAGE *p, t_image_size x, t_image_size y, t_image_size radius,

                                          t_image_data r, t_image_data g, t_image_data b, WORD how);

Draws a circle centered at at (x,y) with the given radius. If fill is FALSE then only the outline is draw, otherwise the circle is solid. Returns p.

Note, unspecified results if the endpoints are not within the image's bounds.

IMAGE_compose()

IMAGE*       IMAGE_compose     (IMAGE *d, IMAGE *s, int x, int y, WORD how,

                                          t_image_data (*func)(t_image_data d, t_image_data s));

Combines two images by overlaying the second image (s) onto the first (or destination) image (d). The size of the first image is unchanged. The second image is shifted by (x,y) before being overlaid. Returns d, the pointer to the destination image.

The how parameter dictates how the value of the pixel in the destination image is to be modified. The options are as follows:

IMAGE_NEW - Uses the value from the second image.

IMAGE_MIN - Uses the minimum value of the components from the two images.

IMAGE_MAX - Uses the maximum value of the components from the two images.

IMAGE_AVG - Uses the average value of the components from the two images.

IMAGE_SUM - Uses the sum of the components from the two images.

IMAGE_SUB - Uses the difference of the components from the two images (destination - source)/

IMAGE_FUN - Use a custom function. The pointer to this function must be passed as the final argument.

The images are combined component-by-component, pixel-by-pixel. Thus it is not possible (using this function) to use information from surrounding pixels (or even the other components within the same pixel) in determining the new pixel color. One potential consequence of this is color shifting if a pixel's color components are clipped. This is only possible with the SUM and SUB options (as well as the custom option, of course) and is particularly likely with the SUB option.

If IMAGE_FUN is passed as the how parameter, then the function uses a user-supplied custom combining function; a pointer to this function must be passed as the final argument (which can be set to NULL for all other how choices). This function will be passed the pixel component values, one-by-one and pixel-by-pixel, from the corresponding pixels from first and second images and must return the value that destination pixel should be set to.

If the bit depths of the two images are not equal, the second is scaled to match the first and then scaled back afterwards. The possibility of scaling artifacts persisting in the second image exists.