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