Added more docs, mostly header stuff, but some real docs in
[blender.git] / source / blender / imbuf / intern / amiga.c
1 /**
2  * amiga.c
3  *
4  * $Id$
5  *
6  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version. The Blender
12  * Foundation also sells licenses for use in proprietary software under
13  * the Blender License.  See http://www.blender.org/BL/ for information
14  * about this.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  *
25  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
26  * All rights reserved.
27  *
28  * The Original Code is: all of this file.
29  *
30  * Contributor(s): none yet.
31  *
32  * ***** END GPL/BL DUAL LICENSE BLOCK *****
33  */
34 /**
35  * \file amiga.c
36  * \brief This file handles loading and saving of amiga files.
37  * \ingroup imbuf
38  * \warning This file contains endian code.  Some way should be found to move
39  * this code out of here.
40  * \help Endian #defines are in multiple files!
41  */
42
43 #include "imbuf.h"
44 #include "imbuf_patch.h"
45
46 #include "IMB_imbuf_types.h"
47 #include "IMB_imbuf.h"
48
49 #include "IMB_cmap.h"
50 #include "IMB_allocimbuf.h"
51 #include "IMB_bitplanes.h"
52 #include "IMB_amiga.h"
53
54 #ifdef HAVE_CONFIG_H
55 #include <config.h>
56 #endif
57
58 /* actually hard coded endianness */
59 /**
60  * \brief Makes a 4 bit id for a 32 bit value: Big-endian
61  * \todo How is this used?
62  */
63 #define GET_BIG_LONG(x) (((uchar *) (x))[0] << 24 | ((uchar *) (x))[1] << 16 | ((uchar *) (x))[2] << 8 | ((uchar *) (x))[3])
64 /**
65  * \brief Makes a 4 bit id for a 16? bit value: Little-endian
66  * \todo How is this used?
67  */
68 #define GET_LITTLE_LONG(x) (((uchar *) (x))[3] << 24 | ((uchar *) (x))[2] << 16 | ((uchar *) (x))[1] << 8 | ((uchar *) (x))[0])
69 /**
70  * \brief Converts between little and big endian: 32 bit values
71  */
72 #define SWAP_L(x) (((x << 24) & 0xff000000) | ((x << 8) & 0xff0000) | ((x >> 8) & 0xff00) | ((x >> 24) & 0xff))
73 /**
74  * \brief Converts between little and big endian:  16 bit values
75  */
76 #define SWAP_S(x) (((x << 8) & 0xff00) | ((x >> 8) & 0xff))
77
78 /* more endianness... should move to a separate file... */
79 #if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
80 #define GET_ID GET_BIG_LONG
81 #define LITTLE_LONG SWAP_LONG
82 #else
83 #define GET_ID GET_LITTLE_LONG
84 #define LITTLE_LONG ENDIAN_NOP
85 #endif
86
87 static uchar *decodebodyscanl(uchar *body, short bytes, uchar **list, short d)
88 {
89         for (;d>0;d--){
90                 uchar *point;
91                 short todo;
92                 uchar i,j;
93
94                 point = *(list++);
95                 todo=bytes;
96                 while (todo>0){
97                         i = *body++;
98
99                         if (i & 128){                   /* fill */
100                                 if (i==128) continue;   /* nop  */
101
102                                 i=257-i;
103                                 todo-=i;
104                                 j = *(body++);
105                                 do{
106                                         *(point++) = j;
107                                         i--;
108                                 }while (i);
109                         } else{                         /* copy */
110                                 i++;
111                                 todo-=i;
112
113                                 do{
114                                         *(point++) = *(body++);
115                                         i--;
116                                 }while (i);
117                         }
118                 }
119                 if (todo) return (0);
120         }
121         return(body);
122 }
123
124
125 static uchar *decodebodyh(struct ImBuf *ibuf, uchar *body)
126 {
127         if (ibuf->y==1) {
128                 body=decodebodyscanl(body, WIDTHB(ibuf->x), (uchar **)ibuf->planes, ibuf->depth);
129         }
130         else {
131                 unsigned int **list;
132                 short skipx,i,bytes,y;
133
134                 list = imb_copyplanelist(ibuf);
135                 if (list == 0) return (0);
136
137                 y=ibuf->y;
138                 bytes = WIDTHB(ibuf->x);
139                 skipx = ibuf->skipx;
140
141                 for (;y>0;y--){
142                         body=decodebodyscanl(body, bytes, (uchar **)list, ibuf->depth);
143                         if (body == 0) return (0);
144
145                         for (i=ibuf->depth-1;i>=0;i--){
146                                 list[i] += skipx;
147                         }
148                 }
149                 free(list);
150         }
151         return(body);
152 }
153
154
155 static uchar *decodebodykolum(uchar *body, short bytes, uchar **list, short d, int next)
156 {
157         for (;d>0;d--){
158                 uchar *point;
159                 short todo;
160                 uchar i,j;
161
162                 point = *(list++);
163                 todo=bytes;
164                 while (todo>0){
165                         i = *body++;
166
167                         if (i & 128){                   /* fill */
168                                 if (i==128) continue;   /* nop  */
169
170                                 i=257-i;
171                                 todo-=i;
172                                 j = *body++;
173                                 do{
174                                         *point = j;
175                                         point += next;
176                                         i--;
177                                 }while (i);
178                         }
179                         else{                           /* copy */
180                                 i++;
181                                 todo-=i;
182
183                                 do{
184                                         *point = *body++;
185                                         point += next;
186                                         i--;
187                                 }while (i);
188                         }
189                 }
190                 if (todo) return (0);
191         }
192         return(body);
193 }
194
195
196 static uchar *decodebodyv(struct ImBuf *ibuf, uchar *body)
197 {
198         uchar **list;
199         short skipx,i,bytes,times;
200
201         list = (uchar **)imb_copyplanelist(ibuf);
202         if (list == 0) return (0);
203
204         bytes = ibuf->y;
205         times = WIDTHB(ibuf->x);
206         skipx = ibuf->skipx << 2;
207
208         for (;times>0;times--){
209                 body=decodebodykolum(body,bytes,list,ibuf->depth,skipx);
210                 if (body == 0) return (0);
211
212                 for (i=ibuf->depth-1;i>=0;i--){
213                         list[i] += 1;
214                 }
215         }
216         free(list);
217         return(body);
218 }
219
220 static uchar *makebody(uchar **planes, short bytes, short depth, uchar *buf)
221 {
222         uchar *bitplstart,*temp;
223
224         register uchar last,this,*bitpl;
225         register short todo;
226         register int copy;
227
228         bytes--;
229         for (;depth>0;depth--){
230                 bitpl = *(planes++);
231                 bitplstart = bitpl;
232                 todo = bytes;
233                 last = *bitpl++;
234                 this = *bitpl++;
235                 copy = last^this;
236                 while (todo>0){
237
238                         if (copy){
239                                 do{
240                                         last = this;
241                                         this = *bitpl++;
242                                         if (last == this){
243                                                 if (this == bitpl[-3]){         /* three identical ones? */
244                                                         todo -= 1;              /* set todo */
245                                                         break;
246                                                 }
247                                         }
248                                 }while (--todo != 0);
249
250                                 copy=bitpl-bitplstart;
251                                 copy -= 1;
252                                 if (todo) copy -= 2;
253
254                                 temp = bitpl;
255                                 bitpl = bitplstart;
256
257                                 while (copy){
258                                         last = copy;
259                                         if (copy>MAXDAT) last = MAXDAT;
260                                         copy -= last;
261                                         *buf++ = last-1;
262                                         do{
263                                                 *buf++ = *bitpl++;
264                                         }while(--last != 0);
265                                 }
266                                 bitplstart = bitpl;
267                                 bitpl = temp;
268                                 last = this;
269
270                                 copy = FALSE;
271                         }
272                         else{
273                                 while (*bitpl++ == this){       /* search for first different bye */
274                                         if (--todo == 0) break; /* or end of line */
275                                 }
276                                 bitpl -= 1;
277                                 copy = bitpl-bitplstart;
278                                 bitplstart = bitpl;
279                                 todo -= 1;
280                                 this = *bitpl++;
281
282                                 while (copy){
283                                         if (copy>MAXRUN){
284                                                 *buf++ = -(MAXRUN-1);
285                                                 *buf++ = last;
286                                                 copy -= MAXRUN;
287                                         }
288                                         else{
289                                                 *buf++ = -(copy-1);
290                                                 *buf++ = last;
291                                                 break;
292                                         }
293                                 }
294                                 copy=TRUE;
295                         }
296                 }
297         }
298         return (buf);
299 }
300
301
302 short imb_encodebodyh(struct ImBuf *ibuf, int file)
303 {
304         uchar *buf, *endbuf, *max;
305         int size, line, ok = TRUE;
306         unsigned int **list;
307         short skipx,i,y;
308
309         line = WIDTHB(ibuf->x) * ibuf->depth;
310         line += (line >> 6) + 10;
311         size = 16 * line;
312         if (size < 16384) size = 16384;
313         
314         buf = (uchar *) malloc(size);
315         if (buf == 0) return (0);
316
317         max = buf + size - line;
318         
319         list = imb_copyplanelist(ibuf);
320         if (list == 0){
321                 free(buf);
322                 return (0);
323         }
324
325         y=ibuf->y;
326         skipx = ibuf->skipx;
327         endbuf = buf;
328         
329         for (y=ibuf->y;y>0;y--){
330                 endbuf = makebody((uchar **)list, WIDTHB(ibuf->x), ibuf->depth, endbuf);
331                 if (endbuf==0){
332                         ok = -20;
333                         break;
334                 }
335                 if (endbuf >= max || y == 1){ 
336                         size = endbuf-buf;
337                         if (write(file,buf,size)!=size) ok = -19;
338                         endbuf = buf;
339                 }
340                 for (i=ibuf->depth-1;i>=0;i--){
341                         list[i] += skipx;
342                 }
343                 if (ok != TRUE) break;
344         }
345         free(list);
346
347         free(buf);
348         return(ok);
349 }
350
351
352 short imb_encodebodyv(struct ImBuf *ibuf, int file)
353 {
354         struct ImBuf *ibufv;
355         uchar *buf,*endbuf;
356         short x,offset;
357
358         buf = (uchar *) malloc((ibuf->y + (ibuf->y >> 6) + 10) * ibuf->depth);
359         if (buf == 0) return (0);
360
361         ibufv=IMB_allocImBuf((ibuf->y)<<3,1, ibuf->depth, 0, 1);
362         if (ibufv == 0){
363                 free(buf);
364                 return (0);
365         }
366
367         offset=0;
368
369         for(x = WIDTHB(ibuf->x);x>0;x--){
370                 register short i;
371
372                 for(i = ibuf->depth-1 ;i>=0;i--){
373                         register uchar *p1,*p2;
374                         register int skipx;
375                         register short y;
376
377                         skipx = (ibuf->skipx)*sizeof(int *);
378                         p1=(uchar *)ibuf->planes[i];
379                         p2=(uchar *)ibufv->planes[i];
380                         p1 += offset;
381
382                         for (y=ibuf->y;y>0;y--){
383                                 *(p2++) = *p1;
384                                 p1 += skipx;
385                         }
386                 }
387                 offset += 1;
388
389                 endbuf=makebody((uchar **)ibufv->planes, ibuf->y, ibuf->depth, buf);
390                 if (endbuf==0) return (-20);
391                 if (write(file,buf,endbuf-buf)!=endbuf-buf) return (-19);
392         }
393         free(buf);
394         IMB_freeImBuf(ibufv);
395         return (TRUE);
396 }
397
398 static uchar *readbody(struct ImBuf *ibuf, uchar *body)
399 {
400         int skipbuf,skipbdy,depth,y,offset = 0;
401
402         skipbuf = ibuf->skipx;
403         skipbdy = WIDTHB(ibuf->x);
404
405         for (y = ibuf->y; y> 0; y--){
406                 for( depth = 0; depth < ibuf->depth; depth ++){
407                         memcpy(ibuf->planes[depth] + offset, body, skipbdy);
408                         body += skipbdy;
409                 }
410                 offset += skipbuf;
411         }
412         return body;
413 }
414
415 /**
416  * \brief Loads an amiga (.ami) image.
417  * \ingroup imbuf
418  * \param iffmem A pointer to a memory location.
419  * \param flags A set of bit flags determining what parts of the image to load.
420  * \return Returns 0 if loading the image fails, otherwise returns a pointer to an ImBuf.
421  * 
422  * I am fairly certain of what is going on in this function, so if I am
423  * wrong, please let me know, so I can update the docs!
424  */
425 struct ImBuf *imb_loadamiga(int *iffmem,int flags)
426 {
427         int chunk,totlen,len,*cmap=0,cmaplen,*mem,ftype=0;
428         uchar *body=0;
429         struct BitMapHeader bmhd;
430         struct ImBuf *ibuf=0;
431
432         /**
433          * \internal The memory address to the data is copiend into mem.
434          */
435         mem = iffmem;
436         /**
437          * \internal The w member of the BitMapHeader is initialized to 0 because 
438          * it will be tested to see if it has been set later.
439          */
440         bmhd.w = 0;
441
442         /**
443          * \internal The first three chunks must have the form: FORMxxxxILBM
444          * else the function returns with 0;
445          * FORM and ILBM are defined in imbuf_patch.h
446          */
447         if (GET_ID(mem) != FORM) return (0);
448         if (GET_ID(mem+2) != ILBM) return (0);
449         /**
450          * \internal The second chunk is the total size of the image.
451          */
452         totlen= (GET_BIG_LONG(mem+1) + 1) & ~1;
453         /**
454          * \internal mem is incremented to skip the first three chunks.
455          */
456         mem += 3;
457         /**
458          * \internal Anyone know why the total length is decreased by four here?
459          */
460         totlen -= 4;
461
462
463         /**
464          * \internal The while loop retrieves at most four blocks of memory:
465          *  - bmhd: the bit map header
466          *  - body: which is the image data
467          *  - cmap: the color map
468          *  - ftype: the file type (what does CAMG stand for?)
469          * The body and the bitmap header are required.
470          */
471         while(totlen > 0){
472                 chunk = GET_ID(mem);
473                 len= (GET_BIG_LONG(mem+1) + 1) & ~1;
474                 mem += 2;
475
476                 totlen -= len+8;
477
478                 switch (chunk){
479                 case BMHD:
480                         memcpy(&bmhd, mem, sizeof(struct BitMapHeader));
481
482                         bmhd.w = BIG_SHORT(bmhd.w);
483                         bmhd.h = BIG_SHORT(bmhd.h);
484                         bmhd.x = BIG_SHORT(bmhd.x);
485                         bmhd.y = BIG_SHORT(bmhd.y);
486                         bmhd.transparentColor = BIG_SHORT(bmhd.transparentColor);
487                         bmhd.pageWidth = BIG_SHORT(bmhd.pageWidth);
488                         bmhd.pageHeight = BIG_SHORT(bmhd.pageHeight);
489                         
490                         break;
491                 case BODY:
492                         body = (uchar *)mem;
493                         break;
494                 case CMAP:
495                         cmap = mem;
496                         cmaplen = len/3;
497                         break;
498                 case CAMG:
499                         ftype = GET_BIG_LONG(mem);
500                         break;
501                 }
502                 mem = (int *)((uchar *)mem +len);
503                 /**
504                  * \intern Anything after the first BODY ID is discarded.
505                  */
506                 if (body) break;
507         }
508         /**
509          * \internal After the while loop, the existance of body and bmhd are detected.
510          */
511         if (bmhd.w == 0) return (0);
512         if (body == 0) return (0);
513         
514         /**
515          * \internal if the IB_test bit is set in flags, don't do masking.
516          * (I'm not too sure about this)  In any case, allocate the memory
517          * for the imbuf, and return 0 if this fails.
518          */
519         if (flags & IB_test) ibuf = IMB_allocImBuf(bmhd.w, bmhd.h, bmhd.nPlanes, 0, 0);
520         else ibuf = IMB_allocImBuf(bmhd.w, bmhd.h, bmhd.nPlanes + (bmhd.masking & 1),0,1);
521
522         if (ibuf == 0) return (0);
523
524         /**
525          * \internal Set the AMI bit in ftype.
526          */
527         ibuf->ftype = (ftype | AMI);
528         
529         /**
530          * \internal If there was a cmap chunk in the data, add the cmap
531          * to the ImBuf and copy the data there.
532          */
533         if (cmap){
534                 ibuf->mincol = 0;
535                 ibuf->maxcol = cmaplen;
536                 imb_addcmapImBuf(ibuf);
537                 /* this functions needs a 3rd arg: the number of
538          * columns.... why did this work before? */
539 /*              imb_makecolarray(ibuf, cmap); */
540                 imb_makecolarray(ibuf, cmap, 0);
541         }
542
543         /**
544          * \internal If the IB_test bit of flags was set, we're done:
545          * If the IB_freem bit is set, free the data pointed to by iffmem.
546          * Return the data.
547          */
548         if (flags & IB_test){
549                 if (flags & IB_freem) free(iffmem);
550                 return(ibuf);
551         }
552         
553         /**
554          * \internal Check the bitmap header to see if there is any
555          * compression.  0 is no, 1 is horizontal, 2 is vertical.
556          * Load the data according to the type of compression.
557          */
558         switch (bmhd.compression){
559         case 0:
560                 body= readbody(ibuf, body);
561                 break;
562         case 1:
563                 body= decodebodyh(ibuf,body);
564                 break;
565         case 2:
566                 body= decodebodyv(ibuf,body);
567                 ibuf->type |= IB_subdlta;
568                 break;
569         }
570
571         /**
572          * \internal If the IB_freem bit is set, free the data pointed to by iffmem.
573          */
574         if (flags & IB_freem) free(iffmem);
575
576         /**
577          * \internal If there was some problem loading the body
578          * data, free the memory already allocated in ibuf and
579          * return 0.
580          */
581         if (body == 0){
582                 free (ibuf);
583                 return(0);
584         }
585         
586         /**
587          * \internal Set the bit depth to the number of planes in bmhd.
588          * This discards the "stencil" data (What is the stencil? Alpha channel?)
589          */
590         /* forget stencil */
591         ibuf->depth = bmhd.nPlanes;
592         
593         /**
594          * \internal If the IB_rect bit is set in flags, add the rect and
595          * get rid of the planes.
596          */
597         if (flags & IB_rect){
598                 imb_addrectImBuf(ibuf);
599                 imb_bptolong(ibuf);
600                 imb_freeplanesImBuf(ibuf);
601                 /**
602                  * \internal If the image has a color map, apply it.
603                  */
604                 if (ibuf->cmap){
605                         if ((flags & IB_cmap) == 0) IMB_applycmap(ibuf);
606                 } else if (ibuf->depth == 18){ /** \internal No color map, and the bit depths is 18, convert to 24-bit */
607                         int i,col;
608                         unsigned int *rect;
609
610                         rect = ibuf->rect;
611                         for(i=ibuf->x * ibuf->y ; i>0 ; i--){
612                                 col = *rect;
613                                 col = ((col & 0x3f000) << 6) + ((col & 0xfc0) << 4) + ((col & 0x3f) << 2);
614                                 col += (col & 0xc0c0c0) >> 6;
615                                 *rect++ = col;
616                         }
617                         ibuf->depth = 24;
618                 } else if (ibuf->depth <= 8) { /** \internal No colormap and no 24 bits, so it's b&w */
619                         uchar *rect;
620                         int size, shift;
621
622                         if (ibuf->depth < 8){
623                                 rect = (uchar *) ibuf->rect;
624                                 rect += 3;
625                                 shift = 8 - ibuf->depth;
626                                 for (size = ibuf->x * ibuf->y; size > 0; size --){
627                                         rect[0] <<= shift;
628                                         rect += 4;
629                                 }
630                         }
631                         rect = (uchar *) ibuf->rect;
632                         for (size = ibuf->x * ibuf->y; size > 0; size --){
633                                 rect[1] = rect[2] = rect[3];
634                                 rect += 4;
635                         }
636                         ibuf->depth = 8;
637                 }
638         }
639
640         /**
641          * \internal Anyone know what IB_ttob is?  What does IMB_flipy do?
642          */
643         if ((flags & IB_ttob) == 0) IMB_flipy(ibuf);
644
645         /**
646          * \internal Last thing to do before returning is to flip the bits from rgba to abgr.
647          */
648         if (ibuf) {
649                 if (ibuf->rect) 
650                         IMB_convert_rgba_to_abgr(ibuf->x*ibuf->y, ibuf->rect);
651         }
652         
653         return (ibuf);
654 }