457e4846709bec58a78d082a73b408dbcf900761
Christian Heimke BlinkenLib v.0.1.1 (2005-01...

Christian Heimke authored 13 years ago

1) /* BlinkenLib
Christian Heimke BlinkenLib v.0.3 (2005-02-16)

Christian Heimke authored 13 years ago

2)  * version 0.3 date 2005-02-16
Christian Heimke BlinkenLib v.0.2 (2005-01-27)

Christian Heimke authored 13 years ago

3)  * Copyright 2004-2005 Stefan Schuermans <1stein@schuermans.info>
Christian Heimke BlinkenLib v.0.1.1 (2005-01...

Christian Heimke authored 13 years ago

4)  * Copyleft: GNU public license - http://www.gnu.org/copyleft/gpl.html
5)  * a blinkenarea.org project
6)  * powered by eventphone.de
7)  */
8) 
9) #include <stdio.h>
10) #include <stdlib.h>
11) #include <string.h>
Christian Heimke BlinkenLib v.0.3 (2005-02-16)

Christian Heimke authored 13 years ago

12) #include <unistd.h>
13) #include <sys/time.h>
14) #include <sys/types.h>
15) #include <sys/socket.h>
16) #include <sys/select.h>
Christian Heimke BlinkenLib v.0.1.1 (2005-01...

Christian Heimke authored 13 years ago

17) 
18) #include "BlinkenConstants.h"
19) #include "BlinkenFrame.h"
20) #include "BlinkenMovie.h"
21) #include "Tools.h"
22) 
23) struct sBlinkenMovie
24) {
25)   int height;
26)   int width;
27)   int channels;
28)   int maxval;
29)   int infoCnt;
30)   char * * * pppInfos;
31)   int frameCnt;
32)   stBlinkenFrame * * ppFrames;
33) };
34) 
35) stBlinkenMovie * BlinkenMovieNew( int height, int width, int channels, int maxval )
36) {
37)   stBlinkenMovie * pMovie;
38) 
39)   if( height < BlinkenHeightMin ) height = BlinkenHeightMin;
40)   if( height > BlinkenHeightMax ) height = BlinkenHeightMax;
41)   if( width < BlinkenWidthMin ) width = BlinkenWidthMin;
42)   if( width > BlinkenWidthMax ) width = BlinkenWidthMax;
43)   if( channels < BlinkenChannelsMin ) channels = BlinkenChannelsMin;
44)   if( channels > BlinkenChannelsMax ) channels = BlinkenMaxvalMax;
45)   if( maxval < BlinkenMaxvalMin ) maxval = BlinkenMaxvalMin;
46)   if( maxval > BlinkenMaxvalMax ) maxval = BlinkenMaxvalMax;
47) 
48)   pMovie = (stBlinkenMovie *)malloc( sizeof( stBlinkenMovie ) );
49)   if( pMovie == NULL )
50)     return NULL;
51) 
52)   pMovie->height = height;
53)   pMovie->width = width;
54)   pMovie->channels = channels;
55)   pMovie->maxval = maxval;
56)   pMovie->infoCnt = 0;
57)   pMovie->pppInfos = (char * * *)malloc2D( 0, 2, sizeof( char * ) );
58)   if( pMovie->pppInfos == NULL )
59)   {
60)     free( pMovie );
61)     return NULL;
62)   }
63)   pMovie->frameCnt = 0;
64)   pMovie->ppFrames = (stBlinkenFrame * *)malloc1D( 0, sizeof( stBlinkenFrame * ) );
65)   if( pMovie->ppFrames == NULL )
66)   {
67)     free( pMovie->pppInfos );
68)     free( pMovie );
69)     return NULL;
70)   }
71) 
72)   return pMovie;
73) }
74) 
75) stBlinkenMovie * BlinkenMovieClone( stBlinkenMovie * pSrcMovie )
76) {
77)   stBlinkenMovie * pMovie;
Christian Heimke BlinkenLib v.0.3 (2005-02-16)

Christian Heimke authored 13 years ago

78)   stBlinkenFrame * pFrame;
Christian Heimke BlinkenLib v.0.1.1 (2005-01...

Christian Heimke authored 13 years ago

79)   int i;
80) 
81)   pMovie = BlinkenMovieNew( pSrcMovie->height, pSrcMovie->width, pSrcMovie->channels, pSrcMovie->maxval );
82)   if( pMovie == NULL )
83)     return NULL;
84) 
85)   for( i = 0; i < pSrcMovie->infoCnt; i++ )
86)     BlinkenMovieAppendInfo( pMovie, pSrcMovie->pppInfos[i][0], pSrcMovie->pppInfos[i][1] );
87) 
88)   for( i = 0; i < pSrcMovie->frameCnt; i++ )
Christian Heimke BlinkenLib v.0.3 (2005-02-16)

Christian Heimke authored 13 years ago

89)   {
90)     pFrame = BlinkenFrameClone( pSrcMovie->ppFrames[i] );
91)     if( BlinkenMovieAppendFrame( pMovie, pFrame ) != 0 )
92)       BlinkenFrameFree( pFrame );
93)   }
Christian Heimke BlinkenLib v.0.1.1 (2005-01...

Christian Heimke authored 13 years ago

94) 
95)   return pMovie;
96) }
97) 
98) void BlinkenMovieFree( stBlinkenMovie * pMovie )
99) {
100)   int i;
101) 
102)   if( pMovie == NULL )
103)     return;
104) 
105)   for( i = 0; i < pMovie->infoCnt; i++ )
106)   {
107)     free( pMovie->pppInfos[i][0] );
108)     free( pMovie->pppInfos[i][1] );
109)   }
110)   free( pMovie->pppInfos );
111) 
112)   for( i = 0; i < pMovie->frameCnt; i++ )
113)     BlinkenFrameFree( pMovie->ppFrames[i] );
114)   free( pMovie->ppFrames );
115) 
116)   free( pMovie );
117) }
118) 
119) int BlinkenMovieGetHeight( stBlinkenMovie * pMovie )
120) {
121)   if( pMovie == NULL )
122)     return 0;
123) 
124)   return pMovie->height;
125) }
126) 
127) int BlinkenMovieGetWidth( stBlinkenMovie * pMovie )
128) {
129)   if( pMovie == NULL )
130)     return 0;
131) 
132)   return pMovie->width;
133) }
134) 
135) int BlinkenMovieGetChannels( stBlinkenMovie * pMovie )
136) {
137)   if( pMovie == NULL )
138)     return 0;
139) 
140)   return pMovie->channels;
141) }
142) 
143) int BlinkenMovieGetMaxval( stBlinkenMovie * pMovie )
144) {
145)   if( pMovie == NULL )
146)     return 0;
147) 
148)   return pMovie->maxval;
149) }
150) 
151) int BlinkenMovieGetDuration( stBlinkenMovie * pMovie )
152) {
153)   int i, duration;
154) 
155)   if( pMovie == NULL )
156)     return 0;
157) 
158)   duration = 0;
159)   for( i = 0; i < pMovie->frameCnt; i++ )
160)     duration += BlinkenFrameGetDuration( pMovie->ppFrames[i] );
161)   return duration;
162) }
163) 
164) int BlinkenMovieGetInfoCnt( stBlinkenMovie * pMovie )
165) {
166)   if( pMovie == NULL )
167)     return 0;
168) 
169)   return pMovie->infoCnt;
170) }
171) 
172) char * BlinkenMovieGetInfoType( stBlinkenMovie * pMovie, int infoNo )
173) {
174)   if( pMovie == NULL || pMovie->infoCnt < 1 )
175)     return "";
176) 
177)   if( infoNo < 0 ) infoNo = 0;
178)   if( infoNo >= pMovie->infoCnt ) infoNo = pMovie->infoCnt - 1;
179)   return pMovie->pppInfos[infoNo][0];
180) }
181) 
182) char * BlinkenMovieGetInfoData( stBlinkenMovie * pMovie, int infoNo )
183) {
184)   if( pMovie == NULL || pMovie->infoCnt < 1 )
185)     return "";
186) 
187)   if( infoNo < 0 ) infoNo = 0;
188)   if( infoNo >= pMovie->infoCnt ) infoNo = pMovie->infoCnt - 1;
189)   return pMovie->pppInfos[infoNo][1];
190) }
191) 
192) void BlinkenMovieSetInfo( stBlinkenMovie * pMovie, int infoNo, char * pInfoType, char * pInfoData )
193) {
194)   char * pType, * pData;
195) 
196)   if( pMovie == NULL || infoNo < 0 || infoNo >= pMovie->infoCnt )
197)     return;
198) 
199)   pType = strdup( pInfoType );
200)   if( pType == NULL )
201)     return;
202)   pData = strdup( pInfoData );
203)   if( pData == NULL )
204)   {
205)     free( pType );
206)     return;
207)   }
208) 
209)   free( pMovie->pppInfos[infoNo][0] );
210)   pMovie->pppInfos[infoNo][0] = pType;
211)   free( pMovie->pppInfos[infoNo][1] );
212)   pMovie->pppInfos[infoNo][1] = pData;
213) }
214) 
215) void BlinkenMovieInsertInfo( stBlinkenMovie * pMovie, int infoNo, char * pInfoType, char * pInfoData )
216) {
217)   char * * * pppNewInfos, * pType, * pData;
218)   int i;
219) 
220)   if( pMovie == NULL || infoNo < 0 || infoNo > pMovie->infoCnt )
221)     return;
222) 
223)   pppNewInfos = (char * * *)malloc2D( pMovie->infoCnt + 1, 2, sizeof( char * ) );
224)   if( pppNewInfos == NULL )
225)     return;
226) 
227)   pType = strdup( pInfoType );
228)   if( pType == NULL )
229)   {
230)     free( pppNewInfos );
231)     return;
232)   }
233)   pData = strdup( pInfoData );
234)   if( pData == NULL )
235)   {
236)     free( pppNewInfos );
237)     free( pType );
238)     return;
239)   }
240) 
241)   for( i = 0; i < infoNo; i++ )
242)   {
243)     pppNewInfos[i][0] = pMovie->pppInfos[i][0];
244)     pppNewInfos[i][1] = pMovie->pppInfos[i][1];
245)   }
246) 
247)   pppNewInfos[infoNo][0] = pType;
248)   pppNewInfos[infoNo][1] = pData;
249) 
250)   for( i = infoNo; i < pMovie->infoCnt; i++ )
251)   {
252)     pppNewInfos[i+1][0] = pMovie->pppInfos[i][0];
253)     pppNewInfos[i+1][1] = pMovie->pppInfos[i][1];
254)   }
255) 
256)   free( pMovie->pppInfos );
257)   pMovie->pppInfos = pppNewInfos;
258)   pMovie->infoCnt++;
259) }
260) 
261) void BlinkenMovieAppendInfo( stBlinkenMovie * pMovie, char * pInfoType, char * pInfoData )
262) {
263)   if( pMovie == NULL )
264)     return;
265) 
266)   BlinkenMovieInsertInfo( pMovie, pMovie->infoCnt, pInfoType, pInfoData );
267) }
268) 
269) void BlinkenMovieDeleteInfo( stBlinkenMovie * pMovie, int infoNo )
270) {
271)   char * * * pppNewInfos;
272)   int i;
273) 
274)   if( pMovie == NULL || infoNo < 0 || infoNo >= pMovie->infoCnt )
275)     return;
276) 
277)   pppNewInfos = (char * * *)malloc2D( pMovie->infoCnt - 1, 2, sizeof( char * ) );
278)   if( pppNewInfos == NULL )
279)     return;
280) 
281)   for( i = 0; i < infoNo; i++ )
282)   {
283)     pppNewInfos[i][0] = pMovie->pppInfos[i][0];
284)     pppNewInfos[i][1] = pMovie->pppInfos[i][1];
285)   }
286) 
287)   free( pMovie->pppInfos[infoNo][0] );
288)   free( pMovie->pppInfos[infoNo][1] );
289) 
290)   for( i = infoNo; i < pMovie->infoCnt - 1; i++ )
291)   {
292)     pppNewInfos[i][0] = pMovie->pppInfos[i+1][0];
293)     pppNewInfos[i][1] = pMovie->pppInfos[i+1][1];
294)   }
295) 
296)   free( pMovie->pppInfos );
297)   pMovie->pppInfos = pppNewInfos;
298)   pMovie->infoCnt--;
299) }
300) 
301) void BlinkenMovieDeleteInfos( stBlinkenMovie * pMovie )
302) {
303)   char * * * pppNewInfos;
304)   int i;
305) 
306)   if( pMovie == NULL )
307)     return;
308) 
309)   pppNewInfos = (char * * *)malloc2D( 0, 2, sizeof( char * ) );
310)   if( pppNewInfos == NULL )
311)     return;
312) 
313)   for( i = 0; i < pMovie->infoCnt; i++ )
314)   {
315)     free( pMovie->pppInfos[i][0] );
316)     free( pMovie->pppInfos[i][1] );
317)   }
318) 
319)   free( pMovie->pppInfos );
320)   pMovie->pppInfos = pppNewInfos;
321)   pMovie->infoCnt = 0;
322) }
323) 
324) int BlinkenMovieGetFrameCnt( stBlinkenMovie * pMovie )
325) {
326)   if( pMovie == NULL )
327)     return 0;
328) 
329)   return pMovie->frameCnt;
330) }
331) 
332) stBlinkenFrame * BlinkenMovieGetFrame( stBlinkenMovie * pMovie, int frameNo )
333) {
334)   if( pMovie == NULL || pMovie->frameCnt < 1 )
335)     return NULL;
336) 
337)   if( frameNo < 0 ) frameNo = 0;
338)   if( frameNo >= pMovie->frameCnt ) frameNo = pMovie->frameCnt - 1;
339)   return pMovie->ppFrames[frameNo];
340) }
341) 
342) void BlinkenMovieSetFrame( stBlinkenMovie * pMovie, int frameNo, stBlinkenFrame * pFrame )
343) {
344)   if( pMovie == NULL || frameNo < 0 || frameNo >= pMovie->frameCnt )
345)     return;
346) 
347)   BlinkenFrameResize( pFrame, pMovie->height, pMovie->width, pMovie->channels, pMovie->maxval );
348)   pMovie->ppFrames[frameNo] = pFrame;
349) }
350) 
Christian Heimke BlinkenLib v.0.3 (2005-02-16)

Christian Heimke authored 13 years ago

351) int BlinkenMovieInsertFrame( stBlinkenMovie * pMovie, int frameNo, stBlinkenFrame * pFrame )
Christian Heimke BlinkenLib v.0.1.1 (2005-01...

Christian Heimke authored 13 years ago

352) {
353)   stBlinkenFrame * * ppNewFrames;
354)   int i;
355) 
356)   if( pMovie == NULL || frameNo < 0 || frameNo > pMovie->frameCnt )
Christian Heimke BlinkenLib v.0.3 (2005-02-16)

Christian Heimke authored 13 years ago

357)     return -1;
Christian Heimke BlinkenLib v.0.1.1 (2005-01...

Christian Heimke authored 13 years ago

358) 
359)   ppNewFrames = (stBlinkenFrame * *)malloc1D( pMovie->frameCnt + 1, sizeof( stBlinkenFrame * ) );
360)   if( ppNewFrames == NULL )
Christian Heimke BlinkenLib v.0.3 (2005-02-16)

Christian Heimke authored 13 years ago

361)     return -1;
Christian Heimke BlinkenLib v.0.1.1 (2005-01...

Christian Heimke authored 13 years ago

362) 
363)   for( i = 0; i < frameNo; i++ )
364)     ppNewFrames[i] = pMovie->ppFrames[i];
365) 
366)   BlinkenFrameResize( pFrame, pMovie->height, pMovie->width, pMovie->channels, pMovie->maxval );
367)   ppNewFrames[frameNo] = pFrame;
368) 
369)   for( i = frameNo; i < pMovie->frameCnt; i++ )
370)     ppNewFrames[i+1] = pMovie->ppFrames[i];
371) 
372)   free( pMovie->ppFrames );
373)   pMovie->ppFrames = ppNewFrames;
374)   pMovie->frameCnt++;
Christian Heimke BlinkenLib v.0.3 (2005-02-16)

Christian Heimke authored 13 years ago

375)   return 0;
Christian Heimke BlinkenLib v.0.1.1 (2005-01...

Christian Heimke authored 13 years ago

376) }
377) 
Christian Heimke BlinkenLib v.0.3 (2005-02-16)

Christian Heimke authored 13 years ago

378) int BlinkenMovieAppendFrame( stBlinkenMovie * pMovie, stBlinkenFrame * pFrame )
Christian Heimke BlinkenLib v.0.1.1 (2005-01...

Christian Heimke authored 13 years ago

379) {
380)   if( pMovie == NULL )
Christian Heimke BlinkenLib v.0.3 (2005-02-16)

Christian Heimke authored 13 years ago

381)     return -1;
Christian Heimke BlinkenLib v.0.1.1 (2005-01...

Christian Heimke authored 13 years ago

382) 
Christian Heimke BlinkenLib v.0.3 (2005-02-16)

Christian Heimke authored 13 years ago

383)   return BlinkenMovieInsertFrame( pMovie, pMovie->frameCnt, pFrame );
Christian Heimke BlinkenLib v.0.1.1 (2005-01...

Christian Heimke authored 13 years ago

384) }
385) 
386) void BlinkenMovieDeleteFrame( stBlinkenMovie * pMovie, int frameNo )
387) {
388)   stBlinkenFrame * * ppNewFrames;
389)   int i;
390) 
391)   if( pMovie == NULL || frameNo < 0 || frameNo >= pMovie->frameCnt )
392)     return;
393) 
394)   ppNewFrames = (stBlinkenFrame * *)malloc1D( pMovie->frameCnt - 1, sizeof( stBlinkenFrame * ) );
395)   if( ppNewFrames == NULL )
396)     return;
397) 
398)   for( i = 0; i < frameNo; i++ )
399)     ppNewFrames[i] = pMovie->ppFrames[i];
400) 
401)   BlinkenFrameFree( pMovie->ppFrames[frameNo] );
402) 
403)   for( i = frameNo; i < pMovie->frameCnt - 1; i++ )
404)     ppNewFrames[i] = pMovie->ppFrames[i+1];
405) 
406)   free( pMovie->ppFrames );
407)   pMovie->ppFrames = ppNewFrames;
408)   pMovie->frameCnt--;
409) }
410) 
411) void BlinkenMovieDeleteFrames( stBlinkenMovie * pMovie )
412) {
413)   stBlinkenFrame * * ppNewFrames;
414)   int i;
415) 
416)   if( pMovie == NULL )
417)     return;
418) 
419)   ppNewFrames = (stBlinkenFrame * *)malloc1D( 0, sizeof( stBlinkenFrame * ) );
420)   if( ppNewFrames == NULL )
421)     return;
422) 
423)   for( i = 0; i < pMovie->frameCnt; i++ )
424)     BlinkenFrameFree( pMovie->ppFrames[i] );
425) 
426)   free( pMovie->ppFrames );
427)   pMovie->ppFrames = ppNewFrames;
428)   pMovie->frameCnt = 0;
429) }
430) 
431) void BlinkenMovieResize( stBlinkenMovie * pMovie, int height, int width, int channels, int maxval )
432) {
433)   int i;
434) 
435)   if( pMovie == NULL )
436)     return;
437) 
438)   if( height < BlinkenHeightMin ) height = BlinkenHeightMin;
439)   if( height > BlinkenHeightMax ) height = BlinkenHeightMax;
440)   if( width < BlinkenWidthMin ) width = BlinkenWidthMin;
441)   if( width > BlinkenWidthMax ) width = BlinkenWidthMax;
442)   if( channels < BlinkenChannelsMin ) channels = BlinkenChannelsMin;
443)   if( channels > BlinkenChannelsMax ) channels = BlinkenMaxvalMax;
444)   if( maxval < BlinkenMaxvalMin ) maxval = BlinkenMaxvalMin;
445)   if( maxval > BlinkenMaxvalMax ) maxval = BlinkenMaxvalMax;
446) 
447)   pMovie->height = height;
448)   pMovie->width = width;
449)   pMovie->channels = channels;
450)   pMovie->maxval = maxval;
451) 
452)   for( i = 0; i < pMovie->frameCnt; i++ )
453)     BlinkenFrameResize( pMovie->ppFrames[i], height, width, channels, maxval );
454) }
455) 
456) void BlinkenMovieScale( stBlinkenMovie * pMovie, int height, int width )
457) {
458)   int i;
459) 
460)   if( pMovie == NULL )
461)     return;
462) 
463)   if( height < BlinkenHeightMin ) height = BlinkenHeightMin;
464)   if( height > BlinkenHeightMax ) height = BlinkenHeightMax;
465)   if( width < BlinkenWidthMin ) width = BlinkenWidthMin;
466)   if( width > BlinkenWidthMax ) width = BlinkenWidthMax;
467) 
468)   pMovie->height = height;
469)   pMovie->width = width;
470) 
471)   for( i = 0; i < pMovie->frameCnt; i++ )
472)     BlinkenFrameScale( pMovie->ppFrames[i], height, width );
473) }
474) 
475) char * BlinkenMovieToString( stBlinkenMovie * pMovie )
476) {
477)   char * * strs, * str, * ptr;
478)   int i, size;
479) 
480)   if( pMovie == NULL )
481)     return NULL;
482) 
483)   strs = (char * *)malloc1D( pMovie->frameCnt, sizeof( char * ) );
484)   if( strs == NULL )
485)     return NULL;
486) 
487)   for( i = 0; i < pMovie->frameCnt; i++ )
488)   {
489)     strs[i] = BlinkenFrameToString( pMovie->ppFrames[i] );
490)     if( strs[i] == NULL )
491)     {
492)       for( i--; i >= 0; i-- )
493)         free( strs[i] );
494)       free( strs );
495)       return NULL;
496)     }
497)   }
498) 
499)   size = 128;
500)   for( i = 0; i < pMovie->infoCnt; i++ )
501)     size += strlen( pMovie->pppInfos[i][0] ) + strlen( pMovie->pppInfos[i][1] ) + 8;
502)   for( i = 0; i < pMovie->frameCnt; i++ )
503)     size += strlen( strs[i] ) + 32;
504) 
505)   str = (char *)malloc( size );
506)   if( str == NULL )
507)   {
508)     for( i = 0; i < pMovie->frameCnt; i++ )
509)       free( strs[i] );
510)     free( strs );
511)     return NULL;
512)   }
513) 
514)   ptr = str;
515) 
516)   sprintf( ptr, "BlinkenMovie %ux%u-%u/%u\n", pMovie->width, pMovie->height, pMovie->channels, pMovie->maxval );
517)   ptr += strlen( ptr );
518) 
519)   for( i = 0; i < pMovie->infoCnt; i++ )
520)   {
521)     sprintf( ptr, "%s = %s\n", pMovie->pppInfos[i][0], pMovie->pppInfos[i][1] );
522)     ptr += strlen( ptr );
523)   }
524) 
525)   for( i = 0; i < pMovie->frameCnt; i++ )
526)   {
527)     sprintf( ptr, "frame %u\n%s", i, strs[i] );
528)     ptr += strlen( ptr );
529)     free( strs[i] );
530)   }
531)   free( strs );
532) 
533)   return str;  
534) }
535) 
536) stBlinkenMovie * BlinkenMovieLoadBlm( char * pFilename )
537) {
538)   FILE * pFile;
539)   stBlinkenMovie * pMovie;
540)   stBlinkenFrame * pFrame;
541)   int width, height, y, x, chr, duration;
542)   char infoType[256], infoData[1024], pixel[2];
543) 
544)   if( pFilename == NULL )
545)     return NULL;
546) 
547)   //open file
548)   pFile = fopen( pFilename, "rt" );
Christian Heimke BlinkenLib v.0.2 (2005-01-27)

Christian Heimke authored 13 years ago

549)   if( pFile == NULL )
550)     return NULL;
Christian Heimke BlinkenLib v.0.1.1 (2005-01...

Christian Heimke authored 13 years ago

551) 
552)   //read magic and size
553)   if( fscanf( pFile, " # BlinkenLights Movie %ux%u", &width, &height ) != 2 )
554)   {
555)     fclose( pFile );
556)     return NULL;
557)   }
558) 
559)   //allocate a new movie
560)   pMovie = BlinkenMovieNew( height, width, 1, 1 );
561)   if( pMovie == NULL )
562)   {
563)     fclose( pFile );
564)     return NULL;
565)   }
566) 
567)   //no frame yet
568)   pFrame = NULL;
569)   y = 0;
570) 
571)   //read frames
572)   while( ! feof( pFile ) )
573)   {
574)     //skip rest of previous line (including newline)
575)     while( (chr = fgetc( pFile )) != '\n' && chr != EOF );
576) 
577)     //info line
578)     if( fscanf( pFile, " # %255[A-Za-z0-9] %*[=:] %1023[^\n]", infoType, infoData ) == 2 )
579)     {
580)       BlinkenMovieAppendInfo( pMovie, infoType, infoData );
581)     }
582) 
583)     //start of frame
584)     else if( fscanf( pFile, " @ %u", &duration ) == 1 )
585)     {
586)       //create new frame and append it to movie
587)       pFrame = BlinkenFrameNew( height, width, 1, 1, duration );
588)       if( pFrame != NULL )
589)       {
590)         BlinkenFrameClear( pFrame );
Christian Heimke BlinkenLib v.0.3 (2005-02-16)

Christian Heimke authored 13 years ago

591)         if( BlinkenMovieAppendFrame( pMovie, pFrame ) != 0 )
592)         {
593)           BlinkenFrameFree( pFrame );
594)           pFrame = NULL;
595)         }
Christian Heimke BlinkenLib v.0.1.1 (2005-01...

Christian Heimke authored 13 years ago

596)         y = 0;
597)       }
598)     }
599) 
600)     //data line
601)     else if( fscanf( pFile, "%1[01]", pixel ) == 1 )
602)     {
603)       if( pFrame != NULL )
604)       {
605)         for( x = 0; ; x++ )
606)         {
607)           BlinkenFrameSetPixel( pFrame, y, x, 0, pixel[0] == '1' ? 1 : 0 ); //set pixel
608)           if( fscanf( pFile, "%1[01]", pixel ) != 1 ) //read next pixel
609)             break;
610)         }  
611)         y++; //next row
612)       }
613)     }
614) 
615)   } //while( ! feof( pFile ) )
616) 
617)   //close file
618)   fclose( pFile );
619) 
620)   return pMovie;
621) }
622) 
623) stBlinkenMovie * BlinkenMovieLoadBmm( char * pFilename )
624) {
625)   FILE * pFile;
626)   stBlinkenMovie * pMovie;
627)   stBlinkenFrame * pFrame;
628)   int width, height, y, x, chr, duration, val;
629)   char infoType[256], infoData[1024], pixel[8];
630) 
631)   if( pFilename == NULL )
632)     return NULL;
633) 
634)   //open file
635)   pFile = fopen( pFilename, "rt" );
Christian Heimke BlinkenLib v.0.2 (2005-01-27)

Christian Heimke authored 13 years ago

636)   if( pFile == NULL )
637)     return NULL;
Christian Heimke BlinkenLib v.0.1.1 (2005-01...

Christian Heimke authored 13 years ago

638) 
639)   //read magic and size
640)   if( fscanf( pFile, " # BlinkenMini Movie %ux%u", &width, &height ) != 2 )
641)   {
642)     fclose( pFile );
643)     return NULL;
644)   }
645) 
646)   //allocate a new movie
647)   pMovie = BlinkenMovieNew( height, width, 1, 255 );
648)   if( pMovie == NULL )
649)   {
650)     fclose( pFile );
651)     return NULL;
652)   }
653) 
654)   //no frame yet
655)   pFrame = NULL;
656)   y = 0;
657) 
658)   //read frames
659)   while( ! feof( pFile ) )
660)   {
661)     //skip rest of previous line (including newline)
662)     while( (chr = fgetc( pFile )) != '\n' && chr != EOF );
663) 
664)     //info line
665)     if( fscanf( pFile, " # %255[A-Za-z0-9] %*[=:] %1023[^\n]", infoType, infoData ) == 2 )
666)     {
667)       BlinkenMovieAppendInfo( pMovie, infoType, infoData );
668)     }
669) 
670)     //start of frame
671)     else if( fscanf( pFile, " @ %u", &duration ) == 1 )
672)     {
673)       //create new frame and append it to movie
674)       pFrame = BlinkenFrameNew( height, width, 1, 255, duration );
675)       if( pFrame != NULL )
676)       {
677)         BlinkenFrameClear( pFrame );
Christian Heimke BlinkenLib v.0.3 (2005-02-16)

Christian Heimke authored 13 years ago

678)         if( BlinkenMovieAppendFrame( pMovie, pFrame ) != 0 )
679)         {
680)           BlinkenFrameFree( pFrame );
681)           pFrame = NULL;
682)         }
Christian Heimke BlinkenLib v.0.1.1 (2005-01...

Christian Heimke authored 13 years ago

683)         y = 0;
684)       }
685)     }
686) 
687)     //data line
688)     else if( fscanf( pFile, "%7[0-9A-FXa-fx]", pixel ) == 1 )
689)     {
690)       if( pFrame != NULL )
691)       {
692)         for( x = 0; ; x++ )
693)         {
694)           if( sscanf( pixel, "%i", &val ) != 1 ) //convert pixel to number
695)             break;
696)           BlinkenFrameSetPixel( pFrame, y, x, 0, (unsigned char)val ); //set pixel
697)           fscanf( pFile, "%*[ \t]" ); //kill space
698)           if( fscanf( pFile, "%7[0-9A-FXa-fx]", pixel ) != 1 ) //read next pixel
699)             break;
700)         }  
701)         y++; //next row
702)       }
703)     }
704) 
705)   } //while( ! feof( pFile ) )
706) 
707)   //close file
708)   fclose( pFile );
709) 
710)   return pMovie;
711) }
712) 
713) stBlinkenMovie * BlinkenMovieLoadBml( char * pFilename )
714) {
715)   FILE * pFile;
716)   stBlinkenMovie * pMovie;
717)   stBlinkenFrame * pFrame;
718)   int width, height, channels, bits, maxval, chrs, y, x, c, duration, val;
719)   char buffer[2048], infoType[256], infoData[1024], pixelFormat[16], pixel[8], * ptr, chr;
720) 
721)   if( pFilename == NULL )
722)     return NULL;
723) 
724)   //open file
725)   pFile = fopen( pFilename, "rt" );
Christian Heimke BlinkenLib v.0.2 (2005-01-27)

Christian Heimke authored 13 years ago

726)   if( pFile == NULL )
727)     return NULL;
Christian Heimke BlinkenLib v.0.1.1 (2005-01...

Christian Heimke authored 13 years ago

728) 
729)   //no movie yet - blm tag not yet found
730)   pMovie = NULL;
731) 
732)   //no frame yet
733)   pFrame = NULL;
734)   y = 0;
735) 
736)   //read tags
737)   maxval = 0;
738)   while( ! feof( pFile ) )
739)   {
740) 
741)     //skip to just before beginning of next tag
742)     fscanf( pFile, "%*[^<]" );
743)     //skip beginning character of next tag
744)     if( fgetc( pFile ) != '<' )
745)       //end loop (no more tags)
746)       break;
747) 
748)     //no blm tag yet
749)     if( pMovie == NULL )
750)     {
751) 
752)       //blm tag
753)       if( fscanf( pFile, "blm%2047[^>]", buffer ) == 1 )
754)       {
755)         //get attributes
756)         width = 0;
757)         height = 0;
758)         channels = 0;
759)         bits = 0;
760)         maxval = 0;
761)         if( (ptr = strstr( buffer, "height=\"" )) != NULL ) //height
762)           sscanf( ptr+8, "%u", &height );
763)         if( (ptr = strstr( buffer, "width=\"" )) != NULL ) //width
764)           sscanf( ptr+7, "%u", &width );
765)         if( (ptr = strstr( buffer, "channels=\"" )) != NULL ) //channels
766)           sscanf( ptr+10, "%u", &channels );
767)         if( (ptr = strstr( buffer, "bits=\"" )) != NULL ) //bits
768)           sscanf( ptr+6, "%u", &bits );
769)         maxval = (1 << bits) - 1; //maxval
770) 
771)         //allocate a new movie
772)         pMovie = BlinkenMovieNew( height, width, channels, maxval );
773)         if( pMovie == NULL )
774)         {
775)           fclose( pFile );
776)           return NULL;
777)         }
778) 
779)         //get number of characters per channel
780)         chrs = (bits + 3) >> 2;
781)         //get fscanf formart string for reading a pixel
782)         sprintf( pixelFormat, "%%%d[0-9A-Fa-f]", chrs > 4 ? 5 : chrs ); //read max 5 chars (2 already in use by prefix)
783)         //initialize pixel buffer with hex prefix
784)         strcpy( pixel, "0x" );
785)       }
786) 
787)     } //if( pMovie == NULL )
788) 
789)     //blm tag was already found
790)     else //if( pMovie == NULL )
791)     {
792) 
793)       //title tag
794)       if( fscanf( pFile, "title>%2047[^<]", buffer ) == 1 )
795)       {
796)         //add info to movie
797)         BlinkenMovieAppendInfo( pMovie, "title", buffer );
798)       }
799) 
800)       //description tag
801)       else if( fscanf( pFile, "description>%2047[^<]", buffer ) == 1 )
802)       {
803)         //check if generic info
804)         if( sscanf( buffer, "%255[A-Za-z0-9] %*[=:] %1023[^\n]", infoType, infoData ) == 2 )
805)           //add info to movie
806)           BlinkenMovieAppendInfo( pMovie, infoType, infoData );
807)         else
808)           //add info to movie
809)           BlinkenMovieAppendInfo( pMovie, "description", buffer );
810)       }
811) 
812)       //creator tag
813)       else if( fscanf( pFile, "creator>%2047[^<]", buffer ) == 1 )
814)       {
815)         //add info to movie
816)         BlinkenMovieAppendInfo( pMovie, "creator", buffer );
817)       }
818) 
819)       //author tag
820)       else if( fscanf( pFile, "author>%2047[^<]", buffer ) == 1 )
821)       {
822)         //add info to movie
823)         BlinkenMovieAppendInfo( pMovie, "author", buffer );
824)       }
825) 
826)       //email tag
827)       else if( fscanf( pFile, "email>%2047[^<]", buffer ) == 1 )
828)       {
829)         //add info to movie
830)         BlinkenMovieAppendInfo( pMovie, "email", buffer );
831)       }
832) 
833)       //url tag
834)       else if( fscanf( pFile, "url>%2047[^<]", buffer ) == 1 )
835)       {
836)         //add info to movie
837)         BlinkenMovieAppendInfo( pMovie, "url", buffer );
838)       }
839) 
840)       //frame tag
841)       else if( fscanf( pFile, "frame%2047[^>]", buffer ) == 1 )
842)       {
843)         //get attributes
844)         duration = 0;
845)         if( (ptr = strstr( buffer, "duration=\"" )) != NULL ) //duration
846)           sscanf( ptr+10, "%u", &duration );
847)         //create new frame and append it to movie
848)         pFrame = BlinkenFrameNew( height, width, channels, maxval, duration );
849)         if( pFrame != NULL )
850)         {
851)           BlinkenFrameClear( pFrame );
Christian Heimke BlinkenLib v.0.3 (2005-02-16)

Christian Heimke authored 13 years ago

852)           if( BlinkenMovieAppendFrame( pMovie, pFrame ) != 0 )
853)           {
854)             BlinkenFrameFree( pFrame );
855)             pFrame = NULL;
856)           }
Christian Heimke BlinkenLib v.0.1.1 (2005-01...

Christian Heimke authored 13 years ago

857)           y = 0;
858)         }
859)       }
860) 
861)       //row tag
862)       else if( fscanf( pFile, "row%c", &chr ) == 1 && chr == '>' )
863)       {
864)         if( pFrame != NULL )
865)         {
866)           //parse row
867)           for( x = 0; x < width; x++ )
868)           {
869)             for( c = 0; c < channels; c++ )
870)             {
871)               //read next pixel (one channel of pixel)
872)               if( fscanf( pFile, pixelFormat, pixel+2 ) != 1 )
873)               {
874)                 x = width; //also terminate x loop
875)                 break;
876)               }
877)               //convert pixel (one channel of pixel) to number
878)               if( sscanf( pixel, "%i", &val ) != 1 )
879)               {
880)                 x = width; //also terminate x loop
881)                 break;
882)               }
883)               //set pixel (one channel of pixel)
884)               BlinkenFrameSetPixel( pFrame, y, x, c, (unsigned char)val );
885)             }
886)           }
887)           y++; //next row
888)         }
889)       }
890) 
891)     } //if( pMovie == NULL ) ... else
892) 
893)   } //while( ! feof( pFile ) )
894) 
895)   //close file
896)   fclose( pFile );
897) 
898)   return pMovie;
899) }
900) 
901) stBlinkenMovie * BlinkenMovieLoadBbm( char * pFilename )
902) {
903)   FILE * pFile;
904)   stBlinkenMovie * pMovie;
905)   stBlinkenFrame * pFrame;
906)   unsigned char header[24], subHeader[6], frameStartMarker[4];
907)   unsigned long headerMagic, headerFrameCnt, headerDuration, headerFramePtr;
908)   unsigned short headerHeight, headerWidth, headerChannels, headerMaxval;
909)   unsigned long subHeaderMagic, frameStartMarkerMagic;
910)   unsigned short subHeaderSize;
911)   unsigned char * pInfoHeader, * pInfoHeaderX, * pFrameData;
912)   int len, duration, y, x, c, i;
913) 
914)   if( pFilename == NULL )
915)     return NULL;
916) 
917)   //open file
918)   pFile = fopen( pFilename, "rb" );
Christian Heimke BlinkenLib v.0.2 (2005-01-27)

Christian Heimke authored 13 years ago

919)   if( pFile == NULL )
920)     return NULL;
Christian Heimke BlinkenLib v.0.1.1 (2005-01...

Christian Heimke authored 13 years ago

921) 
922)   //read header
923)   if( fread( header, 1, 24, pFile ) != 24 )
924)   {
925)     fclose( pFile );
926)     return NULL;
927)   }
928)   headerMagic = (unsigned long)header[0] << 24 | (unsigned long)header[1] << 16 | (unsigned long)header[2] << 8 | (unsigned long)header[3];
929)   headerHeight = (unsigned short)header[4] << 8 | (unsigned short)header[5];
930)   headerWidth = (unsigned short)header[6] << 8 | (unsigned short)header[7];
931)   headerChannels = (unsigned short)header[8] << 8 | (unsigned short)header[9];
932)   headerMaxval = (unsigned short)header[10] << 8 | (unsigned short)header[11];
933)   headerFrameCnt = (unsigned long)header[12] << 24 | (unsigned long)header[13] << 16 | (unsigned long)header[14] << 8 | (unsigned long)header[15];
934)   headerDuration = (unsigned long)header[16] << 24 | (unsigned long)header[17] << 16 | (unsigned long)header[18] << 8 | (unsigned long)header[19];
935)   headerFramePtr = (unsigned long)header[20] << 24 | (unsigned long)header[21] << 16 | (unsigned long)header[22] << 8 | (unsigned long)header[23];
936)   //check magic
937)   if( headerMagic != 0x23542666 )
938)   {
939)     fclose( pFile );
940)     return NULL;
941)   }
942) 
943)   //allocate a new movie
944)   pMovie = BlinkenMovieNew( headerHeight, headerWidth, headerChannels, headerMaxval );
945)   if( pMovie == NULL )
946)   {
947)     fclose( pFile );
948)     return NULL;
949)   }
950) 
951)   //read subheaders
952)   while( ftell( pFile ) + 6 <= (long)headerFramePtr )
953)   {
954)     if( fread( subHeader, 1, 6, pFile ) != 6 )
955)     {
956)       BlinkenMovieFree( pMovie );
957)       fclose( pFile );
958)       return NULL;
959)     }
960)     subHeaderMagic = (unsigned long)subHeader[0] << 24 | (unsigned long)subHeader[1] << 16 | (unsigned long)subHeader[2] << 8 | (unsigned long)subHeader[3];
961)     subHeaderSize = (unsigned short)subHeader[4] << 8 | (unsigned short)subHeader[5];
962) 
963)     //header fits into gap to frame start
964)     if( subHeaderSize >= 6 && ftell( pFile ) + subHeaderSize - 6 <= (long)headerFramePtr )
965)     {
966)       //info header
967)       if( subHeaderMagic == 0x696E666F ) //'i' 'n' 'f' 'o'
968)       {
969)         //read rest of info header
970)         pInfoHeader = (unsigned char *)malloc( subHeaderSize - 6 );
971)         if( pInfoHeader == NULL )
972)         {
973)           BlinkenMovieFree( pMovie );
974)           fclose( pFile );
975)           return NULL;
976)         }
977)         if( fread( pInfoHeader, 1, subHeaderSize - 6, pFile ) != (unsigned short)(subHeaderSize - 6) )
978)         {
979)           free( pInfoHeader );
980)           BlinkenMovieFree( pMovie );
981)           fclose( pFile );
982)           return NULL;
983)         }
984)         //parse information
985)         if( (pInfoHeaderX = memchr( pInfoHeader, 0, subHeaderSize - 6 )) != NULL )
986)         {
987)           pInfoHeaderX++;
988)           len = pInfoHeaderX - pInfoHeader;
989)           if( memchr( pInfoHeaderX, 0, subHeaderSize - 6 - len ) != NULL )
990)             BlinkenMovieAppendInfo( pMovie, pInfoHeader, pInfoHeaderX );
991)         }
992)         free( pInfoHeader );
993)       }
994) 
995)       //unknown subHeader
996)       else
997)         //skip
998)         fseek( pFile, subHeaderSize - 6, SEEK_CUR );
999) 
1000)     } //if( ftell( pFile ) ...
1001)   } //while( ftell( pFile ) ...
1002) 
1003)   //seek to start of frames
1004)   fseek( pFile, headerFramePtr, SEEK_SET );
1005) 
1006)   //read frame start marker
1007)   if( fread( frameStartMarker, 1, 4, pFile ) != 4 )
1008)   {
1009)     BlinkenMovieFree( pMovie );
1010)     fclose( pFile );
1011)     return NULL;
1012)   }
1013)   frameStartMarkerMagic = (unsigned long)frameStartMarker[0] << 24 | (unsigned long)frameStartMarker[1] << 16 | (unsigned long)frameStartMarker[2] << 8 | (unsigned long)frameStartMarker[3];
1014)   if( frameStartMarkerMagic != 0x66726D73 ) //'f' 'r' 'm' 's'
1015)   {
1016)     BlinkenMovieFree( pMovie );
1017)     fclose( pFile );
1018)     return NULL;
1019)   }
1020) 
1021)   //allocate buffer for frame data
1022)   len = 2 + headerHeight * headerWidth * headerChannels;
1023)   pFrameData = (unsigned char *)malloc( len );
1024)   if( pFrameData == NULL )
1025)   {
1026)     BlinkenMovieFree( pMovie );
1027)     fclose( pFile );
1028)     return NULL;
1029)   }
1030) 
1031)   //read frames
1032)   for( ; ; )
1033)   {
1034)     //read frame
1035)     if( fread( pFrameData, 1, len, pFile ) != (unsigned int)len )
1036)       break;
1037)     duration = (unsigned short)pFrameData[0] << 8 | (unsigned short)pFrameData[1];
1038)     //build frame and append it to movie
1039)     pFrame = BlinkenFrameNew( headerHeight, headerWidth, headerChannels, headerMaxval, duration );
1040)     if( pFrame == NULL )
1041)       break;
1042)     i = 2;
1043)     for( y = 0; y < headerHeight; y++ )
1044)       for( x = 0; x < headerWidth; x++ )
1045)         for( c = 0; c < headerChannels; c++, i++ )
1046)           BlinkenFrameSetPixel( pFrame, y, x, c, pFrameData[i] );
Christian Heimke BlinkenLib v.0.3 (2005-02-16)

Christian Heimke authored 13 years ago

1047)     if( BlinkenMovieAppendFrame( pMovie, pFrame ) != 0 )
1048)     {
1049)       BlinkenFrameFree( pFrame );
1050)       pFrame = NULL;
1051)     }
Christian Heimke BlinkenLib v.0.1.1 (2005-01...

Christian Heimke authored 13 years ago

1052) 
1053)   } //for( ; ; )
1054) 
1055)   //free buffer for frame data
1056)   free( pFrameData );
1057) 
1058)   //close file
1059)   fclose( pFile );
1060) 
1061)   return pMovie;
1062) }
1063) 
1064) stBlinkenMovie * BlinkenMovieLoad( char * pFilename )
1065) {
1066)   int len;
1067) 
1068)   if( pFilename == NULL )
1069)     return NULL;
1070) 
1071)   len = strlen( pFilename );
1072)   if( len > 4 && strcmp( pFilename + len - 4, ".blm" ) == 0 )
1073)     return BlinkenMovieLoadBlm( pFilename );
1074)   if( len > 4 && strcmp( pFilename + len - 4, ".bmm" ) == 0 )
1075)     return BlinkenMovieLoadBmm( pFilename );
1076)   if( len > 4 && strcmp( pFilename + len - 4, ".bml" ) == 0 )
1077)     return BlinkenMovieLoadBml( pFilename );
1078)   if( len > 4 && strcmp( pFilename + len - 4, ".bbm" ) == 0 )
1079)     return BlinkenMovieLoadBbm( pFilename );
1080)   return NULL;
1081) }
1082) 
1083) int BlinkenMovieSaveBlm( stBlinkenMovie * pMovie, char * pFilename )
1084) {
1085)   stBlinkenMovie * pOutMovie;
1086)   FILE * pFile;
1087)   int i, y, x;
1088) 
1089)   if( pMovie == NULL || pFilename == NULL )
1090)     return -1;
1091) 
1092)   //convert movie to suitable format
1093)   pOutMovie = BlinkenMovieClone( pMovie );
1094)   if( pOutMovie == NULL )
1095)     return -1;
1096)   BlinkenMovieResize( pOutMovie, pOutMovie->height, pOutMovie->width, 1, 1 );
1097) 
1098)   //open file
1099)   pFile = fopen( pFilename, "wt" );
1100)   if( pFile == NULL )
1101)   {
1102)     BlinkenMovieFree( pOutMovie );
1103)     return -1;
1104)   }
1105) 
1106)   //write header line
1107)   fprintf( pFile, "# BlinkenLights Movie %ux%u\n", pOutMovie->width, pOutMovie->height );
1108) 
1109)   //write information lines
1110)   for( i = 0; i < pOutMovie->infoCnt; i++ )
1111)     fprintf( pFile, "# %s = %s\n", pOutMovie->pppInfos[i][0], pOutMovie->pppInfos[i][1] );
1112) 
1113)   //write frames
1114)   for( i = 0; i < pOutMovie->frameCnt; i++ )
1115)   {
1116)     fprintf( pFile, "\n@%u\n", BlinkenFrameGetDuration( pOutMovie->ppFrames[i] ) );
1117)     for( y = 0; y < pOutMovie->height; y++ )
1118)     {
1119)       for( x = 0; x < pOutMovie->width; x++ )
1120)       {
1121)         if( BlinkenFrameGetPixel( pOutMovie->ppFrames[i], y, x, 0 ) != 0 )
1122)           fprintf( pFile, "1" );
1123)         else
1124)           fprintf( pFile, "0" );
1125)       }
1126)       fprintf( pFile, "\n" );
1127)     }
1128)   }
1129) 
1130)   //close file
1131)   fclose( pFile );
1132) 
1133)   //free copied movie
1134)   BlinkenMovieFree( pOutMovie );
1135) 
1136)   //success
1137)   return 0;
1138) }
1139) 
1140) int BlinkenMovieSaveBmm( stBlinkenMovie * pMovie, char * pFilename )
1141) {
1142)   stBlinkenMovie * pOutMovie;
1143)   FILE * pFile;
1144)   int i, y, x;
1145) 
1146)   if( pMovie == NULL || pFilename == NULL )
1147)     return -1;
1148) 
1149)   //convert movie to suitable format
1150)   pOutMovie = BlinkenMovieClone( pMovie );
1151)   if( pOutMovie == NULL )
1152)     return -1;
1153)   BlinkenMovieResize( pOutMovie, pOutMovie->height, pOutMovie->width, 1, 255 );
1154) 
1155)   //open file
1156)   pFile = fopen( pFilename, "wt" );
1157)   if( pFile == NULL )
1158)   {
1159)     BlinkenMovieFree( pOutMovie );
1160)     return -1;
1161)   }
1162) 
1163)   //write header line
1164)   fprintf( pFile, "# BlinkenMini Movie %ux%u\n", pOutMovie->width, pOutMovie->height );
1165) 
1166)   //write information lines
1167)   for( i = 0; i < pOutMovie->infoCnt; i++ )
1168)     fprintf( pFile, "# %s = %s\n", pOutMovie->pppInfos[i][0], pOutMovie->pppInfos[i][1] );
1169) 
1170)   //write frames
1171)   for( i = 0; i < pOutMovie->frameCnt; i++ )
1172)   {
1173)     fprintf( pFile, "\n@%u\n", BlinkenFrameGetDuration( pOutMovie->ppFrames[i] ) );
1174)     for( y = 0; y < pOutMovie->height; y++ )
1175)     {
1176)       fprintf( pFile, "0x%02X", BlinkenFrameGetPixel( pOutMovie->ppFrames[i], y, 0, 0 ) );
1177)       for( x = 1; x < pOutMovie->width; x++ )
1178)         fprintf( pFile, " 0x%02X", BlinkenFrameGetPixel( pOutMovie->ppFrames[i], y, x, 0 ) );
1179)       fprintf( pFile, "\n" );
1180)     }
1181)   }
1182) 
1183)   //close file
1184)   fclose( pFile );
1185) 
1186)   //free copied movie
1187)   BlinkenMovieFree( pOutMovie );
1188) 
1189)   //success
1190)   return 0;
1191) }
1192) 
1193) int BlinkenMovieSaveBml( stBlinkenMovie * pMovie, char * pFilename )
1194) {
1195)   stBlinkenMovie * pOutMovie;
1196)   FILE * pFile;
1197)   int bits, val, i, y, x, c;
1198) 
1199)   if( pMovie == NULL || pFilename == NULL )
1200)     return -1;
1201) 
1202)   //convert movie to suitable format
1203)   pOutMovie = BlinkenMovieClone( pMovie );
1204)   if( pOutMovie == NULL )
1205)     return -1;
1206)   val = pOutMovie->maxval; //get number of bits
1207)   for( bits = 0; val != 0; val >>= 1, bits++ );
1208)   BlinkenMovieResize( pOutMovie, pOutMovie->height, pOutMovie->width, pOutMovie->channels, (1 << bits) - 1 );
1209) 
1210)   //open file
1211)   pFile = fopen( pFilename, "wt" );
1212)   if( pFile == NULL )
1213)   {
1214)     BlinkenMovieFree( pOutMovie );
1215)     return -1;
1216)   }
1217) 
1218)   //write header line
1219)   fprintf( pFile, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" );
1220) 
1221)   //write blm start tag
1222)   fprintf( pFile, "<blm width=\"%u\" height=\"%u\" bits=\"%u\" channels=\"%u\">\n",
1223)            pOutMovie->width, pOutMovie->height, bits, pOutMovie->channels );
1224) 
1225)   //write information lines
1226)   fprintf( pFile, "\t<header>\n" );
1227)   for( i = 0; i < pOutMovie->infoCnt; i++ )
1228)   {
1229)     if( strcmp( pOutMovie->pppInfos[i][0], "title" ) == 0 )
1230)       fprintf( pFile, "\t\t<title>%s</title>\n", pOutMovie->pppInfos[i][1] );
1231)     else if( strcmp( pOutMovie->pppInfos[i][0], "description" ) == 0 )
1232)       fprintf( pFile, "\t\t<description>%s</description>\n", pOutMovie->pppInfos[i][1] );
1233)     else if( strcmp( pOutMovie->pppInfos[i][0], "creator" ) == 0 )
1234)       fprintf( pFile, "\t\t<creator>%s</creator>\n", pOutMovie->pppInfos[i][1] );
1235)     else if( strcmp( pOutMovie->pppInfos[i][0], "author" ) == 0)
1236)       fprintf( pFile, "\t\t<author>%s</author>\n", pOutMovie->pppInfos[i][1] );
1237)     else if( strcmp( pOutMovie->pppInfos[i][0], "email" ) == 0)
1238)       fprintf( pFile, "\t\t<email>%s</email>\n", pOutMovie->pppInfos[i][1] );
1239)     else if( strcmp( pOutMovie->pppInfos[i][0], "url" ) == 0)
1240)       fprintf( pFile, "\t\t<url>%s</url>\n", pOutMovie->pppInfos[i][1] );
1241)     else
1242)       fprintf( pFile, "\t\t<description>%s: %s</description>\n", pOutMovie->pppInfos[i][0], pOutMovie->pppInfos[i][1] );
1243)   }
1244)   fprintf( pFile, "\t</header>\n" );
1245) 
1246)   //write frames
1247)   for( i = 0; i < pOutMovie->frameCnt; i++ )
1248)   {
1249)     fprintf( pFile, "\n\t<frame duration=\"%u\">\n", BlinkenFrameGetDuration( pOutMovie->ppFrames[i] ) );
1250)     for( y = 0; y < pOutMovie->height; y++ )
1251)     {
1252)       fprintf( pFile, "\t\t<row>" );
1253)       for( x = 0; x < pOutMovie->width; x++ )
1254)         for( c = 0; c < pOutMovie->channels; c++ )
1255)           fprintf( pFile, bits > 4 ? "%02X" : "%01X",
1256)             BlinkenFrameGetPixel( pOutMovie->ppFrames[i], y, x, c ) );
1257)       fprintf( pFile, "</row>\n" );
1258)     }
1259)     fprintf( pFile, "\t</frame>\n" );
1260)   }
1261) 
1262)   //write blm end tag
1263)   fprintf( pFile, "</blm>\n" );
1264) 
1265)   //close file
1266)   fclose( pFile );
1267) 
1268)   //free copied movie
1269)   BlinkenMovieFree( pOutMovie );
1270) 
1271)   //success
1272)   return 0;
1273) }
1274) 
1275) int BlinkenMovieSaveBbm( stBlinkenMovie * pMovie, char * pFilename )
1276) {
1277)   unsigned char * pFrameData;
1278)   FILE * pFile;
1279)   unsigned char header[24], infoHeader[6], framePointer[4], frameStartMarker[4];
1280)   int duration, len, len0, len1, i, j, y, x, c, val;
1281)   long pos;
1282) 
1283)   if( pMovie == NULL || pFilename == NULL )
1284)     return -1;
1285) 
1286)   //allocate frame data buffer
1287)   pFrameData = (unsigned char *)malloc( 2 + pMovie->height * pMovie->width * pMovie->channels );
1288)   if( pFrameData == NULL )
1289)     return -1;
1290) 
1291)   //open file
1292)   pFile = fopen( pFilename, "wb" );
1293)   if( pFile == NULL )
1294)   {
1295)     free( pFrameData );
1296)     return -1;
1297)   }
1298) 
1299)   //write header
1300)   header[0] = 0x23; //magic
1301)   header[1] = 0x54;
1302)   header[2] = 0x26;
1303)   header[3] = 0x66;
1304)   header[4] = (unsigned char)(pMovie->height >> 8);
1305)   header[5] = (unsigned char)pMovie->height;
1306)   header[6] = (unsigned char)(pMovie->width >> 8);
1307)   header[7] = (unsigned char)pMovie->width;
1308)   header[8] = (unsigned char)(pMovie->channels >> 8);
1309)   header[9] = (unsigned char)pMovie->channels;
1310)   header[10] = (unsigned char)(pMovie->maxval >> 8);
1311)   header[11] = (unsigned char)pMovie->maxval;
1312)   header[12] = (unsigned char)(pMovie->frameCnt >> 24);
1313)   header[13] = (unsigned char)(pMovie->frameCnt >> 16);
1314)   header[14] = (unsigned char)(pMovie->frameCnt >> 8);
1315)   header[15] = (unsigned char)pMovie->frameCnt;
1316)   duration = 0;
1317)   for( i = 0; i < pMovie->frameCnt; i++ )
1318)     duration += BlinkenFrameGetDuration( pMovie->ppFrames[i] ); 
1319)   header[16] = (unsigned char)(duration >> 24);
1320)   header[17] = (unsigned char)(duration >> 16);
1321)   header[18] = (unsigned char)(duration >> 8);
1322)   header[19] = (unsigned char)duration;
1323)   header[20] = 0; //frame pointer is written later
1324)   header[21] = 0;
1325)   header[22] = 0;
1326)   header[23] = 0;
1327)   fwrite( header, 1, 24, pFile );
1328) 
1329)   //write information
1330)   for( i = 0; i < pMovie->infoCnt; i++ )
1331)   {
1332)     len0 = strlen( pMovie->pppInfos[i][0] );
1333)     if( len0 > 32760 )
1334)       len0 = 32760;
1335)     len1 = strlen( pMovie->pppInfos[i][1] );
1336)     if( len1 > 32760 )
1337)       len1 = 32760;
1338)     len = 8 + len0 + len1;
1339)     infoHeader[0] = 0x69; //'i'
1340)     infoHeader[1] = 0x6E; //'n'
1341)     infoHeader[2] = 0x66; //'f'
1342)     infoHeader[3] = 0x6F; //'o'
1343)     infoHeader[4] = (unsigned char)(len >> 8);
1344)     infoHeader[5] = (unsigned char)len;
1345)     fwrite( infoHeader, 1, 6, pFile );
1346)     fwrite( pMovie->pppInfos[i][0], 1, len0, pFile );
1347)     fwrite( "\0", 1, 1, pFile );
1348)     fwrite( pMovie->pppInfos[i][1], 1, len1, pFile );
1349)     fwrite( "\0", 1, 1, pFile );
1350)   }
1351) 
1352)   //write frame pointer
1353)   pos = ftell( pFile );
1354)   framePointer[0] = (unsigned char)(pos >> 24);
1355)   framePointer[1] = (unsigned char)(pos >> 16);
1356)   framePointer[2] = (unsigned char)(pos >> 8);
1357)   framePointer[3] = (unsigned char)pos;
1358)   fseek( pFile, 20, SEEK_SET );
1359)   fwrite( framePointer, 1, 4, pFile );
1360)   fseek( pFile, pos, SEEK_SET );
1361) 
1362)   //write frame start marker
1363)   frameStartMarker[0] = 0x66; //'f'
1364)   frameStartMarker[1] = 0x72; //'r'
1365)   frameStartMarker[2] = 0x6D; //'m'
1366)   frameStartMarker[3] = 0x73; //'s'
1367)   fwrite( frameStartMarker, 1, 4, pFile );
1368) 
1369)   //write frames
1370)   for( i = 0; i < pMovie->frameCnt; i++ )
1371)   {
1372)     val = BlinkenFrameGetDuration( pMovie->ppFrames[i] );
1373)     pFrameData[0] = (unsigned char)(val >> 8);
1374)     pFrameData[1] = (unsigned char)val;
1375)     for( j = 2, y = 0; y < pMovie->height; y++ )
1376)       for( x = 0; x < pMovie->width; x++ )
1377)         for( c = 0; c < pMovie->channels; c++, j++ )
1378)           pFrameData[j] = BlinkenFrameGetPixel( pMovie->ppFrames[i], y, x, c );
1379)     fwrite( pFrameData, 1, j, pFile );
1380)   }
1381) 
1382)   //free frame data buffer
1383)   free( pFrameData );
1384) 
1385)   //close file
1386)   fclose( pFile );
1387) 
1388)   //success
1389)   return 0;
1390) }
1391) 
1392) int BlinkenMovieSave( stBlinkenMovie * pMovie, char * pFilename )
1393) {
1394)   int len;
1395) 
1396)   if( pMovie == NULL || pFilename == NULL )
1397)     return -1;
1398) 
1399)   len = strlen( pFilename );
1400)   if( len > 4 && strcmp( pFilename + len - 4, ".blm" ) == 0 )
1401)     return BlinkenMovieSaveBlm( pMovie, pFilename );
1402)   if( len > 4 && strcmp( pFilename + len - 4, ".bmm" ) == 0 )
1403)     return BlinkenMovieSaveBmm( pMovie, pFilename );
1404)   if( len > 4 && strcmp( pFilename + len - 4, ".bml" ) == 0 )
1405)     return BlinkenMovieSaveBml( pMovie, pFilename );
1406)   if( len > 4 && strcmp( pFilename + len - 4, ".bbm" ) == 0 )
1407)     return BlinkenMovieSaveBbm( pMovie, pFilename );
1408)   return -1;
1409) }
1410)