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