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