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