64ad70ca347367816472e1c06f7083457289d445
Christian Heimke BlinkenLibJava v.0.1.1 (200...

Christian Heimke authored 13 years ago

1) /* BlinkenLib
Stefan Schuermans update copyright year

Stefan Schuermans authored 6 years ago

2)  * Copyright (C) 2004-2018: Stefan Schuermans <stefan@schuermans.info>
Christian Heimke BlinkenLibJava v.0.1.1 (200...

Christian Heimke authored 13 years ago

3)  * Copyleft: GNU public license - http://www.gnu.org/copyleft/gpl.html
4)  * a blinkenarea.org project
5)  */
6) 
7) package org.blinkenarea.BlinkenLib;
8) 
9) import java.util.*;
10) import java.util.regex.*;
11) import java.io.*;
Stefan Schuermans first version fo GIF read s...

Stefan Schuermans authored 6 years ago

12) import java.awt.*;
13) import java.awt.image.*;
14) import javax.imageio.*;
15) import javax.imageio.metadata.*;
16) import javax.imageio.stream.*;
17) import org.w3c.dom.*;
Christian Heimke BlinkenLibJava v.0.1.1 (200...

Christian Heimke authored 13 years ago

18) import org.blinkenarea.BlinkenLib.*;
19) 
20) public class BlinkenMovie
21) {
22) 
23)   private int height;
24)   private int width;
25)   private int channels;
26)   private int maxval;
27)   private int infoCnt;
28)   private String[][] infos;
29)   private int frameCnt;
30)   private BlinkenFrame[] frames;
31) 
32)   public BlinkenMovie( int height, int width, int channels, int maxval )
33)   {
34)     if( height < BlinkenConstants.BlinkenHeightMin ) height = BlinkenConstants.BlinkenHeightMin;
35)     if( height > BlinkenConstants.BlinkenHeightMax ) height = BlinkenConstants.BlinkenHeightMax;
36)     if( width < BlinkenConstants.BlinkenWidthMin ) width = BlinkenConstants.BlinkenWidthMin;
37)     if( width > BlinkenConstants.BlinkenWidthMax ) width = BlinkenConstants.BlinkenWidthMax;
38)     if( channels < BlinkenConstants.BlinkenChannelsMin ) channels = BlinkenConstants.BlinkenChannelsMin;
39)     if( channels > BlinkenConstants.BlinkenChannelsMax ) channels = BlinkenConstants.BlinkenChannelsMax;
40)     if( maxval < BlinkenConstants.BlinkenMaxvalMin ) maxval = BlinkenConstants.BlinkenMaxvalMin;
41)     if( maxval > BlinkenConstants.BlinkenMaxvalMax ) maxval = BlinkenConstants.BlinkenMaxvalMax;
42) 
43)     this.height = height;
44)     this.width = width;
45)     this.channels = channels;
46)     this.maxval = maxval;
47)     infoCnt = 0;
48)     infos = new String[0][2];
49)     frameCnt = 0;
50)     frames = new BlinkenFrame[0];
51)   }
52) 
53)   public BlinkenMovie( BlinkenMovie movie )
54)   {
55)     int i;
56) 
57)     height = movie.height;
58)     width = movie.width;
59)     channels = movie.channels;
60)     maxval = movie.maxval;
61)     infoCnt = 0;
62)     infos = new String[0][2];
63)     frameCnt = 0;
64)     frames = new BlinkenFrame[0];
65) 
66)     for( i = 0; i < movie.infoCnt; i++ )
67)       appendInfo( new String( movie.infos[i][0] ), new String( movie.infos[i][1] ) );
68) 
69)     for( i = 0; i < movie.frameCnt; i++ )
70)       appendFrame( new BlinkenFrame( movie.frames[i] ) );
71)   }
72) 
73)   public int getHeight( )
74)   {
75)     return height;
76)   }
77) 
78)   public int getWidth( )
79)   {
80)     return width;
81)   }
82) 
83)   public int getChannels( )
84)   {
85)     return channels;
86)   }
87) 
88)   public int getMaxval( )
89)   {
90)     return maxval;
91)   }
92) 
93)   public int getDuration( )
94)   {
95)     int duration, i;
96)     duration = 0;
97)     for( i = 0; i < frameCnt; i++ )
98)       duration += frames[i].getDuration( );
99)     return duration;
100)   }
101) 
102)   public int getInfoCnt( )
103)   {
104)     return infoCnt;
105)   }
106) 
107)   public String getInfoType( int infoNo )
108)   {
109)     if( infoCnt < 1 ) return "";
110)     if( infoNo < 0 ) infoNo = 0;
111)     if( infoNo >= infoCnt ) infoNo = infoCnt - 1;
112)     return infos[infoNo][0];
113)   }
114) 
115)   public String getInfoData( int infoNo )
116)   {
117)     if( infoCnt < 1 ) return "";
118)     if( infoNo < 0 ) infoNo = 0;
119)     if( infoNo >= infoCnt ) infoNo = infoCnt - 1;
120)     return infos[infoNo][1];
121)   }
122) 
123)   public void setInfo( int infoNo, String infoType, String infoData )
124)   {
125)     if( infoNo < 0 || infoNo >= infoCnt )
126)       return;
127)     infos[infoNo][0] = infoType;
128)     infos[infoNo][1] = infoData;
129)   }
130) 
131)   public void insertInfo( int infoNo, String infoType, String infoData )
132)   {
133)     String[][] new_infos;
134)     int i;
135) 
136)     if( infoNo < 0 || infoNo > infoCnt )
137)       return;
138) 
139)     new_infos = new String[infoCnt+1][2];
140) 
141)     for( i = 0; i < infoNo; i++ )
142)     {
143)       new_infos[i][0] = infos[i][0];
144)       new_infos[i][1] = infos[i][1];
145)     }
146) 
147)     new_infos[infoNo][0] = infoType;
148)     new_infos[infoNo][1] = infoData;
149) 
150)     for( i = infoNo; i < infoCnt; i++ )
151)     {
152)       new_infos[i+1][0] = infos[i][0];
153)       new_infos[i+1][1] = infos[i][1];
154)     }
155) 
156)     infos = new_infos;
157)     infoCnt++;
158)   }
159)   
160)   public void appendInfo( String infoType, String infoData )
161)   {
162)     insertInfo( infoCnt, infoType, infoData );
163)   }
164) 
165)   public void deleteInfo( int infoNo )
166)   {
167)     String[][] new_infos;
168)     int i;
169) 
170)     if( infoNo < 0 || infoNo >= infoCnt )
171)       return;
172) 
173)     new_infos = new String[infoCnt-1][2];
174) 
175)     for( i = 0; i < infoNo; i++ )
176)     {
177)       new_infos[i][0] = infos[i][0];
178)       new_infos[i][1] = infos[i][1];
179)     }
180) 
181)     for( i = infoNo; i < infoCnt-1; i++ )
182)     {
183)       new_infos[i][0] = infos[i+1][0];
184)       new_infos[i][1] = infos[i+1][1];
185)     }
186) 
187)     infos = new_infos;
188)     infoCnt--;
189)   }
190)   
191)   public void deleteInfos( )
192)   {
193)     infos = new String[0][2];
194)     infoCnt = 0;
195)   }
196) 
197)   public int getFrameCnt( )
198)   {
199)     return frameCnt;
200)   }
201) 
202)   public BlinkenFrame getFrame( int frameNo )
203)   {
204)     BlinkenFrame frame;
205)     if( frameCnt < 1 )
206)     {
207)       frame = new BlinkenFrame( height, width, channels, maxval, 0 );
208)       frame.clear( );
209)       return frame;
210)     }
211)     if( frameNo < 0 ) frameNo = 0;
212)     if( frameNo >= frameCnt ) frameNo = frameCnt - 1;
213)     return frames[frameNo];
214)   }
215) 
216)   public void setFrame( int frameNo, BlinkenFrame frame )
217)   {
218)     if( frameNo < 0 || frameNo >= frameCnt )
219)       return;
220)     frame.resize( height, width, channels, maxval );
221)     frames[frameNo] = frame;
222)   }
223) 
224)   public void insertFrame( int frameNo, BlinkenFrame frame )
225)   {
226)     BlinkenFrame[] new_frames;
227)     int i;
228) 
229)     if( frameNo < 0 || frameNo > frameCnt )
230)       return;
231) 
232)     new_frames = new BlinkenFrame[frameCnt+1];
233) 
234)     for( i = 0; i < frameNo; i++ )
235)       new_frames[i] = frames[i];
236) 
237)     frame.resize( height, width, channels, maxval );
238)     new_frames[frameNo] = frame;
239) 
240)     for( i = frameNo; i < frameCnt; i++ )
241)       new_frames[i+1] = frames[i];
242) 
243)     frames = new_frames;
244)     frameCnt++;
245)   }
246)   
247)   public void appendFrame( BlinkenFrame frame )
248)   {
249)     insertFrame( frameCnt, frame );
250)   }
251) 
252)   public void deleteFrame( int frameNo )
253)   {
254)     BlinkenFrame[] new_frames;
255)     int i;
256) 
257)     if( frameNo < 0 || frameNo >= frameCnt )
258)       return;
259) 
260)     new_frames = new BlinkenFrame[frameCnt-1];
261) 
262)     for( i = 0; i < frameNo; i++ )
263)       new_frames[i] = frames[i];
264) 
265)     for( i = frameNo; i < frameCnt-1; i++ )
266)       new_frames[i] = frames[i+1];
267) 
268)     frames = new_frames;
269)     frameCnt--;
270)   }
271)   
272)   public void deleteFrames( )
273)   {
274)     frames = new BlinkenFrame[0];
275)     frameCnt = 0;
276)   }
277) 
278)   public void resize( int height, int width, int channels, int maxval )
279)   {
280)     int i;
281) 
282)     if( height < BlinkenConstants.BlinkenHeightMin ) height = BlinkenConstants.BlinkenHeightMin;
283)     if( height > BlinkenConstants.BlinkenHeightMax ) height = BlinkenConstants.BlinkenHeightMax;
284)     if( width < BlinkenConstants.BlinkenWidthMin ) width = BlinkenConstants.BlinkenWidthMin;
285)     if( width > BlinkenConstants.BlinkenWidthMax ) width = BlinkenConstants.BlinkenWidthMax;
286)     if( channels < BlinkenConstants.BlinkenChannelsMin ) channels = BlinkenConstants.BlinkenChannelsMin;
287)     if( channels > BlinkenConstants.BlinkenChannelsMax ) channels = BlinkenConstants.BlinkenChannelsMax;
288)     if( maxval < BlinkenConstants.BlinkenMaxvalMin ) maxval = BlinkenConstants.BlinkenMaxvalMin;
289)     if( maxval > BlinkenConstants.BlinkenMaxvalMax ) maxval = BlinkenConstants.BlinkenMaxvalMax;
290) 
291)     this.height = height;
292)     this.width = width;
293)     this.channels = channels;
294)     this.maxval = maxval;
295) 
296)     for( i = 0; i < frameCnt; i++ )
297)       frames[i].resize( height, width, channels, maxval );
298)   }
299) 
300)   public void scale( int height, int width )
301)   {
302)     int i;
303) 
304)     if( height < BlinkenConstants.BlinkenHeightMin ) height = BlinkenConstants.BlinkenHeightMin;
305)     if( height > BlinkenConstants.BlinkenHeightMax ) height = BlinkenConstants.BlinkenHeightMax;
306)     if( width < BlinkenConstants.BlinkenWidthMin ) width = BlinkenConstants.BlinkenWidthMin;
307)     if( width > BlinkenConstants.BlinkenWidthMax ) width = BlinkenConstants.BlinkenWidthMax;
308) 
309)     this.height = height;
310)     this.width = width;
311) 
312)     for( i = 0; i < frameCnt; i++ )
313)       frames[i].scale( height, width );
314)   }
315) 
316)   public String toString( )
317)   {
318)     String str = "BlinkenMovie " + width + "x" + height + "-" + channels + "/" + (maxval + 1) + "\n";
319)     int i;
320)     for( i = 0; i < infoCnt; i++ )
321)       str += infos[i][0] + " = " + infos[i][1] + "\n";
322)     for( i = 0; i < frameCnt; i++ )
323)       str += "frame " + i + "\n" + frames[i].toString( );
324)     return str;
325)   }
326) 
327)   public boolean loadBlm( BufferedReader reader )
328)   {
329)     Pattern header, infoLine, startOfFrame, dataLine;
330)     String line, pixel;
331)     Matcher matcher;
332)     int new_width, new_height, new_duration, y, x, val;
333)     BlinkenFrame frame;
334) 
335)     //initialize needed regexp patterns
336)     header = Pattern.compile( "^ *# BlinkenLights Movie ([0-9]+)x([0-9]+)" );
337)     infoLine = Pattern.compile( "^ *# ?([A-Za-z0-9]+)(?: *= *|: *)(.*)" );
338)     startOfFrame = Pattern.compile( "^ *@([0-9]+)" );
339)     dataLine = Pattern.compile( " *([01])" );
340) 
341)     //delete all frames
342)     deleteInfos( );
343)     deleteFrames( );
344)     resize( 0, 0, 0, 0 );
345) 
346)     //try to read from buffered reader
347)     try
348)     {
349)       //read magic and size
350)       if( (line = reader.readLine( )) != null )
351)       {
352)         if( (matcher = header.matcher( line )).find( ) )
353)         {
354)           new_width = Integer.parseInt( matcher.group( 1 ) );
355)           new_height = Integer.parseInt( matcher.group( 2 ) );
356)           resize( new_height, new_width, 1, 1 );
357) 
358)           //create unused dummy frame for beginning
359)           frame = new BlinkenFrame( height, width, 1, 1, 0 );
360)           y = 0;
361) 
362)           //read frames
363)           while( (line = reader.readLine( )) != null )
364)           {
365) 
366)             //info line
367)             if( (matcher = infoLine.matcher( line )).find( ) )
368)             {
369)               appendInfo( matcher.group( 1 ), matcher.group( 2 ) );
370)             }
371) 
372)             //start of frame
373)             else if( (matcher = startOfFrame.matcher( line )).find( ) )
374)             {
375)               new_duration = Integer.parseInt( matcher.group( 1 ) );
376)               //create new frame and append it to movie
377)               frame = new BlinkenFrame( height, width, 1, 1, new_duration );
378)               frame.clear( );
379)               appendFrame( frame );
380)               y = 0;
381)             }
382) 
383)             //data line
384)             else if( (matcher = dataLine.matcher( line )).find( ) )
385)             {
386)               x = 0;
387)               while( true )
388)               {
389)                 pixel = matcher.group( 1 );
390)                 val = Integer.parseInt( pixel );
391)                 frame.setPixel( y, x, 0, (byte)val ); //set pixel
392)                 if( ! matcher.find( ) ) //get next pixel
393)                   break;
394)                 x++; //next pixel
395)               }
396)               y++; //next row
397)             }
398) 
399)           } //while( (line = ...
400)         } //if( matcher = header..matcher( ...
401)       } //if( (line = ...
402) 
403)       //success
404)       return true;
405)     }
406)     catch( IOException e ) { }
407) 
408)     //some error
409)     return false;
410)   }
411) 
412)   public boolean loadBlm( String filename )
413)   {
414)     try
415)     {
416)       BufferedReader file = new BufferedReader( new FileReader( filename ) );
417)       boolean ret = loadBlm( file );
418)       file.close( );
419)       return ret;
420)     }
421)     catch( IOException e )
422)     {
423)       return false;
424)     }
425)   }
426) 
427)   public boolean loadBmm( BufferedReader reader )
428)   {
429)     Pattern header, infoLine, startOfFrame, dataLine;
430)     String line, pixel;
431)     Matcher matcher;
432)     int new_width, new_height, new_duration, y, x, val;
433)     BlinkenFrame frame;
434) 
435)     //initialize needed regexp patterns
436)     header = Pattern.compile( "^ *# BlinkenMini Movie ([0-9]+)x([0-9]+)" );
437)     infoLine = Pattern.compile( "^ *# ?([A-Za-z0-9]+)(?: *= *|: *)(.*)" );
438)     startOfFrame = Pattern.compile( "^ *@([0-9]+)" );
439)     dataLine = Pattern.compile( " *(0x[0-9A-Fa-f]+|[0-9]+)" );
440) 
441)     //delete all frames
442)     deleteInfos( );
443)     deleteFrames( );
444)     resize( 0, 0, 0, 0 );
445) 
446)     //try to read from buffered reader
447)     try
448)     {
449)       //read magic and size
450)       if( (line = reader.readLine( )) != null )
451)       {
452)         if( (matcher = header.matcher( line )).find( ) )
453)         {
454)           new_width = Integer.parseInt( matcher.group( 1 ) );
455)           new_height = Integer.parseInt( matcher.group( 2 ) );
456)           resize( new_height, new_width, 1, 255 );
457) 
458)           //create unused dummy frame for beginning
459)           frame = new BlinkenFrame( height, width, 1, 255, 0 );
460)           y = 0;
461) 
462)           //read frames
463)           while( (line = reader.readLine( )) != null )
464)           {
465) 
466)             //info line
467)             if( (matcher = infoLine.matcher( line )).find( ) )
468)             {
469)               appendInfo( matcher.group( 1 ), matcher.group( 2 ) );
470)             }
471) 
472)             //start of frame
473)             else if( (matcher = startOfFrame.matcher( line )).find( ) )
474)             {
475)               new_duration = Integer.parseInt( matcher.group( 1 ) );
476)               //create new frame and append it to movie
477)               frame = new BlinkenFrame( height, width, 1, 255, new_duration );
478)               frame.clear( );
479)               appendFrame( frame );
480)               y = 0;
481)             }
482) 
483)             //data line
484)             else if( (matcher = dataLine.matcher( line )).find( ) )
485)             {
486)               x = 0;
487)               while( true )
488)               {
489)                 pixel = matcher.group( 1 );
490)                 if( pixel.length( ) >= 2 && pixel.substring( 0, 2 ).equals( "0x" ) )
491)                   val = Integer.parseInt( pixel.substring( 2 ), 0x10 );
492)                 else
493)                   val = Integer.parseInt( pixel );
494)                 frame.setPixel( y, x, 0, (byte)val ); //set pixel
495)                 if( ! matcher.find( ) ) //get next pixel
496)                   break;
497)                 x++; //next pixel
498)               }
499)               y++; //next row
500)             }
501) 
502)           } //while( (line = ...
503)         } //if( matcher = header..matcher( ...
504)       } //if( (line = ...
505) 
506)       //success
507)       return true;
508)     }
509)     catch( IOException e ) { }
510) 
511)     //some error
512)     return false;
513)   }
514) 
515)   public boolean loadBmm( String filename )
516)   {
517)     try
518)     {
519)       BufferedReader file = new BufferedReader( new FileReader( filename ) );
520)       boolean ret = loadBmm( file );
521)       file.close( );
522)       return ret;
523)     }
524)     catch( IOException e )
525)     {
526)       return false;
527)     }
528)   }
529) 
530)   public boolean loadBml( BufferedReader reader )
531)   {
532)     Pattern blmTag, blmHeight, blmWidth, blmChannels, blmBits;
533)     Pattern infoTitle, infoDescription, infoGeneric, infoCreator, infoAuthor, infoEmail, infoUrl;
534)     Pattern frameTag, frameDuration, rowTag, tag;
535)     String line, data, row;
536)     boolean blmTagFound;
537)     Matcher matcher, submatcher;
538)     int new_height, new_width, new_channels, bits, new_maxval, chrs, duration, y, x, c, len, i, val;
539)     BlinkenFrame frame;
540) 
541)     //initialize needed regexp patterns
542)     blmTag = Pattern.compile( "^[^<]*<blm([^>]*)>" );
543)     blmHeight = Pattern.compile( "height=\"?([0-9]*)\"?" );
544)     blmWidth = Pattern.compile( "width=\"?([0-9]*)\"?" );
545)     blmChannels = Pattern.compile( "channels=\"?([0-9]*)\"?" );
546)     blmBits = Pattern.compile( "bits=\"?([0-9]*)\"?" );
547)     infoTitle = Pattern.compile( "^[^<]*<title>([^<]*)</title>" );
548)     infoDescription = Pattern.compile( "[^<]*<description>([^<]*)</description>" );
549)     infoGeneric = Pattern.compile( "^([A-Za-z0-9]+)(?: *= *|: *)(.*)" );
550)     infoCreator = Pattern.compile( "^[^<]*<creator>([^<]*)</creator>" );
551)     infoAuthor = Pattern.compile( "^[^<]*<author>([^<]*)</author>" );
552)     infoEmail = Pattern.compile( "^[^<]*<email>([^<]*)</email>" );
553)     infoUrl = Pattern.compile( "^[^<]*<url>([^<]*)</url>" );
554)     frameTag = Pattern.compile( "^[^<]*<frame([^>]*)>" );
555)     frameDuration = Pattern.compile( "duration=\"?([0-9]*)\"?" );
556)     rowTag = Pattern.compile( "^[^<]*<row>([0-9A-Fa-f]*)</row>" );
557)     tag = Pattern.compile( "^[^<]*<[^>]*>" );
558) 
559)     //delete all frames
560)     deleteInfos( );
561)     deleteFrames( );
562)     resize( 0, 0, 0, 0 );
563) 
564)     //try to read from buffered reader
565)     try
566)     {
567)       //create unused dummy frame for beginning
568)       frame = new BlinkenFrame( 0, 0, 0, 0, 0 );
569)       y = 0;
570)       chrs = 1;
571) 
572)       //read
573)       data = "";
574)       blmTagFound = false;
575)       while( (line = reader.readLine( )) != null )
576)       {
577)         data += " " + line; //add new line to data
578) 
579)         //match tags
580)         while( true )
581)         {
582) 
583)           //no blm tag yet
584)           if( ! blmTagFound )
585)           {
586) 
587)             //blm tag
588)             if( (matcher = blmTag.matcher( data )).find( ) )
589)             {
590)               //remove matched part
591)               data = data.substring( matcher.end( ) );
592)               //get attributes
593)               new_width = 0;
594)               new_height = 0;
595)               new_channels = 1;
596)               bits = 4;
597)               new_maxval = 15;
598)               if( (submatcher = blmHeight.matcher( matcher.group( 1 ) )).find( ) ) //height
599)                 new_height = Integer.parseInt( submatcher.group( 1 ) );
600)               if( (submatcher = blmWidth.matcher( matcher.group( 1 ) )).find( ) ) //width
601)                 new_width = Integer.parseInt( submatcher.group( 1 ) );
602)               if( (submatcher = blmChannels.matcher( matcher.group( 1 ) )).find( ) ) //channels
603)                 new_channels = Integer.parseInt( submatcher.group( 1 ) );
604)               if( (submatcher = blmBits.matcher( matcher.group( 1 ) )).find( ) ) //bits
605)                 new_maxval = (1 << (bits = Integer.parseInt( submatcher.group( 1 ) ))) - 1;
606)               //remember that blm tag was found
607)               blmTagFound = true;
608)               //set movie size
609)               resize( new_height, new_width, new_channels, new_maxval );
610)               //get number of characters per channel
611)               chrs = (bits + 3) >> 2;
612)             }
613) 
614)             //unknown tag
615)             else if( (matcher = tag.matcher( data )).find( ) )
616)               //remove matched part
617)               data = data.substring( matcher.end( ) );
618) 
619)             //nothing matches
620)             else
621)               //end loop
622)               break;
623) 
624)           } //if( ! blmTagFound )
625) 
626)           //blm tag was already found
627)           else
628)           {
629) 
630)             //title tag
631)             if( (matcher = infoTitle.matcher( data )).find( ) )
632)             {
633)               //remove matched part
634)               data = data.substring( matcher.end( ) );
635)               //add info to movie
636)               appendInfo( "title", matcher.group( 1 ) );
637)             }
638) 
639)             //description tag
640)             else if( (matcher = infoDescription.matcher( data )).find( ) )
641)             {
642)               //remove matched part
643)               data = data.substring( matcher.end( ) );
644)               //check if generic info
645)               if( (submatcher = infoGeneric.matcher( matcher.group( 1 ) )).find( ) )
646)                 //add info to movie
647)                 appendInfo( submatcher.group( 1 ), submatcher.group( 2 ) );
648)               else
649)                 //add info to movie
650)                 appendInfo( "description", matcher.group( 1 ) );
651)             }
652) 
653)             //creator tag
654)             else if( (matcher = infoCreator.matcher( data )).find( ) )
655)             {
656)               //remove matched part
657)               data = data.substring( matcher.end( ) );
658)               //add info to movie
659)               appendInfo( "creator", matcher.group( 1 ) );
660)             }
661) 
662)             //author tag
663)             else if( (matcher = infoAuthor.matcher( data )).find( ) )
664)             {
665)               //remove matched part
666)               data = data.substring( matcher.end( ) );
667)               //add info to movie
668)               appendInfo( "author", matcher.group( 1 ) );
669)             }
670) 
671)             //email tag
672)             else if( (matcher = infoEmail.matcher( data )).find( ) )
673)             {
674)               //remove matched part
675)               data = data.substring( matcher.end( ) );
676)               //add info to movie
677)               appendInfo( "email", matcher.group( 1 ) );
678)             }
679) 
680)             //url tag
681)             else if( (matcher = infoUrl.matcher( data )).find( ) )
682)             {
683)               //remove matched part
684)               data = data.substring( matcher.end( ) );
685)               //add info to movie
686)               appendInfo( "url", matcher.group( 1 ) );
687)             }
688) 
689)             //frame tag
690)             else if( (matcher = frameTag.matcher( data )).find( ) )
691)             {
692)               //remove matched part
693)               data = data.substring( matcher.end( ) );
694)               //get attributes
695)               duration = 0;
696)               if( (submatcher = frameDuration.matcher( matcher.group( 1 ) )).find( ) ) //duration
697)                 duration = Integer.parseInt( submatcher.group( 1 ) );
698)               //create new frame and append it to movie
699)               frame = new BlinkenFrame( height, width, channels, maxval, duration );
700)               frame.clear( );
701)               appendFrame( frame );
702)               y = 0;
703)             }
704) 
705)             //row tag
706)             else if( (matcher = rowTag.matcher( data )).find( ) )
707)             {
708)               //remove matched part
709)               data = data.substring( matcher.end( ) );
710)               //parse row
711)               row = matcher.group( 1 );
712)               len = row.length( );
713)               i = 0;
714)               for( x = 0; x < this.width && i + chrs <= len; x++ )
715)               {
716)                 for( c = 0; c < this.channels && i + chrs <= len; c++, i += chrs )
717)                 {
718)                   val = Integer.parseInt( row.substring( i, i + chrs ), 0x10 );
719)                   frame.setPixel( y, x, c, (byte)val ); //set pixel
720)                 }
721)               }
722)               y++; //next row
723)             }
724) 
725)             //unknown tag
726)             else if( (matcher = tag.matcher( data )).find( ) )
727)               //remove matched part
728)               data = data.substring( matcher.end( ) );
729) 
730)             //nothing matches
731)             else
732)               //end loop
733)               break;
734) 
735)           } //if( ! blmTagFound ) ... else
736) 
737)         } //while( true )
738) 
739)       } //while( (line = ...
740) 
741)       //success
742)       return true;
743)     }
744)     catch( IOException e ) { }
745) 
746)     //some error
747)     return false;
748)   }
749) 
750)   public boolean loadBml( String filename )
751)   {
752)     try
753)     {
754)       BufferedReader file = new BufferedReader( new FileReader( filename ) );
755)       boolean ret = loadBml( file );
756)       file.close( );
757)       return ret;
758)     }
759)     catch( IOException e )
760)     {
761)       return false;
762)     }
763)   }
764) 
765)   public boolean loadBbm( String filename )
766)   {
767)     RandomAccessFile file;
768)     byte[] header, subHeader, infoHeader, frameStartMarker, frameData;
769)     int headerMagic, headerHeight, headerWidth, headerChannels, headerMaxval;
770)     int headerFrameCnt, headerDuration, headerFramePtr;
771)     int subHeaderMagic, subHeaderSize;
772)     int frameStartMarkerMagic;
773)     StringTokenizer tokenizer;
774)     String infoType, infoData;
775)     int fileLength, frameLength;
776)     int duration, i, y, x, c;
777)     BlinkenFrame frame;
778) 
779)     //delete all frames
780)     deleteInfos( );
781)     deleteFrames( );
782)     resize( 0, 0, 0, 0 );
783) 
784)     //try to read file
785)     try
786)     {
787)       //open file
788)       file = new RandomAccessFile( filename, "r" );
789) 
790)       //read header
791)       header = new byte[24];
792)       file.readFully( header );
793)       headerMagic = ((int)header[0] & 0xFF) << 24 | ((int)header[1] & 0xFF) << 16 | ((int)header[2] & 0xFF) << 8 | ((int)header[3] & 0xFF);
794)       headerHeight = ((int)header[4] & 0xFF) << 8 | ((int)header[5] & 0xFF);
795)       headerWidth = ((int)header[6] & 0xFF) << 8 | ((int)header[7] & 0xFF);
796)       headerChannels = ((int)header[8] & 0xFF) << 8 | ((int)header[9] & 0xFF);
797)       headerMaxval = ((int)header[10] & 0xFF) << 8 | ((int)header[11] & 0xFF);
798)       headerFrameCnt = ((int)header[12] & 0xFF) << 24 | ((int)header[13] & 0xFF) << 16 | ((int)header[14] & 0xFF) << 8 | ((int)header[15] & 0xFF);
799)       headerDuration = ((int)header[16] & 0xFF) << 24 | ((int)header[17] & 0xFF) << 16 | ((int)header[18] & 0xFF) << 8 | ((int)header[19] & 0xFF);
800)       headerFramePtr = ((int)header[20] & 0xFF) << 24 | ((int)header[21] & 0xFF) << 16 | ((int)header[22] & 0xFF) << 8 | ((int)header[23] & 0xFF);
801)       //check magic
802)       if( headerMagic == 0x23542666 )
803)       {
804) 
805)         //adapt movie format
806)         resize( headerHeight, headerWidth, headerChannels, headerMaxval );
807) 
808)         //read subheaders
809)         subHeader = new byte[6];
810)         while( file.getFilePointer( ) + 6 <= headerFramePtr )
811)         {
812)           file.readFully( subHeader );
813)           subHeaderMagic = ((int)subHeader[0] & 0xFF) << 24 | ((int)subHeader[1] & 0xFF) << 16 | ((int)subHeader[2] & 0xFF) << 8 | ((int)subHeader[3] & 0xFF);
814)           subHeaderSize = ((int)subHeader[4] & 0xFF) << 8 | ((int)subHeader[5] & 0xFF);
815) 
816)           //header fits into gap to frame start
817)           if( subHeaderSize >= 6 && file.getFilePointer( ) + subHeaderSize - 6 <= headerFramePtr )
818)           {
819)             //info header
820)             if( subHeaderMagic == 0x696E666F ) //'i' 'n' 'f' 'o'
821)             {
822)               //read rest of info header
823)               infoHeader = new byte[subHeaderSize - 6];
824)               file.readFully( infoHeader );
825)               //parse information
826)               tokenizer = new StringTokenizer( new String( infoHeader ), "\000" );
827)               if( tokenizer.countTokens( ) >= 2 )
828)               {
Stefan Schuermans unify white space

Stefan Schuermans authored 6 years ago

829)                 infoType = tokenizer.nextToken( );
830)                 infoData = tokenizer.nextToken( );
Christian Heimke BlinkenLibJava v.0.1.1 (200...

Christian Heimke authored 13 years ago

831)                 appendInfo( infoType, infoData );
832)               }
833)             }
834) 
835)             //unknown subHeader
836)             else
837)               //skip
838)               file.skipBytes( subHeaderSize - 6 );
839) 
840)           } //if( file.getFilePointer( ) ...
841)         } //while( file.getFilePointer( ) ...
842) 
843)         //seek to start of frames
844)         file.seek( headerFramePtr );
845) 
846)         //read frame start marker
847)         frameStartMarker = new byte[4];
848)         file.readFully( frameStartMarker );
849)         frameStartMarkerMagic = ((int)frameStartMarker[0] & 0xFF) << 24 | ((int)frameStartMarker[1] & 0xFF) << 16 | ((int)frameStartMarker[2] & 0xFF) << 8 | ((int)frameStartMarker[3] & 0xFF);
850)         if( frameStartMarkerMagic == 0x66726D73 ) //'f' 'r' 'm' 's'
851)         {
852) 
853)           //read frames
854)           fileLength = (int)file.length( );
855)           frameLength = 2 + headerHeight * headerWidth * headerChannels;
856)           frameData = new byte[frameLength];
857)           while( file.getFilePointer( ) + frameLength <= fileLength )
858)           {
859)             //read frame
860)             file.readFully( frameData );
861)             duration = ((int)frameData[0] & 0xFF) << 8 | ((int)frameData[1] & 0xFF);
862)             //build frame and append it to movie
863)             frame = new BlinkenFrame( height, width, channels, maxval, duration );
864)             i = 2;
865)             for( y = 0; y < headerHeight; y++ )
866)               for( x = 0; x < headerWidth; x++ )
867)                 for( c = 0; c < headerChannels; c++, i++ )
868)                   frame.setPixel( y, x, c, frameData[i] );
869)             appendFrame( frame );
870) 
871)           } //while( file.getFilePointer ...
872) 
873)         } //if( frameStartMarkerMagic ...
874) 
875)       } //if( headerMagic ...
876) 
877)       //close file
878)       file.close( );
879) 
880)       //success
881)       return true;
882)     }
883)     catch( IOException e ) { }
884) 
885)     //some error
886)     return false;
887)   }
888) 
Stefan Schuermans first version fo GIF read s...

Stefan Schuermans authored 6 years ago

889)   public boolean loadGif( String filename )
890)   {
891)     //delete all frames
892)     deleteInfos( );
893)     deleteFrames( );
894)     resize( 0, 0, 0, 0 );
895) 
896)     //try to read file
897)     try
898)     {
899)       //load file
900)       ImageReader reader = (ImageReader)ImageIO.getImageReadersByFormatName( "gif").next( );
901)       ImageInputStream inStrm = ImageIO.createImageInputStream( new File( filename ) );
902)       reader.setInput( inStrm, false );
903) 
904)       //get global metadata
905)       IIOMetadata meta = reader.getStreamMetadata( );
906)       Node tree = meta.getAsTree( "javax_imageio_gif_stream_1.0" );
907)       NodeList children = tree.getChildNodes( );
908) 
909)       //parse global metadata
910)       Color bgColor = Color.BLACK;
Stefan Schuermans unify white space

Stefan Schuermans authored 6 years ago

911)       for( int chi = 0; chi < children.getLength( ); ++chi )
Stefan Schuermans first version fo GIF read s...

Stefan Schuermans authored 6 years ago

912)       {
913)         Node child = children.item( chi );
914) 
915)         if( child.getNodeName( ).equals( "GlobalColorTable" ) )
916)         {
Stefan Schuermans unify white space

Stefan Schuermans authored 6 years ago

917)           NamedNodeMap attr = child.getAttributes( );
Stefan Schuermans first version fo GIF read s...

Stefan Schuermans authored 6 years ago

918)           Node bgIdxNode = attr.getNamedItem( "backgroundColorIndex" );
919)           if( bgIdxNode != null )
920)           {
921)             int bgIdx = Integer.valueOf( bgIdxNode.getNodeValue( ) );
922) 
923)             NodeList entries = child.getChildNodes( );
924)             for( int ent = 0; ent < entries.getLength( ); ++ent )
925)             {
926)               Node entry = entries.item( ent );
927)               if( entry.getNodeName( ).equals( "ColorTableEntry" ) )
928)               {
Stefan Schuermans unify white space

Stefan Schuermans authored 6 years ago

929)                 NamedNodeMap entryAttr = entry.getAttributes( );
Stefan Schuermans first version fo GIF read s...

Stefan Schuermans authored 6 years ago

930)                 int index = Integer.valueOf( entryAttr.getNamedItem(
931)                               "index" ).getNodeValue( ) );
932)                 if( index == bgIdx )
933)                 {
934)                   int red   = Integer.valueOf( entryAttr.getNamedItem(
935)                                 "red" ).getNodeValue( ) );
936)                   int green = Integer.valueOf( entryAttr.getNamedItem(
937)                                 "green" ).getNodeValue( ) );
938)                   int blue  = Integer.valueOf( entryAttr.getNamedItem(
939)                                 "blue" ).getNodeValue( ) );
940)                   bgColor = new Color(red, green, blue);
941)                   break;
942)                 } //if index
943)               } //if entry
944)             } //for ent
945)           } //if bgIdxNode
946)         } //if child
947)       } //for chi
948) 
949)       //iterate through all frames
950)       int frameCnt = reader.getNumImages( true );
951)       int movieWidth = 0;
952)       int movieHeight = 0;
953)       BufferedImage canvas = null, backup = null;
954)       for( int frame = 0; frame < frameCnt; ++frame )
955)       {
956)         //get image
957)         BufferedImage img = reader.read( frame );
958) 
959)         //get image metadata
960)         meta = reader.getImageMetadata( frame );
961)         tree = meta.getAsTree( "javax_imageio_gif_image_1.0" );
962)         children = tree.getChildNodes( );
963) 
964)         //parse metadata for this image
965)         int left = -1, top = -1, width = -1, height = -1;
966)         int duration = 100;
967)         boolean restoreToPrevious = false;
968)         boolean restoreToBackgroundColor = false;
969)         for( int chi = 0; chi < children.getLength( ); ++chi )
970)         {
971)           Node child = children.item( chi );
972) 
973)           if( child.getNodeName( ).equals( "ImageDescriptor" ) )
974)           {
Stefan Schuermans unify white space

Stefan Schuermans authored 6 years ago

975)             NamedNodeMap attr = child.getAttributes( );
Stefan Schuermans first version fo GIF read s...

Stefan Schuermans authored 6 years ago

976)             left   = Integer.valueOf( attr.getNamedItem(
977)                        "imageLeftPosition" ).getNodeValue( ) );
978)             top    = Integer.valueOf( attr.getNamedItem(
979)                        "imageTopPosition" ).getNodeValue( ) );
980)             width  = Integer.valueOf( attr.getNamedItem(
981)                        "imageWidth" ).getNodeValue( ) );
982)             height = Integer.valueOf( attr.getNamedItem(
983)                        "imageHeight" ).getNodeValue( ) );
984)           } //if ImageDescriptor
985)           if( child.getNodeName( ).equals( "GraphicControlExtension" ) )
986)           {
Stefan Schuermans unify white space

Stefan Schuermans authored 6 years ago

987)             NamedNodeMap attr = child.getAttributes( );
Stefan Schuermans first version fo GIF read s...

Stefan Schuermans authored 6 years ago

988)             Node disposalMethod = attr.getNamedItem( "disposalMethod" );
989)             if( disposalMethod != null )
990)             {
991)               String disposalMethodStr = disposalMethod.getNodeValue( );
992)               if( disposalMethodStr.equals( "restoreToPrevious" ) )
993)                 restoreToPrevious = true;
994)               else if( disposalMethodStr.equals( "restoreToBackgroundColor" ) )
995)                 restoreToBackgroundColor = true;
996)             }
997)             Node durationNode = attr.getNamedItem( "delayTime" );
998)             if( durationNode != null )
999)                duration = Integer.valueOf( durationNode.getNodeValue( ) ) * 10;
1000)           } //if GraphicControlExtension
1001)         } //for chi
1002) 
1003)         //no position -> ignore this frame
1004)         if (left < 0 || top < 0 || width < 0 || height < 0)
1005)           continue;
1006) 
1007)         //first frame determines movie size
1008)         if( canvas == null )
1009)         {
1010)           movieWidth = width;
1011)           movieHeight = height;
1012)           resize( movieHeight, movieWidth, 3, 255 );
1013)           canvas = new BufferedImage( movieWidth, movieHeight,
1014)                                       BufferedImage.TYPE_INT_ARGB );
1015)           backup = new BufferedImage( movieWidth, movieHeight,
1016)                                       BufferedImage.TYPE_INT_ARGB );
1017)         }
1018) 
1019)         // keep backup if needed
1020)         if( restoreToPrevious )
1021)         {
Stefan Schuermans unify white space

Stefan Schuermans authored 6 years ago

1022)           Graphics g = backup.getGraphics( );
1023)           g.drawImage( canvas, 0, 0, null );
1024)           g.dispose( );
Stefan Schuermans first version fo GIF read s...

Stefan Schuermans authored 6 years ago

1025)         }
1026) 
1027)         // draw new image to canvas
1028)         Graphics g = canvas.getGraphics( );
1029)         g.drawImage( img, left, top, null );
Stefan Schuermans unify white space

Stefan Schuermans authored 6 years ago

1030)         g.dispose( );
Stefan Schuermans first version fo GIF read s...

Stefan Schuermans authored 6 years ago

1031) 
1032)         // convert canvas to new frame and append to movie
1033)         BlinkenFrame newFrame = new BlinkenFrame( movieHeight, movieWidth,
1034)                                                   3, 255, duration );
1035)         for( int y = 0; y < movieHeight; y++ )
1036)           for( int x = 0; x < movieWidth; x++ )
1037)             newFrame.setColor( y, x, new Color( canvas.getRGB( x, y ) ) );
1038)         appendFrame( newFrame );
1039) 
1040)         // disposal of image on canvas
1041)         if( restoreToPrevious )
1042)         {
Stefan Schuermans unify white space

Stefan Schuermans authored 6 years ago

1043)           g = canvas.getGraphics( );
1044)           g.drawImage( backup, 0, 0, null );
1045)           g.dispose( );
Stefan Schuermans first version fo GIF read s...

Stefan Schuermans authored 6 years ago

1046)         }
1047)         if( restoreToBackgroundColor )
1048)         {
Stefan Schuermans unify white space

Stefan Schuermans authored 6 years ago

1049)           Graphics2D g2d = canvas.createGraphics( );
1050)           g2d.setColor( bgColor );
1051)           g2d.fill( new Rectangle( left, top, width, height ) );
1052)           g2d.dispose( );
Stefan Schuermans first version fo GIF read s...

Stefan Schuermans authored 6 years ago

1053)         }
1054) 
1055)       } //for frame
1056) 
1057)       //success
1058)       return true;
1059)     }
1060)     catch( IOException e ) { }
1061) 
1062)     //some error
1063)     return false;
1064)   }
1065) 
Christian Heimke BlinkenLibJava v.0.1.1 (200...

Christian Heimke authored 13 years ago

1066)   public boolean load( String filename )
1067)   {
1068)     if( filename.endsWith( ".blm" ) )
1069)       return loadBlm( filename );
1070)     if( filename.endsWith( ".bmm" ) )
1071)       return loadBmm( filename );
1072)     if( filename.endsWith( ".bml" ) )
1073)       return loadBml( filename );
1074)     if( filename.endsWith( ".bbm" ) )
1075)       return loadBbm( filename );
Stefan Schuermans first version fo GIF read s...

Stefan Schuermans authored 6 years ago

1076)     if( filename.endsWith( ".gif" ) )
1077)       return loadGif( filename );
Christian Heimke BlinkenLibJava v.0.1.1 (200...

Christian Heimke authored 13 years ago

1078)     deleteFrames( );
1079)     return false;
1080)   }
1081) 
1082)   public boolean saveBlm( BufferedWriter writer )
1083)   {
1084)     BlinkenMovie movie;
1085)     int cnt, i, y, x;
1086)     String line;
1087) 
1088)     //convert movie to suitable format
1089)     movie = new BlinkenMovie( this );
1090)     movie.resize( movie.height, movie.width, 1, 1 );
1091) 
1092)     try
1093)     {
1094)       //write header line
1095)       writer.write( "# BlinkenLights Movie " + movie.width + "x" + movie.height + "\n" );
1096) 
1097)       //write information lines
1098)       cnt = movie.getInfoCnt( );
1099)       for( i = 0; i < cnt; i++ )
1100)         writer.write( "# " + movie.getInfoType( i ) + " = " + movie.getInfoData( i ) + "\n" );
1101) 
1102)       //write frames
1103)       cnt = movie.getFrameCnt( );
1104)       for( i = 0; i < cnt; i++ )
1105)       {
1106)         writer.write( "\n@" + movie.frames[i].getDuration( ) + "\n" );
1107)         for( y = 0; y < movie.height; y++ )
1108)         {
1109)           line = "";
1110)           for( x = 0; x < movie.width; x++ )
1111)           {
1112)             if( movie.frames[i].getPixel( y, x, 0 ) != 0 )
1113)               line = line + "1";
1114)             else
1115)               line = line + "0";
1116)           }
1117)           writer.write( line + "\n" );
1118)         }
1119)       }
1120) 
1121)       //success
1122)       return true;
1123)     }
1124)     catch( IOException e ) { }
1125) 
1126)     //some error
1127)     return false;
1128)   }
1129) 
1130)   public boolean saveBlm( String filename )
1131)   {
1132)     try
1133)     {
1134)       BufferedWriter file = new BufferedWriter( new FileWriter( filename ) );
1135)       boolean ret = saveBlm( file );
1136)       file.close( );
1137)       return ret;
1138)     }
1139)     catch( IOException e )
1140)     {
1141)       return false;
1142)     }
1143)   }
1144) 
1145)   public boolean saveBmm( BufferedWriter writer )
1146)   {
1147)     BlinkenMovie movie;
1148)     int cnt, i, y, x, val;
1149)     String line;
1150) 
1151)     //convert movie to suitable format
1152)     movie = new BlinkenMovie( this );
1153)     movie.resize( movie.height, movie.width, 1, 255 );
1154) 
1155)     try
1156)     {
1157)       //write header line
1158)       writer.write( "# BlinkenMini Movie " + movie.width + "x" + movie.height + "\n" );
1159) 
1160)       //write information lines
1161)       cnt = movie.getInfoCnt( );
1162)       for( i = 0; i < cnt; i++ )
1163)         writer.write( "# " + movie.getInfoType( i ) + " = " + movie.getInfoData( i ) + "\n" );
1164) 
1165)       //write frames
1166)       cnt = movie.getFrameCnt( );
1167)       for( i = 0; i < cnt; i++ )
1168)       {
1169)         writer.write( "\n@" + movie.frames[i].getDuration( ) + "\n" );
1170)         for( y = 0; y < movie.height; y++ )
1171)         {
1172)           line = "";
1173)           for( x = 0; x < movie.width; x++ )
1174)           {
1175)             val = (int)movie.frames[i].getPixel( y, x, 0 ) & 0xFF;
1176)             if( val < 0x10 )
1177)               line = line + " 0x0" + Integer.toHexString( val ).toUpperCase( );
1178)             else
1179)               line = line + " 0x" + Integer.toHexString( val ).toUpperCase( );
1180)           }
1181)           writer.write( line.substring( 1 ) + "\n" );
1182)         }
1183)       }
1184) 
1185)       //success
1186)       return true;
1187)     }
1188)     catch( IOException e ) { }
1189) 
1190)     //some error
1191)     return false;
1192)   }
1193) 
1194)   public boolean saveBmm( String filename )
1195)   {
1196)     try
1197)     {
1198)       BufferedWriter file = new BufferedWriter( new FileWriter( filename ) );
1199)       boolean ret = saveBmm( file );
1200)       file.close( );
1201)       return ret;
1202)     }
1203)     catch( IOException e )
1204)     {
1205)       return false;
1206)     }
1207)   }
1208) 
1209)   public boolean saveBml( BufferedWriter writer )
1210)   {
1211)     BlinkenMovie movie;
1212)     int bits, cnt, i, y, x, c, val;
1213)     String infoType, infoData, line;
1214) 
1215)     //convert movie to suitable format
1216)     movie = new BlinkenMovie( this );
1217)     val = movie.maxval; //get number of bits
1218)     for( bits = 0; val != 0; val >>= 1, bits++ );
1219)     movie.resize( movie.height, movie.width, movie.channels, (1 << bits) - 1 );
1220) 
1221)     try
1222)     {
1223)       //write header line
1224)       writer.write( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" );
1225) 
1226)       //write blm start tag
1227)       writer.write( "<blm width=\"" + movie.width + "\" height=\"" + movie.height
1228)                   + "\" bits=\"" + bits + "\" channels=\"" + movie.channels + "\">\n" );
1229) 
1230)       //write information lines
1231)       writer.write( "\t<header>\n" );
1232)       cnt = movie.getInfoCnt( );
1233)       for( i = 0; i < cnt; i++ )
1234)       {
1235)         infoType = movie.getInfoType( i );
1236)         infoData = movie.getInfoData( i );
1237)         if( infoType.equals( "title" ) )
1238)           writer.write( "\t\t<title>" + infoData + "</title>\n" );
1239)         else if( infoType.equals( "description" ) )
1240)           writer.write( "\t\t<description>" + infoData + "</description>\n" );
1241)         else if( infoType.equals( "creator" ) )
1242)           writer.write( "\t\t<creator>" + infoData + "</creator>\n" );
1243)         else if( infoType.equals( "author" ) )
1244)           writer.write( "\t\t<author>" + infoData + "</author>\n" );
1245)         else if( infoType.equals( "email" ) )
1246)           writer.write( "\t\t<email>" + infoData + "</email>\n" );
1247)         else if( infoType.equals( "url" ) )
1248)           writer.write( "\t\t<url>" + infoData + "</url>\n" );
1249)         else
1250)           writer.write( "\t\t<description>" + infoType + ": " + infoData + "</description>\n" );
1251)       }
1252)       writer.write( "\t</header>\n" );
1253) 
1254)       //write frames
1255)       cnt = movie.getFrameCnt( );
1256)       for( i = 0; i < cnt; i++ )
1257)       {
1258)         writer.write( "\n\t<frame duration=\"" + movie.frames[i].getDuration( ) + "\">\n" );
1259)         for( y = 0; y < movie.height; y++ )
1260)         {
1261)           line = "";
1262)           for( x = 0; x < movie.width; x++ )
1263)           {
1264)             for( c = 0; c < movie.channels; c++ )
1265)             {
1266)               val = (int)movie.frames[i].getPixel( y, x, c ) & 0xFF;
1267)               if( bits > 4 && val < 0x10 )
1268)                 line = line + "0" + Integer.toHexString( val ).toUpperCase( );
1269)               else
1270)                 line = line + Integer.toHexString( val ).toUpperCase( );
1271)             }
1272)           }
1273)           writer.write( "\t\t<row>" + line + "</row>\n" );
1274)         }
1275)         writer.write( "\t</frame>\n" );
1276)       }
1277) 
1278)       //write blm end tag
1279)       writer.write( "</blm>\n" );
1280) 
1281)       //success
1282)       return true;
1283)     }
1284)     catch( IOException e ) { }
1285) 
1286)     //some error
1287)     return false;
1288)   }
1289) 
1290)   public boolean saveBml( String filename )
1291)   {
1292)     try
1293)     {
1294)       BufferedWriter file = new BufferedWriter( new FileWriter( filename ) );
1295)       boolean ret = saveBml( file );
1296)       file.close( );
1297)       return ret;
1298)     }
1299)     catch( IOException e )
1300)     {
1301)       return false;
1302)     }
1303)   }
1304) 
1305)   public boolean saveBbm( String filename )
1306)   {
1307)     RandomAccessFile file;
1308)     byte[] header, infoHeader, framePointer, frameStartMarker, frameData;
1309)     int cnt, duration, i, j, len, y, x, c, val;
1310)     String infoType, infoData, line;
1311) 
1312)     try
1313)     {
1314)       //open file
1315)       file = new RandomAccessFile( filename, "rw" );
1316) 
Christian Heimke BlinkenLibJava v.0.1.3 (200...

Christian Heimke authored 13 years ago

1317)       //truncate file
Stefan Schuermans whitespace fix

Stefan Schuermans authored 6 years ago

1318)       file.setLength( 0 );
Christian Heimke BlinkenLibJava v.0.1.3 (200...

Christian Heimke authored 13 years ago

1319) 
Christian Heimke BlinkenLibJava v.0.1.1 (200...

Christian Heimke authored 13 years ago

1320)       //write header
1321)       header = new byte[24];
1322)       header[0] = 0x23; //magic
1323)       header[1] = 0x54;
1324)       header[2] = 0x26;
1325)       header[3] = 0x66;
1326)       header[4] = (byte)(this.height >> 8);
1327)       header[5] = (byte)this.height;
1328)       header[6] = (byte)(this.width >> 8);
1329)       header[7] = (byte)this.width;
1330)       header[8] = (byte)(this.channels >> 8);
1331)       header[9] = (byte)this.channels;
1332)       header[10] = (byte)(this.maxval >> 8);
1333)       header[11] = (byte)this.maxval;
1334)       cnt = this.getFrameCnt( );
1335)       header[12] = (byte)(cnt >> 24);
1336)       header[13] = (byte)(cnt >> 16);
1337)       header[14] = (byte)(cnt >> 8);
1338)       header[15] = (byte)cnt;
1339)       duration = 0;
1340)       for( i = 0; i < cnt; i++ )
1341)         duration += this.frames[i].getDuration( ); 
1342)       header[16] = (byte)(duration >> 24);
1343)       header[17] = (byte)(duration >> 16);
1344)       header[18] = (byte)(duration >> 8);
1345)       header[19] = (byte)duration;
1346)       header[20] = 0; //frame pointer is written later
1347)       header[21] = 0;
1348)       header[22] = 0;
1349)       header[23] = 0;
1350)       file.write( header );
1351) 
1352)       //write information
1353)       cnt = this.getInfoCnt( );
1354)       for( i = 0; i < cnt; i++ )
1355)       {
1356)         infoType = this.getInfoType( i );
1357)         if( infoType.length( ) > 32760 )
1358)           infoType = infoType.substring( 0, 32760 );
1359)         infoData = this.getInfoData( i );
1360)         if( infoData.length( ) > 32760 )
1361)           infoData = infoData.substring( 0, 32760 );
1362)         len = 8 + infoType.length( ) + infoData.length( );
1363)         infoHeader = new byte[6];
1364)         infoHeader[0] = 0x69; //'i'
1365)         infoHeader[1] = 0x6E; //'n'
1366)         infoHeader[2] = 0x66; //'f'
1367)         infoHeader[3] = 0x6F; //'o'
1368)         infoHeader[4] = (byte)(len >> 8);
1369)         infoHeader[5] = (byte)len;
1370)         file.write( infoHeader );
1371)         file.write( (infoType + "\000" + infoData + "\000").getBytes( ) );
1372)       }
1373) 
1374)       //write frame pointer
1375)       framePointer = new byte[4];
1376)       val = (int)file.getFilePointer( );
1377)       framePointer[0] = (byte)(val >> 24);
1378)       framePointer[1] = (byte)(val >> 16);
1379)       framePointer[2] = (byte)(val >> 8);
1380)       framePointer[3] = (byte)val;
1381)       file.seek( 20 );
1382)       file.write( framePointer );
1383)       file.seek( val );
1384) 
1385)       //write frame start marker
1386)       frameStartMarker = new byte[4];
1387)       frameStartMarker[0] = 0x66; //'f'
1388)       frameStartMarker[1] = 0x72; //'r'
1389)       frameStartMarker[2] = 0x6D; //'m'
1390)       frameStartMarker[3] = 0x73; //'s'
1391)       file.write( frameStartMarker );
1392) 
1393)       //write frames
1394)       len = 2 + this.height * this.width * this.channels;
1395)       frameData = new byte[len];
1396)       cnt = this.getFrameCnt( );
1397)       for( i = 0; i < cnt; i++ )
1398)       {
1399)         val = this.frames[i].getDuration( );
1400)         frameData[0] = (byte)(val >> 8);
1401)         frameData[1] = (byte)val;
1402)         for( j = 2, y = 0; y < this.height; y++ )
1403)           for( x = 0; x < this.width; x++ )
1404)             for( c = 0; c < this.channels; c++, j++ )
1405)               frameData[j] = this.frames[i].getPixel( y, x, c );
1406)         file.write( frameData );
1407)       }
1408) 
1409)       //close file
1410)       file.close( );
1411) 
1412)       //success
1413)       return true;
1414)     }
1415)     catch( IOException e ) { }
1416) 
1417)     //some error
1418)     return false;
1419)   }
1420) 
Stefan Schuermans first version of GIF write...

Stefan Schuermans authored 6 years ago

1421)   public boolean saveGif( String filename )
1422)   {
1423)     try {
1424) 
1425)       //create GIF writer
1426)       ImageWriter gifWr = null;
1427)       {
1428)         Iterator<ImageWriter> it = ImageIO.getImageWritersBySuffix( "gif" );
1429)         if ( ! it.hasNext( ) ) {
1430)           return false;
1431)         }
Stefan Schuermans unify white space

Stefan Schuermans authored 6 years ago

1432)         gifWr = it.next( );
Stefan Schuermans first version of GIF write...

Stefan Schuermans authored 6 years ago

1433)       }
1434) 
1435)       //begin writing image
1436)       ImageOutputStream out = new FileImageOutputStream( new File( filename ) );
1437)       gifWr.setOutput( out );
1438)       gifWr.prepareWriteSequence( null );
1439) 
1440)       //create buffered image with correct dimensions
1441)       BufferedImage img = new BufferedImage( this.width, this.height,
1442)                                              BufferedImage.TYPE_INT_ARGB );
1443) 
1444)       //process all frames
1445)       int cnt = this.getFrameCnt( );
1446)       for( int i = 0; i < cnt; i++ )
1447)       {
1448) 
1449)         //frame data into buffered image
1450)         for( int y = 0; y < this.height; y++ )
1451)           for( int x = 0; x < this.width; x++ )
1452)             img.setRGB( x, y, this.frames[i].getColor( y, x ).getRGB( ) );
1453) 
1454)         //get frame duration
1455)         int duration = this.frames[i].getDuration( );
1456) 
1457)         //construct metadata
1458)         ImageWriteParam prm = gifWr.getDefaultWriteParam( );
1459)         ImageTypeSpecifier typeSpec = ImageTypeSpecifier.createFromBufferedImageType( img.getType( ) );
1460)         IIOMetadata meta = gifWr.getDefaultImageMetadata( typeSpec, prm );
1461)         String metaFmt = meta.getNativeMetadataFormatName( );
1462)         IIOMetadataNode metaRoot = (IIOMetadataNode)meta.getAsTree( metaFmt );
1463)         String nameGCE = "GraphicControlExtension";
1464)         IIOMetadataNode metaGCE = null;
Stefan Schuermans unify white space

Stefan Schuermans authored 6 years ago

1465)         for( int n = 0; n < metaRoot.getLength( ); n++ ) {
Stefan Schuermans first version of GIF write...

Stefan Schuermans authored 6 years ago

1466)           Node node = metaRoot.item(n);
Stefan Schuermans unify white space

Stefan Schuermans authored 6 years ago

1467)           if( node.getNodeName( ).compareToIgnoreCase( nameGCE ) == 0 ) {
Stefan Schuermans first version of GIF write...

Stefan Schuermans authored 6 years ago

1468)             metaGCE = (IIOMetadataNode)node;
1469)           }
1470)         }
1471)         if( metaGCE == null ) {
1472)           metaGCE = new IIOMetadataNode( nameGCE );
1473)           metaRoot.appendChild( metaGCE );
1474)         }
1475)         metaGCE.setAttribute( "disposalMethod", "doNotDispose" );
1476)         metaGCE.setAttribute( "transparentColorFlag", "FALSE" );
1477)         metaGCE.setAttribute( "transparentColorIndex", "0" );
1478)         metaGCE.setAttribute( "delayTime", Integer.toString( (duration + 5) / 10 ) );
1479)         metaGCE.setAttribute( "userInputFlag", "FALSE" );
1480)         meta.setFromTree( metaFmt, metaRoot );
1481) 
1482)         //write image
1483)         gifWr.writeToSequence( new IIOImage( img, null, meta ), prm );
1484) 
1485)       }
1486) 
1487)       //finalize image
1488)       gifWr.endWriteSequence( );
1489)       out.close( );
1490) 
1491)       return true;
1492)     }
1493)     catch( IOException e ) { }
1494) 
1495)     return false;
1496)   }
1497) 
Christian Heimke BlinkenLibJava v.0.1.1 (200...

Christian Heimke authored 13 years ago

1498)   public boolean save( String filename )
1499)   {
1500)     if( filename.endsWith( ".blm" ) )
1501)       return saveBlm( filename );
1502)     if( filename.endsWith( ".bmm" ) )
1503)       return saveBmm( filename );
1504)     if( filename.endsWith( ".bml" ) )
1505)       return saveBml( filename );
1506)     if( filename.endsWith( ".bbm" ) )
1507)       return saveBbm( filename );
Stefan Schuermans first version of GIF write...

Stefan Schuermans authored 6 years ago

1508)     if( filename.endsWith( ".gif" ) )
1509)       return saveGif( filename );