blob: 7d71a356222569958f0d78ed3e5d38c8301ce3ea [file] [log] [blame]
Guido van Rossumaa9de671992-03-04 16:40:03 +00001/***********************************************************
Guido van Rossumbab9d031992-04-05 14:26:55 +00002Copyright 1991, 1992 by Stichting Mathematisch Centrum, Amsterdam, The
Guido van Rossumaa9de671992-03-04 16:40:03 +00003Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
Guido van Rossuma5f61381992-09-03 20:41:22 +000025/* IMGFILE module - Interface to sgi libimage */
Guido van Rossumaa9de671992-03-04 16:40:03 +000026
Guido van Rossum2c4be641992-06-03 17:06:36 +000027/* XXX This modele should be done better at some point. It should return
Guido van Rossumaa9de671992-03-04 16:40:03 +000028** an object of image file class, and have routines to manipulate these
29** image files in a neater way (so you can get rgb images off a greyscale
30** file, for instance, or do a straight display without having to get the
31** image bits into python, etc).
32*/
33
34#include "allobjects.h"
35#include "modsupport.h"
36
37#include <gl/image.h>
Guido van Rossuma5f61381992-09-03 20:41:22 +000038#include <errno.h>
Guido van Rossumaa9de671992-03-04 16:40:03 +000039
Guido van Rossuma5f61381992-09-03 20:41:22 +000040static object * ImgfileError; /* Exception we raise for various trouble */
Guido van Rossumaa9de671992-03-04 16:40:03 +000041
Guido van Rossumaa9de671992-03-04 16:40:03 +000042
Guido van Rossuma5f61381992-09-03 20:41:22 +000043/* The image library does not always call the error hander :-(,
44 therefore we have a global variable indicating that it was called.
45 It is cleared by imgfile_open(). */
Guido van Rossumaa9de671992-03-04 16:40:03 +000046
Guido van Rossum3e941971992-03-23 18:21:32 +000047static int error_called;
48
Guido van Rossuma5f61381992-09-03 20:41:22 +000049
50/* The error handler */
51
Guido van Rossum3e941971992-03-23 18:21:32 +000052static imgfile_error(str)
53 char *str;
54{
55 err_setstr(ImgfileError, str);
56 error_called = 1;
57 return; /* To imglib, which will return a failure indictaor */
58}
Guido van Rossumaa9de671992-03-04 16:40:03 +000059
Guido van Rossuma5f61381992-09-03 20:41:22 +000060
61/* Open an image file and return a pointer to it.
62 Make sure we raise an exception if we fail. */
63
64static IMAGE *
Guido van Rossum2c4be641992-06-03 17:06:36 +000065imgfile_open(fname)
Guido van Rossumaa9de671992-03-04 16:40:03 +000066 char *fname;
Guido van Rossum2c4be641992-06-03 17:06:36 +000067{
Guido van Rossuma5f61381992-09-03 20:41:22 +000068 IMAGE *image;
Guido van Rossum3e941971992-03-23 18:21:32 +000069 i_seterror(imgfile_error);
70 error_called = 0;
Guido van Rossuma5f61381992-09-03 20:41:22 +000071 errno = 0;
72 if ( (image = iopen(fname, "r")) == NULL ) {
Guido van Rossum3e941971992-03-23 18:21:32 +000073 /* Error may already be set by imgfile_error */
Guido van Rossuma5f61381992-09-03 20:41:22 +000074 if ( !error_called ) {
75 if (errno)
76 err_errno(ImgfileError);
77 else
78 err_setstr(ImgfileError, "Can't open image file");
79 }
80 return NULL;
Guido van Rossumaa9de671992-03-04 16:40:03 +000081 }
Guido van Rossuma5f61381992-09-03 20:41:22 +000082 return image;
Guido van Rossumaa9de671992-03-04 16:40:03 +000083}
84
Guido van Rossuma5f61381992-09-03 20:41:22 +000085
Guido van Rossumaa9de671992-03-04 16:40:03 +000086static object *
87imgfile_read(self, args)
88 object *self;
89 object *args;
90{
91 char *fname;
92 object *rv;
93 int xsize, ysize, zsize;
94 char *cdatap;
95 long *idatap;
96 static short rs[8192], gs[8192], bs[8192];
97 int x, y;
Guido van Rossuma5f61381992-09-03 20:41:22 +000098 IMAGE *image;
Guido van Rossumaa9de671992-03-04 16:40:03 +000099
Guido van Rossum2c4be641992-06-03 17:06:36 +0000100 if ( !getargs(args, "s", &fname) )
Guido van Rossuma5f61381992-09-03 20:41:22 +0000101 return NULL;
Guido van Rossum2c4be641992-06-03 17:06:36 +0000102
Guido van Rossuma5f61381992-09-03 20:41:22 +0000103 if ( (image = imgfile_open(fname)) == NULL )
Guido van Rossumaa9de671992-03-04 16:40:03 +0000104 return NULL;
105
106 if ( image->colormap != CM_NORMAL ) {
Guido van Rossuma5f61381992-09-03 20:41:22 +0000107 iclose(image);
Guido van Rossumaa9de671992-03-04 16:40:03 +0000108 err_setstr(ImgfileError, "Can only handle CM_NORMAL images");
109 return NULL;
110 }
111 if ( BPP(image->type) != 1 ) {
Guido van Rossuma5f61381992-09-03 20:41:22 +0000112 iclose(image);
113 err_setstr(ImgfileError, "Can't handle imgfiles with bpp!=1");
Guido van Rossumaa9de671992-03-04 16:40:03 +0000114 return NULL;
115 }
116 xsize = image->xsize;
117 ysize = image->ysize;
118 zsize = image->zsize;
119 if ( zsize != 1 && zsize != 3) {
Guido van Rossuma5f61381992-09-03 20:41:22 +0000120 iclose(image);
Guido van Rossumaa9de671992-03-04 16:40:03 +0000121 err_setstr(ImgfileError, "Can only handle 1 or 3 byte pixels");
122 return NULL;
123 }
Guido van Rossuma5f61381992-09-03 20:41:22 +0000124 if ( xsize > 8192 ) {
125 iclose(image);
126 err_setstr(ImgfileError, "Can't handle image with > 8192 columns");
127 return NULL;
128 }
Guido van Rossumaa9de671992-03-04 16:40:03 +0000129
130 if ( zsize == 3 ) zsize = 4;
Guido van Rossuma5f61381992-09-03 20:41:22 +0000131 rv = newsizedstringobject((char *)NULL, xsize*ysize*zsize);
132 if ( rv == NULL ) {
133 iclose(image);
Guido van Rossumaa9de671992-03-04 16:40:03 +0000134 return NULL;
Guido van Rossuma5f61381992-09-03 20:41:22 +0000135 }
Guido van Rossumaa9de671992-03-04 16:40:03 +0000136 cdatap = getstringvalue(rv);
137 idatap = (long *)cdatap;
Guido van Rossum3e941971992-03-23 18:21:32 +0000138 for ( y=0; y < ysize && !error_called; y++ ) {
Guido van Rossumaa9de671992-03-04 16:40:03 +0000139 if ( zsize == 1 ) {
140 getrow(image, rs, y, 0);
141 for(x=0; x<xsize; x++ )
142 *cdatap++ = rs[x];
143 } else {
144 getrow(image, rs, y, 0);
145 getrow(image, gs, y, 1);
146 getrow(image, bs, y, 2);
147 for(x=0; x<xsize; x++ )
148 *idatap++ = (rs[x] & 0xff) |
149 ((gs[x] & 0xff)<<8) |
150 ((bs[x] & 0xff)<<16);
151 }
152 }
Jack Jansen3accf981992-08-20 11:54:27 +0000153 iclose(image);
Guido van Rossum3e941971992-03-23 18:21:32 +0000154 if ( error_called ) {
155 DECREF(rv);
156 return NULL;
157 }
Guido van Rossumaa9de671992-03-04 16:40:03 +0000158 return rv;
159}
160
Guido van Rossuma5f61381992-09-03 20:41:22 +0000161
Guido van Rossumaa9de671992-03-04 16:40:03 +0000162static object *
Guido van Rossum2c4be641992-06-03 17:06:36 +0000163imgfile_readscaled(self, args)
164 object *self;
165 object *args;
166{
167 char *fname;
168 object *rv;
169 int xsize, ysize, zsize;
170 char *cdatap;
171 long *idatap;
172 static short rs[8192], gs[8192], bs[8192];
173 int x, y;
174 int xwtd, ywtd, xorig, yorig;
175 float xfac, yfac;
176 int cnt;
Guido van Rossuma5f61381992-09-03 20:41:22 +0000177 IMAGE *image;
Guido van Rossum2c4be641992-06-03 17:06:36 +0000178
179 if ( !getargs(args, "(sii)", &fname, &xwtd, &ywtd) )
Guido van Rossuma5f61381992-09-03 20:41:22 +0000180 return NULL;
Guido van Rossum2c4be641992-06-03 17:06:36 +0000181
Guido van Rossuma5f61381992-09-03 20:41:22 +0000182 if ( (image = imgfile_open(fname)) == NULL )
Guido van Rossum2c4be641992-06-03 17:06:36 +0000183 return NULL;
184
185 if ( image->colormap != CM_NORMAL ) {
Guido van Rossuma5f61381992-09-03 20:41:22 +0000186 iclose(image);
Guido van Rossum2c4be641992-06-03 17:06:36 +0000187 err_setstr(ImgfileError, "Can only handle CM_NORMAL images");
188 return NULL;
189 }
190 if ( BPP(image->type) != 1 ) {
Guido van Rossuma5f61381992-09-03 20:41:22 +0000191 iclose(image);
192 err_setstr(ImgfileError, "Can't handle imgfiles with bpp!=1");
Guido van Rossum2c4be641992-06-03 17:06:36 +0000193 return NULL;
194 }
195 xsize = image->xsize;
196 ysize = image->ysize;
197 zsize = image->zsize;
198 if ( zsize != 1 && zsize != 3) {
Guido van Rossuma5f61381992-09-03 20:41:22 +0000199 iclose(image);
Guido van Rossum2c4be641992-06-03 17:06:36 +0000200 err_setstr(ImgfileError, "Can only handle 1 or 3 byte pixels");
201 return NULL;
202 }
Guido van Rossuma5f61381992-09-03 20:41:22 +0000203 if ( xsize > 8192 ) {
204 iclose(image);
205 err_setstr(ImgfileError, "Can't handle image with > 8192 columns");
206 return NULL;
207 }
Guido van Rossum2c4be641992-06-03 17:06:36 +0000208
209 if ( zsize == 3 ) zsize = 4;
210 rv = newsizedstringobject(NULL, xwtd*ywtd*zsize);
Guido van Rossuma5f61381992-09-03 20:41:22 +0000211 if ( rv == NULL ) {
212 iclose(image);
213 return NULL;
214 }
Guido van Rossum2c4be641992-06-03 17:06:36 +0000215 xfac = (float)xsize/(float)xwtd;
216 yfac = (float)ysize/(float)ywtd;
Guido van Rossum2c4be641992-06-03 17:06:36 +0000217 cdatap = getstringvalue(rv);
218 idatap = (long *)cdatap;
219 for ( y=0; y < ywtd && !error_called; y++ ) {
220 yorig = (int)(y*yfac);
221 if ( zsize == 1 ) {
222 getrow(image, rs, yorig, 0);
223 for(x=0; x<xwtd; x++ ) {
224 *cdatap++ = rs[(int)(x*xfac)];
225 }
226 } else {
227 getrow(image, rs, yorig, 0);
228 getrow(image, gs, yorig, 1);
229 getrow(image, bs, yorig, 2);
230 for(x=0; x<xwtd; x++ ) {
231 xorig = (int)(x*xfac);
232 *idatap++ = (rs[xorig] & 0xff) |
233 ((gs[xorig] & 0xff)<<8) |
234 ((bs[xorig] & 0xff)<<16);
235 }
236 }
237 }
Guido van Rossuma5f61381992-09-03 20:41:22 +0000238 iclose(image);
Guido van Rossum2c4be641992-06-03 17:06:36 +0000239 if ( error_called ) {
240 DECREF(rv);
241 return NULL;
242 }
243 return rv;
244}
245
Guido van Rossuma5f61381992-09-03 20:41:22 +0000246
Guido van Rossum2c4be641992-06-03 17:06:36 +0000247static object *
Guido van Rossumaa9de671992-03-04 16:40:03 +0000248imgfile_getsizes(self, args)
249 object *self;
250 object *args;
251{
252 char *fname;
253 object *rv;
Guido van Rossuma5f61381992-09-03 20:41:22 +0000254 IMAGE *image;
Guido van Rossumaa9de671992-03-04 16:40:03 +0000255
Guido van Rossum2c4be641992-06-03 17:06:36 +0000256 if ( !getargs(args, "s", &fname) )
Guido van Rossuma5f61381992-09-03 20:41:22 +0000257 return NULL;
Guido van Rossum2c4be641992-06-03 17:06:36 +0000258
Guido van Rossuma5f61381992-09-03 20:41:22 +0000259 if ( (image = imgfile_open(fname)) == NULL )
Guido van Rossumaa9de671992-03-04 16:40:03 +0000260 return NULL;
Guido van Rossuma5f61381992-09-03 20:41:22 +0000261 rv = mkvalue("(iii)", image->xsize, image->ysize, image->zsize);
262 iclose(image);
Guido van Rossumaa9de671992-03-04 16:40:03 +0000263 return rv;
264}
265
Guido van Rossuma5f61381992-09-03 20:41:22 +0000266
Jack Jansen3accf981992-08-20 11:54:27 +0000267static object *
268imgfile_write(self, args)
269 object *self;
270 object *args;
271{
272 IMAGE *image;
273 char *fname;
274 int xsize, ysize, zsize, len;
275 char *cdatap;
276 long *idatap;
277 short rs[8192], gs[8192], bs[8192];
278 short r, g, b;
279 long rgb;
280 int x, y;
281
282 if ( !getargs(args, "(ss#iii)",
283 &fname, &cdatap, &len, &xsize, &ysize, &zsize) )
Guido van Rossuma5f61381992-09-03 20:41:22 +0000284 return NULL;
Jack Jansen3accf981992-08-20 11:54:27 +0000285
286 if ( zsize != 1 && zsize != 3 ) {
287 err_setstr(ImgfileError, "Can only handle 1 or 3 byte pixels");
Guido van Rossuma5f61381992-09-03 20:41:22 +0000288 return NULL;
Jack Jansen3accf981992-08-20 11:54:27 +0000289 }
Guido van Rossuma5f61381992-09-03 20:41:22 +0000290 if ( len != xsize * ysize * (zsize == 1 ? 1 : 4) ) {
Jack Jansen3accf981992-08-20 11:54:27 +0000291 err_setstr(ImgfileError, "Data does not match sizes");
Guido van Rossuma5f61381992-09-03 20:41:22 +0000292 return NULL;
293 }
294 if ( xsize > 8192 ) {
295 err_setstr(ImgfileError, "Can't handle image with > 8192 columns");
296 return NULL;
Jack Jansen3accf981992-08-20 11:54:27 +0000297 }
298
Guido van Rossuma5f61381992-09-03 20:41:22 +0000299 error_called = 0;
300 errno = 0;
Jack Jansen3accf981992-08-20 11:54:27 +0000301 image =iopen(fname, "w", RLE(1), 3, xsize, ysize, zsize);
302 if ( image == 0 ) {
Guido van Rossuma5f61381992-09-03 20:41:22 +0000303 if ( ! error_called ) {
304 if (errno)
305 err_errno(ImgfileError);
306 else
307 err_setstr(ImgfileError, "Can't create image file");
308 }
309 return NULL;
Jack Jansen3accf981992-08-20 11:54:27 +0000310 }
311
312 idatap = (long *)cdatap;
313
314 for( y=0; y<ysize && !error_called; y++ ) {
315 if ( zsize == 1 ) {
316 for( x=0; x<xsize; x++ )
317 rs[x] = *cdatap++;
318 putrow(image, rs, y, 0);
319 } else {
320 for( x=0; x<xsize; x++ ) {
321 rgb = *idatap++;
322 r = rgb & 0xff;
323 g = (rgb >> 8 ) & 0xff;
324 b = (rgb >> 16 ) & 0xff;
325 rs[x] = r;
326 gs[x] = g;
327 bs[x] = b;
328 }
329 putrow(image, rs, y, 0);
330 putrow(image, gs, y, 1);
331 putrow(image, bs, y, 2);
332 }
333 }
334 iclose(image);
335 if ( error_called )
Guido van Rossuma5f61381992-09-03 20:41:22 +0000336 return NULL;
Jack Jansen3accf981992-08-20 11:54:27 +0000337 INCREF(None);
338 return None;
339
340}
Guido van Rossumaa9de671992-03-04 16:40:03 +0000341
Guido van Rossuma5f61381992-09-03 20:41:22 +0000342
Guido van Rossumaa9de671992-03-04 16:40:03 +0000343static struct methodlist imgfile_methods[] = {
Guido van Rossum2c4be641992-06-03 17:06:36 +0000344 { "getsizes", imgfile_getsizes },
345 { "read", imgfile_read },
346 { "readscaled", imgfile_readscaled },
Jack Jansen3accf981992-08-20 11:54:27 +0000347 { "write", imgfile_write },
Guido van Rossuma5f61381992-09-03 20:41:22 +0000348 { NULL, NULL } /* Sentinel */
Guido van Rossumaa9de671992-03-04 16:40:03 +0000349};
350
351
352void
353initimgfile()
354{
355 object *m, *d;
356 m = initmodule("imgfile", imgfile_methods);
357 d = getmoduledict(m);
358 ImgfileError = newstringobject("imgfile.error");
Guido van Rossuma5f61381992-09-03 20:41:22 +0000359 if ( ImgfileError == NULL || dictinsert(d, "error", ImgfileError) )
Guido van Rossumaa9de671992-03-04 16:40:03 +0000360 fatal("can't define imgfile.error");
361}