doxygen: prevent GPL license block from being parsed as doxygen comment.
[blender.git] / source / blender / imbuf / intern / iris.c
1 /*
2  *
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  * iris.c
28  *
29  * $Id$
30  */
31
32 #include <string.h>
33
34 #include "BLI_blenlib.h"
35 #include "MEM_guardedalloc.h"
36
37 #include "imbuf.h"
38 #include "IMB_imbuf_types.h"
39 #include "IMB_imbuf.h"
40 #include "IMB_allocimbuf.h"
41 #include "IMB_filetype.h"
42
43 typedef struct {
44         unsigned short  imagic;         /* stuff saved on disk . . */
45         unsigned short  type;
46         unsigned short  dim;
47         unsigned short  xsize;
48         unsigned short  ysize;
49         unsigned short  zsize;
50         unsigned int    min;
51         unsigned int    max;
52         unsigned int    wastebytes;     
53         char            name[80];
54         unsigned int    colormap;
55
56         int             file;           /* stuff used in core only */
57         unsigned short  flags;
58         short           dorev;
59         short           x;
60         short           y;
61         short           z;
62         short           cnt;
63         unsigned short  *ptr;
64         unsigned short  *base;
65         unsigned short  *tmpbuf;
66         unsigned int    offset;
67         unsigned int    rleend;         /* for rle images */
68         unsigned int    *rowstart;      /* for rle images */
69         int             *rowsize;       /* for rle images */
70 } IMAGE;
71
72 #define RINTLUM (79)
73 #define GINTLUM (156)
74 #define BINTLUM (21)
75
76 #define ILUM(r,g,b)     ((int)(RINTLUM*(r)+GINTLUM*(g)+BINTLUM*(b))>>8)
77
78 #define OFFSET_R        0       /* this is byte order dependent */
79 #define OFFSET_G        1
80 #define OFFSET_B        2
81 #define OFFSET_A        3
82
83 #define CHANOFFSET(z)   (3-(z)) /* this is byte order dependent */
84
85 #define TYPEMASK                0xff00
86 #define BPPMASK                 0x00ff
87 #define ITYPE_VERBATIM          0x0000
88 #define ITYPE_RLE               0x0100
89 #define ISRLE(type)             (((type) & 0xff00) == ITYPE_RLE)
90 #define ISVERBATIM(type)        (((type) & 0xff00) == ITYPE_VERBATIM)
91 #define BPP(type)               ((type) & BPPMASK)
92 #define RLE(bpp)                (ITYPE_RLE | (bpp))
93 #define VERBATIM(bpp)           (ITYPE_VERBATIM | (bpp))
94 #define IBUFSIZE(pixels)        ((pixels+(pixels>>6))<<2)
95 #define RLE_NOP                 0x00
96
97 /* funcs */
98 static void readheader(FILE *inf, IMAGE *image);
99 static int writeheader(FILE *outf, IMAGE *image);
100
101 static unsigned short getshort(FILE *inf);
102 static unsigned int getlong(FILE *inf);
103 static void putshort(FILE *outf, unsigned short val);
104 static int putlong(FILE *outf, unsigned int val);
105 static int writetab(FILE *outf, unsigned int *tab, int len);
106 static void readtab(FILE *inf, unsigned int *tab, int len);
107
108 static void expandrow(unsigned char *optr, unsigned char *iptr, int z);
109 static void expandrow2(float *optr, unsigned char *iptr, int z);
110 static void interleaverow(unsigned char *lptr, unsigned char *cptr, int z, int n);
111 static void interleaverow2(float *lptr, unsigned char *cptr, int z, int n);
112 static int compressrow(unsigned char *lbuf, unsigned char *rlebuf, int z, int cnt);
113 static void lumrow(unsigned char *rgbptr, unsigned char *lumptr, int n);
114
115 /*
116  *      byte order independent read/write of shorts and ints.
117  *
118  */
119
120 static uchar * file_data;
121 static int file_offset;
122
123 static unsigned short getshort(FILE *inf)
124 {
125         unsigned char * buf;
126         (void)inf; /* unused */
127
128         buf = file_data + file_offset;
129         file_offset += 2;
130         
131         return (buf[0]<<8)+(buf[1]<<0);
132 }
133
134 static unsigned int getlong(FILE *inf)
135 {
136         unsigned char * buf;
137         (void)inf; /* unused */
138         
139         buf = file_data + file_offset;
140         file_offset += 4;
141         
142         return (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+(buf[3]<<0);
143 }
144
145 static void putshort(FILE *outf, unsigned short val)
146 {
147         unsigned char buf[2];
148
149         buf[0] = (val>>8);
150         buf[1] = (val>>0);
151         fwrite(buf,2,1,outf);
152 }
153
154 static int putlong(FILE *outf, unsigned int val)
155 {
156         unsigned char buf[4];
157
158         buf[0] = (val>>24);
159         buf[1] = (val>>16);
160         buf[2] = (val>>8);
161         buf[3] = (val>>0);
162         return fwrite(buf,4,1,outf);
163 }
164
165 static void readheader(FILE *inf, IMAGE *image)
166 {
167         memset(image, 0, sizeof(IMAGE));
168         image->imagic = getshort(inf);
169         image->type = getshort(inf);
170         image->dim = getshort(inf);
171         image->xsize = getshort(inf);
172         image->ysize = getshort(inf);
173         image->zsize = getshort(inf);
174 }
175
176 static int writeheader(FILE *outf, IMAGE *image)
177 {
178         IMAGE t= {0};
179
180         fwrite(&t,sizeof(IMAGE),1,outf);
181         fseek(outf,0,SEEK_SET);
182         putshort(outf,image->imagic);
183         putshort(outf,image->type);
184         putshort(outf,image->dim);
185         putshort(outf,image->xsize);
186         putshort(outf,image->ysize);
187         putshort(outf,image->zsize);
188         putlong(outf,image->min);
189         putlong(outf,image->max);
190         putlong(outf,0);
191         return fwrite("no name",8,1,outf);
192 }
193
194 static int writetab(FILE *outf, unsigned int *tab, int len)
195 {
196         int r = 0;
197
198         while(len) {
199                 r = putlong(outf,*tab++);
200                 len -= 4;
201         }
202         return r;
203 }
204
205 static void readtab(FILE *inf, unsigned int *tab, int len)
206 {
207         while(len) {
208                 *tab++ = getlong(inf);
209                 len -= 4;
210         }
211 }
212
213 static void test_endian_zbuf(struct ImBuf *ibuf)
214 {
215         int len;
216         int *zval;
217         
218         if( BIG_LONG(1) == 1 ) return;
219         if(ibuf->zbuf==0) return;
220         
221         len= ibuf->x*ibuf->y;
222         zval= ibuf->zbuf;
223         
224         while(len--) {
225                 zval[0]= BIG_LONG(zval[0]);
226                 zval++;
227         }
228 }
229
230 /* from misc_util: flip the bytes from x  */
231 #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1])
232
233 /* this one is only def-ed once, strangely... */
234 #define GSS(x) (((uchar *)(x))[1] << 8 | ((uchar *)(x))[0])
235
236 int imb_is_a_iris(unsigned char *mem)
237 {
238         return ((GS(mem) == IMAGIC) || (GSS(mem) == IMAGIC));
239 }
240
241 /*
242  *      longimagedata - 
243  *              read in a B/W RGB or RGBA iris image file and return a 
244  *      pointer to an array of ints.
245  *
246  */
247
248 struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags)
249 {
250         unsigned int *base, *lptr = NULL;
251         float *fbase, *fptr = NULL;
252         unsigned int *zbase, *zptr;
253         unsigned char *rledat;
254         unsigned int *starttab, *lengthtab;
255         FILE *inf = NULL;
256         IMAGE image;
257         int x, y, z, tablen;
258         int xsize, ysize, zsize;
259         int bpp, rle, cur, badorder;
260         ImBuf * ibuf;
261
262         (void)size; /* unused */
263         
264         if(!imb_is_a_iris(mem)) return NULL;
265
266         /*printf("new iris\n");*/
267         
268         file_data = mem;
269         file_offset = 0;
270         
271         readheader(inf, &image);
272         if(image.imagic != IMAGIC) {
273                 fprintf(stderr,"longimagedata: bad magic number in image file\n");
274                 return(0);
275         }
276         
277         rle = ISRLE(image.type);
278         bpp = BPP(image.type);
279         if(bpp != 1 && bpp != 2) {
280                 fprintf(stderr,"longimagedata: image must have 1 or 2 byte per pix chan\n");
281                 return(0);
282         }
283         
284         xsize = image.xsize;
285         ysize = image.ysize;
286         zsize = image.zsize;
287         
288         if (flags & IB_test) {
289                 ibuf = IMB_allocImBuf(image.xsize, image.ysize, 8 * image.zsize, 0);
290                 if (ibuf) ibuf->ftype = IMAGIC;
291                 return(ibuf);
292         }
293         
294         if (rle) {
295                 
296                 tablen = ysize*zsize*sizeof(int);
297                 starttab = (unsigned int *)MEM_mallocN(tablen, "iris starttab");
298                 lengthtab = (unsigned int *)MEM_mallocN(tablen, "iris endtab");
299                 file_offset = 512;
300                 
301                 readtab(inf,starttab,tablen);
302                 readtab(inf,lengthtab,tablen);
303         
304                 /* check data order */
305                 cur = 0;
306                 badorder = 0;
307                 for (y = 0; y<ysize; y++) {
308                         for (z = 0; z<zsize; z++) {
309                                 if (starttab[y+z*ysize]<cur) {
310                                         badorder = 1;
311                                         break;
312                                 }
313                                 cur = starttab[y+z*ysize];
314                         }
315                         if(badorder)
316                                 break;
317                 }
318         
319                 if (bpp == 1) {
320                         
321                         ibuf = IMB_allocImBuf(xsize, ysize, 8 * zsize, IB_rect);
322                         if (ibuf->depth > 32) ibuf->depth = 32;
323                         base = ibuf->rect;
324                         zbase = (unsigned int *)ibuf->zbuf;
325                         
326                         if (badorder) {
327                                 for(z=0; z<zsize; z++) {
328                                         lptr = base;
329                                         for(y=0; y<ysize; y++) {
330                                                 file_offset = starttab[y+z*ysize];
331                                                 
332                                                 rledat = file_data + file_offset;
333                                                 file_offset += lengthtab[y+z*ysize];
334                                                 
335                                                 expandrow((uchar *)lptr, rledat, 3-z);
336                                                 lptr += xsize;
337                                         }
338                                 }
339                         } else {
340                                 lptr = base;
341                                 zptr = zbase;
342                                 for(y=0; y<ysize; y++) {
343                                 
344                                         for(z=0; z<zsize; z++) {
345                                                 
346                                                 file_offset = starttab[y+z*ysize];
347
348                                                 rledat = file_data + file_offset;
349                                                 file_offset += lengthtab[y+z*ysize];
350                                                 
351                                                 if(z<4) expandrow((uchar *)lptr, rledat, 3-z);
352                                                 else if(z<8) expandrow((uchar *)zptr, rledat, 7-z);
353                                         }
354                                         lptr += xsize;
355                                         zptr += xsize;
356                                 }
357                         }
358                         
359
360                 } else {        /* bpp == 2 */
361                         
362                         ibuf = IMB_allocImBuf(xsize, ysize, 32, (flags & IB_rect)|IB_rectfloat);
363                         
364                         fbase = ibuf->rect_float;
365                         
366                         if (badorder) {
367                                 for(z=0; z<zsize; z++) {
368                                         fptr = fbase;
369                                         for(y=0; y<ysize; y++) {
370                                                 file_offset = starttab[y+z*ysize];
371                                                 
372                                                 rledat = file_data + file_offset;
373                                                 file_offset += lengthtab[y+z*ysize];
374                                                 
375                                                 expandrow2(fptr, rledat, 3-z);
376                                                 fptr += xsize * 4;
377                                         }
378                                 }
379                         } else {
380                                 fptr = fbase;
381
382                                 for(y=0; y<ysize; y++) {
383                                 
384                                         for(z=0; z<zsize; z++) {
385                                                 
386                                                 file_offset = starttab[y+z*ysize];
387
388                                                 rledat = file_data + file_offset;
389                                                 file_offset += lengthtab[y+z*ysize];
390                                                 
391                                                 expandrow2(fptr, rledat, 3-z);
392                                                 
393                                         }
394                                         fptr += xsize * 4;
395                                 }
396                         }
397                 }
398                 
399                 MEM_freeN(starttab);
400                 MEM_freeN(lengthtab);   
401
402         } else {
403                 if (bpp == 1) {
404                         
405                         ibuf = IMB_allocImBuf(xsize, ysize, 8 * zsize, IB_rect);
406                         if (ibuf->depth > 32) ibuf->depth = 32;
407
408                         base = ibuf->rect;
409                         zbase = (unsigned int *)ibuf->zbuf;
410                         
411                         file_offset = 512;
412                         rledat = file_data + file_offset;
413                         
414                         for(z = 0; z < zsize; z++) {
415                                 
416                                 if(z<4) lptr = base;
417                                 else if(z<8) lptr= zbase;
418                                 
419                                 for(y = 0; y < ysize; y++) {
420
421                                         interleaverow((uchar *)lptr, rledat, 3-z, xsize);
422                                         rledat += xsize;
423                                         
424                                         lptr += xsize;
425                                 }
426                         }
427                         
428                 } else {        /* bpp == 2 */
429                         
430                         ibuf = IMB_allocImBuf(xsize, ysize, 32, (flags & IB_rect)|IB_rectfloat);
431
432                         fbase = ibuf->rect_float;
433
434                         file_offset = 512;
435                         rledat = file_data + file_offset;
436                         
437                         for(z = 0; z < zsize; z++) {
438                                 
439                                 fptr = fbase;
440                                 
441                                 for(y = 0; y < ysize; y++) {
442
443                                         interleaverow2(fptr, rledat, 3-z, xsize);
444                                         rledat += xsize * 2;
445                                         
446                                         fptr += xsize * 4;
447                                 }
448                         }
449                         
450                 }
451         }
452         
453         
454         if (bpp == 1) {
455                 uchar * rect;
456                 
457                 if (image.zsize == 1){
458                         rect = (uchar *) ibuf->rect;
459                         for (x = ibuf->x * ibuf->y; x > 0; x--) {
460                                 rect[0] = 255;
461                                 rect[1] = rect[2] = rect[3];
462                                 rect += 4;
463                         }
464                 } else if (image.zsize == 2){
465                         /* grayscale with alpha */
466                         rect = (uchar *) ibuf->rect;
467                         for (x = ibuf->x * ibuf->y; x > 0; x--) {
468                                 rect[0] = rect[2];
469                                 rect[1] = rect[2] = rect[3];
470                                 rect += 4;
471                         }
472                 } else if (image.zsize == 3){
473                         /* add alpha */
474                         rect = (uchar *) ibuf->rect;
475                         for (x = ibuf->x * ibuf->y; x > 0; x--) {
476                                 rect[0] = 255;
477                                 rect += 4;
478                         }
479                 }
480                 
481         } else {        /* bpp == 2 */
482                 
483                 if (image.zsize == 1){
484                         fbase = ibuf->rect_float;
485                         for (x = ibuf->x * ibuf->y; x > 0; x--) {
486                                 fbase[0] = 1;
487                                 fbase[1] = fbase[2] = fbase[3];
488                                 fbase += 4;
489                         }
490                 } else if (image.zsize == 2){
491                         /* grayscale with alpha */
492                         fbase = ibuf->rect_float;
493                         for (x = ibuf->x * ibuf->y; x > 0; x--) {
494                                 fbase[0] = fbase[2];
495                                 fbase[1] = fbase[2] = fbase[3];
496                                 fbase += 4;
497                         }
498                 } else if (image.zsize == 3){
499                         /* add alpha */
500                         fbase = ibuf->rect_float;
501                         for (x = ibuf->x * ibuf->y; x > 0; x--) {
502                                 fbase[0] = 1;
503                                 fbase += 4;
504                         }
505                 }
506                 
507                 if (flags & IB_rect) {
508                         IMB_rect_from_float(ibuf);
509                 }
510                 
511         }
512
513         ibuf->ftype = IMAGIC;
514         ibuf->profile = IB_PROFILE_SRGB;
515         
516         test_endian_zbuf(ibuf);
517         
518         if (ibuf) {
519                 if (ibuf->rect) 
520                         IMB_convert_rgba_to_abgr(ibuf);
521         }
522
523         return(ibuf);
524 }
525
526 /* static utility functions for longimagedata */
527
528 static void interleaverow(unsigned char *lptr, unsigned char *cptr, int z, int n)
529 {
530         lptr += z;
531         while(n--) {
532                 *lptr = *cptr++;
533                 lptr += 4;
534         }
535 }
536
537 static void interleaverow2(float *lptr, unsigned char *cptr, int z, int n)
538 {
539         lptr += z;
540         while(n--) {
541                 *lptr = ((cptr[0]<<8) | (cptr[1]<<0)) / (float)0xFFFF;          
542                 cptr += 2;
543                 lptr += 4;
544         }
545 }
546
547 static void expandrow2(float *optr, unsigned char *iptr, int z)
548 {
549         unsigned short pixel, count;
550         float pixel_f;
551
552         optr += z;
553         while(1) {
554                 pixel = (iptr[0]<<8) | (iptr[1]<<0);
555                 iptr += 2;
556                 
557                 if ( !(count = (pixel & 0x7f)) )
558                         return;
559                 if(pixel & 0x80) {
560                         while(count>=8) {
561                                 optr[0*4] = ((iptr[0]<<8) | (iptr[1]<<0))/(float)0xFFFF;
562                                 optr[1*4] = ((iptr[2]<<8) | (iptr[3]<<0))/(float)0xFFFF;
563                                 optr[2*4] = ((iptr[4]<<8) | (iptr[5]<<0))/(float)0xFFFF;
564                                 optr[3*4] = ((iptr[6]<<8) | (iptr[7]<<0))/(float)0xFFFF;
565                                 optr[4*4] = ((iptr[8]<<8) | (iptr[9]<<0))/(float)0xFFFF;
566                                 optr[5*4] = ((iptr[10]<<8) | (iptr[11]<<0))/(float)0xFFFF;
567                                 optr[6*4] = ((iptr[12]<<8) | (iptr[13]<<0))/(float)0xFFFF;
568                                 optr[7*4] = ((iptr[14]<<8) | (iptr[15]<<0))/(float)0xFFFF;
569                                 optr += 8*4;
570                                 iptr += 8*2;
571                                 count -= 8;
572                         }
573                         while(count--) {
574                                 *optr = ((iptr[0]<<8) | (iptr[1]<<0))/(float)0xFFFF;
575                                 iptr+=2;
576                                 optr+=4;
577                         }
578                 } else {
579                         pixel_f = ((iptr[0]<<8) | (iptr[1]<<0))/(float)0xFFFF;
580                         iptr += 2;
581
582                         while(count>=8) {
583                                 optr[0*4] = pixel_f;
584                                 optr[1*4] = pixel_f;
585                                 optr[2*4] = pixel_f;
586                                 optr[3*4] = pixel_f;
587                                 optr[4*4] = pixel_f;
588                                 optr[5*4] = pixel_f;
589                                 optr[6*4] = pixel_f;
590                                 optr[7*4] = pixel_f;
591                                 optr += 8*4;
592                                 count -= 8;
593                         }
594                         while(count--) {
595                                 *optr = pixel_f;
596                                 optr+=4;
597                         }
598                 }
599         }       
600 }
601
602 static void expandrow(unsigned char *optr, unsigned char *iptr, int z)
603 {
604         unsigned char pixel, count;
605
606         optr += z;
607         while(1) {
608                 pixel = *iptr++;
609                 if ( !(count = (pixel & 0x7f)) )
610                         return;
611                 if(pixel & 0x80) {
612                         while(count>=8) {
613                                 optr[0*4] = iptr[0];
614                                 optr[1*4] = iptr[1];
615                                 optr[2*4] = iptr[2];
616                                 optr[3*4] = iptr[3];
617                                 optr[4*4] = iptr[4];
618                                 optr[5*4] = iptr[5];
619                                 optr[6*4] = iptr[6];
620                                 optr[7*4] = iptr[7];
621                                 optr += 8*4;
622                                 iptr += 8;
623                                 count -= 8;
624                         }
625                         while(count--) {
626                                 *optr = *iptr++;
627                                 optr+=4;
628                         }
629                 } else {
630                         pixel = *iptr++;
631                         while(count>=8) {
632                                 optr[0*4] = pixel;
633                                 optr[1*4] = pixel;
634                                 optr[2*4] = pixel;
635                                 optr[3*4] = pixel;
636                                 optr[4*4] = pixel;
637                                 optr[5*4] = pixel;
638                                 optr[6*4] = pixel;
639                                 optr[7*4] = pixel;
640                                 optr += 8*4;
641                                 count -= 8;
642                         }
643                         while(count--) {
644                                 *optr = pixel;
645                                 optr+=4;
646                         }
647                 }
648         }
649 }
650
651 /*
652  *      output_iris -
653  *              copy an array of ints to an iris image file.  Each int
654  *      represents one pixel.  xsize and ysize specify the dimensions of
655  *      the pixel array.  zsize specifies what kind of image file to
656  *      write out.  if zsize is 1, the luminance of the pixels are
657  *      calculated, and a sinlge channel black and white image is saved.
658  *      If zsize is 3, an RGB image file is saved.  If zsize is 4, an
659  *      RGBA image file is saved.
660  *
661  *  Added: zbuf write
662  */
663
664 static int output_iris(unsigned int *lptr, int xsize, int ysize, int zsize, const char *name, int *zptr)
665 {
666         FILE *outf;
667         IMAGE *image;
668         int tablen, y, z, pos, len = 0;
669         unsigned int *starttab, *lengthtab;
670         unsigned char *rlebuf;
671         unsigned int *lumbuf;
672         int rlebuflen, goodwrite;
673
674         goodwrite = 1;
675         outf = fopen(name, "wb");
676         if(!outf) return 0;
677
678         tablen = ysize*zsize*sizeof(int);
679
680         image = (IMAGE *)MEM_mallocN(sizeof(IMAGE), "iris image");
681         starttab = (unsigned int *)MEM_mallocN(tablen, "iris starttab");
682         lengthtab = (unsigned int *)MEM_mallocN(tablen, "iris lengthtab");
683         rlebuflen = 1.05*xsize+10;
684         rlebuf = (unsigned char *)MEM_mallocN(rlebuflen, "iris rlebuf");
685         lumbuf = (unsigned int *)MEM_mallocN(xsize*sizeof(int), "iris lumbuf");
686
687         memset(image, 0, sizeof(IMAGE));
688         image->imagic = IMAGIC;
689         image->type = RLE(1);
690         if(zsize>1)
691                 image->dim = 3;
692         else
693                 image->dim = 2;
694         image->xsize = xsize;
695         image->ysize = ysize;
696         image->zsize = zsize;
697         image->min = 0;
698         image->max = 255;
699         goodwrite *= writeheader(outf,image);
700         fseek(outf,512+2*tablen,SEEK_SET);
701         pos = 512+2*tablen;
702         
703         for (y = 0; y < ysize; y++) {
704                 for (z = 0; z < zsize; z++) {
705                         
706                         if (zsize == 1) {
707                                 lumrow((uchar *)lptr,(uchar *)lumbuf,xsize);
708                                 len = compressrow((uchar *)lumbuf,rlebuf,CHANOFFSET(z),xsize);
709                         }
710                         else {
711                                 if(z<4) {
712                                         len = compressrow((uchar *)lptr, rlebuf,CHANOFFSET(z),xsize);
713                                 }
714                                 else if(z<8 && zptr) {
715                                         len = compressrow((uchar *)zptr, rlebuf,CHANOFFSET(z-4),xsize);
716                                 }
717                         }
718                         if(len>rlebuflen) {
719                                 fprintf(stderr,"output_iris: rlebuf is too small - bad poop\n");
720                                 exit(1);
721                         }
722                         goodwrite *= fwrite(rlebuf, len, 1, outf);
723                         starttab[y+z*ysize] = pos;
724                         lengthtab[y+z*ysize] = len;
725                         pos += len;
726                 }
727                 lptr += xsize;
728                 if(zptr) zptr += xsize;
729         }
730
731         fseek(outf,512,SEEK_SET);
732         goodwrite *= writetab(outf,starttab,tablen);
733         goodwrite *= writetab(outf,lengthtab,tablen);
734         MEM_freeN(image);
735         MEM_freeN(starttab);
736         MEM_freeN(lengthtab);
737         MEM_freeN(rlebuf);
738         MEM_freeN(lumbuf);
739         fclose(outf);
740         if(goodwrite)
741                 return 1;
742         else {
743                 fprintf(stderr,"output_iris: not enough space for image!!\n");
744                 return 0;
745         }
746 }
747
748 /* static utility functions for output_iris */
749
750 static void lumrow(unsigned char *rgbptr, unsigned char *lumptr, int n)
751 {
752         lumptr += CHANOFFSET(0);
753         while(n--) {
754                 *lumptr = ILUM(rgbptr[OFFSET_R],rgbptr[OFFSET_G],rgbptr[OFFSET_B]);
755                 lumptr += 4;
756                 rgbptr += 4;
757         }
758 }
759
760 static int compressrow(unsigned char *lbuf, unsigned char *rlebuf, int z, int cnt)
761 {
762         unsigned char *iptr, *ibufend, *sptr, *optr;
763         short todo, cc;
764         int count;
765
766         lbuf += z;
767         iptr = lbuf;
768         ibufend = iptr+cnt*4;
769         optr = rlebuf;
770
771         while(iptr<ibufend) {
772                 sptr = iptr;
773                 iptr += 8;
774                 while((iptr<ibufend)&& ((iptr[-8]!=iptr[-4])||(iptr[-4]!=iptr[0])))
775                         iptr+=4;
776                 iptr -= 8;
777                 count = (iptr-sptr)/4;
778                 while(count) {
779                         todo = count>126 ? 126:count;
780                         count -= todo;
781                         *optr++ = 0x80|todo;
782                         while(todo>8) {
783                                 optr[0] = sptr[0*4];
784                                 optr[1] = sptr[1*4];
785                                 optr[2] = sptr[2*4];
786                                 optr[3] = sptr[3*4];
787                                 optr[4] = sptr[4*4];
788                                 optr[5] = sptr[5*4];
789                                 optr[6] = sptr[6*4];
790                                 optr[7] = sptr[7*4];
791
792                                 optr += 8;
793                                 sptr += 8*4;
794                                 todo -= 8;
795                         }
796                         while(todo--) {
797                                 *optr++ = *sptr;
798                                 sptr += 4;
799                         }
800                 }
801                 sptr = iptr;
802                 cc = *iptr;
803                 iptr += 4;
804                 while( (iptr<ibufend) && (*iptr == cc) )
805                         iptr += 4;
806                 count = (iptr-sptr)/4;
807                 while(count) {
808                         todo = count>126 ? 126:count;
809                         count -= todo;
810                         *optr++ = todo;
811                         *optr++ = cc;
812                 }
813         }
814         *optr++ = 0;
815         return optr - (unsigned char *)rlebuf;
816 }
817
818 int imb_saveiris(struct ImBuf * ibuf, const char *name, int flags)
819 {
820         short zsize;
821         int ret;
822
823         zsize = (ibuf->depth + 7) >> 3;
824         if (flags & IB_zbuf &&  ibuf->zbuf != 0) zsize = 8;
825         
826         IMB_convert_rgba_to_abgr(ibuf);
827         test_endian_zbuf(ibuf);
828
829         ret = output_iris(ibuf->rect, ibuf->x, ibuf->y, zsize, name, ibuf->zbuf);
830
831         /* restore! Quite clumsy, 2 times a switch... maybe better a malloc ? */
832         IMB_convert_rgba_to_abgr(ibuf);
833         test_endian_zbuf(ibuf);
834
835         return(ret);
836 }
837