| Sjoerd Mullender | c4f169c | 1993-12-21 17:06:12 +0000 | [diff] [blame] | 1 | /* | 
 | 2 |  *   	fastimg - | 
 | 3 |  *		Faster reading and writing of image files. | 
 | 4 |  * | 
 | 5 |  *      This code should work on machines with any byte order. | 
 | 6 |  * | 
 | 7 |  *	Could someone make this run real fast using multiple processors  | 
 | 8 |  *	or how about using memory mapped files to speed it up? | 
 | 9 |  * | 
 | 10 |  *				Paul Haeberli - 1991 | 
 | 11 |  * | 
 | 12 |  *	Changed to return sizes. | 
 | 13 |  *				Sjoerd Mullender - 1993 | 
 | 14 |  *	Changed to incorporate into Python. | 
 | 15 |  *				Sjoerd Mullender - 1993 | 
 | 16 |  */ | 
 | 17 | #include "allobjects.h" | 
 | 18 | #include "modsupport.h" | 
 | 19 | #include <unistd.h> | 
| Sjoerd Mullender | 92fa23f | 1993-12-24 10:05:51 +0000 | [diff] [blame^] | 20 | #include <string.h> | 
| Sjoerd Mullender | c4f169c | 1993-12-21 17:06:12 +0000 | [diff] [blame] | 21 |  | 
 | 22 | /* | 
 | 23 |  *	from image.h | 
 | 24 |  * | 
 | 25 |  */ | 
 | 26 | typedef struct { | 
 | 27 |     unsigned short	imagic;		/* stuff saved on disk . . */ | 
 | 28 |     unsigned short 	type; | 
 | 29 |     unsigned short 	dim; | 
 | 30 |     unsigned short 	xsize; | 
 | 31 |     unsigned short 	ysize; | 
 | 32 |     unsigned short 	zsize; | 
 | 33 |     unsigned long 	min; | 
 | 34 |     unsigned long 	max; | 
 | 35 |     unsigned long	wastebytes;	 | 
 | 36 |     char 		name[80]; | 
 | 37 |     unsigned long	colormap; | 
 | 38 |  | 
 | 39 |     long 		file;		/* stuff used in core only */ | 
 | 40 |     unsigned short 	flags; | 
 | 41 |     short		dorev; | 
 | 42 |     short		x; | 
 | 43 |     short		y; | 
 | 44 |     short		z; | 
 | 45 |     short		cnt; | 
 | 46 |     unsigned short	*ptr; | 
 | 47 |     unsigned short	*base; | 
 | 48 |     unsigned short	*tmpbuf; | 
 | 49 |     unsigned long	offset; | 
 | 50 |     unsigned long	rleend;		/* for rle images */ | 
 | 51 |     unsigned long	*rowstart;	/* for rle images */ | 
 | 52 |     long		*rowsize;	/* for rle images */ | 
 | 53 | } IMAGE; | 
 | 54 |  | 
 | 55 | #define IMAGIC 	0732 | 
 | 56 |  | 
 | 57 | #define TYPEMASK		0xff00 | 
 | 58 | #define BPPMASK			0x00ff | 
 | 59 | #define ITYPE_VERBATIM		0x0000 | 
 | 60 | #define ITYPE_RLE		0x0100 | 
 | 61 | #define ISRLE(type)		(((type) & 0xff00) == ITYPE_RLE) | 
 | 62 | #define ISVERBATIM(type)	(((type) & 0xff00) == ITYPE_VERBATIM) | 
 | 63 | #define BPP(type)		((type) & BPPMASK) | 
 | 64 | #define RLE(bpp)		(ITYPE_RLE | (bpp)) | 
 | 65 | #define VERBATIM(bpp)		(ITYPE_VERBATIM | (bpp)) | 
 | 66 | /* | 
 | 67 |  *	end of image.h stuff | 
 | 68 |  * | 
 | 69 |  */ | 
 | 70 |  | 
 | 71 | #define RINTLUM (79) | 
 | 72 | #define GINTLUM (156) | 
 | 73 | #define BINTLUM (21) | 
 | 74 |  | 
 | 75 | #define ILUM(r,g,b)     ((int)(RINTLUM*(r)+GINTLUM*(g)+BINTLUM*(b))>>8) | 
 | 76 |  | 
 | 77 | #define OFFSET_R	3	/* this is byte order dependent */ | 
 | 78 | #define OFFSET_G	2 | 
 | 79 | #define OFFSET_B	1 | 
 | 80 | #define OFFSET_A	0 | 
 | 81 |  | 
 | 82 | #define CHANOFFSET(z)	(3-(z))	/* this is byte order dependent */ | 
 | 83 |  | 
| Sjoerd Mullender | 92fa23f | 1993-12-24 10:05:51 +0000 | [diff] [blame^] | 84 | static expandrow PROTO((unsigned char *, unsigned char *, int)); | 
 | 85 | static setalpha PROTO((unsigned char *, int)); | 
 | 86 | static copybw PROTO((long *, int)); | 
 | 87 | static interleaverow PROTO((unsigned char *, unsigned char *, int, int)); | 
 | 88 | static int compressrow PROTO((unsigned char *, unsigned char *, int, int)); | 
 | 89 | static lumrow PROTO((unsigned char *, unsigned char *, int)); | 
| Sjoerd Mullender | c4f169c | 1993-12-21 17:06:12 +0000 | [diff] [blame] | 90 |  | 
 | 91 | #ifdef ADD_TAGS | 
 | 92 | #define TAGLEN	(5) | 
 | 93 | #else | 
 | 94 | #define TAGLEN	(0) | 
 | 95 | #endif | 
 | 96 |  | 
 | 97 | static object *ImgfileError; | 
 | 98 |  | 
 | 99 | #ifdef ADD_TAGS | 
 | 100 | /* | 
 | 101 |  *	addlongimgtag -  | 
 | 102 |  *		this is used to extract image data from core dumps. | 
 | 103 |  * | 
 | 104 |  */ | 
 | 105 | addlongimgtag(dptr,xsize,ysize) | 
 | 106 | unsigned long *dptr; | 
 | 107 | int xsize, ysize; | 
 | 108 | { | 
 | 109 |     dptr = dptr+(xsize*ysize); | 
 | 110 |     dptr[0] = 0x12345678; | 
 | 111 |     dptr[1] = 0x59493333; | 
 | 112 |     dptr[2] = 0x69434222; | 
 | 113 |     dptr[3] = xsize; | 
 | 114 |     dptr[4] = ysize; | 
 | 115 | } | 
 | 116 | #endif | 
 | 117 |  | 
 | 118 | /* | 
 | 119 |  *	byte order independent read/write of shorts and longs. | 
 | 120 |  * | 
 | 121 |  */ | 
 | 122 | static unsigned short getshort(inf) | 
 | 123 | FILE *inf; | 
 | 124 | { | 
 | 125 |     unsigned char buf[2]; | 
 | 126 |  | 
 | 127 |     fread(buf,2,1,inf); | 
 | 128 |     return (buf[0]<<8)+(buf[1]<<0); | 
 | 129 | } | 
 | 130 |  | 
 | 131 | static unsigned long getlong(inf) | 
 | 132 | FILE *inf; | 
 | 133 | { | 
 | 134 |     unsigned char buf[4]; | 
 | 135 |  | 
 | 136 |     fread(buf,4,1,inf); | 
 | 137 |     return (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+(buf[3]<<0); | 
 | 138 | } | 
 | 139 |  | 
 | 140 | static putshort(outf,val) | 
 | 141 | FILE *outf; | 
 | 142 | unsigned short val; | 
 | 143 | { | 
 | 144 |     unsigned char buf[2]; | 
 | 145 |  | 
 | 146 |     buf[0] = (val>>8); | 
 | 147 |     buf[1] = (val>>0); | 
 | 148 |     fwrite(buf,2,1,outf); | 
 | 149 | } | 
 | 150 |  | 
 | 151 | static int putlong(outf,val) | 
 | 152 | FILE *outf; | 
 | 153 | unsigned long val; | 
 | 154 | { | 
 | 155 |     unsigned char buf[4]; | 
 | 156 |  | 
 | 157 |     buf[0] = (val>>24); | 
 | 158 |     buf[1] = (val>>16); | 
 | 159 |     buf[2] = (val>>8); | 
 | 160 |     buf[3] = (val>>0); | 
 | 161 |     return fwrite(buf,4,1,outf); | 
 | 162 | } | 
 | 163 |  | 
 | 164 | static readheader(inf,image) | 
 | 165 | FILE *inf; | 
 | 166 | IMAGE *image; | 
 | 167 | { | 
| Sjoerd Mullender | 92fa23f | 1993-12-24 10:05:51 +0000 | [diff] [blame^] | 168 |     memset(image,0,sizeof(IMAGE)); | 
| Sjoerd Mullender | c4f169c | 1993-12-21 17:06:12 +0000 | [diff] [blame] | 169 |     image->imagic = getshort(inf); | 
 | 170 |     image->type = getshort(inf); | 
 | 171 |     image->dim = getshort(inf); | 
 | 172 |     image->xsize = getshort(inf); | 
 | 173 |     image->ysize = getshort(inf); | 
 | 174 |     image->zsize = getshort(inf); | 
 | 175 | } | 
 | 176 |  | 
 | 177 | static int writeheader(outf,image) | 
 | 178 | FILE *outf; | 
 | 179 | IMAGE *image; | 
 | 180 | { | 
 | 181 |     IMAGE t; | 
 | 182 |  | 
| Sjoerd Mullender | 92fa23f | 1993-12-24 10:05:51 +0000 | [diff] [blame^] | 183 |     memset(&t,0,sizeof(IMAGE)); | 
| Sjoerd Mullender | c4f169c | 1993-12-21 17:06:12 +0000 | [diff] [blame] | 184 |     fwrite(&t,sizeof(IMAGE),1,outf); | 
 | 185 |     fseek(outf,0,SEEK_SET); | 
 | 186 |     putshort(outf,image->imagic); | 
 | 187 |     putshort(outf,image->type); | 
 | 188 |     putshort(outf,image->dim); | 
 | 189 |     putshort(outf,image->xsize); | 
 | 190 |     putshort(outf,image->ysize); | 
 | 191 |     putshort(outf,image->zsize); | 
 | 192 |     putlong(outf,image->min); | 
 | 193 |     putlong(outf,image->max); | 
 | 194 |     putlong(outf,0); | 
 | 195 |     return fwrite("no name",8,1,outf); | 
 | 196 | } | 
 | 197 |  | 
 | 198 | static int writetab(outf,tab,len) | 
 | 199 | FILE *outf; | 
 | 200 | unsigned long *tab; | 
 | 201 | int len; | 
 | 202 | { | 
 | 203 |     int r; | 
 | 204 |  | 
 | 205 |     while(len) { | 
 | 206 | 	r = putlong(outf,*tab++); | 
 | 207 | 	len -= 4; | 
 | 208 |     } | 
 | 209 |     return r; | 
 | 210 | } | 
 | 211 |  | 
 | 212 | static readtab(inf,tab,len) | 
 | 213 | FILE *inf; | 
 | 214 | unsigned long *tab; | 
 | 215 | int len; | 
 | 216 | { | 
 | 217 |     while(len) { | 
 | 218 | 	*tab++ = getlong(inf); | 
 | 219 | 	len -= 4; | 
 | 220 |     } | 
 | 221 | } | 
 | 222 |  | 
 | 223 | /* | 
 | 224 |  *	sizeofimage -  | 
 | 225 |  *		return the xsize and ysize of an iris image file. | 
 | 226 |  * | 
 | 227 |  */ | 
 | 228 | static object * | 
 | 229 | sizeofimage(self, args) | 
 | 230 |     object *self, *args; | 
 | 231 | { | 
 | 232 |     char *name; | 
 | 233 |     IMAGE image; | 
 | 234 |     FILE *inf; | 
 | 235 |  | 
 | 236 |     if (!getargs(args, "s", &name)) | 
 | 237 | 	return NULL; | 
 | 238 |  | 
 | 239 |     inf = fopen(name,"r"); | 
 | 240 |     if(!inf) { | 
 | 241 | 	err_setstr(ImgfileError, "can't open image file"); | 
 | 242 | 	return NULL; | 
 | 243 |     } | 
 | 244 |     readheader(inf,&image); | 
 | 245 |     fclose(inf); | 
 | 246 |     if(image.imagic != IMAGIC) { | 
 | 247 | 	err_setstr(ImgfileError, "bad magic number in image file"); | 
 | 248 | 	return NULL; | 
 | 249 |     } | 
 | 250 |     return mkvalue("(ii)", image.xsize, image.ysize); | 
 | 251 | } | 
 | 252 |  | 
 | 253 | /* | 
 | 254 |  *	longimagedata -  | 
 | 255 |  *		read in a B/W RGB or RGBA iris image file and return a  | 
 | 256 |  *	pointer to an array of longs. | 
 | 257 |  * | 
 | 258 |  */ | 
 | 259 | static object * | 
 | 260 | longimagedata(self, args) | 
 | 261 |     object *self, *args; | 
 | 262 | { | 
 | 263 |     char *name; | 
| Sjoerd Mullender | 92fa23f | 1993-12-24 10:05:51 +0000 | [diff] [blame^] | 264 |     unsigned char *base, *lptr; | 
| Sjoerd Mullender | c4f169c | 1993-12-21 17:06:12 +0000 | [diff] [blame] | 265 |     unsigned char *rledat, *verdat; | 
 | 266 |     long *starttab, *lengthtab; | 
 | 267 |     FILE *inf; | 
 | 268 |     IMAGE image; | 
 | 269 |     int y, z, pos, len, tablen; | 
 | 270 |     int xsize, ysize, zsize; | 
 | 271 |     int bpp, rle, cur, badorder; | 
 | 272 |     int rlebuflen; | 
 | 273 |     object *rv; | 
 | 274 |  | 
 | 275 |     if (!getargs(args, "s", &name)) | 
 | 276 | 	return NULL; | 
 | 277 |  | 
 | 278 |     inf = fopen(name,"r"); | 
 | 279 |     if(!inf) { | 
 | 280 | 	err_setstr(ImgfileError,"can't open image file"); | 
 | 281 | 	return NULL; | 
 | 282 |     } | 
 | 283 |     readheader(inf,&image); | 
 | 284 |     if(image.imagic != IMAGIC) { | 
 | 285 | 	err_setstr(ImgfileError,"bad magic number in image file"); | 
 | 286 | 	fclose(inf); | 
 | 287 | 	return NULL; | 
 | 288 |     } | 
 | 289 |     rle = ISRLE(image.type); | 
 | 290 |     bpp = BPP(image.type); | 
 | 291 |     if(bpp != 1 ) { | 
 | 292 | 	err_setstr(ImgfileError,"image must have 1 byte per pix chan"); | 
 | 293 | 	fclose(inf); | 
 | 294 | 	return NULL; | 
 | 295 |     } | 
 | 296 |     xsize = image.xsize; | 
 | 297 |     ysize = image.ysize; | 
 | 298 |     zsize = image.zsize; | 
 | 299 |     if(rle) { | 
 | 300 | 	tablen = ysize*zsize*sizeof(long); | 
 | 301 | 	starttab = (long *)malloc(tablen); | 
 | 302 | 	lengthtab = (long *)malloc(tablen); | 
 | 303 | 	rlebuflen = 1.05*xsize+10; | 
 | 304 | 	rledat = (unsigned char *)malloc(rlebuflen); | 
 | 305 | 	fseek(inf,512,SEEK_SET); | 
 | 306 |  	readtab(inf,starttab,tablen); | 
 | 307 | 	readtab(inf,lengthtab,tablen); | 
 | 308 |  | 
 | 309 | /* check data order */ | 
 | 310 | 	cur = 0; | 
 | 311 | 	badorder = 0; | 
 | 312 | 	for(y=0; y<ysize; y++) { | 
 | 313 | 	    for(z=0; z<zsize; z++) { | 
 | 314 | 		if(starttab[y+z*ysize]<cur) { | 
 | 315 | 		    badorder = 1; | 
 | 316 | 		    break; | 
 | 317 | 		} | 
 | 318 | 		cur = starttab[y+z*ysize]; | 
 | 319 | 	    } | 
 | 320 | 	    if(badorder)  | 
 | 321 | 		break; | 
 | 322 | 	} | 
 | 323 |  | 
 | 324 | 	fseek(inf,512+2*tablen,SEEK_SET); | 
 | 325 | 	cur = 512+2*tablen; | 
 | 326 | 	rv = newsizedstringobject((char *) 0, | 
 | 327 | 				  (xsize*ysize+TAGLEN)*sizeof(long)); | 
 | 328 | 	if (rv == NULL) { | 
 | 329 | 	    fclose(inf); | 
 | 330 | 	    free(lengthtab); | 
 | 331 | 	    free(starttab); | 
 | 332 | 	    free(rledat); | 
 | 333 | 	    return NULL; | 
 | 334 | 	} | 
| Sjoerd Mullender | 92fa23f | 1993-12-24 10:05:51 +0000 | [diff] [blame^] | 335 | 	base = (unsigned char *) getstringvalue(rv); | 
| Sjoerd Mullender | c4f169c | 1993-12-21 17:06:12 +0000 | [diff] [blame] | 336 | #ifdef ADD_TAGS | 
 | 337 | 	addlongimgtag(base,xsize,ysize); | 
 | 338 | #endif | 
 | 339 |   	if(badorder) { | 
 | 340 | 	    for(z=0; z<zsize; z++) { | 
 | 341 | 		lptr = base; | 
 | 342 | 		for(y=0; y<ysize; y++) { | 
 | 343 | 		    if(cur != starttab[y+z*ysize]) { | 
 | 344 | 			fseek(inf,starttab[y+z*ysize],SEEK_SET); | 
 | 345 | 			cur = starttab[y+z*ysize]; | 
 | 346 | 		    } | 
 | 347 | 		    if(lengthtab[y+z*ysize]>rlebuflen) { | 
 | 348 | 			err_setstr(ImgfileError,"rlebuf is too small - bad poop"); | 
 | 349 | 			fclose(inf); | 
 | 350 | 			DECREF(rv); | 
 | 351 | 			free(rledat); | 
 | 352 | 			free(starttab); | 
 | 353 | 			free(lengthtab); | 
 | 354 | 			return NULL; | 
 | 355 | 		    } | 
 | 356 | 		    fread(rledat,lengthtab[y+z*ysize],1,inf); | 
 | 357 | 		    cur += lengthtab[y+z*ysize]; | 
 | 358 | 		    expandrow(lptr,rledat,3-z); | 
| Sjoerd Mullender | 92fa23f | 1993-12-24 10:05:51 +0000 | [diff] [blame^] | 359 | 		    lptr += xsize * sizeof(unsigned long); | 
| Sjoerd Mullender | c4f169c | 1993-12-21 17:06:12 +0000 | [diff] [blame] | 360 | 		} | 
 | 361 | 	    } | 
 | 362 | 	} else { | 
 | 363 | 	    lptr = base; | 
 | 364 | 	    for(y=0; y<ysize; y++) { | 
 | 365 | 		for(z=0; z<zsize; z++) { | 
 | 366 | 		    if(cur != starttab[y+z*ysize]) { | 
 | 367 | 			fseek(inf,starttab[y+z*ysize],SEEK_SET); | 
 | 368 | 			cur = starttab[y+z*ysize]; | 
 | 369 | 		    } | 
 | 370 | 		    fread(rledat,lengthtab[y+z*ysize],1,inf); | 
 | 371 | 		    cur += lengthtab[y+z*ysize]; | 
 | 372 | 		    expandrow(lptr,rledat,3-z); | 
 | 373 | 		} | 
| Sjoerd Mullender | 92fa23f | 1993-12-24 10:05:51 +0000 | [diff] [blame^] | 374 | 		lptr += xsize * sizeof(unsigned long); | 
| Sjoerd Mullender | c4f169c | 1993-12-21 17:06:12 +0000 | [diff] [blame] | 375 | 	    } | 
 | 376 |     	} | 
 | 377 | 	if(zsize == 3)  | 
 | 378 | 	    setalpha(base,xsize*ysize); | 
 | 379 | 	else if(zsize<3)  | 
| Sjoerd Mullender | 92fa23f | 1993-12-24 10:05:51 +0000 | [diff] [blame^] | 380 | 	    copybw((long *) base,xsize*ysize); | 
| Sjoerd Mullender | c4f169c | 1993-12-21 17:06:12 +0000 | [diff] [blame] | 381 | 	fclose(inf); | 
 | 382 | 	free(starttab); | 
 | 383 | 	free(lengthtab); | 
 | 384 | 	free(rledat); | 
 | 385 | 	return rv; | 
 | 386 |     } else { | 
 | 387 | 	rv = newsizedstringobject((char *) 0, | 
 | 388 | 				  (xsize*ysize+TAGLEN)*sizeof(long)); | 
 | 389 | 	if (rv == NULL) { | 
 | 390 | 	    fclose(inf); | 
 | 391 | 	    return NULL; | 
 | 392 | 	} | 
| Sjoerd Mullender | 92fa23f | 1993-12-24 10:05:51 +0000 | [diff] [blame^] | 393 | 	base = (unsigned char *) getstringvalue(rv); | 
| Sjoerd Mullender | c4f169c | 1993-12-21 17:06:12 +0000 | [diff] [blame] | 394 | #ifdef ADD_TAGS | 
 | 395 | 	addlongimgtag(base,xsize,ysize); | 
 | 396 | #endif | 
 | 397 | 	verdat = (unsigned char *)malloc(xsize); | 
 | 398 | 	fseek(inf,512,SEEK_SET); | 
 | 399 | 	for(z=0; z<zsize; z++) { | 
 | 400 | 	    lptr = base; | 
 | 401 | 	    for(y=0; y<ysize; y++) { | 
 | 402 | 		fread(verdat,xsize,1,inf); | 
 | 403 | 		interleaverow(lptr,verdat,3-z,xsize); | 
| Sjoerd Mullender | 92fa23f | 1993-12-24 10:05:51 +0000 | [diff] [blame^] | 404 | 		lptr += xsize * sizeof(unsigned long); | 
| Sjoerd Mullender | c4f169c | 1993-12-21 17:06:12 +0000 | [diff] [blame] | 405 | 	    } | 
 | 406 | 	} | 
 | 407 | 	if(zsize == 3)  | 
 | 408 | 	    setalpha(base,xsize*ysize); | 
 | 409 | 	else if(zsize<3)  | 
| Sjoerd Mullender | 92fa23f | 1993-12-24 10:05:51 +0000 | [diff] [blame^] | 410 | 	    copybw((long *) base,xsize*ysize); | 
| Sjoerd Mullender | c4f169c | 1993-12-21 17:06:12 +0000 | [diff] [blame] | 411 | 	fclose(inf); | 
 | 412 | 	free(verdat); | 
 | 413 | 	return rv; | 
 | 414 |     } | 
 | 415 | } | 
 | 416 |  | 
 | 417 | /* static utility functions for longimagedata */ | 
 | 418 |  | 
 | 419 | static interleaverow(lptr,cptr,z,n) | 
 | 420 | unsigned char *lptr, *cptr; | 
 | 421 | int z, n; | 
 | 422 | { | 
 | 423 |     lptr += z; | 
 | 424 |     while(n--) { | 
 | 425 | 	*lptr = *cptr++; | 
 | 426 | 	lptr += 4; | 
 | 427 |     } | 
 | 428 | } | 
 | 429 |  | 
 | 430 | static copybw(lptr,n) | 
 | 431 | long *lptr; | 
 | 432 | int n; | 
 | 433 | { | 
 | 434 |     while(n>=8) { | 
 | 435 | 	lptr[0] = 0xff000000+(0x010101*(lptr[0]&0xff)); | 
 | 436 | 	lptr[1] = 0xff000000+(0x010101*(lptr[1]&0xff)); | 
 | 437 | 	lptr[2] = 0xff000000+(0x010101*(lptr[2]&0xff)); | 
 | 438 | 	lptr[3] = 0xff000000+(0x010101*(lptr[3]&0xff)); | 
 | 439 | 	lptr[4] = 0xff000000+(0x010101*(lptr[4]&0xff)); | 
 | 440 | 	lptr[5] = 0xff000000+(0x010101*(lptr[5]&0xff)); | 
 | 441 | 	lptr[6] = 0xff000000+(0x010101*(lptr[6]&0xff)); | 
 | 442 | 	lptr[7] = 0xff000000+(0x010101*(lptr[7]&0xff)); | 
 | 443 | 	lptr += 8; | 
 | 444 | 	n-=8; | 
 | 445 |     } | 
 | 446 |     while(n--) { | 
 | 447 | 	*lptr = 0xff000000+(0x010101*(*lptr&0xff)); | 
 | 448 | 	lptr++; | 
 | 449 |     } | 
 | 450 | } | 
 | 451 |  | 
 | 452 | static setalpha(lptr,n) | 
 | 453 | unsigned char *lptr; | 
 | 454 | { | 
 | 455 |     while(n>=8) { | 
 | 456 | 	lptr[0*4] = 0xff; | 
 | 457 | 	lptr[1*4] = 0xff; | 
 | 458 | 	lptr[2*4] = 0xff; | 
 | 459 | 	lptr[3*4] = 0xff; | 
 | 460 | 	lptr[4*4] = 0xff; | 
 | 461 | 	lptr[5*4] = 0xff; | 
 | 462 | 	lptr[6*4] = 0xff; | 
 | 463 | 	lptr[7*4] = 0xff; | 
 | 464 | 	lptr += 4*8; | 
 | 465 | 	n -= 8; | 
 | 466 |     } | 
 | 467 |     while(n--) { | 
 | 468 | 	*lptr = 0xff; | 
 | 469 | 	lptr += 4; | 
 | 470 |     } | 
 | 471 | } | 
 | 472 |  | 
 | 473 | static expandrow(optr,iptr,z) | 
 | 474 | unsigned char *optr, *iptr; | 
 | 475 | int z; | 
 | 476 | { | 
 | 477 |     unsigned char pixel, count; | 
 | 478 |  | 
 | 479 |     optr += z; | 
 | 480 |     while(1) { | 
 | 481 | 	pixel = *iptr++; | 
 | 482 | 	if ( !(count = (pixel & 0x7f)) ) | 
 | 483 | 	    return; | 
 | 484 | 	if(pixel & 0x80) { | 
 | 485 | 	    while(count>=8) { | 
 | 486 | 		optr[0*4] = iptr[0]; | 
 | 487 | 		optr[1*4] = iptr[1]; | 
 | 488 | 		optr[2*4] = iptr[2]; | 
 | 489 | 		optr[3*4] = iptr[3]; | 
 | 490 | 		optr[4*4] = iptr[4]; | 
 | 491 | 		optr[5*4] = iptr[5]; | 
 | 492 | 		optr[6*4] = iptr[6]; | 
 | 493 | 		optr[7*4] = iptr[7]; | 
 | 494 | 		optr += 8*4; | 
 | 495 | 		iptr += 8; | 
 | 496 | 		count -= 8; | 
 | 497 | 	    } | 
 | 498 | 	    while(count--) { | 
 | 499 | 		*optr = *iptr++; | 
 | 500 | 		optr+=4; | 
 | 501 | 	    } | 
 | 502 | 	} else { | 
 | 503 | 	    pixel = *iptr++; | 
 | 504 | 	    while(count>=8) { | 
 | 505 | 		optr[0*4] = pixel; | 
 | 506 | 		optr[1*4] = pixel; | 
 | 507 | 		optr[2*4] = pixel; | 
 | 508 | 		optr[3*4] = pixel; | 
 | 509 | 		optr[4*4] = pixel; | 
 | 510 | 		optr[5*4] = pixel; | 
 | 511 | 		optr[6*4] = pixel; | 
 | 512 | 		optr[7*4] = pixel; | 
 | 513 | 		optr += 8*4; | 
 | 514 | 		count -= 8; | 
 | 515 | 	    } | 
 | 516 | 	    while(count--) { | 
 | 517 | 		*optr = pixel; | 
 | 518 | 		optr+=4; | 
 | 519 | 	    } | 
 | 520 | 	} | 
 | 521 |     } | 
 | 522 | } | 
 | 523 |  | 
 | 524 | /* | 
 | 525 |  *	longstoimage - | 
 | 526 |  *		copy an array of longs to an iris image file.  Each long | 
 | 527 |  *	represents one pixel.  xsize and ysize specify the dimensions of | 
 | 528 |  *	the pixel array.  zsize specifies what kind of image file to | 
 | 529 |  *	write out.  if zsize is 1, the luminance of the pixels are | 
 | 530 |  *	calculated, and a sinlge channel black and white image is saved. | 
 | 531 |  *	If zsize is 3, an RGB image file is saved.  If zsize is 4, an | 
 | 532 |  *	RGBA image file is saved. | 
 | 533 |  * | 
 | 534 |  */ | 
 | 535 | static object * | 
 | 536 | longstoimage(self, args) | 
 | 537 |     object *self, *args; | 
 | 538 | { | 
| Sjoerd Mullender | 92fa23f | 1993-12-24 10:05:51 +0000 | [diff] [blame^] | 539 |     unsigned char *lptr; | 
| Sjoerd Mullender | c4f169c | 1993-12-21 17:06:12 +0000 | [diff] [blame] | 540 |     char *name; | 
 | 541 |     int xsize, ysize, zsize; | 
 | 542 |     FILE *outf; | 
 | 543 |     IMAGE image; | 
 | 544 |     int tablen, y, z, pos, len; | 
 | 545 |     long *starttab, *lengthtab; | 
 | 546 |     unsigned char *rlebuf; | 
| Sjoerd Mullender | 92fa23f | 1993-12-24 10:05:51 +0000 | [diff] [blame^] | 547 |     unsigned char *lumbuf; | 
| Sjoerd Mullender | c4f169c | 1993-12-21 17:06:12 +0000 | [diff] [blame] | 548 |     int rlebuflen, goodwrite; | 
 | 549 |  | 
 | 550 |     if (!getargs(args, "(s#iiis)", &lptr, &len, &xsize, &ysize, &zsize, &name)) | 
 | 551 | 	return NULL; | 
 | 552 |  | 
 | 553 |     goodwrite = 1; | 
 | 554 |     outf = fopen(name,"w"); | 
 | 555 |     if(!outf) { | 
 | 556 | 	err_setstr(ImgfileError,"can't open output file"); | 
 | 557 | 	return NULL; | 
 | 558 |     } | 
 | 559 |     tablen = ysize*zsize*sizeof(long); | 
 | 560 |  | 
 | 561 |     starttab = (long *)malloc(tablen); | 
 | 562 |     lengthtab = (long *)malloc(tablen); | 
 | 563 |     rlebuflen = 1.05*xsize+10; | 
 | 564 |     rlebuf = (unsigned char *)malloc(rlebuflen); | 
| Sjoerd Mullender | 92fa23f | 1993-12-24 10:05:51 +0000 | [diff] [blame^] | 565 |     lumbuf = (unsigned char *)malloc(xsize*sizeof(long)); | 
| Sjoerd Mullender | c4f169c | 1993-12-21 17:06:12 +0000 | [diff] [blame] | 566 |  | 
| Sjoerd Mullender | 92fa23f | 1993-12-24 10:05:51 +0000 | [diff] [blame^] | 567 |     memset(&image,0,sizeof(IMAGE)); | 
| Sjoerd Mullender | c4f169c | 1993-12-21 17:06:12 +0000 | [diff] [blame] | 568 |     image.imagic = IMAGIC;  | 
 | 569 |     image.type = RLE(1); | 
 | 570 |     if(zsize>1) | 
 | 571 | 	image.dim = 3; | 
 | 572 |     else | 
 | 573 | 	image.dim = 2; | 
 | 574 |     image.xsize = xsize; | 
 | 575 |     image.ysize = ysize; | 
 | 576 |     image.zsize = zsize; | 
 | 577 |     image.min = 0; | 
 | 578 |     image.max = 255; | 
 | 579 |     goodwrite *= writeheader(outf,&image); | 
 | 580 |     fseek(outf,512+2*tablen,SEEK_SET); | 
 | 581 |     pos = 512+2*tablen; | 
 | 582 |     for(y=0; y<ysize; y++) { | 
 | 583 | 	for(z=0; z<zsize; z++) { | 
 | 584 | 	    if(zsize == 1) { | 
 | 585 | 		lumrow(lptr,lumbuf,xsize); | 
 | 586 | 		len = compressrow(lumbuf,rlebuf,CHANOFFSET(z),xsize); | 
 | 587 | 	    } else { | 
 | 588 | 		len = compressrow(lptr,rlebuf,CHANOFFSET(z),xsize); | 
 | 589 | 	    } | 
 | 590 | 	    if(len>rlebuflen) { | 
 | 591 | 		err_setstr(ImgfileError,"rlebuf is too small - bad poop"); | 
 | 592 | 		free(starttab); | 
 | 593 | 		free(lengthtab); | 
 | 594 | 		free(rlebuf); | 
 | 595 | 		free(lumbuf); | 
 | 596 | 		fclose(outf); | 
 | 597 | 		return NULL; | 
 | 598 | 	    } | 
 | 599 | 	    goodwrite *= fwrite(rlebuf,len,1,outf); | 
 | 600 | 	    starttab[y+z*ysize] = pos; | 
 | 601 | 	    lengthtab[y+z*ysize] = len; | 
 | 602 | 	    pos += len; | 
 | 603 | 	} | 
| Sjoerd Mullender | 92fa23f | 1993-12-24 10:05:51 +0000 | [diff] [blame^] | 604 | 	lptr += xsize * sizeof(unsigned long); | 
| Sjoerd Mullender | c4f169c | 1993-12-21 17:06:12 +0000 | [diff] [blame] | 605 |     } | 
 | 606 |  | 
 | 607 |     fseek(outf,512,SEEK_SET); | 
 | 608 |     goodwrite *= writetab(outf,starttab,tablen); | 
 | 609 |     goodwrite *= writetab(outf,lengthtab,tablen); | 
 | 610 |     free(starttab); | 
 | 611 |     free(lengthtab); | 
 | 612 |     free(rlebuf); | 
 | 613 |     free(lumbuf); | 
 | 614 |     fclose(outf); | 
 | 615 |     if(goodwrite) { | 
 | 616 | 	INCREF(None); | 
 | 617 | 	return None; | 
 | 618 |     } else { | 
 | 619 | 	err_setstr(ImgfileError,"not enough space for image!!"); | 
 | 620 | 	return NULL; | 
 | 621 |     } | 
 | 622 | } | 
 | 623 |  | 
 | 624 | /* static utility functions for longstoimage */ | 
 | 625 |  | 
 | 626 | static lumrow(rgbptr,lumptr,n)  | 
 | 627 | unsigned char *rgbptr, *lumptr; | 
 | 628 | int n; | 
 | 629 | { | 
 | 630 |     lumptr += CHANOFFSET(0); | 
 | 631 |     while(n--) { | 
 | 632 | 	*lumptr = ILUM(rgbptr[OFFSET_R],rgbptr[OFFSET_G],rgbptr[OFFSET_B]); | 
 | 633 | 	lumptr += 4; | 
 | 634 | 	rgbptr += 4; | 
 | 635 |     } | 
 | 636 | } | 
 | 637 |  | 
 | 638 | static int compressrow(lbuf,rlebuf,z,cnt) | 
 | 639 | unsigned char *lbuf, *rlebuf; | 
 | 640 | int z, cnt; | 
 | 641 | { | 
 | 642 |     unsigned char *iptr, *ibufend, *sptr, *optr; | 
 | 643 |     short todo, cc;							 | 
 | 644 |     long count; | 
 | 645 |  | 
 | 646 |     lbuf += z; | 
 | 647 |     iptr = lbuf; | 
 | 648 |     ibufend = iptr+cnt*4; | 
 | 649 |     optr = rlebuf; | 
 | 650 |  | 
 | 651 |     while(iptr<ibufend) { | 
 | 652 | 	sptr = iptr; | 
 | 653 | 	iptr += 8; | 
 | 654 | 	while((iptr<ibufend)&& ((iptr[-8]!=iptr[-4])||(iptr[-4]!=iptr[0]))) | 
 | 655 | 	    iptr+=4; | 
 | 656 | 	iptr -= 8; | 
 | 657 | 	count = (iptr-sptr)/4; | 
 | 658 | 	while(count) { | 
 | 659 | 	    todo = count>126 ? 126:count; | 
 | 660 | 	    count -= todo; | 
 | 661 | 	    *optr++ = 0x80|todo; | 
 | 662 | 	    while(todo>8) { | 
 | 663 | 		optr[0] = sptr[0*4]; | 
 | 664 | 		optr[1] = sptr[1*4]; | 
 | 665 | 		optr[2] = sptr[2*4]; | 
 | 666 | 		optr[3] = sptr[3*4]; | 
 | 667 | 		optr[4] = sptr[4*4]; | 
 | 668 | 		optr[5] = sptr[5*4]; | 
 | 669 | 		optr[6] = sptr[6*4]; | 
 | 670 | 		optr[7] = sptr[7*4]; | 
 | 671 | 		optr += 8; | 
 | 672 | 		sptr += 8*4; | 
 | 673 | 		todo -= 8; | 
 | 674 | 	    } | 
 | 675 | 	    while(todo--) { | 
 | 676 | 		*optr++ = *sptr; | 
 | 677 | 		sptr += 4; | 
 | 678 | 	    } | 
 | 679 | 	} | 
 | 680 | 	sptr = iptr; | 
 | 681 | 	cc = *iptr; | 
 | 682 | 	iptr += 4; | 
 | 683 | 	while( (iptr<ibufend) && (*iptr == cc) ) | 
 | 684 | 	    iptr += 4; | 
 | 685 | 	count = (iptr-sptr)/4; | 
 | 686 | 	while(count) { | 
 | 687 | 	    todo = count>126 ? 126:count; | 
 | 688 | 	    count -= todo; | 
 | 689 | 	    *optr++ = todo; | 
 | 690 | 	    *optr++ = cc; | 
 | 691 | 	} | 
 | 692 |     } | 
 | 693 |     *optr++ = 0; | 
 | 694 |     return optr - (unsigned char *)rlebuf; | 
 | 695 | } | 
 | 696 |  | 
 | 697 | static struct methodlist rgbimg_methods[] = { | 
 | 698 |     {"sizeofimage",	sizeofimage}, | 
 | 699 |     {"longimagedata",	longimagedata}, | 
 | 700 |     {"longstoimage",	longstoimage}, | 
 | 701 |     {NULL, NULL}		/* sentinel */ | 
 | 702 | }; | 
 | 703 |  | 
 | 704 | void | 
 | 705 | initrgbimg() | 
 | 706 | { | 
 | 707 |     object *m, *d; | 
 | 708 |     m = initmodule("rgbimg", rgbimg_methods); | 
 | 709 |     d = getmoduledict(m); | 
 | 710 |     ImgfileError = newstringobject("rgbimg,error"); | 
 | 711 |     if (ImgfileError == NULL || dictinsert(d, "error", ImgfileError)) | 
 | 712 | 	fatal("can't define rgbimg.error"); | 
 | 713 | } |