This looks like a lot but its a few small changes.
[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 #ifdef HAVE_CONFIG_H
45 #include <config.h>
46 #endif
47
48 typedef struct {
49     unsigned short      imagic;         /* stuff saved on disk . . */
50     unsigned short      type;
51     unsigned short      dim;
52     unsigned short      xsize;
53     unsigned short      ysize;
54     unsigned short      zsize;
55     unsigned int        min;
56     unsigned int        max;
57     unsigned int        wastebytes;     
58     char                name[80];
59     unsigned int        colormap;
60
61     int                 file;           /* stuff used in core only */
62     unsigned short      flags;
63     short               dorev;
64     short               x;
65     short               y;
66     short               z;
67     short               cnt;
68     unsigned short      *ptr;
69     unsigned short      *base;
70     unsigned short      *tmpbuf;
71     unsigned int        offset;
72     unsigned int        rleend;         /* for rle images */
73     unsigned int        *rowstart;      /* for rle images */
74     int                 *rowsize;       /* for rle images */
75 } IMAGE;
76
77 #define RINTLUM (79)
78 #define GINTLUM (156)
79 #define BINTLUM (21)
80
81 #define ILUM(r,g,b)     ((int)(RINTLUM*(r)+GINTLUM*(g)+BINTLUM*(b))>>8)
82
83 #define OFFSET_R        0       /* this is byte order dependent */
84 #define OFFSET_G        1
85 #define OFFSET_B        2
86 #define OFFSET_A        3
87
88 #define CHANOFFSET(z)   (3-(z)) /* this is byte order dependent */
89
90 #define TYPEMASK                0xff00
91 #define BPPMASK                 0x00ff
92 #define ITYPE_VERBATIM          0x0000
93 #define ITYPE_RLE               0x0100
94 #define ISRLE(type)             (((type) & 0xff00) == ITYPE_RLE)
95 #define ISVERBATIM(type)        (((type) & 0xff00) == ITYPE_VERBATIM)
96 #define BPP(type)               ((type) & BPPMASK)
97 #define RLE(bpp)                (ITYPE_RLE | (bpp))
98 #define VERBATIM(bpp)           (ITYPE_VERBATIM | (bpp))
99 #define IBUFSIZE(pixels)        ((pixels+(pixels>>6))<<2)
100 #define RLE_NOP                 0x00
101
102 /* funcs */
103 static void readheader(FILE *inf, IMAGE *image);
104 static int writeheader(FILE *outf, IMAGE *image);
105
106 static unsigned short getshort(FILE *inf);
107 static unsigned int getlong(FILE *inf);
108 static void putshort(FILE *outf, unsigned short val);
109 static int putlong(FILE *outf, unsigned int val);
110 static int writetab(FILE *outf, unsigned int *tab, int len);
111 static void readtab(FILE *inf, unsigned int *tab, int len);
112
113 static void expandrow(unsigned char *optr, unsigned char *iptr, int z);
114 static void interleaverow(unsigned char *lptr, unsigned char *cptr, int z, int n);
115 static int compressrow(unsigned char *lbuf, unsigned char *rlebuf, int z, int cnt);
116 static void lumrow(unsigned char *rgbptr, unsigned char *lumptr, int n);
117
118 /* not used... */
119 /*  static void copybw(int *lptr, int n); */
120 /*  static void setalpha(unsigned char *lptr, int n); */
121
122 /*
123  *      byte order independent read/write of shorts and ints.
124  *
125  */
126
127 static uchar * file_data;
128 static int file_offset;
129
130 static unsigned short getshort(FILE *inf)
131 {
132         unsigned char * buf;
133         
134         buf = file_data + file_offset;
135         file_offset += 2;
136         
137         return (buf[0]<<8)+(buf[1]<<0);
138 }
139
140 static unsigned int getlong(FILE *inf)
141 {
142         unsigned char * buf;
143         
144         buf = file_data + file_offset;
145         file_offset += 4;
146         
147         return (buf[0]<<24)+(buf[1]<<16)+(buf[2]<<8)+(buf[3]<<0);
148 }
149
150 static void putshort(FILE *outf, unsigned short val)
151 {
152         unsigned char buf[2];
153
154         buf[0] = (val>>8);
155         buf[1] = (val>>0);
156         fwrite(buf,2,1,outf);
157 }
158
159 static int putlong(FILE *outf, unsigned int val)
160 {
161         unsigned char buf[4];
162
163         buf[0] = (val>>24);
164         buf[1] = (val>>16);
165         buf[2] = (val>>8);
166         buf[3] = (val>>0);
167         return fwrite(buf,4,1,outf);
168 }
169
170 static void readheader(FILE *inf, IMAGE *image)
171 {
172         memset(image, 0, sizeof(IMAGE));
173         image->imagic = getshort(inf);
174         image->type = getshort(inf);
175         image->dim = getshort(inf);
176         image->xsize = getshort(inf);
177         image->ysize = getshort(inf);
178         image->zsize = getshort(inf);
179 }
180
181 static int writeheader(FILE *outf, IMAGE *image)
182 {
183         IMAGE t;
184
185         memset(&t, 0, sizeof(IMAGE));
186         fwrite(&t,sizeof(IMAGE),1,outf);
187         fseek(outf,0,SEEK_SET);
188         putshort(outf,image->imagic);
189         putshort(outf,image->type);
190         putshort(outf,image->dim);
191         putshort(outf,image->xsize);
192         putshort(outf,image->ysize);
193         putshort(outf,image->zsize);
194         putlong(outf,image->min);
195         putlong(outf,image->max);
196         putlong(outf,0);
197         return fwrite("no name",8,1,outf);
198 }
199
200 static int writetab(FILE *outf, unsigned int *tab, int len)
201 {
202         int r = 0;
203
204         while(len) {
205                 r = putlong(outf,*tab++);
206                 len -= 4;
207         }
208         return r;
209 }
210
211 static void readtab(FILE *inf, unsigned int *tab, int len)
212 {
213         while(len) {
214                 *tab++ = getlong(inf);
215                 len -= 4;
216         }
217 }
218
219 static void test_endian_zbuf(struct ImBuf *ibuf)
220 {
221         int len;
222         int *zval;
223         
224         if( BIG_LONG(1) == 1 ) return;
225         if(ibuf->zbuf==0) return;
226         
227         len= ibuf->x*ibuf->y;
228         zval= ibuf->zbuf;
229         
230         while(len--) {
231                 zval[0]= BIG_LONG(zval[0]);
232                 zval++;
233         }
234 }
235
236
237 /*
238  *      longimagedata - 
239  *              read in a B/W RGB or RGBA iris image file and return a 
240  *      pointer to an array of ints.
241  *
242  */
243
244 struct ImBuf *imb_loadiris(unsigned char *mem, int flags)
245 {
246         unsigned int *base, *lptr;
247         unsigned int *zbase, *zptr;
248         unsigned char *rledat;
249         int *starttab, *lengthtab;
250         FILE *inf;
251         IMAGE image;
252         int x, y, z, tablen;
253         int xsize, ysize, zsize;
254         int bpp, rle, cur, badorder;
255         ImBuf * ibuf;
256         uchar * rect;
257         
258         /*printf("new iris\n");*/
259         
260         file_data = mem;
261         file_offset = 0;
262         
263         readheader(inf, &image);
264         if(image.imagic != IMAGIC) {
265                 fprintf(stderr,"longimagedata: bad magic number in image file\n");
266                 return(0);
267         }
268         
269         rle = ISRLE(image.type);
270         bpp = BPP(image.type);
271         if(bpp != 1 ) {
272                 fprintf(stderr,"longimagedata: image must have 1 byte per pix chan\n");
273                 return(0);
274         }
275         
276         xsize = image.xsize;
277         ysize = image.ysize;
278         zsize = image.zsize;
279         
280         if (flags & IB_test) {
281                 ibuf = IMB_allocImBuf(image.xsize, image.ysize, 8 * image.zsize, 0, 0);
282                 if (ibuf) ibuf->ftype = IMAGIC;
283                 return(ibuf);
284         }
285         
286         if (rle) {
287                 tablen = ysize*zsize*sizeof(int);
288                 starttab = (int *)malloc(tablen);
289                 lengthtab = (int *)malloc(tablen);
290                 file_offset = 512;
291                 
292                 readtab(inf,starttab,tablen);
293                 readtab(inf,lengthtab,tablen);
294
295                 /* check data order */
296                 cur = 0;
297                 badorder = 0;
298                 for (y = 0; y<ysize; y++) {
299                         for (z = 0; z<zsize; z++) {
300                                 if (starttab[y+z*ysize]<cur) {
301                                         badorder = 1;
302                                         break;
303                                 }
304                                 cur = starttab[y+z*ysize];
305                         }
306                         if(badorder)
307                                 break;
308                 }
309
310                 ibuf = IMB_allocImBuf(xsize, ysize, 8 * zsize, IB_rect, 0);
311                 if (ibuf->depth > 32) ibuf->depth = 32;
312                 base = ibuf->rect;
313                 zbase = (unsigned int *)ibuf->zbuf;
314                 
315                 if (badorder) {
316                         for(z=0; z<zsize; z++) {
317                                 lptr = base;
318                                 for(y=0; y<ysize; y++) {
319                                         file_offset = starttab[y+z*ysize];
320                                         
321                                         rledat = file_data + file_offset;
322                                         file_offset += lengthtab[y+z*ysize];
323                                         
324                                         expandrow((uchar *)lptr, rledat, 3-z);
325                                         lptr += xsize;
326                                 }
327                         }
328                 }
329                 else {
330                         lptr = base;
331                         zptr = zbase;
332                         for(y=0; y<ysize; y++) {
333                         
334                                 for(z=0; z<zsize; z++) {
335                                         
336                                         file_offset = starttab[y+z*ysize];
337
338                                         rledat = file_data + file_offset;
339                                         file_offset += lengthtab[y+z*ysize];
340                                         
341                                         if(z<4) expandrow((uchar *)lptr, rledat, 3-z);
342                                         else if(z<8) expandrow((uchar *)zptr, rledat, 7-z);
343                                 }
344                                 lptr += xsize;
345                                 zptr += xsize;
346                         }
347                 }
348                 
349                 free(starttab);
350                 free(lengthtab);
351         } 
352         else {
353         
354                 ibuf = IMB_allocImBuf(xsize, ysize, 8 * zsize, IB_rect, 0);
355                 if (ibuf->depth > 32) ibuf->depth = 32;
356
357                 base = ibuf->rect;
358                 zbase = (unsigned int *)ibuf->zbuf;
359                 
360                 file_offset = 512;
361                 rledat = file_data + file_offset;
362                 
363                 for(z = 0; z < zsize; z++) {
364                         
365                         if(z<4) lptr = base;
366                         else if(z<8) lptr= zbase;
367                         
368                         for(y = 0; y < ysize; y++) {
369
370                                 interleaverow((uchar *)lptr, rledat, 3-z, xsize);
371                                 rledat += xsize;
372                                 
373                                 lptr += xsize;
374                         }
375                 }
376         }
377         
378         if (image.zsize == 1){
379                 rect = (uchar *) ibuf->rect;
380                 for (x = ibuf->x * ibuf->y; x > 0; x--) {
381                         rect[0] = 255;
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->x*ibuf->y, ibuf->rect);
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 /* not used? */
419 /*static void copybw(int *lptr, int n) */
420 /*  int *lptr; */
421 /*  int n; */
422 /*{
423         while(n>=8) {
424                 lptr[0] = 0xff000000+(0x010101*(lptr[0]&0xff));
425                 lptr[1] = 0xff000000+(0x010101*(lptr[1]&0xff));
426                 lptr[2] = 0xff000000+(0x010101*(lptr[2]&0xff));
427                 lptr[3] = 0xff000000+(0x010101*(lptr[3]&0xff));
428                 lptr[4] = 0xff000000+(0x010101*(lptr[4]&0xff));
429                 lptr[5] = 0xff000000+(0x010101*(lptr[5]&0xff));
430                 lptr[6] = 0xff000000+(0x010101*(lptr[6]&0xff));
431                 lptr[7] = 0xff000000+(0x010101*(lptr[7]&0xff));
432                 lptr += 8;
433                 n-=8;
434         }
435         while(n--) {
436                 *lptr = 0xff000000+(0x010101*(*lptr&0xff));
437                 lptr++;
438         }
439 }
440 */
441
442 /* not used ? */
443 /*static void setalpha(unsigned char *lptr, int n)*/
444 /*  unsigned char *lptr; */
445 /*{
446         while(n>=8) {
447                 lptr[0*4] = 0xff;
448                 lptr[1*4] = 0xff;
449                 lptr[2*4] = 0xff;
450                 lptr[3*4] = 0xff;
451                 lptr[4*4] = 0xff;
452                 lptr[5*4] = 0xff;
453                 lptr[6*4] = 0xff;
454                 lptr[7*4] = 0xff;
455                 lptr += 4*8;
456                 n -= 8;
457         }
458         while(n--) {
459                 *lptr = 0xff;
460                 lptr += 4;
461         }
462 }
463 */
464
465 static void expandrow(unsigned char *optr, unsigned char *iptr, int z)
466 {
467         unsigned char pixel, count;
468
469         optr += z;
470         while(1) {
471                 pixel = *iptr++;
472                 if ( !(count = (pixel & 0x7f)) )
473                         return;
474                 if(pixel & 0x80) {
475                         while(count>=8) {
476                                 optr[0*4] = iptr[0];
477                                 optr[1*4] = iptr[1];
478                                 optr[2*4] = iptr[2];
479                                 optr[3*4] = iptr[3];
480                                 optr[4*4] = iptr[4];
481                                 optr[5*4] = iptr[5];
482                                 optr[6*4] = iptr[6];
483                                 optr[7*4] = iptr[7];
484                                 optr += 8*4;
485                                 iptr += 8;
486                                 count -= 8;
487                         }
488                         while(count--) {
489                                 *optr = *iptr++;
490                                 optr+=4;
491                         }
492                 } else {
493                         pixel = *iptr++;
494                         while(count>=8) {
495                                 optr[0*4] = pixel;
496                                 optr[1*4] = pixel;
497                                 optr[2*4] = pixel;
498                                 optr[3*4] = pixel;
499                                 optr[4*4] = pixel;
500                                 optr[5*4] = pixel;
501                                 optr[6*4] = pixel;
502                                 optr[7*4] = pixel;
503                                 optr += 8*4;
504                                 count -= 8;
505                         }
506                         while(count--) {
507                                 *optr = pixel;
508                                 optr+=4;
509                         }
510                 }
511         }
512 }
513
514 /*
515  *      output_iris -
516  *              copy an array of ints to an iris image file.  Each int
517  *      represents one pixel.  xsize and ysize specify the dimensions of
518  *      the pixel array.  zsize specifies what kind of image file to
519  *      write out.  if zsize is 1, the luminance of the pixels are
520  *      calculated, and a sinlge channel black and white image is saved.
521  *      If zsize is 3, an RGB image file is saved.  If zsize is 4, an
522  *      RGBA image file is saved.
523  *
524  *  Added: zbuf write
525  */
526
527 static int output_iris(unsigned int *lptr, int xsize, int ysize, int zsize, int file, int *zptr)
528 {
529         FILE *outf;
530         IMAGE *image;
531         int tablen, y, z, pos, len = 0;
532         int *starttab, *lengthtab;
533         unsigned char *rlebuf;
534         unsigned int *lumbuf;
535         int rlebuflen, goodwrite;
536
537         goodwrite = 1;
538         outf = fdopen(file, "wb");
539
540         if(!outf) {
541                 perror("fdopen");
542                 fprintf(stderr,"output_iris: can't open output file\n");
543                 return 0;
544         }
545         tablen = ysize*zsize*sizeof(int);
546
547         image = (IMAGE *)malloc(sizeof(IMAGE));
548         starttab = (int *)malloc(tablen);
549         lengthtab = (int *)malloc(tablen);
550         rlebuflen = 1.05*xsize+10;
551         rlebuf = (unsigned char *)malloc(rlebuflen);
552         lumbuf = (unsigned int *)malloc(xsize*sizeof(int));
553
554         memset(image, 0, sizeof(IMAGE));
555         image->imagic = IMAGIC;
556         image->type = RLE(1);
557         if(zsize>1)
558                 image->dim = 3;
559         else
560                 image->dim = 2;
561         image->xsize = xsize;
562         image->ysize = ysize;
563         image->zsize = zsize;
564         image->min = 0;
565         image->max = 255;
566         goodwrite *= writeheader(outf,image);
567         fseek(outf,512+2*tablen,SEEK_SET);
568         pos = 512+2*tablen;
569         
570         for (y = 0; y < ysize; y++) {
571                 for (z = 0; z < zsize; z++) {
572                         
573                         if (zsize == 1) {
574                                 lumrow((uchar *)lptr,(uchar *)lumbuf,xsize);
575                                 len = compressrow((uchar *)lumbuf,rlebuf,CHANOFFSET(z),xsize);
576                         }
577                         else {
578                                 if(z<4) {
579                                         len = compressrow((uchar *)lptr, rlebuf,CHANOFFSET(z),xsize);
580                                 }
581                                 else if(z<8 && zptr) {
582                                         len = compressrow((uchar *)zptr, rlebuf,CHANOFFSET(z-4),xsize);
583                                 }
584                         }
585                         if(len>rlebuflen) {
586                                 fprintf(stderr,"output_iris: rlebuf is too small - bad poop\n");
587                                 exit(1);
588                         }
589                         goodwrite *= fwrite(rlebuf, len, 1, outf);
590                         starttab[y+z*ysize] = pos;
591                         lengthtab[y+z*ysize] = len;
592                         pos += len;
593                 }
594                 lptr += xsize;
595                 if(zptr) zptr += xsize;
596         }
597
598         fseek(outf,512,SEEK_SET);
599         goodwrite *= writetab(outf,starttab,tablen);
600         goodwrite *= writetab(outf,lengthtab,tablen);
601         free(image);
602         free(starttab);
603         free(lengthtab);
604         free(rlebuf);
605         free(lumbuf);
606         fclose(outf);
607         if(goodwrite)
608                 return 1;
609         else {
610                 fprintf(stderr,"output_iris: not enough space for image!!\n");
611                 return 0;
612         }
613 }
614
615 /* static utility functions for output_iris */
616
617 static void lumrow(unsigned char *rgbptr, unsigned char *lumptr, int n)
618 {
619         lumptr += CHANOFFSET(0);
620         while(n--) {
621                 *lumptr = ILUM(rgbptr[OFFSET_R],rgbptr[OFFSET_G],rgbptr[OFFSET_B]);
622                 lumptr += 4;
623                 rgbptr += 4;
624         }
625 }
626
627 static int compressrow(unsigned char *lbuf, unsigned char *rlebuf, int z, int cnt)
628 {
629         unsigned char *iptr, *ibufend, *sptr, *optr;
630         short todo, cc;
631         int count;
632
633         lbuf += z;
634         iptr = lbuf;
635         ibufend = iptr+cnt*4;
636         optr = rlebuf;
637
638         while(iptr<ibufend) {
639                 sptr = iptr;
640                 iptr += 8;
641                 while((iptr<ibufend)&& ((iptr[-8]!=iptr[-4])||(iptr[-4]!=iptr[0])))
642                         iptr+=4;
643                 iptr -= 8;
644                 count = (iptr-sptr)/4;
645                 while(count) {
646                         todo = count>126 ? 126:count;
647                         count -= todo;
648                         *optr++ = 0x80|todo;
649                         while(todo>8) {
650                                 optr[0] = sptr[0*4];
651                                 optr[1] = sptr[1*4];
652                                 optr[2] = sptr[2*4];
653                                 optr[3] = sptr[3*4];
654                                 optr[4] = sptr[4*4];
655                                 optr[5] = sptr[5*4];
656                                 optr[6] = sptr[6*4];
657                                 optr[7] = sptr[7*4];
658
659                                 optr += 8;
660                                 sptr += 8*4;
661                                 todo -= 8;
662                         }
663                         while(todo--) {
664                                 *optr++ = *sptr;
665                                 sptr += 4;
666                         }
667                 }
668                 sptr = iptr;
669                 cc = *iptr;
670                 iptr += 4;
671                 while( (iptr<ibufend) && (*iptr == cc) )
672                         iptr += 4;
673                 count = (iptr-sptr)/4;
674                 while(count) {
675                         todo = count>126 ? 126:count;
676                         count -= todo;
677                         *optr++ = todo;
678                         *optr++ = cc;
679                 }
680         }
681         *optr++ = 0;
682         return optr - (unsigned char *)rlebuf;
683 }
684
685 short imb_saveiris(struct ImBuf * ibuf, int file, int flags)
686 {
687         short zsize;
688         int ret;
689
690         zsize = (ibuf->depth + 7) >> 3;
691         if (flags & IB_zbuf &&  ibuf->zbuf != 0) zsize = 8;
692         
693         IMB_convert_rgba_to_abgr(ibuf->x*ibuf->y, ibuf->rect);
694         test_endian_zbuf(ibuf);
695
696         ret = output_iris(ibuf->rect, ibuf->x, ibuf->y, zsize, file, ibuf->zbuf);
697
698         /* restore! Quite clumsy, 2 times a switch... maybe better a malloc ? */
699         IMB_convert_rgba_to_abgr(ibuf->x*ibuf->y, ibuf->rect);
700         test_endian_zbuf(ibuf);
701
702         return(ret);
703 }
704