remove MTC_ functions, (don't merge)
[blender-staging.git] / source / blender / imbuf / intern / anim5.c
1 /**
2  * anim5.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): phase, code torn apart from anim.c
28  *
29  * ***** END GPL LICENSE BLOCK *****
30  */
31
32 #include "BLI_blenlib.h" /* BLI_remlink BLI_filesize BLI_addtail
33                             BLI_countlist BLI_stringdec */
34 #include "imbuf.h"
35 #include "imbuf_patch.h"
36
37 #include "IMB_imbuf_types.h"
38 #include "IMB_imbuf.h"
39
40 #include "IMB_cmap.h"
41 #include "IMB_allocimbuf.h"
42 #include "IMB_bitplanes.h"
43 #include "IMB_amiga.h"
44
45 #include "IMB_anim.h"
46
47 #include "IMB_anim5.h"
48
49 typedef struct Anhd{
50         unsigned char type, mask;
51         unsigned short w, h;
52         unsigned short x, y;
53         unsigned short abs16, abs, reala6, real;
54         unsigned char interleave, pad0;
55         unsigned short bits16, bits;
56         unsigned char pad[16];
57 }Anhd;
58
59 typedef struct Anim5Delta {
60         struct Anim5Delta * next, * prev;
61         void * data;
62         int type;
63 }Anim5Delta;
64
65
66 /* om anim5's te kunnen lezen, moet een aantal gegevens bijgehouden worden:
67  * Een lijst van pointers naar delta's, in geheugen of ge'mmap'ed
68  * 
69  * Mogelijk kan er ook een 'skiptab' aangelegd worden, om sneller
70  * sprongen te kunnen maken.
71  * 
72  * Er moeten niet direct al plaatjes gegenereed worden, dit maakt de 
73  * routines onbruikbaar om snel naar het goede plaatje te springen.
74  * Een routine voert dus de delta's uit, een andere routine maakt van
75  * voorgrondplaatje een ibuf;
76  */
77
78
79 /*
80    een aantal functie pointers moet geinporteerd worden, zodat er niet
81    nog meer library's / objects meegelinkt hoeven te worden.
82
83    Dezelfde structuur moet ook gebruikt kunnen worden voor het wegschrijven
84    van animaties. Hoe geef je dit aan ?
85    
86    Hoe snel kunnen 10 .dlta's gedecomprimeerd worden
87    (zonder omzetten naar rect).
88    
89    1 - zoek naar 1e plaatje, animatie die aan de eisen voldoet
90    2 - probeer volgende plaatje te vinden:
91                 anim5 - decomprimeer
92                 sequence - teller ophogen
93                 directory - volgende entry
94    3 - geen succes ? ga naar 1.
95    
96    
97 */
98
99 /*
100         1. Initialiseer routine met toegestane reeksen, en eerste naam
101                 - series op naam (.0001)
102                 - directories
103                 - anim5 animaties
104                 - TGA delta's
105                 - iff 24bits delta's (.delta)
106         
107         2. haal volgende (vorige ?) plaatje op.
108         
109         3. vrijgeven
110 */
111
112 /* selectie volgorde is:
113         1 - anim5()
114         2 - name
115         3 - dir
116 */
117
118 void free_anim_anim5(struct anim * anim) {
119         ListBase * animbase;
120         Anim5Delta * delta, * next;
121
122         if (anim == NULL) return;
123
124         animbase = &anim->anim5base;
125         delta = animbase->first;
126
127         while (delta) {
128                 next = delta->next;
129
130                 if (delta->type == ANIM5_MALLOC) free(delta->data);
131                 BLI_remlink(animbase, delta);
132                 free(delta);
133
134                 delta = next;
135         }
136
137         if (anim->anim5mmap && anim->anim5len) {
138                 MEM_freeN(anim->anim5mmap);
139         }
140
141         anim->anim5mmap = NULL;
142         anim->anim5len = 0;
143         anim->anim5curdlta = 0;
144         anim->duration = 0;
145 }
146
147 static void planes_to_rect(struct ImBuf * ibuf, int flags) {
148         if (ibuf == 0) return;
149
150         /* dit komt regelrecht uit de amiga.c */
151
152         if (flags & IB_rect && ibuf->rect == 0) {
153                 imb_addrectImBuf(ibuf);
154                 imb_bptolong(ibuf);
155                 IMB_flipy(ibuf);
156                 imb_freeplanesImBuf(ibuf);
157
158                 if (ibuf->cmap){
159                         if ((flags & IB_cmap) == 0) {
160                                 IMB_applycmap(ibuf);
161                                 IMB_convert_rgba_to_abgr(ibuf);
162                         }
163                 } else if (ibuf->depth == 18){
164                         int i,col;
165                         unsigned int *rect;
166
167                         rect = ibuf->rect;
168                         for(i=ibuf->x * ibuf->y ; i>0 ; i--){
169                                 col = *rect;
170                                 col = ((col & 0x3f000) << 6) + ((col & 0xfc0) << 4)
171                                         + ((col & 0x3f) << 2);
172                                 col += (col & 0xc0c0c0) >> 6;
173                                 *rect++ = col;
174                         }
175                         ibuf->depth = 24;
176                 } else if (ibuf->depth <= 8) {
177                         /* geen colormap en geen 24 bits: zwartwit */
178                         uchar *rect;
179                         int size, shift;
180
181                         if (ibuf->depth < 8){
182                                 rect = (uchar *) ibuf->rect;
183                                 rect += 3;
184                                 shift = 8 - ibuf->depth;
185                                 for (size = ibuf->x * ibuf->y; size > 0; size --){
186                                         rect[0] <<= shift;
187                                         rect += 4;
188                                 }
189                         }
190                         rect = (uchar *) ibuf->rect;
191                         for (size = ibuf->x * ibuf->y; size > 0; size --){
192                                 rect[1] = rect[2] = rect[3];
193                                 rect += 4;
194                         }
195                         ibuf->depth = 8;
196                 }
197         }
198 }
199
200
201 static void anim5decode(struct ImBuf * ibuf, uchar * dlta) {
202         uchar depth;
203         int skip;
204         int *ofspoint;
205         uchar **planes;
206
207         /*      samenstelling delta:
208                 lijst met ofsets voor delta's per bitplane (ofspoint)
209                 per kolom in delta (point)
210                         aantal handelingen (noops)
211                                 code
212                                         bijbehorende data
213                                 ...
214                         ...
215         */
216
217         dlta += 8;
218
219         ofspoint = (int *)dlta;
220         skip = ibuf->skipx * sizeof(int *);
221         planes = (uchar **)ibuf->planes;
222
223         for(depth=ibuf->depth ; depth>0 ; depth--){
224                 if (GET_BIG_LONG(ofspoint)){
225                         uchar *planestart;
226                         uchar *point;
227                         uchar x;
228
229                         point = dlta + GET_BIG_LONG(ofspoint);
230                         planestart = planes[0];
231                         x = (ibuf->x + 7) >> 3;
232
233                         do{
234                                 uchar noop;
235
236                                 if ( (noop = *(point++)) ){
237                                         uchar *plane;
238                                         uchar code;
239
240                                         plane = planestart;
241                                         do{
242                                                 if ((code = *(point++))==0){
243                                                         uchar val;
244
245                                                         code = *(point++);
246                                                         val = *(point++);
247                                                         do {
248                                                                 plane[0] = val;
249                                                                 plane += skip;
250                                                         } while(--code);
251
252                                                 } else if (code & 128){
253
254                                                         code &= 0x7f;
255                                                         do{
256                                                                 plane[0] = *(point++);
257                                                                 plane += skip;
258                                                         } while(--code);
259
260                                                 } else plane += code * skip;
261
262                                         } while(--noop);
263                                 }
264                                 planestart++;
265                         } while(--x);
266                 }
267                 ofspoint++;
268                 planes++;
269         }
270 }
271
272
273 static void anim5xordecode(struct ImBuf * ibuf, uchar * dlta) {
274         uchar depth;
275         int skip;
276         int *ofspoint;
277         uchar **planes;
278
279         /*      samenstelling delta:
280                 lijst met ofsets voor delta's per bitplane (ofspoint)
281                 per kolom in delta (point)
282                         aantal handelingen (noops)
283                                 code
284                                         bijbehorende data
285                                 ...
286                         ...
287         */
288
289         dlta += 8;
290
291         ofspoint = (int *)dlta;
292         skip = ibuf->skipx * sizeof(int *);
293         planes = (uchar **)ibuf->planes;
294
295         for(depth=ibuf->depth ; depth>0 ; depth--){
296
297                 if (GET_BIG_LONG(ofspoint)){
298                         uchar *planestart;
299                         uchar *point;
300                         uchar x;
301
302                         point = dlta + GET_BIG_LONG(ofspoint);
303                         planestart = planes[0];
304                         x = (ibuf->x + 7) >> 3;
305
306                         do{
307                                 uchar noop;
308
309                                 if ( (noop = *(point++)) ){
310                                         uchar *plane;
311                                         uchar code;
312
313                                         plane = planestart;
314                                         do{
315                                                 if ((code = *(point++))==0){
316                                                         uchar val;
317
318                                                         code = *(point++);
319                                                         val = *(point++);
320                                                         do{
321                                                                 plane[0] ^= val;
322                                                                 plane += skip;
323                                                         }while(--code);
324
325                                                 } else if (code & 128){
326
327                                                         code &= 0x7f;
328                                                         do{
329                                                                 plane[0] ^= *(point++);
330                                                                 plane += skip;
331                                                         }while(--code);
332
333                                                 } else plane += code * skip;
334
335                                         }while(--noop);
336                                 }
337                                 planestart++;
338                         }while(--x);
339                 }
340                 ofspoint++;
341                 planes++;
342         }
343 }
344
345
346 int nextanim5(struct anim * anim) {
347         Anim5Delta * delta;
348         struct ImBuf * ibuf;
349
350         if (anim == 0) return(-1);
351
352         delta = anim->anim5curdlta;
353
354         if (delta == 0) return (-1);
355
356         if (anim->anim5flags & ANIM5_SNGBUF) {
357                 ibuf = anim->ibuf1;
358                 if (ibuf == 0) return (0);
359                 anim->anim5decode(ibuf, delta->data);
360         } else {
361                 ibuf = anim->ibuf2;
362                 if (ibuf == 0) return (0);
363                 anim->anim5decode(ibuf, delta->data);
364                 anim->ibuf2 = anim->ibuf1;
365                 anim->ibuf1 = ibuf;
366         }
367
368         anim->anim5curdlta = anim->anim5curdlta->next;
369         anim->curposition++;
370
371         return(0);
372 }
373
374 int rewindanim5(struct anim * anim) {
375         Anim5Delta * delta;
376         struct ImBuf * ibuf;
377
378         if (anim == 0) return (-1);
379
380         IMB_free_anim_ibuf(anim);
381
382         delta = anim->anim5base.first;
383         if (delta == 0) return (-1);
384
385         ibuf = IMB_loadiffmem(delta->data, IB_planes);
386         if (ibuf == 0) return(-1);
387
388         anim->ibuf1 = ibuf;
389         if ((anim->anim5flags & ANIM5_SNGBUF) == 0) anim->ibuf2 = IMB_dupImBuf(ibuf);
390
391         anim->anim5curdlta = delta->next;
392         anim->curposition = 0;
393
394         return(0);
395 }
396
397
398 int startanim5(struct anim * anim) {
399         int file, buf[20], totlen;
400         unsigned int len;
401         short * mem;
402         ListBase * animbase;
403         Anim5Delta * delta;
404         Anhd anhd;
405
406         /* Controles */
407
408         if (anim == 0) return(-1);
409
410         file = open(anim->name,O_BINARY|O_RDONLY);
411         if (file < 0) return (-1);
412
413         if (read(file, buf, 24) != 24) {
414                 close(file);
415                 return(-1);
416         }
417
418         if ((GET_ID(buf) != FORM) || (GET_ID(buf + 2) != ANIM)
419                 || (GET_ID(buf + 3) != FORM) || (GET_ID(buf + 5) != ILBM)){
420                 printf("No anim5 file %s\n",anim->name);
421                 close(file);
422                 return (-1);
423         }
424
425         /* de hele file wordt in het geheugen gemapped */
426
427         totlen = BLI_filesize(file);
428         if (totlen>0 && file>=0) {
429                 lseek(file, 0L, SEEK_SET);
430                 
431                 mem= MEM_mallocN(totlen, "mmap");
432                 if (read(file, mem, totlen) != totlen) {
433                         MEM_freeN(mem);
434                         mem = NULL;
435                 }
436         } else {
437                 mem = NULL;
438         }
439         close (file);
440
441         if (!mem) return (-1);
442
443         anhd.interleave = 0;
444         anhd.bits = 0;
445         anhd.type = 5;
446
447         anim->anim5mmap = mem;
448         anim->anim5len = totlen;
449         anim->anim5flags = 0;
450         anim->duration = 0;
451
452         animbase = & anim->anim5base;
453         animbase->first = animbase->last = 0;
454
455         /* eerste plaatje inlezen */
456
457         mem = mem + 6;
458         totlen -= 12;
459
460         len = GET_BIG_LONG(mem + 2);
461         len = (len + 8 + 1) & ~1;
462         delta = NEW(Anim5Delta);
463
464         delta->data = mem;
465         delta->type = ANIM5_MMAP;
466
467         BLI_addtail(animbase, delta);
468
469         mem += (len >> 1);
470         totlen -= len;
471
472         while (totlen > 0) {
473                 len = GET_BIG_LONG(mem + 2);
474                 len = (len + 8 + 1) & ~1;
475
476                 switch(GET_ID(mem)){
477                 case FORM:
478                         len = 12;
479                         break;
480                 case ANHD:
481                         memcpy(&anhd, mem + 4, sizeof(Anhd));
482                         break;
483                 case DLTA:
484                         delta = NEW(Anim5Delta);
485                         delta->data = mem;
486                         delta->type = ANIM5_MMAP;
487                         BLI_addtail(animbase, delta);
488                         break;
489                 }
490
491                 mem += (len >> 1);
492                 totlen -= len;
493         }
494
495         if (anhd.interleave == 1) anim->anim5flags |= ANIM5_SNGBUF;
496         if (BIG_SHORT(anhd.bits) & 2) anim->anim5decode = anim5xordecode;
497         else anim->anim5decode = anim5decode;
498
499         /* laatste twee delta's wissen */
500
501         delta = animbase->last;
502         if (delta) {
503                 BLI_remlink(animbase, delta);
504                 free(delta);
505         }
506
507         if ((anim->anim5flags & ANIM5_SNGBUF) == 0) {
508                 delta = animbase->last;
509                 if (delta) {
510                         BLI_remlink(animbase, delta);
511                         free(delta);
512                 }
513         }
514
515         anim->duration = BLI_countlist(animbase);
516
517         return(rewindanim5(anim));
518 }
519
520
521 struct ImBuf * anim5_fetchibuf(struct anim * anim) {
522         struct ImBuf * ibuf;
523
524         if (anim == 0) return (0);
525
526         ibuf = IMB_dupImBuf(anim->ibuf1);
527         planes_to_rect(ibuf, anim->ib_flags);
528
529         return(ibuf);
530 }
531