CRIMP
Artifact [642d6d917f]
Not logged in

Artifact 642d6d917f2dc8976460f252840a9e5671f5ce56:


#ifndef CRIMP_io_sgi_H
#define CRIMP_io_sgi_H

/*
 * CRIMP :: SGI helper dclarations. INTERNAL. Do not export.
 *
 * References
 *     ftp://ftp.sgi.com/graphics/SGIIMAGESPEC
 *     http://en.wikipedia.org/wiki/Silicon_Graphics_Image
 */

#include <crimp_core/crimp_coreDecls.h>

/*
 * sgi decoder information.
 *
 * All multi-byte values (short, long) are stored in bigendian order.
 * General file structure is
 * - Header
 * - Offset tables (optional).
 * - Pixel data
 *
 * In case of multi-channel images all information about the channels
 * is stored separately, not interleaved. This affects both offset
 * tables and the pixel data.
 *
 * The offset tables are present only for RLE encoded images.  They
 * cannot be ignored as they allow additional compression,
 * i.e. identical rows of pixels sharing the compressed data,
 * including sharing between channels.
 *
 * == Header 512 bytes ==
 *
 *   0..  1 |   2 : Magic (Decimal 474, Hex 0x01da)
 *   2..  2 |   1 : Storage format --> sgi_storage_type
 *   3..  3 |   1 : Bytes per pixel per channel (in [1-2]).
 *   4..  5 |   2 : Number of dimensions (in [1-3]).
 *   6..  7 |   2 : Width  (always)
 *   8..  9 |   2 : Height (for #dimensions >= 2)
 *  10.. 11 |   2 : Depth  (for #dimensions == 3), in [1,3,4] (BW,RGB,RGBA)
 *  12.. 15 |   4 : Min pixel value
 *  16.. 19 |   4 : Max pixel value
 *  20.. 23 |   4 : Reserved1
 *  24..103 |  80 : Image name (C string)
 * 104..107 |   4 : Colormap id --> sgi_colormap_type
 * 108..511 | 404 : Reserved, to fill to 512.
 *
 * == Offset tables ==
 *
 * - Are present if and only if pixels are stored RLE compressed.
 * - We have 2 * 'depth' (#channels) tables. Per channel a table of
 *   start offsets, and a table of lengths.
 * - Each table has 'height' entries, i.e. one per scan-line.
 * - Scan lines may share pixel data, i.e. point to the same block
 *   of RLE data.
 * - Tables are stored in the following order:
 *   - Start Offset Tables
 *   - Length Tables
 * - Within each group of tables above data for the 1st channel
 *   is saved first, followed by the other channels in order.
 * - The offsets are relative to the beginning of the file, i.e. absolute
 *   in the file.
 *
 * == Pixel data ==
 *
 * - When stored direct the data of the first channel is provided first,
 *   followed by the others, in order.
 * - The size of each pixel is determined by Bytes/Pixel/Channel.
 * - When stored RLE the data is stored by scan line using the compression
 *   method below.
 *
 * == RLE compression ==
 *
 * - Depending on bytes/pixel/channel the elements below are treated as either
 *   chars, or shorts.
 * - We have x types of packets:
 * - A: 1nnnnnnn <n elements> -- Literal run, copy the elements as is.
 *   B: 0nnnnnnn <value>      -- Repeat vaue <n> times.
 *   C: x0000000              -- End of scanline/data
 *
 * Note that even when elements are shorts the flag and count information for
 * the various packet types is still in the low-order byte of the value.
 *
 * == Line ordering ==
 *
 * SGI puts the coordinate origin into the lower left corner. This means that
 * the first scanline is the bottom row of the image. IOW the scan lines are
 * stored from bottom to top.
 */

typedef enum {
    sgi_storage_verbatim = 0, /* Direct pixel data */
    sgi_storage_rle      = 1  /* RLE compressed pixel data */
} sgi_storage_type;

typedef enum {
    sgi_colormap_normal   = 0, /* Direct pixel data, no color map */
    sgi_colormap_dithered = 1, /* BGR bit-packed 2:3:3, obsolete */
    sgi_colormap_screen   = 2, /* Color-indexed. [1], obsolete */
    sgi_colormap_map      = 3  /* Color map - Image is color map,
				* not display-able */ 
} sgi_colormap_type;

/* (Ad 1 above): Unclear where to get the color map from. While there are
 * images which are colormaps it is unclear how an image determines which
 * color map to use. Decision: Format not supported.
 */

typedef struct sgi_info {
    unsigned int      w;             /* Image width */
    unsigned int      h;             /* Image height */
    unsigned int      d;             /* Image depth */
    unsigned int      bpp;           /* #Bytes/Pixel/Channel [1..2] */
    unsigned int      min;           /* Min and max pixel values */
    unsigned int      max;           /* s.a. */
    sgi_storage_type  storage;       /* Type of raster storage */
    sgi_colormap_type mapType;       /* Colormap information */
    unsigned int*     ostart;        /* Pointer to scan line offsets (RLE only) */
    unsigned int*     olength;       /* Pointer to scan line lengths (ditto) */
    crimp_buffer*     input;         /* buffer holding the image */
} sgi_info;

/*
 * BUILD ASSERTION: The structure above assumes that a variable of type 'int'
 * can hold (at least) 4 bytes (ostart, olength). Failure in the line below
 * tells us that this is not true for the chosen combination of OS, compiler,
 * and compiler flags.
 */

CRIMP_BUILD_ASSERT (sizeof(int) >= 4);

/*
 * Main functions.
 */

extern int
sgi_read_header (Tcl_Interp*     interp,
		 crimp_buffer*   buf,
		 sgi_info*       info);

extern int
sgi_read_pixels (sgi_info*      info,
		 crimp_image**  destination);

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
#endif /* CRIMP_io_sgi_H */