This is patch# 19017 16bit SGI image loading
authorKent Mein <mein@cs.umn.edu>
Fri, 24 Jul 2009 17:17:04 +0000 (17:17 +0000)
committerKent Mein <mein@cs.umn.edu>
Fri, 24 Jul 2009 17:17:04 +0000 (17:17 +0000)
submitted by Albertas Vy┼íniauskas (thezbyg)

Improves SGI image support.

Kent

source/blender/imbuf/intern/iris.c

index aa3015812fc74673ed2edb5599f0738d23cdf441..eba148cb8a5b789f80b90e61e41d004770e6dc95 100644 (file)
@@ -104,7 +104,9 @@ static int writetab(FILE *outf, unsigned int *tab, int len);
 static void readtab(FILE *inf, unsigned int *tab, int len);
 
 static void expandrow(unsigned char *optr, unsigned char *iptr, int z);
+static void expandrow2(float *optr, unsigned char *iptr, int z);
 static void interleaverow(unsigned char *lptr, unsigned char *cptr, int z, int n);
+static void interleaverow2(float *lptr, unsigned char *cptr, int z, int n);
 static int compressrow(unsigned char *lbuf, unsigned char *rlebuf, int z, int cnt);
 static void lumrow(unsigned char *rgbptr, unsigned char *lumptr, int n);
 
@@ -233,6 +235,7 @@ static void test_endian_zbuf(struct ImBuf *ibuf)
 struct ImBuf *imb_loadiris(unsigned char *mem, int flags)
 {
        unsigned int *base, *lptr = NULL;
+       float *fbase, *fptr = NULL;
        unsigned int *zbase, *zptr;
        unsigned char *rledat;
        unsigned int *starttab, *lengthtab;
@@ -257,8 +260,8 @@ struct ImBuf *imb_loadiris(unsigned char *mem, int flags)
        
        rle = ISRLE(image.type);
        bpp = BPP(image.type);
-       if(bpp != 1 ) {
-               fprintf(stderr,"longimagedata: image must have 1 byte per pix chan\n");
+       if(bpp != 1 && bpp != 2) {
+               fprintf(stderr,"longimagedata: image must have 1 or 2 byte per pix chan\n");
                return(0);
        }
        
@@ -273,6 +276,7 @@ struct ImBuf *imb_loadiris(unsigned char *mem, int flags)
        }
        
        if (rle) {
+               
                tablen = ysize*zsize*sizeof(int);
                starttab = (unsigned int *)malloc(tablen);
                lengthtab = (unsigned int *)malloc(tablen);
@@ -280,7 +284,7 @@ struct ImBuf *imb_loadiris(unsigned char *mem, int flags)
                
                readtab(inf,starttab,tablen);
                readtab(inf,lengthtab,tablen);
-
+       
                /* check data order */
                cur = 0;
                badorder = 0;
@@ -295,99 +299,200 @@ struct ImBuf *imb_loadiris(unsigned char *mem, int flags)
                        if(badorder)
                                break;
                }
-
-               ibuf = IMB_allocImBuf(xsize, ysize, 8 * zsize, IB_rect, 0);
-               if (ibuf->depth > 32) ibuf->depth = 32;
-               base = ibuf->rect;
-               zbase = (unsigned int *)ibuf->zbuf;
-               
-               if (badorder) {
-                       for(z=0; z<zsize; z++) {
+       
+               if (bpp == 1) {
+                       
+                       ibuf = IMB_allocImBuf(xsize, ysize, 8 * zsize, IB_rect, 0);
+                       if (ibuf->depth > 32) ibuf->depth = 32;
+                       base = ibuf->rect;
+                       zbase = (unsigned int *)ibuf->zbuf;
+                       
+                       if (badorder) {
+                               for(z=0; z<zsize; z++) {
+                                       lptr = base;
+                                       for(y=0; y<ysize; y++) {
+                                               file_offset = starttab[y+z*ysize];
+                                               
+                                               rledat = file_data + file_offset;
+                                               file_offset += lengthtab[y+z*ysize];
+                                               
+                                               expandrow((uchar *)lptr, rledat, 3-z);
+                                               lptr += xsize;
+                                       }
+                               }
+                       } else {
                                lptr = base;
+                               zptr = zbase;
                                for(y=0; y<ysize; y++) {
-                                       file_offset = starttab[y+z*ysize];
-                                       
-                                       rledat = file_data + file_offset;
-                                       file_offset += lengthtab[y+z*ysize];
-                                       
-                                       expandrow((uchar *)lptr, rledat, 3-z);
+                               
+                                       for(z=0; z<zsize; z++) {
+                                               
+                                               file_offset = starttab[y+z*ysize];
+
+                                               rledat = file_data + file_offset;
+                                               file_offset += lengthtab[y+z*ysize];
+                                               
+                                               if(z<4) expandrow((uchar *)lptr, rledat, 3-z);
+                                               else if(z<8) expandrow((uchar *)zptr, rledat, 7-z);
+                                       }
                                        lptr += xsize;
+                                       zptr += xsize;
                                }
                        }
-               }
-               else {
-                       lptr = base;
-                       zptr = zbase;
-                       for(y=0; y<ysize; y++) {
                        
+
+               } else {        /* bpp == 2 */
+                       
+                       ibuf = IMB_allocImBuf(xsize, ysize, 32, (flags & IB_rect)|IB_rectfloat, 0);
+                       
+                       fbase = ibuf->rect_float;
+                       
+                       if (badorder) {
                                for(z=0; z<zsize; z++) {
-                                       
-                                       file_offset = starttab[y+z*ysize];
+                                       fptr = fbase;
+                                       for(y=0; y<ysize; y++) {
+                                               file_offset = starttab[y+z*ysize];
+                                               
+                                               rledat = file_data + file_offset;
+                                               file_offset += lengthtab[y+z*ysize];
+                                               
+                                               expandrow2(fptr, rledat, 3-z);
+                                               fptr += xsize * 4;
+                                       }
+                               }
+                       } else {
+                               fptr = fbase;
 
-                                       rledat = file_data + file_offset;
-                                       file_offset += lengthtab[y+z*ysize];
-                                       
-                                       if(z<4) expandrow((uchar *)lptr, rledat, 3-z);
-                                       else if(z<8) expandrow((uchar *)zptr, rledat, 7-z);
+                               for(y=0; y<ysize; y++) {
+                               
+                                       for(z=0; z<zsize; z++) {
+                                               
+                                               file_offset = starttab[y+z*ysize];
+
+                                               rledat = file_data + file_offset;
+                                               file_offset += lengthtab[y+z*ysize];
+                                               
+                                               expandrow2(fptr, rledat, 3-z);
+                                               
+                                       }
+                                       fptr += xsize * 4;
                                }
-                               lptr += xsize;
-                               zptr += xsize;
                        }
                }
                
                free(starttab);
-               free(lengthtab);
-       } 
-       else {
-       
-               ibuf = IMB_allocImBuf(xsize, ysize, 8 * zsize, IB_rect, 0);
-               if (ibuf->depth > 32) ibuf->depth = 32;
+               free(lengthtab);        
 
-               base = ibuf->rect;
-               zbase = (unsigned int *)ibuf->zbuf;
-               
-               file_offset = 512;
-               rledat = file_data + file_offset;
-               
-               for(z = 0; z < zsize; z++) {
+       } else {
+               if (bpp == 1) {
+                       
+                       ibuf = IMB_allocImBuf(xsize, ysize, 8 * zsize, IB_rect, 0);
+                       if (ibuf->depth > 32) ibuf->depth = 32;
+
+                       base = ibuf->rect;
+                       zbase = (unsigned int *)ibuf->zbuf;
                        
-                       if(z<4) lptr = base;
-                       else if(z<8) lptr= zbase;
+                       file_offset = 512;
+                       rledat = file_data + file_offset;
                        
-                       for(y = 0; y < ysize; y++) {
+                       for(z = 0; z < zsize; z++) {
+                               
+                               if(z<4) lptr = base;
+                               else if(z<8) lptr= zbase;
+                               
+                               for(y = 0; y < ysize; y++) {
 
-                               interleaverow((uchar *)lptr, rledat, 3-z, xsize);
-                               rledat += xsize;
+                                       interleaverow((uchar *)lptr, rledat, 3-z, xsize);
+                                       rledat += xsize;
+                                       
+                                       lptr += xsize;
+                               }
+                       }
+                       
+               } else {        /* bpp == 2 */
+                       
+                       ibuf = IMB_allocImBuf(xsize, ysize, 32, (flags & IB_rect)|IB_rectfloat, 0);
+
+                       fbase = ibuf->rect_float;
+
+                       file_offset = 512;
+                       rledat = file_data + file_offset;
+                       
+                       for(z = 0; z < zsize; z++) {
+                               
+                               fptr = fbase;
                                
-                               lptr += xsize;
+                               for(y = 0; y < ysize; y++) {
+
+                                       interleaverow2(fptr, rledat, 3-z, xsize);
+                                       rledat += xsize * 2;
+                                       
+                                       fptr += xsize * 4;
+                               }
                        }
+                       
                }
        }
        
-       if (image.zsize == 1){
-               rect = (uchar *) ibuf->rect;
-               for (x = ibuf->x * ibuf->y; x > 0; x--) {
-                       rect[0] = 255;
-                       rect[1] = rect[2] = rect[3];
-                       rect += 4;
+       
+       if (bpp == 1) {
+               
+               if (image.zsize == 1){
+                       rect = (uchar *) ibuf->rect;
+                       for (x = ibuf->x * ibuf->y; x > 0; x--) {
+                               rect[0] = 255;
+                               rect[1] = rect[2] = rect[3];
+                               rect += 4;
+                       }
+               } else if (image.zsize == 2){
+                       /* grayscale with alpha */
+                       rect = (uchar *) ibuf->rect;
+                       for (x = ibuf->x * ibuf->y; x > 0; x--) {
+                               rect[0] = rect[2];
+                               rect[1] = rect[2] = rect[3];
+                               rect += 4;
+                       }
+               } else if (image.zsize == 3){
+                       /* add alpha */
+                       rect = (uchar *) ibuf->rect;
+                       for (x = ibuf->x * ibuf->y; x > 0; x--) {
+                               rect[0] = 255;
+                               rect += 4;
+                       }
                }
-       } else if (image.zsize == 2){
-               /* grayscale with alpha */
-               rect = (uchar *) ibuf->rect;
-               for (x = ibuf->x * ibuf->y; x > 0; x--) {
-                       rect[0] = rect[2];
-                       rect[1] = rect[2] = rect[3];
-                       rect += 4;
+               
+       } else {        /* bpp == 2 */
+               
+               if (image.zsize == 1){
+                       fbase = ibuf->rect_float;
+                       for (x = ibuf->x * ibuf->y; x > 0; x--) {
+                               fbase[0] = 1;
+                               fbase[1] = rect[2] = rect[3];
+                               fbase += 4;
+                       }
+               } else if (image.zsize == 2){
+                       /* grayscale with alpha */
+                       fbase = ibuf->rect_float;
+                       for (x = ibuf->x * ibuf->y; x > 0; x--) {
+                               fbase[0] = fbase[2];
+                               fbase[1] = fbase[2] = fbase[3];
+                               fbase += 4;
+                       }
+               } else if (image.zsize == 3){
+                       /* add alpha */
+                       fbase = ibuf->rect_float;
+                       for (x = ibuf->x * ibuf->y; x > 0; x--) {
+                               fbase[0] = 1;
+                               fbase += 4;
+                       }
                }
-       } else if (image.zsize == 3){
-               /* add alpha */
-               rect = (uchar *) ibuf->rect;
-               for (x = ibuf->x * ibuf->y; x > 0; x--) {
-                       rect[0] = 255;
-                       rect += 4;
+               
+               if (flags & IB_rect) {
+                       IMB_rect_from_float(ibuf);
                }
+               
        }
-       
+
        ibuf->ftype = IMAGIC;
        if (flags & IB_ttob) IMB_flipy(ibuf);
        
@@ -412,6 +517,71 @@ static void interleaverow(unsigned char *lptr, unsigned char *cptr, int z, int n
        }
 }
 
+static void interleaverow2(float *lptr, unsigned char *cptr, int z, int n)
+{
+       lptr += z;
+       while(n--) {
+               *lptr = ((cptr[0]<<8) | (cptr[1]<<0)) / (float)0xFFFF;          
+               cptr += 2;
+               lptr += 4;
+       }
+}
+
+static void expandrow2(float *optr, unsigned char *iptr, int z)
+{
+       unsigned short pixel, count;
+       float pixel_f;
+
+       optr += z;
+       while(1) {
+               pixel = (iptr[0]<<8) | (iptr[1]<<0);
+               iptr += 2;
+               
+               if ( !(count = (pixel & 0x7f)) )
+                       return;
+               if(pixel & 0x80) {
+                       while(count>=8) {
+                               optr[0*4] = ((iptr[0]<<8) | (iptr[1]<<0))/(float)0xFFFF;
+                               optr[1*4] = ((iptr[2]<<8) | (iptr[3]<<0))/(float)0xFFFF;
+                               optr[2*4] = ((iptr[4]<<8) | (iptr[5]<<0))/(float)0xFFFF;
+                               optr[3*4] = ((iptr[6]<<8) | (iptr[7]<<0))/(float)0xFFFF;
+                               optr[4*4] = ((iptr[8]<<8) | (iptr[9]<<0))/(float)0xFFFF;
+                               optr[5*4] = ((iptr[10]<<8) | (iptr[11]<<0))/(float)0xFFFF;
+                               optr[6*4] = ((iptr[12]<<8) | (iptr[13]<<0))/(float)0xFFFF;
+                               optr[7*4] = ((iptr[14]<<8) | (iptr[15]<<0))/(float)0xFFFF;
+                               optr += 8*4;
+                               iptr += 8*2;
+                               count -= 8;
+                       }
+                       while(count--) {
+                               *optr = ((iptr[0]<<8) | (iptr[1]<<0))/(float)0xFFFF;
+                               iptr+=2;
+                               optr+=4;
+                       }
+               } else {
+                       pixel_f = ((iptr[0]<<8) | (iptr[1]<<0))/(float)0xFFFF;
+                       iptr += 2;
+
+                       while(count>=8) {
+                               optr[0*4] = pixel_f;
+                               optr[1*4] = pixel_f;
+                               optr[2*4] = pixel_f;
+                               optr[3*4] = pixel_f;
+                               optr[4*4] = pixel_f;
+                               optr[5*4] = pixel_f;
+                               optr[6*4] = pixel_f;
+                               optr[7*4] = pixel_f;
+                               optr += 8*4;
+                               count -= 8;
+                       }
+                       while(count--) {
+                               *optr = pixel_f;
+                               optr+=4;
+                       }
+               }
+       }       
+}
+
 static void expandrow(unsigned char *optr, unsigned char *iptr, int z)
 {
        unsigned char pixel, count;