The code from the orange branch has now been copied into HEAD.
[blender.git] / source / blender / imbuf / intern / iris.c
1 /**
2  *
3  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. The Blender
9  * Foundation also sells licenses for use in proprietary software under
10  * the Blender License.  See http://www.blender.org/BL/ for information
11  * about this.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30  * iris.c
31  *
32  * $Id$
33  */
34
35 #include <string.h>
36 #include "BLI_blenlib.h"
37 #include "imbuf.h"
38 #include "imbuf_patch.h"
39 #include "IMB_imbuf_types.h"
40 #include "IMB_imbuf.h"
41 #include "IMB_allocimbuf.h"
42 #include "IMB_iris.h"
43
44 typedef struct {
45         unsigned short  imagic;         /* stuff saved on disk . . */
46         unsigned short  type;
47         unsigned short  dim;
48         unsigned short  xsize;
49         unsigned short  ysize;
50         unsigned short  zsize;
51         unsigned int    min;
52         unsigned int    max;
53         unsigned int    wastebytes;     
54         char            name[80];
55         unsigned int    colormap;
56
57         int             file;           /* stuff used in core only */
58         unsigned short  flags;
59         short           dorev;
60         short           x;
61         short           y;
62         short           z;
63         short           cnt;
64         unsigned short  *ptr;
65         unsigned short  *base;
66         unsigned short  *tmpbuf;
67         unsigned int    offset;
68         unsigned int    rleend;         /* for rle images */
69         unsigned int    *rowstart;      /* for rle images */
70         int             *rowsize;       /* for rle images */
71 } IMAGE;
72
73 #define RINTLUM (79)
74 #define GINTLUM (156)
75 #define BINTLUM (21)
76
77 #define ILUM(r,g,b)     ((int)(RINTLUM*(r)+GINTLUM*(g)+BINTLUM*(b))>>8)
78
79 #define OFFSET_R        0       /* this is byte order dependent */
80 #define OFFSET_G        1
81 #define OFFSET_B        2
82 #define OFFSET_A        3
83
84 #define CHANOFFSET(z)   (3-(z)) /* this is byte order dependent */
85
86 #define TYPEMASK                0xff00
87 #define BPPMASK                 0x00ff
88 #define ITYPE_VERBATIM          0x0000
89 #define ITYPE_RLE               0x0100
90 #define ISRLE(type)             (((type) & 0xff00) == ITYPE_RLE)
91 #define ISVERBATIM(type)        (((type) & 0xff00) == ITYPE_VERBATIM)
92 #define BPP(type)               ((type) & BPPMASK)
93 #define RLE(bpp)                (ITYPE_RLE | (bpp))
94 #define VERBATIM(bpp)           (ITYPE_VERBATIM | (bpp))
95 #define IBUFSIZE(pixels)        ((pixels+(pixels>>6))<<2)
96 #define RLE_NOP                 0x00
97
98 /* funcs */
99 static void readheader(FILE *inf, IMAGE *image);
100 static int writeheader(FILE *outf, IMAGE *image);
101
102 static unsigned short getshort(FILE *inf);
103 static unsigned int getlong(FILE *inf);
104 static void putshort(FILE *outf, unsigned short val);
105 static int putlong(FILE *outf, unsigned int val);
106 static int writetab(FILE *outf, unsigned int *tab, int len);
107 static void readtab(FILE *inf, unsigned int *tab, int len);
108
109 static void expandrow(unsigned char *optr, unsigned char *iptr, int z);
110 static void interleaverow(unsigned char *lptr, unsigned char *cptr, int z, int n);
111 static int compressrow(unsigned char *lbuf, unsigned char *rlebuf, int z, int cnt);
112 static void lumrow(unsigned char *rgbptr, unsigned char *lumptr, int n);
113
114 /*
115  *      byte order independent read/write of shorts and ints.
116  *
117  */
118
119 static uchar * file_data;
120 static int file_offset;
121
122 static unsigned short getshort(FILE *inf)
123 {
124         unsigned char * buf;
125         
126         buf = file_data + file_offset;
127         file_offset += 2;
128         
129         return (buf[0]<<8)+(buf[1]<<0);
130 }
131
132 static unsigned int getlong(FILE *inf)
133 {
134         unsigned char * buf;
135         
136         buf = file_data + file_offset;
137         file_offset += 4;
138         
139         return (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+(buf[3]<<0);
140 }
141
142 static void putshort(FILE *outf, unsigned short val)
143 {
144         unsigned char buf[2];
145
146         buf[0] = (val>>8);
147         buf[1] = (val>>0);
148         fwrite(buf,2,1,outf);
149 }
150
151 static int putlong(FILE *outf, unsigned int val)
152 {
153         unsigned char buf[4];
154
155         buf[0] = (val>>24);
156         buf[1] = (val>>16);
157         buf[2] = (val>>8);
158         buf[3] = (val>>0);
159         return fwrite(buf,4,1,outf);
160 }
161
162 static void readheader(FILE *inf, IMAGE *image)
163 {
164         memset(image, 0, sizeof(IMAGE));
165         image->imagic = getshort(inf);
166         image->type = getshort(inf);
167         image->dim = getshort(inf);
168         image->xsize = getshort(inf);
169         image->ysize = getshort(inf);
170         image->zsize = getshort(inf);
171 }
172
173 static int writeheader(FILE *outf, IMAGE *image)
174 {
175         IMAGE t;
176
177         memset(&t, 0, sizeof(IMAGE));
178         fwrite(&t,sizeof(IMAGE),1,outf);
179         fseek(outf,0,SEEK_SET);
180         putshort(outf,image->imagic);
181         putshort(outf,image->type);
182         putshort(outf,image->dim);
183         putshort(outf,image->xsize);
184         putshort(outf,image->ysize);
185         putshort(outf,image->zsize);
186         putlong(outf,image->min);
187         putlong(outf,image->max);
188         putlong(outf,0);
189         return fwrite("no name",8,1,outf);
190 }
191
192 static int writetab(FILE *outf, unsigned int *tab, int len)
193 {
194         int r = 0;
195
196         while(len) {
197                 r = putlong(outf,*tab++);
198                 len -= 4;
199         }
200         return r;
201 }
202
203 static void readtab(FILE *inf, unsigned int *tab, int len)
204 {
205         while(len) {
206                 *tab++ = getlong(inf);
207                 len -= 4;
208         }
209 }
210
211 static void test_endian_zbuf(struct ImBuf *ibuf)
212 {
213         int len;
214         int *zval;
215         
216         if( BIG_LONG(1) == 1 ) return;
217         if(ibuf->zbuf==0) return;
218         
219         len= ibuf->x*ibuf->y;
220         zval= ibuf->zbuf;
221         
222         while(len--) {
223                 zval[0]= BIG_LONG(zval[0]);
224                 zval++;
225         }
226 }
227
228
229 /*
230  *      longimagedata - 
231  *              read in a B/W RGB or RGBA iris image file and return a 
232  *      pointer to an array of ints.
233  *
234  */
235
236 struct ImBuf *imb_loadiris(unsigned char *mem, int flags)
237 {
238         unsigned int *base, *lptr = NULL;
239         unsigned int *zbase, *zptr;
240         unsigned char *rledat;
241         unsigned int *starttab, *lengthtab;
242         FILE *inf = NULL;
243         IMAGE image;
244         int x, y, z, tablen;
245         int xsize, ysize, zsize;
246         int bpp, rle, cur, badorder;
247         ImBuf * ibuf;
248         uchar * rect;
249         
250         /*printf("new iris\n");*/
251         
252         file_data = mem;
253         file_offset = 0;
254         
255         readheader(inf, &image);
256         if(image.imagic != IMAGIC) {
257                 fprintf(stderr,"longimagedata: bad magic number in image file\n");
258                 return(0);
259         }
260         
261         rle = ISRLE(image.type);
262         bpp = BPP(image.type);
263         if(bpp != 1 ) {
264                 fprintf(stderr,"longimagedata: image must have 1 byte per pix chan\n");
265                 return(0);
266         }
267         
268         xsize = image.xsize;
269         ysize = image.ysize;
270         zsize = image.zsize;
271         
272         if (flags & IB_test) {
273                 ibuf = IMB_allocImBuf(image.xsize, image.ysize, 8 * image.zsize, 0, 0);
274                 if (ibuf) ibuf->ftype = IMAGIC;
275                 return(ibuf);
276         }
277         
278         if (rle) {
279                 tablen = ysize*zsize*sizeof(int);
280                 starttab = (unsigned int *)malloc(tablen);
281                 lengthtab = (unsigned int *)malloc(tablen);
282                 file_offset = 512;
283                 
284                 readtab(inf,starttab,tablen);
285                 readtab(inf,lengthtab,tablen);
286
287                 /* check data order */
288                 cur = 0;
289                 badorder = 0;
290                 for (y = 0; y<ysize; y++) {
291                         for (z = 0; z<zsize; z++) {
292                                 if (starttab[y+z*ysize]<cur) {
293                                         badorder = 1;
294                                         break;
295                                 }
296                                 cur = starttab[y+z*ysize];
297                         }
298                         if(badorder)
299                                 break;
300                 }
301
302                 ibuf = IMB_allocImBuf(xsize, ysize, 8 * zsize, IB_rect, 0);
303                 if (ibuf->depth > 32) ibuf->depth = 32;
304                 base = ibuf->rect;
305                 zbase = (unsigned int *)ibuf->zbuf;
306                 
307                 if (badorder) {
308                         for(z=0; z<zsize; z++) {
309                                 lptr = base;
310                                 for(y=0; y<ysize; y++) {
311                                         file_offset = starttab[y+z*ysize];
312                                         
313                                         rledat = file_data + file_offset;
314                                         file_offset += lengthtab[y+z*ysize];
315                                         
316                                         expandrow((uchar *)lptr, rledat, 3-z);
317                                         lptr += xsize;
318                                 }
319                         }
320                 }
321                 else {
322                         lptr = base;
323                         zptr = zbase;
324                         for(y=0; y<ysize; y++) {
325                         
326                                 for(z=0; z<zsize; z++) {
327                                         
328                                         file_offset = starttab[y+z*ysize];
329
330                                         rledat = file_data + file_offset;
331                                         file_offset += lengthtab[y+z*ysize];
332                                         
333                                         if(z<4) expandrow((uchar *)lptr, rledat, 3-z);
334                                         else if(z<8) expandrow((uchar *)zptr, rledat, 7-z);
335                                 }
336                                 lptr += xsize;
337                                 zptr += xsize;
338                         }
339                 }
340                 
341                 free(starttab);
342                 free(lengthtab);
343         } 
344         else {
345         
346                 ibuf = IMB_allocImBuf(xsize, ysize, 8 * zsize, IB_rect, 0);
347                 if (ibuf->depth > 32) ibuf->depth = 32;
348
349                 base = ibuf->rect;
350                 zbase = (unsigned int *)ibuf->zbuf;
351                 
352                 file_offset = 512;
353                 rledat = file_data + file_offset;
354                 
355                 for(z = 0; z < zsize; z++) {
356                         
357                         if(z<4) lptr = base;
358                         else if(z<8) lptr= zbase;
359                         
360                         for(y = 0; y < ysize; y++) {
361
362                                 interleaverow((uchar *)lptr, rledat, 3-z, xsize);
363                                 rledat += xsize;
364                                 
365                                 lptr += xsize;
366                         }
367                 }
368         }
369         
370         if (image.zsize == 1){
371                 rect = (uchar *) ibuf->rect;
372                 for (x = ibuf->x * ibuf->y; x > 0; x--) {
373                         rect[0] = 255;
374                         rect[1] = rect[2] = rect[3];
375                         rect += 4;
376                 }
377         } else if (image.zsize == 2){
378                 /* grayscale with alpha */
379                 rect = (uchar *) ibuf->rect;
380                 for (x = ibuf->x * ibuf->y; x > 0; x--) {
381                         rect[0] = rect[2];
382                         rect[1] = rect[2] = rect[3];
383                         rect += 4;
384                 }
385         } else if (image.zsize == 3){
386                 /* add alpha */
387                 rect = (uchar *) ibuf->rect;
388                 for (x = ibuf->x * ibuf->y; x > 0; x--) {
389                         rect[0] = 255;
390                         rect += 4;
391                 }
392         }
393         
394         ibuf->ftype = IMAGIC;
395         if (flags & IB_ttob) IMB_flipy(ibuf);
396         
397         test_endian_zbuf(ibuf);
398         
399         if (ibuf) {
400                 if (ibuf->rect) 
401                         IMB_convert_rgba_to_abgr(ibuf);
402         }
403
404         return(ibuf);
405 }
406
407 /* static utility functions for longimagedata */
408
409 static void interleaverow(unsigned char *lptr, unsigned char *cptr, int z, int n)
410 {
411         lptr += z;
412         while(n--) {
413                 *lptr = *cptr++;
414                 lptr += 4;
415         }
416 }
417
418 static void expandrow(unsigned char *optr, unsigned char *iptr, int z)
419 {
420         unsigned char pixel, count;
421
422         optr += z;
423         while(1) {
424                 pixel = *iptr++;
425                 if ( !(count = (pixel & 0x7f)) )
426                         return;
427                 if(pixel & 0x80) {
428                         while(count>=8) {
429                                 optr[0*4] = iptr[0];
430                                 optr[1*4] = iptr[1];
431                                 optr[2*4] = iptr[2];
432                                 optr[3*4] = iptr[3];
433                                 optr[4*4] = iptr[4];
434                                 optr[5*4] = iptr[5];
435                                 optr[6*4] = iptr[6];
436                                 optr[7*4] = iptr[7];
437                                 optr += 8*4;
438                                 iptr += 8;
439                                 count -= 8;
440                         }
441                         while(count--) {
442                                 *optr = *iptr++;
443                                 optr+=4;
444                         }
445                 } else {
446                         pixel = *iptr++;
447                         while(count>=8) {
448                                 optr[0*4] = pixel;
449                                 optr[1*4] = pixel;
450                                 optr[2*4] = pixel;
451                                 optr[3*4] = pixel;
452                                 optr[4*4] = pixel;
453                                 optr[5*4] = pixel;
454                                 optr[6*4] = pixel;
455                                 optr[7*4] = pixel;
456                                 optr += 8*4;
457                                 count -= 8;
458                         }
459                         while(count--) {
460                                 *optr = pixel;
461                                 optr+=4;
462                         }
463                 }
464         }
465 }
466
467 /*
468  *      output_iris -
469  *              copy an array of ints to an iris image file.  Each int
470  *      represents one pixel.  xsize and ysize specify the dimensions of
471  *      the pixel array.  zsize specifies what kind of image file to
472  *      write out.  if zsize is 1, the luminance of the pixels are
473  *      calculated, and a sinlge channel black and white image is saved.
474  *      If zsize is 3, an RGB image file is saved.  If zsize is 4, an
475  *      RGBA image file is saved.
476  *
477  *  Added: zbuf write
478  */
479
480 static int output_iris(unsigned int *lptr, int xsize, int ysize, int zsize, char *name, int *zptr)
481 {
482         FILE *outf;
483         IMAGE *image;
484         int tablen, y, z, pos, len = 0;
485         unsigned int *starttab, *lengthtab;
486         unsigned char *rlebuf;
487         unsigned int *lumbuf;
488         int rlebuflen, goodwrite;
489
490         goodwrite = 1;
491         outf = fopen(name, "wb");
492         if(!outf) return 0;
493
494         tablen = ysize*zsize*sizeof(int);
495
496         image = (IMAGE *)malloc(sizeof(IMAGE));
497         starttab = (unsigned int *)malloc(tablen);
498         lengthtab = (unsigned int *)malloc(tablen);
499         rlebuflen = 1.05*xsize+10;
500         rlebuf = (unsigned char *)malloc(rlebuflen);
501         lumbuf = (unsigned int *)malloc(xsize*sizeof(int));
502
503         memset(image, 0, sizeof(IMAGE));
504         image->imagic = IMAGIC;
505         image->type = RLE(1);
506         if(zsize>1)
507                 image->dim = 3;
508         else
509                 image->dim = 2;
510         image->xsize = xsize;
511         image->ysize = ysize;
512         image->zsize = zsize;
513         image->min = 0;
514         image->max = 255;
515         goodwrite *= writeheader(outf,image);
516         fseek(outf,512+2*tablen,SEEK_SET);
517         pos = 512+2*tablen;
518         
519         for (y = 0; y < ysize; y++) {
520                 for (z = 0; z < zsize; z++) {
521                         
522                         if (zsize == 1) {
523                                 lumrow((uchar *)lptr,(uchar *)lumbuf,xsize);
524                                 len = compressrow((uchar *)lumbuf,rlebuf,CHANOFFSET(z),xsize);
525                         }
526                         else {
527                                 if(z<4) {
528                                         len = compressrow((uchar *)lptr, rlebuf,CHANOFFSET(z),xsize);
529                                 }
530                                 else if(z<8 && zptr) {
531                                         len = compressrow((uchar *)zptr, rlebuf,CHANOFFSET(z-4),xsize);
532                                 }
533                         }
534                         if(len>rlebuflen) {
535                                 fprintf(stderr,"output_iris: rlebuf is too small - bad poop\n");
536                                 exit(1);
537                         }
538                         goodwrite *= fwrite(rlebuf, len, 1, outf);
539                         starttab[y+z*ysize] = pos;
540                         lengthtab[y+z*ysize] = len;
541                         pos += len;
542                 }
543                 lptr += xsize;
544                 if(zptr) zptr += xsize;
545         }
546
547         fseek(outf,512,SEEK_SET);
548         goodwrite *= writetab(outf,starttab,tablen);
549         goodwrite *= writetab(outf,lengthtab,tablen);
550         free(image);
551         free(starttab);
552         free(lengthtab);
553         free(rlebuf);
554         free(lumbuf);
555         fclose(outf);
556         if(goodwrite)
557                 return 1;
558         else {
559                 fprintf(stderr,"output_iris: not enough space for image!!\n");
560                 return 0;
561         }
562 }
563
564 /* static utility functions for output_iris */
565
566 static void lumrow(unsigned char *rgbptr, unsigned char *lumptr, int n)
567 {
568         lumptr += CHANOFFSET(0);
569         while(n--) {
570                 *lumptr = ILUM(rgbptr[OFFSET_R],rgbptr[OFFSET_G],rgbptr[OFFSET_B]);
571                 lumptr += 4;
572                 rgbptr += 4;
573         }
574 }
575
576 static int compressrow(unsigned char *lbuf, unsigned char *rlebuf, int z, int cnt)
577 {
578         unsigned char *iptr, *ibufend, *sptr, *optr;
579         short todo, cc;
580         int count;
581
582         lbuf += z;
583         iptr = lbuf;
584         ibufend = iptr+cnt*4;
585         optr = rlebuf;
586
587         while(iptr<ibufend) {
588                 sptr = iptr;
589                 iptr += 8;
590                 while((iptr<ibufend)&& ((iptr[-8]!=iptr[-4])||(iptr[-4]!=iptr[0])))
591                         iptr+=4;
592                 iptr -= 8;
593                 count = (iptr-sptr)/4;
594                 while(count) {
595                         todo = count>126 ? 126:count;
596                         count -= todo;
597                         *optr++ = 0x80|todo;
598                         while(todo>8) {
599                                 optr[0] = sptr[0*4];
600                                 optr[1] = sptr[1*4];
601                                 optr[2] = sptr[2*4];
602                                 optr[3] = sptr[3*4];
603                                 optr[4] = sptr[4*4];
604                                 optr[5] = sptr[5*4];
605                                 optr[6] = sptr[6*4];
606                                 optr[7] = sptr[7*4];
607
608                                 optr += 8;
609                                 sptr += 8*4;
610                                 todo -= 8;
611                         }
612                         while(todo--) {
613                                 *optr++ = *sptr;
614                                 sptr += 4;
615                         }
616                 }
617                 sptr = iptr;
618                 cc = *iptr;
619                 iptr += 4;
620                 while( (iptr<ibufend) && (*iptr == cc) )
621                         iptr += 4;
622                 count = (iptr-sptr)/4;
623                 while(count) {
624                         todo = count>126 ? 126:count;
625                         count -= todo;
626                         *optr++ = todo;
627                         *optr++ = cc;
628                 }
629         }
630         *optr++ = 0;
631         return optr - (unsigned char *)rlebuf;
632 }
633
634 short imb_saveiris(struct ImBuf * ibuf, char *name, int flags)
635 {
636         short zsize;
637         int ret;
638
639         zsize = (ibuf->depth + 7) >> 3;
640         if (flags & IB_zbuf &&  ibuf->zbuf != 0) zsize = 8;
641         
642         IMB_convert_rgba_to_abgr(ibuf);
643         test_endian_zbuf(ibuf);
644
645         ret = output_iris(ibuf->rect, ibuf->x, ibuf->y, zsize, name, ibuf->zbuf);
646
647         /* restore! Quite clumsy, 2 times a switch... maybe better a malloc ? */
648         IMB_convert_rgba_to_abgr(ibuf);
649         test_endian_zbuf(ibuf);
650
651         return(ret);
652 }
653