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