Add facility to read frames in RGB & RGBA format
[imageviewer.git] / rawIOsgi.cpp
blob1a36f8987746197a240dd832ff230b6144b2ce54
1 /* ***** BEGIN LICENSE BLOCK *****
3 * $Id$
5 * The MIT License
7 * Copyright (c) 2008 BBC Research
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
27 * ***** END LICENSE BLOCK ***** */
29 //SGI file format header
30 // 2 bytes | short | MAGIC | IRIS image file magic number
31 // 1 byte | char | STORAGE | Storage format, 0=VERBATIM, 1=RLE
32 // 1 byte | char | BPC | Number of bytes per pixel channel
33 // 2 bytes | ushort | DIMENSION | Number of dimensions, 1=1 line of XSIZE; 2=1 plane of XSIZE*YSIZE (greyscale image); 3=ZSIZE planes of XSIZE*YSIZE (RGB image)
34 // 2 bytes | ushort | XSIZE | X size in pixels
35 // 2 bytes | ushort | YSIZE | Y size in pixels
36 // 2 bytes | ushort | ZSIZE | Number of channels
37 // 4 bytes | long | PIXMIN | Minimum pixel value
38 // 4 bytes | long | PIXMAX | Maximum pixel value
39 // 4 bytes | char | DUMMY | Ignored
40 // 80 bytes | char | IMAGENAME | Image name
41 // 4 bytes | long | COLORMAP | Colormap ID
42 // 404 bytes | char | DUMMY | Ignored
45 #define DEBUG 0
47 #include <assert.h>
49 #include "rawIOsgi.h"
51 //read a 16 bit value, endian safe
52 inline unsigned short getshort(FILE *inf)
54 unsigned char buf[2];
56 fread(buf, 2, 1, inf);
57 return (buf[0]<<8)+(buf[1]<<0);
60 //read a 32 bit value, endian safe
61 inline long getlong(FILE *inf)
63 unsigned char buf[4];
65 fread(buf, 4, 1, inf);
66 return (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+(buf[3]<<0);
69 void RawReadersgi::readHeader()
71 _magic = getshort(infile);
73 //bail out if this does not look like an SGI file
74 if (_magic != 474)
75 return;
77 fread(&_storage, 1, 1, infile);
78 fread(&_bpc, 1, 1, infile);
79 _dimension = getshort(infile);
80 _width = getshort(infile);
81 _height = getshort(infile);
82 _zsize = getshort(infile);
83 _pixmin = getlong(infile);
84 _pixmax = getlong(infile);
85 fseek(infile, 4, SEEK_CUR); //skip dummy 4 bytes
86 fread(&_name, 80, 1, infile); //80 bytes name
87 _name[80]='\0'; //force string termination
88 _colormap = getlong(infile);
89 fseek(infile, 404, SEEK_CUR); //skip dummy 404 bytes
91 //set depth to 8 or 16 bits
92 _depth=8;
93 if (_bpc==2)
94 _depth=16;
96 //we are now 512 bytes into the file, which is the end of the header
97 if (DEBUG) {
98 printf("MAGIC = %d\n", _magic);
99 printf("STORAGE = %d\n", _storage);
100 printf("BPC = %d\n", _bpc);
101 printf("DIMENSIONS = %d\n", _dimension);
102 printf("XSIZE = %d\n", _width);
103 printf("YSIZE = %d\n", _height);
104 printf("ZSIZE = %d\n", _zsize);
105 printf("PIXMIN = %ld\n", _pixmin);
106 printf("PIXMAX = %ld\n", _pixmax);
107 printf("NAME = %s\n", _name);
108 printf("COLORMAP = %ld\n", _colormap);
112 void RawReadersgi::read_plane(Array2d<int> &p, int ysize)
114 size_t linesRead;
115 //note that the scan lines are stored in reverse order, bottom to top of frame
118 switch (_bpc) {
119 case 1:
121 //8 bits per channel
122 unsigned char *inLine = new unsigned char[p.width()];
124 for (int y=ysize-1; y>=0; y--) {
125 linesRead = fread(inLine, p.width(), 1, infile);
127 for (int x = 0; x < p.width(); x++)
128 p[y][x] = inLine[x];
130 if (linesRead < 1)
131 goto exit;
134 break;
136 case 2:
138 //16 bits per channel
139 unsigned char *inLine = new unsigned char[p.width()*2];
140 unsigned char *ptr;
141 for (int y=ysize-1; y>=0; y--) {
143 linesRead = fread(inLine, p.width()*2, 1, infile);
144 ptr = inLine;
145 for (int x = 0; x < p.width(); x++, ptr+=2)
146 p[y][x] = (ptr[0] << 8) | ptr[1];
148 if (linesRead < 1)
149 goto exit;
152 break;
154 default:
155 break;
156 //undefined bpc
159 exit: ;
163 RawFrame& RawReadersgi::read(RawFrame &f)
165 assert(f.chroma == RawFrame::CrRGB);
167 //we don't deal with run length coded files yet
168 if (_storage != 0)
169 return f;
171 switch (_dimension) {
172 case 1:
173 //there is one row of XSIZE pixels
174 read_plane(f.r, 1);
175 break;
177 case 2:
178 //there is one plane of XSIZE * YSIZE
179 read_plane(f.r, _height);
180 break;
182 case 3:
183 //there are ZSIZE planes of XSIZE * YSIZE
184 if (_zsize == 1) {
185 //greyscale
186 read_plane(f.r, _height);
187 f.g = f.r; //copy red plane to blue and green to get greyscale. Inefficient, but works
188 f.b = f.r;
191 if (_zsize == 3 || _zsize == 4) {
192 //RGB or RGBA
193 read_plane(f.r, _height);
194 read_plane(f.g, _height);
195 read_plane(f.b, _height);
197 break;
200 return f;
203 RawFrame& RawReadersgi::read()
205 throw;