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