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