Blender V2.61 - r43446

iris.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include <string.h>
00034 
00035 #include "BLI_blenlib.h"
00036 #include "MEM_guardedalloc.h"
00037 
00038 #include "imbuf.h"
00039 #include "IMB_imbuf_types.h"
00040 #include "IMB_imbuf.h"
00041 #include "IMB_allocimbuf.h"
00042 #include "IMB_filetype.h"
00043 
00044 typedef struct {
00045     unsigned short  imagic;     /* stuff saved on disk . . */
00046     unsigned short  type;
00047     unsigned short  dim;
00048     unsigned short  xsize;
00049     unsigned short  ysize;
00050     unsigned short  zsize;
00051     unsigned int    min;
00052     unsigned int    max;
00053     unsigned int    wastebytes; 
00054     char        name[80];
00055     unsigned int    colormap;
00056 
00057     int         file;       /* stuff used in core only */
00058     unsigned short  flags;
00059     short       dorev;
00060     short       x;
00061     short       y;
00062     short       z;
00063     short       cnt;
00064     unsigned short  *ptr;
00065     unsigned short  *base;
00066     unsigned short  *tmpbuf;
00067     unsigned int    offset;
00068     unsigned int    rleend;     /* for rle images */
00069     unsigned int    *rowstart;  /* for rle images */
00070     int     *rowsize;   /* for rle images */
00071 } IMAGE;
00072 
00073 #define RINTLUM (79)
00074 #define GINTLUM (156)
00075 #define BINTLUM (21)
00076 
00077 #define ILUM(r,g,b) ((int)(RINTLUM*(r)+GINTLUM*(g)+BINTLUM*(b))>>8)
00078 
00079 #define OFFSET_R    0   /* this is byte order dependent */
00080 #define OFFSET_G    1
00081 #define OFFSET_B    2
00082 #define OFFSET_A    3
00083 
00084 #define CHANOFFSET(z)   (3-(z)) /* this is byte order dependent */
00085 
00086 #define TYPEMASK        0xff00
00087 #define BPPMASK         0x00ff
00088 #define ITYPE_VERBATIM      0x0000
00089 #define ITYPE_RLE       0x0100
00090 #define ISRLE(type)     (((type) & 0xff00) == ITYPE_RLE)
00091 #define ISVERBATIM(type)    (((type) & 0xff00) == ITYPE_VERBATIM)
00092 #define BPP(type)       ((type) & BPPMASK)
00093 #define RLE(bpp)        (ITYPE_RLE | (bpp))
00094 #define VERBATIM(bpp)       (ITYPE_VERBATIM | (bpp))
00095 #define IBUFSIZE(pixels)    ((pixels+(pixels>>6))<<2)
00096 #define RLE_NOP         0x00
00097 
00098 /* funcs */
00099 static void readheader(FILE *inf, IMAGE *image);
00100 static int writeheader(FILE *outf, IMAGE *image);
00101 
00102 static unsigned short getshort(FILE *inf);
00103 static unsigned int getlong(FILE *inf);
00104 static void putshort(FILE *outf, unsigned short val);
00105 static int putlong(FILE *outf, unsigned int val);
00106 static int writetab(FILE *outf, unsigned int *tab, int len);
00107 static void readtab(FILE *inf, unsigned int *tab, int len);
00108 
00109 static void expandrow(unsigned char *optr, unsigned char *iptr, int z);
00110 static void expandrow2(float *optr, unsigned char *iptr, int z);
00111 static void interleaverow(unsigned char *lptr, unsigned char *cptr, int z, int n);
00112 static void interleaverow2(float *lptr, unsigned char *cptr, int z, int n);
00113 static int compressrow(unsigned char *lbuf, unsigned char *rlebuf, int z, int cnt);
00114 static void lumrow(unsigned char *rgbptr, unsigned char *lumptr, int n);
00115 
00116 /*
00117  *  byte order independent read/write of shorts and ints.
00118  *
00119  */
00120 
00121 static uchar * file_data;
00122 static int file_offset;
00123 
00124 static unsigned short getshort(FILE *inf)
00125 {
00126     unsigned char * buf;
00127     (void)inf; /* unused */
00128 
00129     buf = file_data + file_offset;
00130     file_offset += 2;
00131     
00132     return (buf[0]<<8)+(buf[1]<<0);
00133 }
00134 
00135 static unsigned int getlong(FILE *inf)
00136 {
00137     unsigned char * buf;
00138     (void)inf; /* unused */
00139     
00140     buf = file_data + file_offset;
00141     file_offset += 4;
00142     
00143     return (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+(buf[3]<<0);
00144 }
00145 
00146 static void putshort(FILE *outf, unsigned short val)
00147 {
00148     unsigned char buf[2];
00149 
00150     buf[0] = (val>>8);
00151     buf[1] = (val>>0);
00152     fwrite(buf,2,1,outf);
00153 }
00154 
00155 static int putlong(FILE *outf, unsigned int val)
00156 {
00157     unsigned char buf[4];
00158 
00159     buf[0] = (val>>24);
00160     buf[1] = (val>>16);
00161     buf[2] = (val>>8);
00162     buf[3] = (val>>0);
00163     return fwrite(buf,4,1,outf);
00164 }
00165 
00166 static void readheader(FILE *inf, IMAGE *image)
00167 {
00168     memset(image, 0, sizeof(IMAGE));
00169     image->imagic = getshort(inf);
00170     image->type = getshort(inf);
00171     image->dim = getshort(inf);
00172     image->xsize = getshort(inf);
00173     image->ysize = getshort(inf);
00174     image->zsize = getshort(inf);
00175 }
00176 
00177 static int writeheader(FILE *outf, IMAGE *image)
00178 {
00179     IMAGE t= {0};
00180 
00181     fwrite(&t,sizeof(IMAGE),1,outf);
00182     fseek(outf,0,SEEK_SET);
00183     putshort(outf,image->imagic);
00184     putshort(outf,image->type);
00185     putshort(outf,image->dim);
00186     putshort(outf,image->xsize);
00187     putshort(outf,image->ysize);
00188     putshort(outf,image->zsize);
00189     putlong(outf,image->min);
00190     putlong(outf,image->max);
00191     putlong(outf,0);
00192     return fwrite("no name",8,1,outf);
00193 }
00194 
00195 static int writetab(FILE *outf, unsigned int *tab, int len)
00196 {
00197     int r = 0;
00198 
00199     while(len) {
00200         r = putlong(outf,*tab++);
00201         len -= 4;
00202     }
00203     return r;
00204 }
00205 
00206 static void readtab(FILE *inf, unsigned int *tab, int len)
00207 {
00208     while(len) {
00209         *tab++ = getlong(inf);
00210         len -= 4;
00211     }
00212 }
00213 
00214 static void test_endian_zbuf(struct ImBuf *ibuf)
00215 {
00216     int len;
00217     int *zval;
00218     
00219     if( BIG_LONG(1) == 1 ) return;
00220     if(ibuf->zbuf == NULL) return;
00221     
00222     len= ibuf->x*ibuf->y;
00223     zval= ibuf->zbuf;
00224     
00225     while(len--) {
00226         zval[0]= BIG_LONG(zval[0]);
00227         zval++;
00228     }
00229 }
00230 
00231 /* from misc_util: flip the bytes from x  */
00232 #define GS(x) (((unsigned char *)(x))[0] << 8 | ((unsigned char *)(x))[1])
00233 
00234 /* this one is only def-ed once, strangely... */
00235 #define GSS(x) (((uchar *)(x))[1] << 8 | ((uchar *)(x))[0])
00236 
00237 int imb_is_a_iris(unsigned char *mem)
00238 {
00239     return ((GS(mem) == IMAGIC) || (GSS(mem) == IMAGIC));
00240 }
00241 
00242 /*
00243  *  longimagedata - 
00244  *      read in a B/W RGB or RGBA iris image file and return a 
00245  *  pointer to an array of ints.
00246  *
00247  */
00248 
00249 struct ImBuf *imb_loadiris(unsigned char *mem, size_t size, int flags)
00250 {
00251     unsigned int *base, *lptr = NULL;
00252     float *fbase, *fptr = NULL;
00253     unsigned int *zbase, *zptr;
00254     unsigned char *rledat;
00255     unsigned int *starttab, *lengthtab;
00256     FILE *inf = NULL;
00257     IMAGE image;
00258     int x, y, z, tablen;
00259     int xsize, ysize, zsize;
00260     int bpp, rle, cur, badorder;
00261     ImBuf * ibuf;
00262 
00263     (void)size; /* unused */
00264     
00265     if(!imb_is_a_iris(mem)) return NULL;
00266 
00267     /*printf("new iris\n");*/
00268     
00269     file_data = mem;
00270     file_offset = 0;
00271     
00272     readheader(inf, &image);
00273     if(image.imagic != IMAGIC) {
00274         fprintf(stderr,"longimagedata: bad magic number in image file\n");
00275         return(NULL);
00276     }
00277     
00278     rle = ISRLE(image.type);
00279     bpp = BPP(image.type);
00280     if(bpp != 1 && bpp != 2) {
00281         fprintf(stderr,"longimagedata: image must have 1 or 2 byte per pix chan\n");
00282         return(NULL);
00283     }
00284     
00285     xsize = image.xsize;
00286     ysize = image.ysize;
00287     zsize = image.zsize;
00288     
00289     if (flags & IB_test) {
00290         ibuf = IMB_allocImBuf(image.xsize, image.ysize, 8 * image.zsize, 0);
00291         if (ibuf) ibuf->ftype = IMAGIC;
00292         return(ibuf);
00293     }
00294     
00295     if (rle) {
00296         
00297         tablen = ysize*zsize*sizeof(int);
00298         starttab = (unsigned int *)MEM_mallocN(tablen, "iris starttab");
00299         lengthtab = (unsigned int *)MEM_mallocN(tablen, "iris endtab");
00300         file_offset = 512;
00301         
00302         readtab(inf,starttab,tablen);
00303         readtab(inf,lengthtab,tablen);
00304     
00305         /* check data order */
00306         cur = 0;
00307         badorder = 0;
00308         for (y = 0; y<ysize; y++) {
00309             for (z = 0; z<zsize; z++) {
00310                 if (starttab[y+z*ysize]<cur) {
00311                     badorder = 1;
00312                     break;
00313                 }
00314                 cur = starttab[y+z*ysize];
00315             }
00316             if(badorder)
00317                 break;
00318         }
00319     
00320         if (bpp == 1) {
00321             
00322             ibuf = IMB_allocImBuf(xsize, ysize, 8 * zsize, IB_rect);
00323             if (ibuf->planes > 32) ibuf->planes = 32;
00324             base = ibuf->rect;
00325             zbase = (unsigned int *)ibuf->zbuf;
00326             
00327             if (badorder) {
00328                 for(z=0; z<zsize; z++) {
00329                     lptr = base;
00330                     for(y=0; y<ysize; y++) {
00331                         file_offset = starttab[y+z*ysize];
00332                         
00333                         rledat = file_data + file_offset;
00334                         file_offset += lengthtab[y+z*ysize];
00335                         
00336                         expandrow((uchar *)lptr, rledat, 3-z);
00337                         lptr += xsize;
00338                     }
00339                 }
00340             } else {
00341                 lptr = base;
00342                 zptr = zbase;
00343                 for(y=0; y<ysize; y++) {
00344                 
00345                     for(z=0; z<zsize; z++) {
00346                         
00347                         file_offset = starttab[y+z*ysize];
00348 
00349                         rledat = file_data + file_offset;
00350                         file_offset += lengthtab[y+z*ysize];
00351                         
00352                         if(z<4) expandrow((uchar *)lptr, rledat, 3-z);
00353                         else if(z<8) expandrow((uchar *)zptr, rledat, 7-z);
00354                     }
00355                     lptr += xsize;
00356                     zptr += xsize;
00357                 }
00358             }
00359             
00360 
00361         } else {    /* bpp == 2 */
00362             
00363             ibuf = IMB_allocImBuf(xsize, ysize, 32, (flags & IB_rect)|IB_rectfloat);
00364             
00365             fbase = ibuf->rect_float;
00366             
00367             if (badorder) {
00368                 for(z=0; z<zsize; z++) {
00369                     fptr = fbase;
00370                     for(y=0; y<ysize; y++) {
00371                         file_offset = starttab[y+z*ysize];
00372                         
00373                         rledat = file_data + file_offset;
00374                         file_offset += lengthtab[y+z*ysize];
00375                         
00376                         expandrow2(fptr, rledat, 3-z);
00377                         fptr += xsize * 4;
00378                     }
00379                 }
00380             } else {
00381                 fptr = fbase;
00382 
00383                 for(y=0; y<ysize; y++) {
00384                 
00385                     for(z=0; z<zsize; z++) {
00386                         
00387                         file_offset = starttab[y+z*ysize];
00388 
00389                         rledat = file_data + file_offset;
00390                         file_offset += lengthtab[y+z*ysize];
00391                         
00392                         expandrow2(fptr, rledat, 3-z);
00393                         
00394                     }
00395                     fptr += xsize * 4;
00396                 }
00397             }
00398         }
00399         
00400         MEM_freeN(starttab);
00401         MEM_freeN(lengthtab);   
00402 
00403     } else {
00404         if (bpp == 1) {
00405             
00406             ibuf = IMB_allocImBuf(xsize, ysize, 8 * zsize, IB_rect);
00407             if (ibuf->planes > 32) ibuf->planes = 32;
00408 
00409             base = ibuf->rect;
00410             zbase = (unsigned int *)ibuf->zbuf;
00411             
00412             file_offset = 512;
00413             rledat = file_data + file_offset;
00414             
00415             for(z = 0; z < zsize; z++) {
00416                 
00417                 if(z<4) lptr = base;
00418                 else if(z<8) lptr= zbase;
00419                 
00420                 for(y = 0; y < ysize; y++) {
00421 
00422                     interleaverow((uchar *)lptr, rledat, 3-z, xsize);
00423                     rledat += xsize;
00424                     
00425                     lptr += xsize;
00426                 }
00427             }
00428             
00429         } else {    /* bpp == 2 */
00430             
00431             ibuf = IMB_allocImBuf(xsize, ysize, 32, (flags & IB_rect)|IB_rectfloat);
00432 
00433             fbase = ibuf->rect_float;
00434 
00435             file_offset = 512;
00436             rledat = file_data + file_offset;
00437             
00438             for(z = 0; z < zsize; z++) {
00439                 
00440                 fptr = fbase;
00441                 
00442                 for(y = 0; y < ysize; y++) {
00443 
00444                     interleaverow2(fptr, rledat, 3-z, xsize);
00445                     rledat += xsize * 2;
00446                     
00447                     fptr += xsize * 4;
00448                 }
00449             }
00450             
00451         }
00452     }
00453     
00454     
00455     if (bpp == 1) {
00456         uchar * rect;
00457         
00458         if (image.zsize == 1){
00459             rect = (uchar *) ibuf->rect;
00460             for (x = ibuf->x * ibuf->y; x > 0; x--) {
00461                 rect[0] = 255;
00462                 rect[1] = rect[2] = rect[3];
00463                 rect += 4;
00464             }
00465         } else if (image.zsize == 2){
00466             /* grayscale with alpha */
00467             rect = (uchar *) ibuf->rect;
00468             for (x = ibuf->x * ibuf->y; x > 0; x--) {
00469                 rect[0] = rect[2];
00470                 rect[1] = rect[2] = rect[3];
00471                 rect += 4;
00472             }
00473         } else if (image.zsize == 3){
00474             /* add alpha */
00475             rect = (uchar *) ibuf->rect;
00476             for (x = ibuf->x * ibuf->y; x > 0; x--) {
00477                 rect[0] = 255;
00478                 rect += 4;
00479             }
00480         }
00481         
00482     } else {    /* bpp == 2 */
00483         
00484         if (image.zsize == 1){
00485             fbase = ibuf->rect_float;
00486             for (x = ibuf->x * ibuf->y; x > 0; x--) {
00487                 fbase[0] = 1;
00488                 fbase[1] = fbase[2] = fbase[3];
00489                 fbase += 4;
00490             }
00491         } else if (image.zsize == 2){
00492             /* grayscale with alpha */
00493             fbase = ibuf->rect_float;
00494             for (x = ibuf->x * ibuf->y; x > 0; x--) {
00495                 fbase[0] = fbase[2];
00496                 fbase[1] = fbase[2] = fbase[3];
00497                 fbase += 4;
00498             }
00499         } else if (image.zsize == 3){
00500             /* add alpha */
00501             fbase = ibuf->rect_float;
00502             for (x = ibuf->x * ibuf->y; x > 0; x--) {
00503                 fbase[0] = 1;
00504                 fbase += 4;
00505             }
00506         }
00507         
00508         if (flags & IB_rect) {
00509             IMB_rect_from_float(ibuf);
00510         }
00511         
00512     }
00513 
00514     if (ibuf) {
00515         ibuf->ftype = IMAGIC;
00516         ibuf->profile = IB_PROFILE_SRGB;
00517 
00518         test_endian_zbuf(ibuf);
00519 
00520         if (ibuf->rect) {
00521             IMB_convert_rgba_to_abgr(ibuf);
00522         }
00523     }
00524 
00525     return(ibuf);
00526 }
00527 
00528 /* static utility functions for longimagedata */
00529 
00530 static void interleaverow(unsigned char *lptr, unsigned char *cptr, int z, int n)
00531 {
00532     lptr += z;
00533     while(n--) {
00534         *lptr = *cptr++;
00535         lptr += 4;
00536     }
00537 }
00538 
00539 static void interleaverow2(float *lptr, unsigned char *cptr, int z, int n)
00540 {
00541     lptr += z;
00542     while(n--) {
00543         *lptr = ((cptr[0]<<8) | (cptr[1]<<0)) / (float)0xFFFF;      
00544         cptr += 2;
00545         lptr += 4;
00546     }
00547 }
00548 
00549 static void expandrow2(float *optr, unsigned char *iptr, int z)
00550 {
00551     unsigned short pixel, count;
00552     float pixel_f;
00553 
00554     optr += z;
00555     while(1) {
00556         pixel = (iptr[0]<<8) | (iptr[1]<<0);
00557         iptr += 2;
00558         
00559         if ( !(count = (pixel & 0x7f)) )
00560             return;
00561         if(pixel & 0x80) {
00562             while(count>=8) {
00563                 optr[0*4] = ((iptr[0]<<8) | (iptr[1]<<0))/(float)0xFFFF;
00564                 optr[1*4] = ((iptr[2]<<8) | (iptr[3]<<0))/(float)0xFFFF;
00565                 optr[2*4] = ((iptr[4]<<8) | (iptr[5]<<0))/(float)0xFFFF;
00566                 optr[3*4] = ((iptr[6]<<8) | (iptr[7]<<0))/(float)0xFFFF;
00567                 optr[4*4] = ((iptr[8]<<8) | (iptr[9]<<0))/(float)0xFFFF;
00568                 optr[5*4] = ((iptr[10]<<8) | (iptr[11]<<0))/(float)0xFFFF;
00569                 optr[6*4] = ((iptr[12]<<8) | (iptr[13]<<0))/(float)0xFFFF;
00570                 optr[7*4] = ((iptr[14]<<8) | (iptr[15]<<0))/(float)0xFFFF;
00571                 optr += 8*4;
00572                 iptr += 8*2;
00573                 count -= 8;
00574             }
00575             while(count--) {
00576                 *optr = ((iptr[0]<<8) | (iptr[1]<<0))/(float)0xFFFF;
00577                 iptr+=2;
00578                 optr+=4;
00579             }
00580         } else {
00581             pixel_f = ((iptr[0]<<8) | (iptr[1]<<0))/(float)0xFFFF;
00582             iptr += 2;
00583 
00584             while(count>=8) {
00585                 optr[0*4] = pixel_f;
00586                 optr[1*4] = pixel_f;
00587                 optr[2*4] = pixel_f;
00588                 optr[3*4] = pixel_f;
00589                 optr[4*4] = pixel_f;
00590                 optr[5*4] = pixel_f;
00591                 optr[6*4] = pixel_f;
00592                 optr[7*4] = pixel_f;
00593                 optr += 8*4;
00594                 count -= 8;
00595             }
00596             while(count--) {
00597                 *optr = pixel_f;
00598                 optr+=4;
00599             }
00600         }
00601     }   
00602 }
00603 
00604 static void expandrow(unsigned char *optr, unsigned char *iptr, int z)
00605 {
00606     unsigned char pixel, count;
00607 
00608     optr += z;
00609     while(1) {
00610         pixel = *iptr++;
00611         if ( !(count = (pixel & 0x7f)) )
00612             return;
00613         if(pixel & 0x80) {
00614             while(count>=8) {
00615                 optr[0*4] = iptr[0];
00616                 optr[1*4] = iptr[1];
00617                 optr[2*4] = iptr[2];
00618                 optr[3*4] = iptr[3];
00619                 optr[4*4] = iptr[4];
00620                 optr[5*4] = iptr[5];
00621                 optr[6*4] = iptr[6];
00622                 optr[7*4] = iptr[7];
00623                 optr += 8*4;
00624                 iptr += 8;
00625                 count -= 8;
00626             }
00627             while(count--) {
00628                 *optr = *iptr++;
00629                 optr+=4;
00630             }
00631         } else {
00632             pixel = *iptr++;
00633             while(count>=8) {
00634                 optr[0*4] = pixel;
00635                 optr[1*4] = pixel;
00636                 optr[2*4] = pixel;
00637                 optr[3*4] = pixel;
00638                 optr[4*4] = pixel;
00639                 optr[5*4] = pixel;
00640                 optr[6*4] = pixel;
00641                 optr[7*4] = pixel;
00642                 optr += 8*4;
00643                 count -= 8;
00644             }
00645             while(count--) {
00646                 *optr = pixel;
00647                 optr+=4;
00648             }
00649         }
00650     }
00651 }
00652 
00653 /*
00654  *  output_iris -
00655  *      copy an array of ints to an iris image file.  Each int
00656  *  represents one pixel.  xsize and ysize specify the dimensions of
00657  *  the pixel array.  zsize specifies what kind of image file to
00658  *  write out.  if zsize is 1, the luminance of the pixels are
00659  *  calculated, and a sinlge channel black and white image is saved.
00660  *  If zsize is 3, an RGB image file is saved.  If zsize is 4, an
00661  *  RGBA image file is saved.
00662  *
00663  *  Added: zbuf write
00664  */
00665 
00666 static int output_iris(unsigned int *lptr, int xsize, int ysize, int zsize, const char *name, int *zptr)
00667 {
00668     FILE *outf;
00669     IMAGE *image;
00670     int tablen, y, z, pos, len = 0;
00671     unsigned int *starttab, *lengthtab;
00672     unsigned char *rlebuf;
00673     unsigned int *lumbuf;
00674     int rlebuflen, goodwrite;
00675 
00676     goodwrite = 1;
00677     outf = fopen(name, "wb");
00678     if(!outf) return 0;
00679 
00680     tablen = ysize*zsize*sizeof(int);
00681 
00682     image = (IMAGE *)MEM_mallocN(sizeof(IMAGE), "iris image");
00683     starttab = (unsigned int *)MEM_mallocN(tablen, "iris starttab");
00684     lengthtab = (unsigned int *)MEM_mallocN(tablen, "iris lengthtab");
00685     rlebuflen = 1.05*xsize+10;
00686     rlebuf = (unsigned char *)MEM_mallocN(rlebuflen, "iris rlebuf");
00687     lumbuf = (unsigned int *)MEM_mallocN(xsize*sizeof(int), "iris lumbuf");
00688 
00689     memset(image, 0, sizeof(IMAGE));
00690     image->imagic = IMAGIC;
00691     image->type = RLE(1);
00692     if(zsize>1)
00693         image->dim = 3;
00694     else
00695         image->dim = 2;
00696     image->xsize = xsize;
00697     image->ysize = ysize;
00698     image->zsize = zsize;
00699     image->min = 0;
00700     image->max = 255;
00701     goodwrite *= writeheader(outf,image);
00702     fseek(outf,512+2*tablen,SEEK_SET);
00703     pos = 512+2*tablen;
00704     
00705     for (y = 0; y < ysize; y++) {
00706         for (z = 0; z < zsize; z++) {
00707             
00708             if (zsize == 1) {
00709                 lumrow((uchar *)lptr,(uchar *)lumbuf,xsize);
00710                 len = compressrow((uchar *)lumbuf,rlebuf,CHANOFFSET(z),xsize);
00711             }
00712             else {
00713                 if(z<4) {
00714                     len = compressrow((uchar *)lptr, rlebuf,CHANOFFSET(z),xsize);
00715                 }
00716                 else if(z<8 && zptr) {
00717                     len = compressrow((uchar *)zptr, rlebuf,CHANOFFSET(z-4),xsize);
00718                 }
00719             }
00720             if(len>rlebuflen) {
00721                 fprintf(stderr,"output_iris: rlebuf is too small - bad poop\n");
00722                 exit(1);
00723             }
00724             goodwrite *= fwrite(rlebuf, len, 1, outf);
00725             starttab[y+z*ysize] = pos;
00726             lengthtab[y+z*ysize] = len;
00727             pos += len;
00728         }
00729         lptr += xsize;
00730         if(zptr) zptr += xsize;
00731     }
00732 
00733     fseek(outf,512,SEEK_SET);
00734     goodwrite *= writetab(outf,starttab,tablen);
00735     goodwrite *= writetab(outf,lengthtab,tablen);
00736     MEM_freeN(image);
00737     MEM_freeN(starttab);
00738     MEM_freeN(lengthtab);
00739     MEM_freeN(rlebuf);
00740     MEM_freeN(lumbuf);
00741     fclose(outf);
00742     if(goodwrite)
00743         return 1;
00744     else {
00745         fprintf(stderr,"output_iris: not enough space for image!!\n");
00746         return 0;
00747     }
00748 }
00749 
00750 /* static utility functions for output_iris */
00751 
00752 static void lumrow(unsigned char *rgbptr, unsigned char *lumptr, int n)
00753 {
00754     lumptr += CHANOFFSET(0);
00755     while(n--) {
00756         *lumptr = ILUM(rgbptr[OFFSET_R],rgbptr[OFFSET_G],rgbptr[OFFSET_B]);
00757         lumptr += 4;
00758         rgbptr += 4;
00759     }
00760 }
00761 
00762 static int compressrow(unsigned char *lbuf, unsigned char *rlebuf, int z, int cnt)
00763 {
00764     unsigned char *iptr, *ibufend, *sptr, *optr;
00765     short todo, cc;
00766     int count;
00767 
00768     lbuf += z;
00769     iptr = lbuf;
00770     ibufend = iptr+cnt*4;
00771     optr = rlebuf;
00772 
00773     while(iptr<ibufend) {
00774         sptr = iptr;
00775         iptr += 8;
00776         while((iptr<ibufend)&& ((iptr[-8]!=iptr[-4])||(iptr[-4]!=iptr[0])))
00777             iptr+=4;
00778         iptr -= 8;
00779         count = (iptr-sptr)/4;
00780         while(count) {
00781             todo = count>126 ? 126:count;
00782             count -= todo;
00783             *optr++ = 0x80|todo;
00784             while(todo>8) {
00785                 optr[0] = sptr[0*4];
00786                 optr[1] = sptr[1*4];
00787                 optr[2] = sptr[2*4];
00788                 optr[3] = sptr[3*4];
00789                 optr[4] = sptr[4*4];
00790                 optr[5] = sptr[5*4];
00791                 optr[6] = sptr[6*4];
00792                 optr[7] = sptr[7*4];
00793 
00794                 optr += 8;
00795                 sptr += 8*4;
00796                 todo -= 8;
00797             }
00798             while(todo--) {
00799                 *optr++ = *sptr;
00800                 sptr += 4;
00801             }
00802         }
00803         sptr = iptr;
00804         cc = *iptr;
00805         iptr += 4;
00806         while( (iptr<ibufend) && (*iptr == cc) )
00807             iptr += 4;
00808         count = (iptr-sptr)/4;
00809         while(count) {
00810             todo = count>126 ? 126:count;
00811             count -= todo;
00812             *optr++ = todo;
00813             *optr++ = cc;
00814         }
00815     }
00816     *optr++ = 0;
00817     return optr - (unsigned char *)rlebuf;
00818 }
00819 
00820 int imb_saveiris(struct ImBuf * ibuf, const char *name, int flags)
00821 {
00822     short zsize;
00823     int ret;
00824 
00825     zsize = (ibuf->planes + 7) >> 3;
00826     if (flags & IB_zbuf &&  ibuf->zbuf != NULL) zsize = 8;
00827     
00828     IMB_convert_rgba_to_abgr(ibuf);
00829     test_endian_zbuf(ibuf);
00830 
00831     ret = output_iris(ibuf->rect, ibuf->x, ibuf->y, zsize, name, ibuf->zbuf);
00832 
00833     /* restore! Quite clumsy, 2 times a switch... maybe better a malloc ? */
00834     IMB_convert_rgba_to_abgr(ibuf);
00835     test_endian_zbuf(ibuf);
00836 
00837     return(ret);
00838 }
00839