Final merge of HEAD (bf-blender) into the orange branch.
[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 #ifdef WIN32
36 #include <io.h>
37 #endif
38 #include "imbuf.h"
39 #include "imbuf_patch.h"
40
41 #include "IMB_imbuf_types.h"
42 #include "IMB_imbuf.h"
43
44 #include "BKE_global.h"
45
46 #include "IMB_cmap.h"
47 #include "IMB_allocimbuf.h"
48 #include "IMB_bitplanes.h"
49 #include "IMB_amiga.h"
50
51 /* actually hard coded endianness */
52 #define GET_BIG_LONG(x) (((uchar *) (x))[0] << 24 | ((uchar *) (x))[1] << 16 | ((uchar *) (x))[2] << 8 | ((uchar *) (x))[3])
53 #define GET_LITTLE_LONG(x) (((uchar *) (x))[3] << 24 | ((uchar *) (x))[2] << 16 | ((uchar *) (x))[1] << 8 | ((uchar *) (x))[0])
54 #define SWAP_L(x) (((x << 24) & 0xff000000) | ((x << 8) & 0xff0000) | ((x >> 8) & 0xff00) | ((x >> 24) & 0xff))
55 #define SWAP_S(x) (((x << 8) & 0xff00) | ((x >> 8) & 0xff))
56
57 /* more endianness... should move to a separate file... */
58 #if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
59 #define GET_ID GET_BIG_LONG
60 #define LITTLE_LONG SWAP_LONG
61 #else
62 #define GET_ID GET_LITTLE_LONG
63 #define LITTLE_LONG ENDIAN_NOP
64 #endif
65
66 static uchar *decodebodyscanl(uchar *body, short bytes, uchar **list, short d)
67 {
68         for (;d>0;d--){
69                 uchar *point;
70                 short todo;
71                 uchar i,j;
72
73                 point = *(list++);
74                 todo=bytes;
75                 while (todo>0){
76                         i = *body++;
77
78                         if (i & 128){                   /* fill */
79                                 if (i==128) continue;   /* nop  */
80
81                                 i=257-i;
82                                 todo-=i;
83                                 j = *(body++);
84                                 do{
85                                         *(point++) = j;
86                                         i--;
87                                 }while (i);
88                         } else{                         /* copy */
89                                 i++;
90                                 todo-=i;
91
92                                 do{
93                                         *(point++) = *(body++);
94                                         i--;
95                                 }while (i);
96                         }
97                 }
98                 if (todo) return (0);
99         }
100         return(body);
101 }
102
103
104 static uchar *decodebodyh(struct ImBuf *ibuf, uchar *body)
105 {
106         if (ibuf->y==1) {
107                 body=decodebodyscanl(body, WIDTHB(ibuf->x), (uchar **)ibuf->planes, ibuf->depth);
108         }
109         else {
110                 unsigned int **list;
111                 short skipx,i,bytes,y;
112
113                 list = imb_copyplanelist(ibuf);
114                 if (list == 0) return (0);
115
116                 y=ibuf->y;
117                 bytes = WIDTHB(ibuf->x);
118                 skipx = ibuf->skipx;
119
120                 for (;y>0;y--){
121                         body=decodebodyscanl(body, bytes, (uchar **)list, ibuf->depth);
122                         if (body == 0) return (0);
123
124                         for (i=ibuf->depth-1;i>=0;i--){
125                                 list[i] += skipx;
126                         }
127                 }
128                 free(list);
129         }
130         return(body);
131 }
132
133
134 static uchar *decodebodykolum(uchar *body, short bytes, uchar **list, short d, int next)
135 {
136         for (;d>0;d--){
137                 uchar *point;
138                 short todo;
139                 uchar i,j;
140
141                 point = *(list++);
142                 todo=bytes;
143                 while (todo>0){
144                         i = *body++;
145
146                         if (i & 128){                   /* fill */
147                                 if (i==128) continue;   /* nop  */
148
149                                 i=257-i;
150                                 todo-=i;
151                                 j = *body++;
152                                 do{
153                                         *point = j;
154                                         point += next;
155                                         i--;
156                                 }while (i);
157                         }
158                         else{                           /* copy */
159                                 i++;
160                                 todo-=i;
161
162                                 do{
163                                         *point = *body++;
164                                         point += next;
165                                         i--;
166                                 }while (i);
167                         }
168                 }
169                 if (todo) return (0);
170         }
171         return(body);
172 }
173
174
175 static uchar *decodebodyv(struct ImBuf *ibuf, uchar *body)
176 {
177         uchar **list;
178         int skipx, i, bytes, times;
179
180         list = (uchar **)imb_copyplanelist(ibuf);
181         if (list == 0) return (0);
182
183         bytes = ibuf->y;
184         times = WIDTHB(ibuf->x);
185         skipx = ibuf->skipx << 2;
186
187         for (;times>0;times--){
188                 body=decodebodykolum(body,bytes,list,ibuf->depth,skipx);
189                 if (body == 0) return (0);
190
191                 for (i=ibuf->depth-1;i>=0;i--){
192                         list[i] += 1;
193                 }
194         }
195         free(list);
196         return(body);
197 }
198
199 static uchar *makebody(uchar **planes, short bytes, short depth, uchar *buf)
200 {
201         uchar *bitplstart,*temp;
202
203         register uchar last,this,*bitpl;
204         register short todo;
205         register int copy;
206
207         bytes--;
208         for (;depth>0;depth--){
209                 bitpl = *(planes++);
210                 bitplstart = bitpl;
211                 todo = bytes;
212                 last = *bitpl++;
213                 this = *bitpl++;
214                 copy = last^this;
215                 while (todo>0){
216
217                         if (copy){
218                                 do{
219                                         last = this;
220                                         this = *bitpl++;
221                                         if (last == this){
222                                                 if (this == bitpl[-3]){         /* three identical ones? */
223                                                         todo -= 1;              /* set todo */
224                                                         break;
225                                                 }
226                                         }
227                                 }while (--todo != 0);
228
229                                 copy=bitpl-bitplstart;
230                                 copy -= 1;
231                                 if (todo) copy -= 2;
232
233                                 temp = bitpl;
234                                 bitpl = bitplstart;
235
236                                 while (copy){
237                                         last = copy;
238                                         if (copy>MAXDAT) last = MAXDAT;
239                                         copy -= last;
240                                         *buf++ = last-1;
241                                         do{
242                                                 *buf++ = *bitpl++;
243                                         }while(--last != 0);
244                                 }
245                                 bitplstart = bitpl;
246                                 bitpl = temp;
247                                 last = this;
248
249                                 copy = FALSE;
250                         }
251                         else{
252                                 while (*bitpl++ == this){       /* search for first different bye */
253                                         if (--todo == 0) break; /* or end of line */
254                                 }
255                                 bitpl -= 1;
256                                 copy = bitpl-bitplstart;
257                                 bitplstart = bitpl;
258                                 todo -= 1;
259                                 this = *bitpl++;
260
261                                 while (copy){
262                                         if (copy>MAXRUN){
263                                                 *buf++ = -(MAXRUN-1);
264                                                 *buf++ = last;
265                                                 copy -= MAXRUN;
266                                         }
267                                         else{
268                                                 *buf++ = -(copy-1);
269                                                 *buf++ = last;
270                                                 break;
271                                         }
272                                 }
273                                 copy=TRUE;
274                         }
275                 }
276         }
277         return (buf);
278 }
279
280
281 short imb_encodebodyh(struct ImBuf *ibuf, int file)
282 {
283         uchar *buf, *endbuf, *max;
284         int size, line, ok = TRUE;
285         unsigned int **list;
286         short skipx,i,y;
287
288         line = WIDTHB(ibuf->x) * ibuf->depth;
289         line += (line >> 6) + 10;
290         size = 16 * line;
291         if (size < 16384) size = 16384;
292         
293         buf = (uchar *) malloc(size);
294         if (buf == 0) return (0);
295
296         max = buf + size - line;
297         
298         list = imb_copyplanelist(ibuf);
299         if (list == 0){
300                 free(buf);
301                 return (0);
302         }
303
304         y=ibuf->y;
305         skipx = ibuf->skipx;
306         endbuf = buf;
307         
308         for (y=ibuf->y;y>0;y--){
309                 endbuf = makebody((uchar **)list, WIDTHB(ibuf->x), ibuf->depth, endbuf);
310                 if (endbuf==0){
311                         ok = -20;
312                         break;
313                 }
314                 if (endbuf >= max || y == 1){ 
315                         size = endbuf-buf;
316                         if (write(file,buf,size)!=size) ok = -19;
317                         endbuf = buf;
318                 }
319                 for (i=ibuf->depth-1;i>=0;i--){
320                         list[i] += skipx;
321                 }
322                 if (ok != TRUE) break;
323         }
324         free(list);
325
326         free(buf);
327         return(ok);
328 }
329
330
331 short imb_encodebodyv(struct ImBuf *ibuf, int file)
332 {
333         struct ImBuf *ibufv;
334         uchar *buf,*endbuf;
335         short x,offset;
336
337         buf = (uchar *) malloc((ibuf->y + (ibuf->y >> 6) + 10) * ibuf->depth);
338         if (buf == 0) return (0);
339
340         ibufv=IMB_allocImBuf((ibuf->y)<<3,1, ibuf->depth, 0, 1);
341         if (ibufv == 0){
342                 free(buf);
343                 return (0);
344         }
345
346         offset=0;
347
348         for(x = WIDTHB(ibuf->x);x>0;x--){
349                 register short i;
350
351                 for(i = ibuf->depth-1 ;i>=0;i--){
352                         register uchar *p1,*p2;
353                         register int skipx;
354                         register short y;
355
356                         skipx = (ibuf->skipx)*sizeof(int *);
357                         p1=(uchar *)ibuf->planes[i];
358                         p2=(uchar *)ibufv->planes[i];
359                         p1 += offset;
360
361                         for (y=ibuf->y;y>0;y--){
362                                 *(p2++) = *p1;
363                                 p1 += skipx;
364                         }
365                 }
366                 offset += 1;
367
368                 endbuf=makebody((uchar **)ibufv->planes, ibuf->y, ibuf->depth, buf);
369                 if (endbuf==0) return (-20);
370                 if (write(file,buf,endbuf-buf)!=endbuf-buf) return (-19);
371         }
372         free(buf);
373         IMB_freeImBuf(ibufv);
374         return (TRUE);
375 }
376
377 static uchar *readbody(struct ImBuf *ibuf, uchar *body)
378 {
379         int skipbuf,skipbdy,depth,y,offset = 0;
380
381         skipbuf = ibuf->skipx;
382         skipbdy = WIDTHB(ibuf->x);
383
384         for (y = ibuf->y; y> 0; y--){
385                 for( depth = 0; depth < ibuf->depth; depth ++){
386                         memcpy(ibuf->planes[depth] + offset, body, skipbdy);
387                         body += skipbdy;
388                 }
389                 offset += skipbuf;
390         }
391         return body;
392 }
393
394 struct ImBuf *imb_loadamiga(int *iffmem,int flags)
395 {
396         int chunk,totlen,len,*cmap=0,cmaplen =0,*mem,ftype=0;
397         uchar *body=0;
398         struct BitMapHeader bmhd;
399         struct ImBuf *ibuf=0;
400
401         mem = iffmem;
402         bmhd.w = 0;
403
404         if (GET_ID(mem) != FORM) return (0);
405         if (GET_ID(mem+2) != ILBM) return (0);
406         totlen= (GET_BIG_LONG(mem+1) + 1) & ~1;
407         mem += 3;
408         totlen -= 4;
409
410
411         while(totlen > 0){
412                 chunk = GET_ID(mem);
413                 len= (GET_BIG_LONG(mem+1) + 1) & ~1;
414                 mem += 2;
415
416                 totlen -= len+8;
417
418                 switch (chunk){
419                 case BMHD:
420                         memcpy(&bmhd, mem, sizeof(struct BitMapHeader));
421
422                         bmhd.w = BIG_SHORT(bmhd.w);
423                         bmhd.h = BIG_SHORT(bmhd.h);
424                         bmhd.x = BIG_SHORT(bmhd.x);
425                         bmhd.y = BIG_SHORT(bmhd.y);
426                         bmhd.transparentColor = BIG_SHORT(bmhd.transparentColor);
427                         bmhd.pageWidth = BIG_SHORT(bmhd.pageWidth);
428                         bmhd.pageHeight = BIG_SHORT(bmhd.pageHeight);
429                         
430                         break;
431                 case BODY:
432                         body = (uchar *)mem;
433                         break;
434                 case CMAP:
435                         cmap = mem;
436                         cmaplen = len/3;
437                         break;
438                 case CAMG:
439                         ftype = GET_BIG_LONG(mem);
440                         break;
441                 }
442                 mem = (int *)((uchar *)mem +len);
443                 if (body) break;
444         }
445         if (bmhd.w == 0) return (0);
446         if (body == 0) return (0);
447         
448         if (flags & IB_test) ibuf = IMB_allocImBuf(bmhd.w, bmhd.h, bmhd.nPlanes, 0, 0);
449         else ibuf = IMB_allocImBuf(bmhd.w, bmhd.h, bmhd.nPlanes + (bmhd.masking & 1),0,1);
450
451         if (ibuf == 0) return (0);
452
453         ibuf->ftype = (ftype | AMI);
454         
455         if (cmap){
456                 ibuf->mincol = 0;
457                 ibuf->maxcol = cmaplen;
458                 imb_addcmapImBuf(ibuf);
459                 imb_makecolarray(ibuf, (uchar *)cmap, 0);
460         }
461
462         if (flags & IB_test){
463                 if (flags & IB_freem) free(iffmem);
464                 return(ibuf);
465         }
466         
467         switch (bmhd.compression){
468         case 0:
469                 body= readbody(ibuf, body);
470                 break;
471         case 1:
472                 body= decodebodyh(ibuf,body);
473                 break;
474         case 2:
475                 body= decodebodyv(ibuf,body);
476                 ibuf->type |= IB_subdlta;
477                 break;
478         }
479
480         if (flags & IB_freem) free(iffmem);
481
482         if (body == 0){
483                 free (ibuf);
484                 return(0);
485         }
486         
487         /* forget stencil */
488         ibuf->depth = bmhd.nPlanes;
489         
490         if (flags & IB_rect){
491                 imb_addrectImBuf(ibuf);
492                 imb_bptolong(ibuf);
493                 imb_freeplanesImBuf(ibuf);
494                 if (ibuf->cmap){
495                         if ((flags & IB_cmap) == 0) IMB_applycmap(ibuf);
496                 } else if (ibuf->depth == 18){
497                         int i,col;
498                         unsigned int *rect;
499
500                         rect = ibuf->rect;
501                         for(i=ibuf->x * ibuf->y ; i>0 ; i--){
502                                 col = *rect;
503                                 col = ((col & 0x3f000) << 6) + ((col & 0xfc0) << 4) + ((col & 0x3f) << 2);
504                                 col += (col & 0xc0c0c0) >> 6;
505                                 *rect++ = col;
506                         }
507                         ibuf->depth = 24;
508                 } else if (ibuf->depth <= 8) { /* no colormap and no 24 bits: b&w */
509                         uchar *rect;
510                         int size, shift;
511
512                         if (ibuf->depth < 8){
513                                 rect = (uchar *) ibuf->rect;
514                                 rect += 3;
515                                 shift = 8 - ibuf->depth;
516                                 for (size = ibuf->x * ibuf->y; size > 0; size --){
517                                         rect[0] <<= shift;
518                                         rect += 4;
519                                 }
520                         }
521                         rect = (uchar *) ibuf->rect;
522                         for (size = ibuf->x * ibuf->y; size > 0; size --){
523                                 rect[1] = rect[2] = rect[3];
524                                 rect += 4;
525                         }
526                         ibuf->depth = 8;
527                 }
528         }
529
530         if ((flags & IB_ttob) == 0) IMB_flipy(ibuf);
531
532         if (ibuf) {
533                 if (ibuf->rect) 
534                         if (G.order == B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf);
535         }
536         
537         return (ibuf);
538 }