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