From 458ef9b3bf307a2265321418f24cb2daff2bbc69 Mon Sep 17 00:00:00 2001 From: Tony Cook Date: Sat, 12 May 2007 05:19:27 +0000 Subject: [PATCH] various bits and pieces of documentation --- announce/0.57.txt | 9 + fileformatdocs/SGIIMAGESPEC.txt | 417 ++++++++++++++++++++++++++++++ fileformatdocs/sgiimage-1.00.html | 417 ++++++++++++++++++++++++++++++ 3 files changed, 843 insertions(+) create mode 100644 announce/0.57.txt create mode 100644 fileformatdocs/SGIIMAGESPEC.txt create mode 100644 fileformatdocs/sgiimage-1.00.html diff --git a/announce/0.57.txt b/announce/0.57.txt new file mode 100644 index 00000000..adc205cd --- /dev/null +++ b/announce/0.57.txt @@ -0,0 +1,9 @@ +

Imager 0.57 is a security fix release.

+ +

After following up on a buqtraq +message describing BMP issues in some viewers I decided to test Imager against the test images.

+ +

Unfortunately Imager failed on some of the test images.

+ +

Imager 0.57 corrects this.

diff --git a/fileformatdocs/SGIIMAGESPEC.txt b/fileformatdocs/SGIIMAGESPEC.txt new file mode 100644 index 00000000..4782f1f2 --- /dev/null +++ b/fileformatdocs/SGIIMAGESPEC.txt @@ -0,0 +1,417 @@ + +For Version 1.00 of this spec see: + +http://reality.sgi.com/grafica/sgiimage.html + + + + + Draft version 0.97 + + The SGI Image File Format + + Paul Haeberli + + paul@sgi.com + + Silicon Graphics Computer Systems + + + + This is the definitive document describing the SGI image file format. This + is a low level spec that describes the actual byte level format of SGI image + files. On SGI machines the preferred way of reading and writing SGI image + files is to use the image library -limage. This library provides a set + of functions that make it easy to read and write SGI images. If you are + on an SGI workstation you can get info on -limage by doing: + + % man 4 rgb + + A note on byte order of values in the SGI image files + + In the following description a notation like bits[7..0] is used to denote + a range of bits in a binary value. Bit 0 is the lowest order bit in + the value. + + All short values are represented by 2 bytes. The first byte stores the + high order 8 bits of the value: bits[15..8]. The second byte stores + the low order 8 bits of the value: bits[7..0]. + + So, this function will read a short value from the file: + + unsigned short getshort(inf) + FILE *inf; + { + unsigned char buf[2]; + + fread(buf,2,1,inf); + return (buf[0]<<8)+(buf[1]<<0); + } + + All long values are represented by 4 bytes. The first byte stores the + high order 8 bits of the value: bits[31..24]. The second byte stores + bits[23..16]. The third byte stores bits[15..8]. The forth byte stores + the low order 8 bits of the value: bits[7..0]. + + So, this function will read a long value from the file: + + static long getlong(inf) + FILE *inf; + { + unsigned char buf[4]; + + fread(buf,4,1,inf); + return (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+(buf[3]<<0); + } + + + The general structure of an SGI image file is as shown below: + + The header indicates whether the image is run length encoded (RLE). + + If the image is not run length encoded, this is the structure: + + The Header + The Image Data + + If the image is run length encoded, this is the structure: + + The Header + The Offset Tables + The Image Data + + + The Header + + The header consists of the following: + + Size | Type | Name | Description + + 2 bytes | short | MAGIC | IRIS image file magic number + 1 byte | char | STORAGE | Storage format + 1 byte | char | BPC | Number of bytes per pixel channel + 2 bytes | ushort | DIMENSION | Number of dimensions + 2 bytes | ushort | XSIZE | X size in pixels + 2 bytes | ushort | YSIZE | Y size in pixels + 2 bytes | ushort | ZSIZE | Number of channels + 4 bytes | long | PIXMIN | Minimum pixel value + 4 bytes | long | PIXMAX | Maximum pixel value + 4 bytes | char | DUMMY | Ignored + 80 bytes | char | IMAGENAME | Image name + 4 bytes | long | COLORMAP | Colormap ID + 404 bytes | char | DUMMY | Ignored + + + Here is a description of each field in the image file header: + + MAGIC - This is the decimal value 474 saved as a short. This + identifies the file as an SGI image file. + + STORAGE - specifies whether the image is stored using run + length encoding (RLE) or not (VERBATIM). If RLE is used, the value + of this byte will be 1. Otherwise the value of this byte will be 0. + The only allowed values for this field are 0 or 1. + + BPC - describes the precision that is used to store each + channel of an image. This is the number of bytes per pixel + component. The majority of SGI image files use 1 byte per + pixel component, giving 256 levels. Some SGI image files use + 2 bytes per component. The only allowed values for this field + are 1 or 2. + + DIMENSION - described the number of dimensions in the data stored + in the image file. The only allowed values are 1, 2, or 3. If + this value is 1, the image file consists of only 1 channel and + only 1 scanline (row). The length of this scanline is given by the + value of XSIZE below. If this value is 2, the file consists of a + single channel with a number of scanlines. The width and height + of the image are given by the values of XSIZE and YSIZE below. + If this value is 3, the file consists of a number of channels. + The width and height of the image are given by the values of + XSIZE and YSIZE below. The number of channels is given by the + value of ZSIZE below. + + XSIZE - The width of the image in pixels + + YSIZE - The height of the image in pixels + + ZSIZE - The number of channels in the image. B/W (greyscale) images + are stored as 2 dimensional images with a ZSIZE or 1. RGB color + images are stored as 3 dimensional images with a ZSIZE of 3. An RGB + image with an ALPHA channel is stored as a 3 dimensional image with + a ZSIZE of 4. There are no inherent limitations in the SGI image + file format that would preclude the creation of image files with more + than 4 channels. + + PINMIN - The minimum pixel value in the image. The value of + 0 may be used if no pixel has a value that is smaller than 0. + + PINMAX - The maximum pixel value in the image. The value of + 255 may be used if no pixel has a value that is greater than 255. + This is the value that is considered to be full brightness in + the image. + + DUMMY - This 4 bytes of data should be set to 0. + + IMAGENAME - An null terminated ascii string of up to 79 characters + terminated by a null may be included here. This is not commonly + used. + + COLORMAP - This controls how the pixel values in the file should be + interpreted. It can have one of these four values: + + 0: NORMAL - The data in the channels represent B/W values + for images with 1 channel, RGB values for images with 3 + channels, and RGBA values for images with 4 channels. + Almost all the SGI image files are of this type. + + 1: DITHERED - The image will have only 1 channel of data. + For each pixel, RGB data is packed into one 8 bit value. + 3 bits are used for red and green, while blue uses 2 bits. + Red data is found in bits[2..0], green data in bits[5..3], + and blue data in bits[7..6]. This format is obsolete. + + 2: SCREEN - The image will have only 1 channel of data. + This format was used to store color-indexed pixels. + To convert the pixel values into RGB values a colormap + must be used. The appropriate color map varies from + image to image. This format is obsolete. + + 3: COLORMAP - The image is used to store a color map from + an SGI machine. In this case the image is not displayable + in the conventional sense. + + DUMMY - This 404 bytes of data should be set to 0. This makes the + header exactly 512 bytes. + + + The Image Data (if not RLE) + + If the image is stored verbatim (without RLE), then image data directly + follows the 512 byte header. The data for each scanline of the first + channel is written first. If the image has more than 1 channel, all + the data for the first channel is written, followed by the remaining + channels. If the BPC value is 1, then each scanline is written as XSIZE + bytes. If the BPC value is 2, then each scanline is written as XSIZE + shorts. These shorts are stored in the byte order described above. + + + The Offset Tables (if RLE) + + If the image is stored using run length encoding, offset tables + follow the header that describe what the file offsets are to the + RLE for each scanline. This information only applies if the value + for STORAGE above is 1. + + Size | Type | Name | Description + + tablen longs | long | STARTTAB | Start table + tablen longs | long | LENGTHTAB | Length table + + One entry in each table is needed for each scanline of RLE data. The + total number of scanlines in the image (tablen) is determined by the + product of the YSIZE and ZSIZE. There are two tables of longs that + are written. Each consists of tablen longs of data. The first + table has the file offsets to the RLE data for each scanline in the + image. In a file with more than 1 channel (ZSIZE > 1) this table first + has all the offsets for the scanlines in the first channel, followed + be offsets for the scanlines in the second channel, etc. The second + table has the RLE data length for each scanline in the image. In a + file with more than 1 channel (ZSIZE > 1) this table first has all the + RLE data lengths for the scanlines in the first channel, followed + be RLE data lengths for the scanlines in the second channel, etc. + + To find the the file offset, and the number of bytes in the RLE data + for a particular scanline, these two arrays may be read in and indexed as + follows: + + To read in the tables: + + unsigned long *starttab, *lengthtab; + + tablen = YSIZE*ZSIZE*sizeof(long); + starttab = (unsigned long *)mymalloc(tablen); + lengthtab = (unsigned long *)mymalloc(tablen); + fseek(inf,512,SEEK_SET); + readlongtab(inf,starttab); + readlongtab(ing,lengthtab); + + + To find the file offset and RLE data length for a scanline: + + rowno is an integer in the range 0 to YSIZE-1 + channo is an integer in the range 0 to ZSIZE-1 + + rleoffset = starttab[rowno+channo*YSIZE] + rlelength = lengthtab[rowno+channo*YSIZE] + + It is possible for two identical rows (scanlines) to share compressed + data. A completely white image could be written as a single compressed + row and having all table entries point to that row. Another little hack + that should work is if you are writing out a RGB RLE file, and a + particular scanline is achromatic (greyscale), you could just make the + r, g and b rows point to the same data!! + + The Image Data (if RLE) + + This information only applies if the value for STORAGE above is 1. If + the image is stored using run length encoding, the image data follows + the offset tables above. The RLE data is not in any particular order. + The offset tables above are used to locate the rle data for any scanline. + + The RLE data must be read in from the file and expanded into pixel + data in the following manner: + + If BPC is 1, then there is one byte per pixel. In this case the + RLE data should be read into an array of chars. To expand + data, the low order seven bits of the first byte: bits[6..0] + are used to form a count. If the high order bit of the first + byte is 1: bit[7], then the count is used to specify how many + bytes to copy from the RLE data buffer to the destination. + Otherwise, if the high order bit of the first byte is 0: bit[7], + then the count is used to specify how many times to repeat the + value of the following byte, in the destination. This process + continues until a count of 0 is found. This should decompress + exactly XSIZE pixels. + + Here is example code to decompress a scanline: + + expandrow(optr,iptr,z) + unsigned char *optr, *iptr; + int z; + { + unsigned char pixel, count; + + optr += z; + while(1) { + pixel = *iptr++; + if ( !(count = (pixel & 0x7f)) ) + return; + if(pixel & 0x80) { + while(count--) { + *optr = *iptr++; + optr+=4; + } + } else { + pixel = *iptr++; + while(count--) { + *optr = pixel; + optr+=4; + } + } + } + } + + If BPC is 2, there is one short (2 bytes) per pixel. In this + case the RLE data should be read into an array of shorts. To + expand data, the low order seven bits of the first short: bits[6..0] + are used to form a count. If bit[7] of the first short is 1, then + the count is used to specify how many shorts to copy from the RLE + data buffer to the destination. Otherwise, if bit[7] of the first + short is 0, then the count is used to specify how many times to + repeat the value of the following short, in the destination. This + process proceeds until a count of 0 is found. This should decompress + exactly XSIZE pixels. Note that the byte order of short data in + the input file should be used, as described above. + + + Implementation notes + + Implementation of both RLE and VERBATIM format for images with + BPC of 1 is required since the great majority of SGI images are in + this format. Support for images with a 2 BPC is encouraged. + + If the ZSIZE of an image is 1, it is assumed to represent B/W + values. If the ZSIZE is 3, it is assumed to represent RGB data, + and if ZSIZE is 4, it is assumed to contain RGB data with alpha. + + The origin for all SGI images is the lower left hand corner. The + first scanline (row 0) is always the bottom row of the image. + + Naming Conventions + + On SGI systems, SGI image files end with the extension .bw if + they are B/W images, they end in .rgb if they contain RGB image + data, and end in .rgba if they are RGB images with alpha channel. + + Sometimes the .sgi extension is used as well. + + An example + +This program will write out a valid B/W SGI image file: + +#include "stdio.h" + +#define IXSIZE (23) +#define IYSIZE (15) + +putbyte(outf,val) +FILE *outf; +unsigned char val; +{ + unsigned char buf[1]; + + buf[0] = val; + fwrite(buf,1,1,outf); +} + +putshort(outf,val) +FILE *outf; +unsigned short val; +{ + unsigned char buf[2]; + + buf[0] = (val>>8); + buf[1] = (val>>0); + fwrite(buf,2,1,outf); +} + +static int putlong(outf,val) +FILE *outf; +unsigned long val; +{ + unsigned char buf[4]; + + buf[0] = (val>>24); + buf[1] = (val>>16); + buf[2] = (val>>8); + buf[3] = (val>>0); + return fwrite(buf,4,1,outf); +} + +main() +{ + FILE *of; + char iname[80]; + unsigned char outbuf[IXSIZE]; + int i, x, y; + + of = fopen("example.rgb","w"); + if(!of) { + fprintf(stderr,"sgiimage: can't open output file\n"); + exit(1); + } + putshort(of,474); /* MAGIC */ + putbyte(of,0); /* STORAGE is VERBATIM */ + putbyte(of,1); /* BPC is 1 */ + putshort(of,2); /* DIMENSION is 2 */ + putshort(of,IXSIZE); /* XSIZE */ + putshort(of,IYSIZE); /* YSIZE */ + putshort(of,1); /* ZSIZE */ + putlong(of,0); /* PIXMIN is 0 */ + putlong(of,255); /* PIXMAX is 255 */ + for(i=0; i<4; i++) /* DUMMY 4 bytes */ + putbyte(of,0); + strcpy(iname,"No Name"); + fwrite(iname,80,1,of); /* IMAGENAME */ + putlong(of,0); /* COLORMAP is 0 */ + for(i=0; i<404; i++) /* DUMMY 404 bytes */ + putbyte(of,0); + + for(y=0; ySGI Image File Format Specification + +
+

The SGI Image File Format

+

+Version 1.00 +

+Paul Haeberli
+Silicon Graphics Computer Systems
+paulhaeberli@yahoo.com
+

+

Introduction

+

+This is the definitive document describing the SGI image file format. This +is a low level spec that describes the actual byte level format of SGI image +files. On SGI machines the preferred way of reading and writing SGI image +files is to use the image library -limage. This library provides a set +of functions that make it easy to read and write SGI images. If you are +on an SGI workstation you can get info on -limage by doing: +

% man 4 rgb
+
+

A note on byte order of values in the SGI image files

+

+In the following description a notation like bits[7..0] is used to denote +a range of bits in a binary value. Bit 0 is the lowest order bit in +the value. +

+All short values are represented by 2 bytes. The first byte stores the +high order 8 bits of the value: bits[15..8]. The second byte stores +the low order 8 bits of the value: bits[7..0]. +

+So this function will read a short value from the file: +

    unsigned short getshort(inf)
+    FILE *inf;
+    {
+	unsigned char buf[2];
+
+	fread(buf,2,1,inf);
+	return (buf[0]<<8)+(buf[1]<<0);
+    }
+
+

+All long values are represented by 4 bytes. The first byte stores the +high order 8 bits of the value: bits[31..24]. The second byte stores +bits[23..16]. The third byte stores bits[15..8]. The forth byte stores +the low order 8 bits of the value: bits[7..0]. +

+And this function will read a long value from the file: +

    static long getlong(inf)
+    FILE *inf;
+    {
+	unsigned char buf[4];
+
+	fread(buf,4,1,inf);
+	return (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+(buf[3]<<0);
+    }
+
+ +

+

The general structure of an SGI image file

+ The header indicates whether the image is run length encoded (RLE). +

+ If the image is not run length encoded, this is the structure: +

+ The Header
+ The Image Data +
+ + If the image is run length encoded, this is the structure: +
+ The Header
+ The Offset Tables
+ The Image Data +
+ +

The Header

+

+The header consists of the following: +

        Size  | Type   | Name      | Description   
+ 
+      2 bytes | short  | MAGIC     | IRIS image file magic number
+      1 byte  | char   | STORAGE   | Storage format
+      1 byte  | char   | BPC       | Number of bytes per pixel channel 
+      2 bytes | ushort | DIMENSION | Number of dimensions
+      2 bytes | ushort | XSIZE     | X size in pixels 
+      2 bytes | ushort | YSIZE     | Y size in pixels 
+      2 bytes | ushort | ZSIZE     | Number of channels
+      4 bytes | long   | PIXMIN    | Minimum pixel value
+      4 bytes | long   | PIXMAX    | Maximum pixel value
+      4 bytes | char   | DUMMY     | Ignored
+     80 bytes | char   | IMAGENAME | Image name
+      4 bytes | long   | COLORMAP  | Colormap ID
+    404 bytes | char   | DUMMY     | Ignored
+
+
+

+Here is a description of each field in the image file header: +

+ MAGIC - This is the decimal value 474 saved as a short. This + identifies the file as an SGI image file. +

+ STORAGE - specifies whether the image is stored using run + length encoding (RLE) or not (VERBATIM). If RLE is used, the value + of this byte will be 1. Otherwise the value of this byte will be 0. + The only allowed values for this field are 0 or 1. +

+ BPC - describes the precision that is used to store each + channel of an image. This is the number of bytes per pixel + component. The majority of SGI image files use 1 byte per + pixel component, giving 256 levels. Some SGI image files use + 2 bytes per component. The only allowed values for this field + are 1 or 2. + +

+ DIMENSION - described the number of dimensions in the data stored + in the image file. The only allowed values are 1, 2, or 3. If + this value is 1, the image file consists of only 1 channel and + only 1 scanline (row). The length of this scanline is given by the + value of XSIZE below. If this value is 2, the file consists of a + single channel with a number of scanlines. The width and height + of the image are given by the values of XSIZE and YSIZE below. + If this value is 3, the file consists of a number of channels. + The width and height of the image are given by the values of + XSIZE and YSIZE below. The number of channels is given by the + value of ZSIZE below. +

+ XSIZE - The width of the image in pixels +

+ + YSIZE - The height of the image in pixels +

+ + ZSIZE - The number of channels in the image. B/W (greyscale) images + are stored as 2 dimensional images with a ZSIZE or 1. RGB color + images are stored as 3 dimensional images with a ZSIZE of 3. An RGB + image with an ALPHA channel is stored as a 3 dimensional image with + a ZSIZE of 4. There are no inherent limitations in the SGI image + file format that would preclude the creation of image files with more + than 4 channels. + +

+ PINMIN - The minimum pixel value in the image. The value of + 0 may be used if no pixel has a value that is smaller than 0. +

+ + PINMAX - The maximum pixel value in the image. The value of + 255 may be used if no pixel has a value that is greater than 255. + This is the value that is considered to be full brightness in + the image. + +

+ DUMMY - This 4 bytes of data should be set to 0. +

+ + IMAGENAME - An null terminated ascii string of up to 79 characters + terminated by a null may be included here. This is not commonly + used. + +

+ COLORMAP - This controls how the pixel values in the file should be + interpreted. It can have one of these four values: + +

+ 0: NORMAL - The data in the channels represent B/W values + for images with 1 channel, RGB values for images with 3 + channels, and RGBA values for images with 4 channels. + Almost all the SGI image files are of this type. + +

+ 1: DITHERED - The image will have only 1 channel of data. + For each pixel, RGB data is packed into one 8 bit value. + 3 bits are used for red and green, while blue uses 2 bits. + Red data is found in bits[2..0], green data in bits[5..3], + and blue data in bits[7..6]. This format is obsolete. + +

+ 2: SCREEN - The image will have only 1 channel of data. + This format was used to store color-indexed pixels. + To convert the pixel values into RGB values a colormap + must be used. The appropriate color map varies from + image to image. This format is obsolete. + +

+ 3: COLORMAP - The image is used to store a color map from + an SGI machine. In this case the image is not displayable + in the conventional sense. + +

+ DUMMY - This 404 bytes of data should be set to 0. This makes the + header exactly 512 bytes. +

+ +

+

The Image Data (if not RLE)

+

+ If the image is stored verbatim (without RLE), then image data directly + follows the 512 byte header. The data for each scanline of the first + channel is written first. If the image has more than 1 channel, all + the data for the first channel is written, followed by the remaining + channels. If the BPC value is 1, then each scanline is written as XSIZE + bytes. If the BPC value is 2, then each scanline is written as XSIZE + shorts. These shorts are stored in the byte order described above. +

+

The Offset Tables (if RLE)

+

+ If the image is stored using run length encoding, offset tables + follow the header that describe what the file offsets are to the + RLE for each scanline. This information only applies if the value + for STORAGE above is 1. +

         Size  | Type   | Name      | Description   
+
+  tablen longs | long   | STARTTAB  | Start table
+  tablen longs | long   | LENGTHTAB | Length table
+
+

+ One entry in each table is needed for each scanline of RLE data. The + total number of scanlines in the image (tablen) is determined by the + product of the YSIZE and ZSIZE. There are two tables of longs that + are written. Each consists of tablen longs of data. The first + table has the file offsets to the RLE data for each scanline in the + image. In a file with more than 1 channel (ZSIZE > 1) this table first + has all the offsets for the scanlines in the first channel, followed + be offsets for the scanlines in the second channel, etc. The second + table has the RLE data length for each scanline in the image. In a + file with more than 1 channel (ZSIZE > 1) this table first has all the + RLE data lengths for the scanlines in the first channel, followed + be RLE data lengths for the scanlines in the second channel, etc. + +

+ To find the the file offset, and the number of bytes in the RLE data + for a particular scanline, these two arrays may be read in and indexed as + follows: + +

+ To read in the tables: +

    unsigned long *starttab, *lengthtab;
+
+    tablen = YSIZE*ZSIZE*sizeof(long);
+    starttab = (unsigned long *)mymalloc(tablen);
+    lengthtab = (unsigned long *)mymalloc(tablen);
+    fseek(inf,512,SEEK_SET);
+    readlongtab(inf,starttab);
+    readlongtab(ing,lengthtab);
+
+ +

+ To find the file offset and RLE data length for a scanline: +

+ rowno is an integer in the range 0 to YSIZE-1 + channo is an integer in the range 0 to ZSIZE-1 +

    rleoffset = starttab[rowno+channo*YSIZE]
+    rlelength = lengthtab[rowno+channo*YSIZE]
+
+

+ It is possible for two identical rows (scanlines) to share compressed + data. A completely white image could be written as a single compressed + row and having all table entries point to that row. Another little hack + that should work is if you are writing out a RGB RLE file, and a + particular scanline is achromatic (greyscale), you could just make the + r, g and b rows point to the same data!! +

The Image Data (if RLE)

+

+ This information only applies if the value for STORAGE above is 1. If + the image is stored using run length encoding, the image data follows + the offset tables above. The RLE data is not in any particular order. + The offset tables above are used to locate the rle data for any scanline. +

+ The RLE data must be read in from the file and expanded into pixel + data in the following manner: +

+ If BPC is 1, then there is one byte per pixel. In this case the + RLE data should be read into an array of chars. To expand + data, the low order seven bits of the first byte: bits[6..0] + are used to form a count. If the high order bit of the first + byte is 1: bit[7], then the count is used to specify how many + bytes to copy from the RLE data buffer to the destination. + Otherwise, if the high order bit of the first byte is 0: bit[7], + then the count is used to specify how many times to repeat the + value of the following byte, in the destination. This process + continues until a count of 0 is found. This should decompress + exactly XSIZE pixels. +

+ Here is example code to decompress a scanline: +

    expandrow(optr,iptr,z)
+    unsigned char *optr, *iptr;
+    int z;
+    {
+	unsigned char pixel, count;
+    
+	optr += z;
+	while(1) {
+	    pixel = *iptr++;
+	    if ( !(count = (pixel & 0x7f)) )
+		return;
+	    if(pixel & 0x80) {
+		while(count--) 
+		    *optr++ = *iptr++;
+	    } else {
+		pixel = *iptr++;
+		while(count--) 
+		    *optr++ = pixel;
+	    }
+	}
+    }
+
+

+ If BPC is 2, there is one short (2 bytes) per pixel. In this + case the RLE data should be read into an array of shorts. To + expand data, the low order seven bits of the first short: bits[6..0] + are used to form a count. If bit[7] of the first short is 1, then + the count is used to specify how many shorts to copy from the RLE + data buffer to the destination. Otherwise, if bit[7] of the first + short is 0, then the count is used to specify how many times to + repeat the value of the following short, in the destination. This + process proceeds until a count of 0 is found. This should decompress + exactly XSIZE pixels. Note that the byte order of short data in + the input file should be used, as described above. +

Implementation notes

+

+ Implementation of both RLE and VERBATIM format for images with + BPC of 1 is required since the great majority of SGI images are in + this format. Support for images with a 2 BPC is encouraged. +

+ If the ZSIZE of an image is 1, it is assumed to represent B/W + values. If the ZSIZE is 3, it is assumed to represent RGB data, + and if ZSIZE is 4, it is assumed to contain RGB data with alpha. +

+ The origin for all SGI images is the lower left hand corner. The + first scanline (row 0) is always the bottom row of the image. +

Naming Conventions

+

+ On SGI systems, SGI image files end with the extension .bw if + they are B/W images, they end in .rgb if they contain RGB image + data, and end in .rgba if they are RGB images with alpha channel. +

+ Sometimes the .sgi extension is used as well. +

An example

+

+This program will write out a valid B/W SGI image file: +

    #include "stdio.h"
+     
+    #define IXSIZE      (23)
+    #define IYSIZE      (15)
+     
+    putbyte(outf,val)
+    FILE *outf;
+    unsigned char val;
+    {
+	unsigned char buf[1];
+     
+	buf[0] = val;
+	fwrite(buf,1,1,outf);
+    }
+     
+    putshort(outf,val)
+    FILE *outf;
+    unsigned short val;
+    {
+	unsigned char buf[2];
+     
+	buf[0] = (val>>8);
+	buf[1] = (val>>0);
+	fwrite(buf,2,1,outf);
+    }
+     
+    static int putlong(outf,val)
+    FILE *outf;
+    unsigned long val;
+    {
+	unsigned char buf[4];
+     
+	buf[0] = (val>>24);
+	buf[1] = (val>>16);
+	buf[2] = (val>>8);
+	buf[3] = (val>>0);
+	return fwrite(buf,4,1,outf);
+    }
+     
+    main()
+    {
+	FILE *of;
+	char iname[80];
+	unsigned char outbuf[IXSIZE];
+	int i, x, y;
+     
+	of = fopen("example.rgb","w");
+	if(!of) {
+	    fprintf(stderr,"sgiimage: can't open output file\n");
+	    exit(1);
+	}
+	putshort(of,474);       /* MAGIC               */
+	putbyte(of,0);          /* STORAGE is VERBATIM */
+	putbyte(of,1);          /* BPC is 1            */
+	putshort(of,2);         /* DIMENSION is 2      */
+	putshort(of,IXSIZE);    /* XSIZE               */
+	putshort(of,IYSIZE);    /* YSIZE               */
+	putshort(of,1);         /* ZSIZE               */
+	putlong(of,0);          /* PIXMIN is 0         */
+	putlong(of,255);        /* PIXMAX is 255       */
+	for(i=0; i<4; i++)      /* DUMMY 4 bytes       */
+	    putbyte(of,0);
+	strcpy(iname,"No Name");
+	fwrite(iname,80,1,of);  /* IMAGENAME           */
+	putlong(of,0);          /* COLORMAP is 0       */
+	for(i=0; i<404; i++)    /* DUMMY 404 bytes     */
+	    putbyte(of,0);
+     
+	for(y=0; y<IYSIZE; y++) {
+	    for(x=0; x<IXSIZE; x++) 
+            outbuf[x] = (255*x)/(IXSIZE-1);
+	    fwrite(outbuf,IXSIZE,1,of);
+	}
+	fclose(of);
+    }
+
+ + \ No newline at end of file -- 2.39.5