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