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