]> git.imager.perl.org - imager.git/blame - rgb.c
avoid most compilter warnings produced by GCC 4.1
[imager.git] / rgb.c
CommitLineData
92bda632 1#include "imager.h"
5ff415bb
AMH
2#include "log.h"
3#include "iolayer.h"
4
5#include <stdlib.h>
6#include <errno.h>
7
8
9/*
10=head1 NAME
11
12rgb.c - implements reading and writing sgi image files, uses io layer.
13
14=head1 SYNOPSIS
15
16 io_glue *ig = io_new_fd( fd );
17 i_img *im = i_readrgb_wiol(ig, -1); // no limit on how much is read
18 // or
19 io_glue *ig = io_new_fd( fd );
20 return_code = i_writergb_wiol(im, ig);
21
22=head1 DESCRIPTION
23
24rgb.c implements the basic functions to read and write portable targa
25files. It uses the iolayer and needs either a seekable source or an
26entire memory mapped buffer.
27
28=head1 FUNCTION REFERENCE
29
30Some of these functions are internal.
31
32=over
33
34=cut
35*/
36
37typedef struct {
38 unsigned short imagic;
39 unsigned char storagetype;
40 unsigned char BPC;
41 unsigned short dimensions;
42 unsigned short xsize, ysize, zsize;
43 unsigned int min, max;
44 char name[80];
45 unsigned int colormap;
46} rgb_header;
47
da1c841c
AMH
48typedef struct {
49 int start, length;
50} stlen_pair;
5ff415bb
AMH
51
52typedef enum { NoInit, Raw, Rle } rle_state;
53
5ff415bb
AMH
54
55
56typedef struct {
57 int compressed;
58 int bytepp;
59 io_glue *ig;
60} rgb_dest;
61
62
63
64
5ff415bb
AMH
65
66
67/*
68=item rgb_header_unpack(header, headbuf)
69
70Unpacks the header structure into from buffer and stores
71in the header structure.
72
73 header - header structure
74 headbuf - buffer to unpack from
75
76=cut
77*/
78
79
80static
81void
82rgb_header_unpack(rgb_header *header, unsigned char *headbuf) {
83 header->imagic = (headbuf[0]<<8) + headbuf[1];
84 header->storagetype = headbuf[2];
85 header->BPC = headbuf[3];
86 header->dimensions = (headbuf[4]<<8) + headbuf[5];
87 header->xsize = (headbuf[6]<<8) + headbuf[7];
88 header->ysize = (headbuf[8]<<8) + headbuf[9];
89 header->zsize = (headbuf[10]<<8) + headbuf[11];
90 header->min = (headbuf[12]<<24) + (headbuf[13]<<16)+(headbuf[14]<<8)+headbuf[15];
91 header->max = (headbuf[16]<<24) + (headbuf[17]<<16)+(headbuf[18]<<8)+headbuf[19];
92 memcpy(header->name,headbuf+20,80);
93 header->colormap = (headbuf[100]<<24) + (headbuf[101]<<16)+(headbuf[102]<<8)+headbuf[103];
94}
95
e4bf9335 96#if 0 /* this is currently unused */
5ff415bb
AMH
97
98/*
99=item rgb_header_pack(header, headbuf)
100
101Packs header structure into buffer for writing.
102
103 header - header structure
104 headbuf - buffer to pack into
105
106=cut
107*/
108
109static
110void
111rgb_header_pack(rgb_header *header, unsigned char headbuf[512]) {
112
113 header->imagic = (headbuf[0]<<8) + headbuf[1];
114 header->storagetype = headbuf[2];
115 header->BPC = headbuf[3];
116 header->dimensions = (headbuf[4]<<8) + headbuf[5];
117 header->xsize = (headbuf[6]<<8) + headbuf[7];
118 header->ysize = (headbuf[8]<<8) + headbuf[9];
119 header->zsize = (headbuf[10]<<8) + headbuf[11];
120 header->min = (headbuf[12]<<24) + (headbuf[13]<<16)+(headbuf[14]<<8)+headbuf[15];
121 header->max = (headbuf[16]<<24) + (headbuf[17]<<16)+(headbuf[18]<<8)+headbuf[19];
122 memcpy(header->name,headbuf+20,80);
123 header->colormap = (headbuf[100]<<24) + (headbuf[101]<<16)+(headbuf[102]<<8)+headbuf[103];
124
125}
126
127
5ff415bb
AMH
128
129
130
131/*
132=item rgb_dest_write(s, buf, pixels)
133
134Writes pixels from buf to destination s. Takes care of compressing if the
135destination is compressed.
136
137 s - data destination
138 buf - source buffer
139 pixels - number of pixels to put write to destination
140
141=cut
142*/
143
144static
145int
146rgb_dest_write(rgb_dest *s, unsigned char *buf, size_t pixels) {
af070d99 147 return -1;
5ff415bb
AMH
148}
149
e4bf9335 150#endif
5ff415bb
AMH
151
152
153
154
155
156
157/*
158=item i_readrgb_wiol(ig, length)
159
160Read in an image from the iolayer data source and return the image structure to it.
161Returns NULL on error.
162
163 ig - io_glue object
164 length - maximum length to read from data source, before closing it -1
165 signifies no limit.
166
167=cut
168*/
169
170i_img *
171i_readrgb_wiol(io_glue *ig, int length) {
172 i_img *img;
a659442a 173 int y, c,i;
5ff415bb
AMH
174 int width, height, channels;
175 unsigned long maxlen;
da1c841c
AMH
176
177 int savemask;
5ff415bb 178
5ff415bb
AMH
179 rgb_header header;
180 unsigned char headbuf[512];
181 unsigned char *databuf;
5ff415bb
AMH
182 unsigned long *starttab, *lengthtab;
183 i_color *linebuf = NULL;
184 i_mempool mp;
185
186 mm_log((1,"i_readrgb(ig %p, length %d)\n", ig, length));
187 i_clear_error();
188 i_mempool_init(&mp);
189
190 io_glue_commit_types(ig);
191
192 if (ig->readcb(ig, headbuf, 512) != 512) {
193 i_push_error(errno, "could not read SGI rgb header");
194 return NULL;
195 }
196
197 rgb_header_unpack(&header, headbuf);
198
199
200 mm_log((1,"imagic: %d\n", header.imagic));
201 mm_log((1,"storagetype: %d\n", header.storagetype));
202 mm_log((1,"BPC: %d\n", header.BPC));
203 mm_log((1,"dimensions: %d\n", header.dimensions));
204 mm_log((1,"xsize: %d\n", header.xsize));
205 mm_log((1,"ysize: %d\n", header.ysize));
206 mm_log((1,"zsize: %d\n", header.zsize));
207 mm_log((1,"min: %d\n", header.min));
208 mm_log((1,"max: %d\n", header.max));
209 mm_log((1,"name [skipped]\n"));
210 mm_log((1,"colormap: %d\n", header.colormap));
211
212 if (header.colormap != 0) {
213 i_push_error(0, "SGI rgb image has a non zero colormap entry - obsolete format");
214 return NULL;
215 }
216
217 if (header.storagetype != 0 && header.storagetype != 1) {
218 i_push_error(0, "SGI rgb image has has invalid storage field");
219 return NULL;
220 }
221
222 width = header.xsize;
223 height = header.ysize;
224 channels = header.zsize;
225
226 img = i_img_empty_ch(NULL, width, height, channels);
50dc291e
TC
227 if (!img)
228 return NULL;
5ff415bb
AMH
229
230 i_tags_add(&img->tags, "rgb_namestr", 0, header.name, 80, 0);
50dc291e 231 i_tags_add(&img->tags, "i_format", 0, "rgb", -1, 0);
da1c841c 232
5ff415bb
AMH
233 switch (header.storagetype) {
234 case 0: /* uncompressed */
235
da1c841c
AMH
236 linebuf = i_mempool_alloc(&mp, width*sizeof(i_color));
237 databuf = i_mempool_alloc(&mp, width);
238
239 savemask = i_img_getmask(img);
240
241 for(c=0; c<channels; c++) {
242 i_img_setmask(img, 1<<c);
243 for(y=0; y<height; y++) {
244 int x;
245
246 if (ig->readcb(ig, databuf, width) != width) {
247 i_push_error(0, "SGI rgb: cannot read");
248 goto ErrorReturn;
249 }
250
251 for(x=0; x<width; x++)
252 linebuf[x].channel[c] = databuf[x];
253
254 i_plin(img, 0, width, height-1-y, linebuf);
255 }
256 }
257 i_img_setmask(img, savemask);
5ff415bb
AMH
258 break;
259 case 1: /* RLE compressed */
260
261 databuf = i_mempool_alloc(&mp, height*channels*4);
262 starttab = i_mempool_alloc(&mp, height*channels*sizeof(unsigned long));
263 lengthtab = i_mempool_alloc(&mp, height*channels*sizeof(unsigned long));
264 linebuf = i_mempool_alloc(&mp, width*sizeof(i_color));
265
266 /* Read offset table */
267 if (ig->readcb(ig, databuf, height*channels*4) != height*channels*4) goto ErrorReturn;
268 for(i=0; i<height*channels; i++) starttab[i] =
269 (databuf[i*4]<<24) |
270 (databuf[i*4+1]<<16) |
271 (databuf[i*4+2]<<8) |
272 (databuf[i*4+3]);
273
274
275 /* Read length table */
276 if (ig->readcb(ig, databuf, height*channels*4) != height*channels*4) goto ErrorReturn;
277 for(i=0; i<height*channels; i++) lengthtab[i] =
278 (databuf[i*4]<<24)+
279 (databuf[i*4+1]<<16)+
280 (databuf[i*4+2]<<8)+
281 (databuf[i*4+3]);
282
283 mm_log((3, "Offset/length table:\n"));
284 for(i=0; i<height*channels; i++)
285 mm_log((3, "%d: %d/%d\n", i, starttab[i], lengthtab[i]));
286
287
288 /* Find max spanlength if someone is making very badly formed RLE data */
289 maxlen = 0;
290 for(y=0; y<height; y++) maxlen = (maxlen>lengthtab[y])?maxlen:lengthtab[y];
291
292 mm_log((1, "maxlen for an rle buffer: %d\n", maxlen));
293
294 databuf = i_mempool_alloc(&mp, maxlen);
295
296 for(y=0; y<height; y++) {
297 for(c=0; c<channels; c++) {
298 unsigned long iidx = 0, oidx = 0, span = 0;
e4bf9335 299 unsigned char cval = 0;
5ff415bb
AMH
300 int rle = 0;
301 int ci = height*c+y;
302 int datalen = lengthtab[ci];
303
304 if (ig->seekcb(ig, starttab[ci], SEEK_SET) != starttab[ci]) {
305 i_push_error(0, "SGI rgb: cannot seek");
306 goto ErrorReturn;
307 }
308 if (ig->readcb(ig, databuf, datalen) != datalen) {
309 i_push_error(0, "SGI rgb: cannot read");
310 goto ErrorReturn;
311 }
312
313 /*
314 mm_log((1, "Buffer length %d\n", datalen));
315 for(i=0; i<datalen; i++)
316 mm_log((1, "0x%x\n", databuf[i]));
317 */
318
319 while( iidx <= datalen && oidx < width ) {
320 if (!span) {
321 span = databuf[iidx] & 0x7f;
322 rle = !(databuf[iidx++] & 0x80);
323 /* mm_log((1,"new span %d, rle %d\n", span, rle)); */
324 if (rle) {
325 if (iidx==datalen) {
326 i_push_error(0, "SGI rgb: bad rle data");
327 goto ErrorReturn;
328 }
329 cval = databuf[iidx++];
330 /* mm_log((1, "rle value %d\n", cval)); */
331 }
332 }
333 linebuf[oidx++].channel[c] = rle ? cval : databuf[iidx++];
334 span--;
335 /*
336 mm_log((1,"iidx=%d/%d, oidx=%d/%d, linebuf[%d].channel[%d] %d\n", iidx-1, datalen, oidx-1, width, oidx-1, c, linebuf[oidx-1].channel[c]));
337 */
338 }
339 }
340 i_plin(img, 0, width, height-1-y, linebuf);
341 }
342
343 break;
344 }
345
50dc291e
TC
346 i_tags_add(&img->tags, "i_format", 0, "rgb", -1, 0);
347
5ff415bb
AMH
348 i_mempool_destroy(&mp);
349 return img;
350
351 ErrorReturn:
352 i_mempool_destroy(&mp);
353 if (img) i_img_destroy(img);
354 return NULL;
355}
356
357
358
359/*
360=item i_writergb_wiol(img, ig)
361
362Writes an image in targa format. Returns 0 on error.
363
364 img - image to store
365 ig - io_glue object
366
367=cut
368*/
369
370undef_int
371i_writergb_wiol(i_img *img, io_glue *ig, int wierdpack, int compress, char *idstring, size_t idlen) {
50dc291e
TC
372 i_clear_error();
373 i_push_error(0, "writing SGI RGB files is not implemented");
5ff415bb 374
50dc291e 375 return 0;
5ff415bb
AMH
376}
377