Commit | Line | Data |
---|---|---|
458ef9b3 TC |
1 | |
2 | For Version 1.00 of this spec see: | |
3 | ||
4 | http://reality.sgi.com/grafica/sgiimage.html | |
5 | ||
6 | ||
7 | ||
8 | ||
9 | Draft version 0.97 | |
10 | ||
11 | The SGI Image File Format | |
12 | ||
13 | Paul Haeberli | |
14 | ||
15 | paul@sgi.com | |
16 | ||
17 | Silicon Graphics Computer Systems | |
18 | ||
19 | ||
20 | ||
21 | This is the definitive document describing the SGI image file format. This | |
22 | is a low level spec that describes the actual byte level format of SGI image | |
23 | files. On SGI machines the preferred way of reading and writing SGI image | |
24 | files is to use the image library -limage. This library provides a set | |
25 | of functions that make it easy to read and write SGI images. If you are | |
26 | on an SGI workstation you can get info on -limage by doing: | |
27 | ||
28 | % man 4 rgb | |
29 | ||
30 | A note on byte order of values in the SGI image files | |
31 | ||
32 | In the following description a notation like bits[7..0] is used to denote | |
33 | a range of bits in a binary value. Bit 0 is the lowest order bit in | |
34 | the value. | |
35 | ||
36 | All short values are represented by 2 bytes. The first byte stores the | |
37 | high order 8 bits of the value: bits[15..8]. The second byte stores | |
38 | the low order 8 bits of the value: bits[7..0]. | |
39 | ||
40 | So, this function will read a short value from the file: | |
41 | ||
42 | unsigned short getshort(inf) | |
43 | FILE *inf; | |
44 | { | |
45 | unsigned char buf[2]; | |
46 | ||
47 | fread(buf,2,1,inf); | |
48 | return (buf[0]<<8)+(buf[1]<<0); | |
49 | } | |
50 | ||
51 | All long values are represented by 4 bytes. The first byte stores the | |
52 | high order 8 bits of the value: bits[31..24]. The second byte stores | |
53 | bits[23..16]. The third byte stores bits[15..8]. The forth byte stores | |
54 | the low order 8 bits of the value: bits[7..0]. | |
55 | ||
56 | So, this function will read a long value from the file: | |
57 | ||
58 | static long getlong(inf) | |
59 | FILE *inf; | |
60 | { | |
61 | unsigned char buf[4]; | |
62 | ||
63 | fread(buf,4,1,inf); | |
64 | return (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+(buf[3]<<0); | |
65 | } | |
66 | ||
67 | ||
68 | The general structure of an SGI image file is as shown below: | |
69 | ||
70 | The header indicates whether the image is run length encoded (RLE). | |
71 | ||
72 | If the image is not run length encoded, this is the structure: | |
73 | ||
74 | The Header | |
75 | The Image Data | |
76 | ||
77 | If the image is run length encoded, this is the structure: | |
78 | ||
79 | The Header | |
80 | The Offset Tables | |
81 | The Image Data | |
82 | ||
83 | ||
84 | The Header | |
85 | ||
86 | The header consists of the following: | |
87 | ||
88 | Size | Type | Name | Description | |
89 | ||
90 | 2 bytes | short | MAGIC | IRIS image file magic number | |
91 | 1 byte | char | STORAGE | Storage format | |
92 | 1 byte | char | BPC | Number of bytes per pixel channel | |
93 | 2 bytes | ushort | DIMENSION | Number of dimensions | |
94 | 2 bytes | ushort | XSIZE | X size in pixels | |
95 | 2 bytes | ushort | YSIZE | Y size in pixels | |
96 | 2 bytes | ushort | ZSIZE | Number of channels | |
97 | 4 bytes | long | PIXMIN | Minimum pixel value | |
98 | 4 bytes | long | PIXMAX | Maximum pixel value | |
99 | 4 bytes | char | DUMMY | Ignored | |
100 | 80 bytes | char | IMAGENAME | Image name | |
101 | 4 bytes | long | COLORMAP | Colormap ID | |
102 | 404 bytes | char | DUMMY | Ignored | |
103 | ||
104 | ||
105 | Here is a description of each field in the image file header: | |
106 | ||
107 | MAGIC - This is the decimal value 474 saved as a short. This | |
108 | identifies the file as an SGI image file. | |
109 | ||
110 | STORAGE - specifies whether the image is stored using run | |
111 | length encoding (RLE) or not (VERBATIM). If RLE is used, the value | |
112 | of this byte will be 1. Otherwise the value of this byte will be 0. | |
113 | The only allowed values for this field are 0 or 1. | |
114 | ||
115 | BPC - describes the precision that is used to store each | |
116 | channel of an image. This is the number of bytes per pixel | |
117 | component. The majority of SGI image files use 1 byte per | |
118 | pixel component, giving 256 levels. Some SGI image files use | |
119 | 2 bytes per component. The only allowed values for this field | |
120 | are 1 or 2. | |
121 | ||
122 | DIMENSION - described the number of dimensions in the data stored | |
123 | in the image file. The only allowed values are 1, 2, or 3. If | |
124 | this value is 1, the image file consists of only 1 channel and | |
125 | only 1 scanline (row). The length of this scanline is given by the | |
126 | value of XSIZE below. If this value is 2, the file consists of a | |
127 | single channel with a number of scanlines. The width and height | |
128 | of the image are given by the values of XSIZE and YSIZE below. | |
129 | If this value is 3, the file consists of a number of channels. | |
130 | The width and height of the image are given by the values of | |
131 | XSIZE and YSIZE below. The number of channels is given by the | |
132 | value of ZSIZE below. | |
133 | ||
134 | XSIZE - The width of the image in pixels | |
135 | ||
136 | YSIZE - The height of the image in pixels | |
137 | ||
138 | ZSIZE - The number of channels in the image. B/W (greyscale) images | |
139 | are stored as 2 dimensional images with a ZSIZE or 1. RGB color | |
140 | images are stored as 3 dimensional images with a ZSIZE of 3. An RGB | |
141 | image with an ALPHA channel is stored as a 3 dimensional image with | |
142 | a ZSIZE of 4. There are no inherent limitations in the SGI image | |
143 | file format that would preclude the creation of image files with more | |
144 | than 4 channels. | |
145 | ||
146 | PINMIN - The minimum pixel value in the image. The value of | |
147 | 0 may be used if no pixel has a value that is smaller than 0. | |
148 | ||
149 | PINMAX - The maximum pixel value in the image. The value of | |
150 | 255 may be used if no pixel has a value that is greater than 255. | |
151 | This is the value that is considered to be full brightness in | |
152 | the image. | |
153 | ||
154 | DUMMY - This 4 bytes of data should be set to 0. | |
155 | ||
156 | IMAGENAME - An null terminated ascii string of up to 79 characters | |
157 | terminated by a null may be included here. This is not commonly | |
158 | used. | |
159 | ||
160 | COLORMAP - This controls how the pixel values in the file should be | |
161 | interpreted. It can have one of these four values: | |
162 | ||
163 | 0: NORMAL - The data in the channels represent B/W values | |
164 | for images with 1 channel, RGB values for images with 3 | |
165 | channels, and RGBA values for images with 4 channels. | |
166 | Almost all the SGI image files are of this type. | |
167 | ||
168 | 1: DITHERED - The image will have only 1 channel of data. | |
169 | For each pixel, RGB data is packed into one 8 bit value. | |
170 | 3 bits are used for red and green, while blue uses 2 bits. | |
171 | Red data is found in bits[2..0], green data in bits[5..3], | |
172 | and blue data in bits[7..6]. This format is obsolete. | |
173 | ||
174 | 2: SCREEN - The image will have only 1 channel of data. | |
175 | This format was used to store color-indexed pixels. | |
176 | To convert the pixel values into RGB values a colormap | |
177 | must be used. The appropriate color map varies from | |
178 | image to image. This format is obsolete. | |
179 | ||
180 | 3: COLORMAP - The image is used to store a color map from | |
181 | an SGI machine. In this case the image is not displayable | |
182 | in the conventional sense. | |
183 | ||
184 | DUMMY - This 404 bytes of data should be set to 0. This makes the | |
185 | header exactly 512 bytes. | |
186 | ||
187 | ||
188 | The Image Data (if not RLE) | |
189 | ||
190 | If the image is stored verbatim (without RLE), then image data directly | |
191 | follows the 512 byte header. The data for each scanline of the first | |
192 | channel is written first. If the image has more than 1 channel, all | |
193 | the data for the first channel is written, followed by the remaining | |
194 | channels. If the BPC value is 1, then each scanline is written as XSIZE | |
195 | bytes. If the BPC value is 2, then each scanline is written as XSIZE | |
196 | shorts. These shorts are stored in the byte order described above. | |
197 | ||
198 | ||
199 | The Offset Tables (if RLE) | |
200 | ||
201 | If the image is stored using run length encoding, offset tables | |
202 | follow the header that describe what the file offsets are to the | |
203 | RLE for each scanline. This information only applies if the value | |
204 | for STORAGE above is 1. | |
205 | ||
206 | Size | Type | Name | Description | |
207 | ||
208 | tablen longs | long | STARTTAB | Start table | |
209 | tablen longs | long | LENGTHTAB | Length table | |
210 | ||
211 | One entry in each table is needed for each scanline of RLE data. The | |
212 | total number of scanlines in the image (tablen) is determined by the | |
213 | product of the YSIZE and ZSIZE. There are two tables of longs that | |
214 | are written. Each consists of tablen longs of data. The first | |
215 | table has the file offsets to the RLE data for each scanline in the | |
216 | image. In a file with more than 1 channel (ZSIZE > 1) this table first | |
217 | has all the offsets for the scanlines in the first channel, followed | |
218 | be offsets for the scanlines in the second channel, etc. The second | |
219 | table has the RLE data length for each scanline in the image. In a | |
220 | file with more than 1 channel (ZSIZE > 1) this table first has all the | |
221 | RLE data lengths for the scanlines in the first channel, followed | |
222 | be RLE data lengths for the scanlines in the second channel, etc. | |
223 | ||
224 | To find the the file offset, and the number of bytes in the RLE data | |
225 | for a particular scanline, these two arrays may be read in and indexed as | |
226 | follows: | |
227 | ||
228 | To read in the tables: | |
229 | ||
230 | unsigned long *starttab, *lengthtab; | |
231 | ||
232 | tablen = YSIZE*ZSIZE*sizeof(long); | |
233 | starttab = (unsigned long *)mymalloc(tablen); | |
234 | lengthtab = (unsigned long *)mymalloc(tablen); | |
235 | fseek(inf,512,SEEK_SET); | |
236 | readlongtab(inf,starttab); | |
237 | readlongtab(ing,lengthtab); | |
238 | ||
239 | ||
240 | To find the file offset and RLE data length for a scanline: | |
241 | ||
242 | rowno is an integer in the range 0 to YSIZE-1 | |
243 | channo is an integer in the range 0 to ZSIZE-1 | |
244 | ||
245 | rleoffset = starttab[rowno+channo*YSIZE] | |
246 | rlelength = lengthtab[rowno+channo*YSIZE] | |
247 | ||
248 | It is possible for two identical rows (scanlines) to share compressed | |
249 | data. A completely white image could be written as a single compressed | |
250 | row and having all table entries point to that row. Another little hack | |
251 | that should work is if you are writing out a RGB RLE file, and a | |
252 | particular scanline is achromatic (greyscale), you could just make the | |
253 | r, g and b rows point to the same data!! | |
254 | ||
255 | The Image Data (if RLE) | |
256 | ||
257 | This information only applies if the value for STORAGE above is 1. If | |
258 | the image is stored using run length encoding, the image data follows | |
259 | the offset tables above. The RLE data is not in any particular order. | |
260 | The offset tables above are used to locate the rle data for any scanline. | |
261 | ||
262 | The RLE data must be read in from the file and expanded into pixel | |
263 | data in the following manner: | |
264 | ||
265 | If BPC is 1, then there is one byte per pixel. In this case the | |
266 | RLE data should be read into an array of chars. To expand | |
267 | data, the low order seven bits of the first byte: bits[6..0] | |
268 | are used to form a count. If the high order bit of the first | |
269 | byte is 1: bit[7], then the count is used to specify how many | |
270 | bytes to copy from the RLE data buffer to the destination. | |
271 | Otherwise, if the high order bit of the first byte is 0: bit[7], | |
272 | then the count is used to specify how many times to repeat the | |
273 | value of the following byte, in the destination. This process | |
274 | continues until a count of 0 is found. This should decompress | |
275 | exactly XSIZE pixels. | |
276 | ||
277 | Here is example code to decompress a scanline: | |
278 | ||
279 | expandrow(optr,iptr,z) | |
280 | unsigned char *optr, *iptr; | |
281 | int z; | |
282 | { | |
283 | unsigned char pixel, count; | |
284 | ||
285 | optr += z; | |
286 | while(1) { | |
287 | pixel = *iptr++; | |
288 | if ( !(count = (pixel & 0x7f)) ) | |
289 | return; | |
290 | if(pixel & 0x80) { | |
291 | while(count--) { | |
292 | *optr = *iptr++; | |
293 | optr+=4; | |
294 | } | |
295 | } else { | |
296 | pixel = *iptr++; | |
297 | while(count--) { | |
298 | *optr = pixel; | |
299 | optr+=4; | |
300 | } | |
301 | } | |
302 | } | |
303 | } | |
304 | ||
305 | If BPC is 2, there is one short (2 bytes) per pixel. In this | |
306 | case the RLE data should be read into an array of shorts. To | |
307 | expand data, the low order seven bits of the first short: bits[6..0] | |
308 | are used to form a count. If bit[7] of the first short is 1, then | |
309 | the count is used to specify how many shorts to copy from the RLE | |
310 | data buffer to the destination. Otherwise, if bit[7] of the first | |
311 | short is 0, then the count is used to specify how many times to | |
312 | repeat the value of the following short, in the destination. This | |
313 | process proceeds until a count of 0 is found. This should decompress | |
314 | exactly XSIZE pixels. Note that the byte order of short data in | |
315 | the input file should be used, as described above. | |
316 | ||
317 | ||
318 | Implementation notes | |
319 | ||
320 | Implementation of both RLE and VERBATIM format for images with | |
321 | BPC of 1 is required since the great majority of SGI images are in | |
322 | this format. Support for images with a 2 BPC is encouraged. | |
323 | ||
324 | If the ZSIZE of an image is 1, it is assumed to represent B/W | |
325 | values. If the ZSIZE is 3, it is assumed to represent RGB data, | |
326 | and if ZSIZE is 4, it is assumed to contain RGB data with alpha. | |
327 | ||
328 | The origin for all SGI images is the lower left hand corner. The | |
329 | first scanline (row 0) is always the bottom row of the image. | |
330 | ||
331 | Naming Conventions | |
332 | ||
333 | On SGI systems, SGI image files end with the extension .bw if | |
334 | they are B/W images, they end in .rgb if they contain RGB image | |
335 | data, and end in .rgba if they are RGB images with alpha channel. | |
336 | ||
337 | Sometimes the .sgi extension is used as well. | |
338 | ||
339 | An example | |
340 | ||
341 | This program will write out a valid B/W SGI image file: | |
342 | ||
343 | #include "stdio.h" | |
344 | ||
345 | #define IXSIZE (23) | |
346 | #define IYSIZE (15) | |
347 | ||
348 | putbyte(outf,val) | |
349 | FILE *outf; | |
350 | unsigned char val; | |
351 | { | |
352 | unsigned char buf[1]; | |
353 | ||
354 | buf[0] = val; | |
355 | fwrite(buf,1,1,outf); | |
356 | } | |
357 | ||
358 | putshort(outf,val) | |
359 | FILE *outf; | |
360 | unsigned short val; | |
361 | { | |
362 | unsigned char buf[2]; | |
363 | ||
364 | buf[0] = (val>>8); | |
365 | buf[1] = (val>>0); | |
366 | fwrite(buf,2,1,outf); | |
367 | } | |
368 | ||
369 | static int putlong(outf,val) | |
370 | FILE *outf; | |
371 | unsigned long val; | |
372 | { | |
373 | unsigned char buf[4]; | |
374 | ||
375 | buf[0] = (val>>24); | |
376 | buf[1] = (val>>16); | |
377 | buf[2] = (val>>8); | |
378 | buf[3] = (val>>0); | |
379 | return fwrite(buf,4,1,outf); | |
380 | } | |
381 | ||
382 | main() | |
383 | { | |
384 | FILE *of; | |
385 | char iname[80]; | |
386 | unsigned char outbuf[IXSIZE]; | |
387 | int i, x, y; | |
388 | ||
389 | of = fopen("example.rgb","w"); | |
390 | if(!of) { | |
391 | fprintf(stderr,"sgiimage: can't open output file\n"); | |
392 | exit(1); | |
393 | } | |
394 | putshort(of,474); /* MAGIC */ | |
395 | putbyte(of,0); /* STORAGE is VERBATIM */ | |
396 | putbyte(of,1); /* BPC is 1 */ | |
397 | putshort(of,2); /* DIMENSION is 2 */ | |
398 | putshort(of,IXSIZE); /* XSIZE */ | |
399 | putshort(of,IYSIZE); /* YSIZE */ | |
400 | putshort(of,1); /* ZSIZE */ | |
401 | putlong(of,0); /* PIXMIN is 0 */ | |
402 | putlong(of,255); /* PIXMAX is 255 */ | |
403 | for(i=0; i<4; i++) /* DUMMY 4 bytes */ | |
404 | putbyte(of,0); | |
405 | strcpy(iname,"No Name"); | |
406 | fwrite(iname,80,1,of); /* IMAGENAME */ | |
407 | putlong(of,0); /* COLORMAP is 0 */ | |
408 | for(i=0; i<404; i++) /* DUMMY 404 bytes */ | |
409 | putbyte(of,0); | |
410 | ||
411 | for(y=0; y<IYSIZE; y++) { | |
412 | for(x=0; x<IXSIZE; x++) | |
413 | outbuf[x] = (255*x)/(IXSIZE-1); | |
414 | fwrite(outbuf,IXSIZE,1,of); | |
415 | } | |
416 | fclose(of); | |
417 | } |