BlinkenArea - GitList
Repositories
Blog
Wiki
BlinkenLibJava
Code
Commits
Branches
Tags
Search
Tree:
ed4753b
Branches
Tags
master
v0.1.1
v0.1.2
v0.1.3
v0.1.4
v0.1.5
BlinkenLibJava
org
blinkenarea
BlinkenLib
BlinkenMovie.java
BlinkenLibJava v.0.1.3 (2008-09-29)
Christian Heimke
commited
ed4753b
at 2011-07-15 08:56:26
BlinkenMovie.java
Blame
History
Raw
/* BlinkenLib * version 0.1.3 date 2008-09-29 * Copyright (C) 2004-2008: Stefan Schuermans <1stein@schuermans.info> * Copyleft: GNU public license - http://www.gnu.org/copyleft/gpl.html * a blinkenarea.org project */ package org.blinkenarea.BlinkenLib; import java.util.*; import java.util.regex.*; import java.io.*; import org.blinkenarea.BlinkenLib.*; public class BlinkenMovie { private int height; private int width; private int channels; private int maxval; private int infoCnt; private String[][] infos; private int frameCnt; private BlinkenFrame[] frames; public BlinkenMovie( int height, int width, int channels, int maxval ) { if( height < BlinkenConstants.BlinkenHeightMin ) height = BlinkenConstants.BlinkenHeightMin; if( height > BlinkenConstants.BlinkenHeightMax ) height = BlinkenConstants.BlinkenHeightMax; if( width < BlinkenConstants.BlinkenWidthMin ) width = BlinkenConstants.BlinkenWidthMin; if( width > BlinkenConstants.BlinkenWidthMax ) width = BlinkenConstants.BlinkenWidthMax; if( channels < BlinkenConstants.BlinkenChannelsMin ) channels = BlinkenConstants.BlinkenChannelsMin; if( channels > BlinkenConstants.BlinkenChannelsMax ) channels = BlinkenConstants.BlinkenChannelsMax; if( maxval < BlinkenConstants.BlinkenMaxvalMin ) maxval = BlinkenConstants.BlinkenMaxvalMin; if( maxval > BlinkenConstants.BlinkenMaxvalMax ) maxval = BlinkenConstants.BlinkenMaxvalMax; this.height = height; this.width = width; this.channels = channels; this.maxval = maxval; infoCnt = 0; infos = new String[0][2]; frameCnt = 0; frames = new BlinkenFrame[0]; } public BlinkenMovie( BlinkenMovie movie ) { int i; height = movie.height; width = movie.width; channels = movie.channels; maxval = movie.maxval; infoCnt = 0; infos = new String[0][2]; frameCnt = 0; frames = new BlinkenFrame[0]; for( i = 0; i < movie.infoCnt; i++ ) appendInfo( new String( movie.infos[i][0] ), new String( movie.infos[i][1] ) ); for( i = 0; i < movie.frameCnt; i++ ) appendFrame( new BlinkenFrame( movie.frames[i] ) ); } public int getHeight( ) { return height; } public int getWidth( ) { return width; } public int getChannels( ) { return channels; } public int getMaxval( ) { return maxval; } public int getDuration( ) { int duration, i; duration = 0; for( i = 0; i < frameCnt; i++ ) duration += frames[i].getDuration( ); return duration; } public int getInfoCnt( ) { return infoCnt; } public String getInfoType( int infoNo ) { if( infoCnt < 1 ) return ""; if( infoNo < 0 ) infoNo = 0; if( infoNo >= infoCnt ) infoNo = infoCnt - 1; return infos[infoNo][0]; } public String getInfoData( int infoNo ) { if( infoCnt < 1 ) return ""; if( infoNo < 0 ) infoNo = 0; if( infoNo >= infoCnt ) infoNo = infoCnt - 1; return infos[infoNo][1]; } public void setInfo( int infoNo, String infoType, String infoData ) { if( infoNo < 0 || infoNo >= infoCnt ) return; infos[infoNo][0] = infoType; infos[infoNo][1] = infoData; } public void insertInfo( int infoNo, String infoType, String infoData ) { String[][] new_infos; int i; if( infoNo < 0 || infoNo > infoCnt ) return; new_infos = new String[infoCnt+1][2]; for( i = 0; i < infoNo; i++ ) { new_infos[i][0] = infos[i][0]; new_infos[i][1] = infos[i][1]; } new_infos[infoNo][0] = infoType; new_infos[infoNo][1] = infoData; for( i = infoNo; i < infoCnt; i++ ) { new_infos[i+1][0] = infos[i][0]; new_infos[i+1][1] = infos[i][1]; } infos = new_infos; infoCnt++; } public void appendInfo( String infoType, String infoData ) { insertInfo( infoCnt, infoType, infoData ); } public void deleteInfo( int infoNo ) { String[][] new_infos; int i; if( infoNo < 0 || infoNo >= infoCnt ) return; new_infos = new String[infoCnt-1][2]; for( i = 0; i < infoNo; i++ ) { new_infos[i][0] = infos[i][0]; new_infos[i][1] = infos[i][1]; } for( i = infoNo; i < infoCnt-1; i++ ) { new_infos[i][0] = infos[i+1][0]; new_infos[i][1] = infos[i+1][1]; } infos = new_infos; infoCnt--; } public void deleteInfos( ) { infos = new String[0][2]; infoCnt = 0; } public int getFrameCnt( ) { return frameCnt; } public BlinkenFrame getFrame( int frameNo ) { BlinkenFrame frame; if( frameCnt < 1 ) { frame = new BlinkenFrame( height, width, channels, maxval, 0 ); frame.clear( ); return frame; } if( frameNo < 0 ) frameNo = 0; if( frameNo >= frameCnt ) frameNo = frameCnt - 1; return frames[frameNo]; } public void setFrame( int frameNo, BlinkenFrame frame ) { if( frameNo < 0 || frameNo >= frameCnt ) return; frame.resize( height, width, channels, maxval ); frames[frameNo] = frame; } public void insertFrame( int frameNo, BlinkenFrame frame ) { BlinkenFrame[] new_frames; int i; if( frameNo < 0 || frameNo > frameCnt ) return; new_frames = new BlinkenFrame[frameCnt+1]; for( i = 0; i < frameNo; i++ ) new_frames[i] = frames[i]; frame.resize( height, width, channels, maxval ); new_frames[frameNo] = frame; for( i = frameNo; i < frameCnt; i++ ) new_frames[i+1] = frames[i]; frames = new_frames; frameCnt++; } public void appendFrame( BlinkenFrame frame ) { insertFrame( frameCnt, frame ); } public void deleteFrame( int frameNo ) { BlinkenFrame[] new_frames; int i; if( frameNo < 0 || frameNo >= frameCnt ) return; new_frames = new BlinkenFrame[frameCnt-1]; for( i = 0; i < frameNo; i++ ) new_frames[i] = frames[i]; for( i = frameNo; i < frameCnt-1; i++ ) new_frames[i] = frames[i+1]; frames = new_frames; frameCnt--; } public void deleteFrames( ) { frames = new BlinkenFrame[0]; frameCnt = 0; } public void resize( int height, int width, int channels, int maxval ) { int i; if( height < BlinkenConstants.BlinkenHeightMin ) height = BlinkenConstants.BlinkenHeightMin; if( height > BlinkenConstants.BlinkenHeightMax ) height = BlinkenConstants.BlinkenHeightMax; if( width < BlinkenConstants.BlinkenWidthMin ) width = BlinkenConstants.BlinkenWidthMin; if( width > BlinkenConstants.BlinkenWidthMax ) width = BlinkenConstants.BlinkenWidthMax; if( channels < BlinkenConstants.BlinkenChannelsMin ) channels = BlinkenConstants.BlinkenChannelsMin; if( channels > BlinkenConstants.BlinkenChannelsMax ) channels = BlinkenConstants.BlinkenChannelsMax; if( maxval < BlinkenConstants.BlinkenMaxvalMin ) maxval = BlinkenConstants.BlinkenMaxvalMin; if( maxval > BlinkenConstants.BlinkenMaxvalMax ) maxval = BlinkenConstants.BlinkenMaxvalMax; this.height = height; this.width = width; this.channels = channels; this.maxval = maxval; for( i = 0; i < frameCnt; i++ ) frames[i].resize( height, width, channels, maxval ); } public void scale( int height, int width ) { int i; if( height < BlinkenConstants.BlinkenHeightMin ) height = BlinkenConstants.BlinkenHeightMin; if( height > BlinkenConstants.BlinkenHeightMax ) height = BlinkenConstants.BlinkenHeightMax; if( width < BlinkenConstants.BlinkenWidthMin ) width = BlinkenConstants.BlinkenWidthMin; if( width > BlinkenConstants.BlinkenWidthMax ) width = BlinkenConstants.BlinkenWidthMax; this.height = height; this.width = width; for( i = 0; i < frameCnt; i++ ) frames[i].scale( height, width ); } public String toString( ) { String str = "BlinkenMovie " + width + "x" + height + "-" + channels + "/" + (maxval + 1) + "\n"; int i; for( i = 0; i < infoCnt; i++ ) str += infos[i][0] + " = " + infos[i][1] + "\n"; for( i = 0; i < frameCnt; i++ ) str += "frame " + i + "\n" + frames[i].toString( ); return str; } public boolean loadBlm( BufferedReader reader ) { Pattern header, infoLine, startOfFrame, dataLine; String line, pixel; Matcher matcher; int new_width, new_height, new_duration, y, x, val; BlinkenFrame frame; //initialize needed regexp patterns header = Pattern.compile( "^ *# BlinkenLights Movie ([0-9]+)x([0-9]+)" ); infoLine = Pattern.compile( "^ *# ?([A-Za-z0-9]+)(?: *= *|: *)(.*)" ); startOfFrame = Pattern.compile( "^ *@([0-9]+)" ); dataLine = Pattern.compile( " *([01])" ); //delete all frames deleteInfos( ); deleteFrames( ); resize( 0, 0, 0, 0 ); //try to read from buffered reader try { //read magic and size if( (line = reader.readLine( )) != null ) { if( (matcher = header.matcher( line )).find( ) ) { new_width = Integer.parseInt( matcher.group( 1 ) ); new_height = Integer.parseInt( matcher.group( 2 ) ); resize( new_height, new_width, 1, 1 ); //create unused dummy frame for beginning frame = new BlinkenFrame( height, width, 1, 1, 0 ); y = 0; //read frames while( (line = reader.readLine( )) != null ) { //info line if( (matcher = infoLine.matcher( line )).find( ) ) { appendInfo( matcher.group( 1 ), matcher.group( 2 ) ); } //start of frame else if( (matcher = startOfFrame.matcher( line )).find( ) ) { new_duration = Integer.parseInt( matcher.group( 1 ) ); //create new frame and append it to movie frame = new BlinkenFrame( height, width, 1, 1, new_duration ); frame.clear( ); appendFrame( frame ); y = 0; } //data line else if( (matcher = dataLine.matcher( line )).find( ) ) { x = 0; while( true ) { pixel = matcher.group( 1 ); val = Integer.parseInt( pixel ); frame.setPixel( y, x, 0, (byte)val ); //set pixel if( ! matcher.find( ) ) //get next pixel break; x++; //next pixel } y++; //next row } } //while( (line = ... } //if( matcher = header..matcher( ... } //if( (line = ... //success return true; } catch( IOException e ) { } //some error return false; } public boolean loadBlm( String filename ) { try { BufferedReader file = new BufferedReader( new FileReader( filename ) ); boolean ret = loadBlm( file ); file.close( ); return ret; } catch( IOException e ) { return false; } } public boolean loadBmm( BufferedReader reader ) { Pattern header, infoLine, startOfFrame, dataLine; String line, pixel; Matcher matcher; int new_width, new_height, new_duration, y, x, val; BlinkenFrame frame; //initialize needed regexp patterns header = Pattern.compile( "^ *# BlinkenMini Movie ([0-9]+)x([0-9]+)" ); infoLine = Pattern.compile( "^ *# ?([A-Za-z0-9]+)(?: *= *|: *)(.*)" ); startOfFrame = Pattern.compile( "^ *@([0-9]+)" ); dataLine = Pattern.compile( " *(0x[0-9A-Fa-f]+|[0-9]+)" ); //delete all frames deleteInfos( ); deleteFrames( ); resize( 0, 0, 0, 0 ); //try to read from buffered reader try { //read magic and size if( (line = reader.readLine( )) != null ) { if( (matcher = header.matcher( line )).find( ) ) { new_width = Integer.parseInt( matcher.group( 1 ) ); new_height = Integer.parseInt( matcher.group( 2 ) ); resize( new_height, new_width, 1, 255 ); //create unused dummy frame for beginning frame = new BlinkenFrame( height, width, 1, 255, 0 ); y = 0; //read frames while( (line = reader.readLine( )) != null ) { //info line if( (matcher = infoLine.matcher( line )).find( ) ) { appendInfo( matcher.group( 1 ), matcher.group( 2 ) ); } //start of frame else if( (matcher = startOfFrame.matcher( line )).find( ) ) { new_duration = Integer.parseInt( matcher.group( 1 ) ); //create new frame and append it to movie frame = new BlinkenFrame( height, width, 1, 255, new_duration ); frame.clear( ); appendFrame( frame ); y = 0; } //data line else if( (matcher = dataLine.matcher( line )).find( ) ) { x = 0; while( true ) { pixel = matcher.group( 1 ); if( pixel.length( ) >= 2 && pixel.substring( 0, 2 ).equals( "0x" ) ) val = Integer.parseInt( pixel.substring( 2 ), 0x10 ); else val = Integer.parseInt( pixel ); frame.setPixel( y, x, 0, (byte)val ); //set pixel if( ! matcher.find( ) ) //get next pixel break; x++; //next pixel } y++; //next row } } //while( (line = ... } //if( matcher = header..matcher( ... } //if( (line = ... //success return true; } catch( IOException e ) { } //some error return false; } public boolean loadBmm( String filename ) { try { BufferedReader file = new BufferedReader( new FileReader( filename ) ); boolean ret = loadBmm( file ); file.close( ); return ret; } catch( IOException e ) { return false; } } public boolean loadBml( BufferedReader reader ) { Pattern blmTag, blmHeight, blmWidth, blmChannels, blmBits; Pattern infoTitle, infoDescription, infoGeneric, infoCreator, infoAuthor, infoEmail, infoUrl; Pattern frameTag, frameDuration, rowTag, tag; String line, data, row; boolean blmTagFound; Matcher matcher, submatcher; int new_height, new_width, new_channels, bits, new_maxval, chrs, duration, y, x, c, len, i, val; BlinkenFrame frame; //initialize needed regexp patterns blmTag = Pattern.compile( "^[^<]*<blm([^>]*)>" ); blmHeight = Pattern.compile( "height=\"?([0-9]*)\"?" ); blmWidth = Pattern.compile( "width=\"?([0-9]*)\"?" ); blmChannels = Pattern.compile( "channels=\"?([0-9]*)\"?" ); blmBits = Pattern.compile( "bits=\"?([0-9]*)\"?" ); infoTitle = Pattern.compile( "^[^<]*<title>([^<]*)</title>" ); infoDescription = Pattern.compile( "[^<]*<description>([^<]*)</description>" ); infoGeneric = Pattern.compile( "^([A-Za-z0-9]+)(?: *= *|: *)(.*)" ); infoCreator = Pattern.compile( "^[^<]*<creator>([^<]*)</creator>" ); infoAuthor = Pattern.compile( "^[^<]*<author>([^<]*)</author>" ); infoEmail = Pattern.compile( "^[^<]*<email>([^<]*)</email>" ); infoUrl = Pattern.compile( "^[^<]*<url>([^<]*)</url>" ); frameTag = Pattern.compile( "^[^<]*<frame([^>]*)>" ); frameDuration = Pattern.compile( "duration=\"?([0-9]*)\"?" ); rowTag = Pattern.compile( "^[^<]*<row>([0-9A-Fa-f]*)</row>" ); tag = Pattern.compile( "^[^<]*<[^>]*>" ); //delete all frames deleteInfos( ); deleteFrames( ); resize( 0, 0, 0, 0 ); //try to read from buffered reader try { //create unused dummy frame for beginning frame = new BlinkenFrame( 0, 0, 0, 0, 0 ); y = 0; chrs = 1; //read data = ""; blmTagFound = false; while( (line = reader.readLine( )) != null ) { data += " " + line; //add new line to data //match tags while( true ) { //no blm tag yet if( ! blmTagFound ) { //blm tag if( (matcher = blmTag.matcher( data )).find( ) ) { //remove matched part data = data.substring( matcher.end( ) ); //get attributes new_width = 0; new_height = 0; new_channels = 1; bits = 4; new_maxval = 15; if( (submatcher = blmHeight.matcher( matcher.group( 1 ) )).find( ) ) //height new_height = Integer.parseInt( submatcher.group( 1 ) ); if( (submatcher = blmWidth.matcher( matcher.group( 1 ) )).find( ) ) //width new_width = Integer.parseInt( submatcher.group( 1 ) ); if( (submatcher = blmChannels.matcher( matcher.group( 1 ) )).find( ) ) //channels new_channels = Integer.parseInt( submatcher.group( 1 ) ); if( (submatcher = blmBits.matcher( matcher.group( 1 ) )).find( ) ) //bits new_maxval = (1 << (bits = Integer.parseInt( submatcher.group( 1 ) ))) - 1; //remember that blm tag was found blmTagFound = true; //set movie size resize( new_height, new_width, new_channels, new_maxval ); //get number of characters per channel chrs = (bits + 3) >> 2; } //unknown tag else if( (matcher = tag.matcher( data )).find( ) ) //remove matched part data = data.substring( matcher.end( ) ); //nothing matches else //end loop break; } //if( ! blmTagFound ) //blm tag was already found else { //title tag if( (matcher = infoTitle.matcher( data )).find( ) ) { //remove matched part data = data.substring( matcher.end( ) ); //add info to movie appendInfo( "title", matcher.group( 1 ) ); } //description tag else if( (matcher = infoDescription.matcher( data )).find( ) ) { //remove matched part data = data.substring( matcher.end( ) ); //check if generic info if( (submatcher = infoGeneric.matcher( matcher.group( 1 ) )).find( ) ) //add info to movie appendInfo( submatcher.group( 1 ), submatcher.group( 2 ) ); else //add info to movie appendInfo( "description", matcher.group( 1 ) ); } //creator tag else if( (matcher = infoCreator.matcher( data )).find( ) ) { //remove matched part data = data.substring( matcher.end( ) ); //add info to movie appendInfo( "creator", matcher.group( 1 ) ); } //author tag else if( (matcher = infoAuthor.matcher( data )).find( ) ) { //remove matched part data = data.substring( matcher.end( ) ); //add info to movie appendInfo( "author", matcher.group( 1 ) ); } //email tag else if( (matcher = infoEmail.matcher( data )).find( ) ) { //remove matched part data = data.substring( matcher.end( ) ); //add info to movie appendInfo( "email", matcher.group( 1 ) ); } //url tag else if( (matcher = infoUrl.matcher( data )).find( ) ) { //remove matched part data = data.substring( matcher.end( ) ); //add info to movie appendInfo( "url", matcher.group( 1 ) ); } //frame tag else if( (matcher = frameTag.matcher( data )).find( ) ) { //remove matched part data = data.substring( matcher.end( ) ); //get attributes duration = 0; if( (submatcher = frameDuration.matcher( matcher.group( 1 ) )).find( ) ) //duration duration = Integer.parseInt( submatcher.group( 1 ) ); //create new frame and append it to movie frame = new BlinkenFrame( height, width, channels, maxval, duration ); frame.clear( ); appendFrame( frame ); y = 0; } //row tag else if( (matcher = rowTag.matcher( data )).find( ) ) { //remove matched part data = data.substring( matcher.end( ) ); //parse row row = matcher.group( 1 ); len = row.length( ); i = 0; for( x = 0; x < this.width && i + chrs <= len; x++ ) { for( c = 0; c < this.channels && i + chrs <= len; c++, i += chrs ) { val = Integer.parseInt( row.substring( i, i + chrs ), 0x10 ); frame.setPixel( y, x, c, (byte)val ); //set pixel } } y++; //next row } //unknown tag else if( (matcher = tag.matcher( data )).find( ) ) //remove matched part data = data.substring( matcher.end( ) ); //nothing matches else //end loop break; } //if( ! blmTagFound ) ... else } //while( true ) } //while( (line = ... //success return true; } catch( IOException e ) { } //some error return false; } public boolean loadBml( String filename ) { try { BufferedReader file = new BufferedReader( new FileReader( filename ) ); boolean ret = loadBml( file ); file.close( ); return ret; } catch( IOException e ) { return false; } } public boolean loadBbm( String filename ) { RandomAccessFile file; byte[] header, subHeader, infoHeader, frameStartMarker, frameData; int headerMagic, headerHeight, headerWidth, headerChannels, headerMaxval; int headerFrameCnt, headerDuration, headerFramePtr; int subHeaderMagic, subHeaderSize; int frameStartMarkerMagic; StringTokenizer tokenizer; String infoType, infoData; int fileLength, frameLength; int duration, i, y, x, c; BlinkenFrame frame; //delete all frames deleteInfos( ); deleteFrames( ); resize( 0, 0, 0, 0 ); //try to read file try { //open file file = new RandomAccessFile( filename, "r" ); //read header header = new byte[24]; file.readFully( header ); headerMagic = ((int)header[0] & 0xFF) << 24 | ((int)header[1] & 0xFF) << 16 | ((int)header[2] & 0xFF) << 8 | ((int)header[3] & 0xFF); headerHeight = ((int)header[4] & 0xFF) << 8 | ((int)header[5] & 0xFF); headerWidth = ((int)header[6] & 0xFF) << 8 | ((int)header[7] & 0xFF); headerChannels = ((int)header[8] & 0xFF) << 8 | ((int)header[9] & 0xFF); headerMaxval = ((int)header[10] & 0xFF) << 8 | ((int)header[11] & 0xFF); headerFrameCnt = ((int)header[12] & 0xFF) << 24 | ((int)header[13] & 0xFF) << 16 | ((int)header[14] & 0xFF) << 8 | ((int)header[15] & 0xFF); headerDuration = ((int)header[16] & 0xFF) << 24 | ((int)header[17] & 0xFF) << 16 | ((int)header[18] & 0xFF) << 8 | ((int)header[19] & 0xFF); headerFramePtr = ((int)header[20] & 0xFF) << 24 | ((int)header[21] & 0xFF) << 16 | ((int)header[22] & 0xFF) << 8 | ((int)header[23] & 0xFF); //check magic if( headerMagic == 0x23542666 ) { //adapt movie format resize( headerHeight, headerWidth, headerChannels, headerMaxval ); //read subheaders subHeader = new byte[6]; while( file.getFilePointer( ) + 6 <= headerFramePtr ) { file.readFully( subHeader ); subHeaderMagic = ((int)subHeader[0] & 0xFF) << 24 | ((int)subHeader[1] & 0xFF) << 16 | ((int)subHeader[2] & 0xFF) << 8 | ((int)subHeader[3] & 0xFF); subHeaderSize = ((int)subHeader[4] & 0xFF) << 8 | ((int)subHeader[5] & 0xFF); //header fits into gap to frame start if( subHeaderSize >= 6 && file.getFilePointer( ) + subHeaderSize - 6 <= headerFramePtr ) { //info header if( subHeaderMagic == 0x696E666F ) //'i' 'n' 'f' 'o' { //read rest of info header infoHeader = new byte[subHeaderSize - 6]; file.readFully( infoHeader ); //parse information tokenizer = new StringTokenizer( new String( infoHeader ), "\000" ); if( tokenizer.countTokens( ) >= 2 ) { infoType = tokenizer.nextToken(); infoData = tokenizer.nextToken(); appendInfo( infoType, infoData ); } } //unknown subHeader else //skip file.skipBytes( subHeaderSize - 6 ); } //if( file.getFilePointer( ) ... } //while( file.getFilePointer( ) ... //seek to start of frames file.seek( headerFramePtr ); //read frame start marker frameStartMarker = new byte[4]; file.readFully( frameStartMarker ); frameStartMarkerMagic = ((int)frameStartMarker[0] & 0xFF) << 24 | ((int)frameStartMarker[1] & 0xFF) << 16 | ((int)frameStartMarker[2] & 0xFF) << 8 | ((int)frameStartMarker[3] & 0xFF); if( frameStartMarkerMagic == 0x66726D73 ) //'f' 'r' 'm' 's' { //read frames fileLength = (int)file.length( ); frameLength = 2 + headerHeight * headerWidth * headerChannels; frameData = new byte[frameLength]; while( file.getFilePointer( ) + frameLength <= fileLength ) { //read frame file.readFully( frameData ); duration = ((int)frameData[0] & 0xFF) << 8 | ((int)frameData[1] & 0xFF); //build frame and append it to movie frame = new BlinkenFrame( height, width, channels, maxval, duration ); i = 2; for( y = 0; y < headerHeight; y++ ) for( x = 0; x < headerWidth; x++ ) for( c = 0; c < headerChannels; c++, i++ ) frame.setPixel( y, x, c, frameData[i] ); appendFrame( frame ); } //while( file.getFilePointer ... } //if( frameStartMarkerMagic ... } //if( headerMagic ... //close file file.close( ); //success return true; } catch( IOException e ) { } //some error return false; } public boolean load( String filename ) { if( filename.endsWith( ".blm" ) ) return loadBlm( filename ); if( filename.endsWith( ".bmm" ) ) return loadBmm( filename ); if( filename.endsWith( ".bml" ) ) return loadBml( filename ); if( filename.endsWith( ".bbm" ) ) return loadBbm( filename ); deleteFrames( ); return false; } public boolean saveBlm( BufferedWriter writer ) { BlinkenMovie movie; int cnt, i, y, x; String line; //convert movie to suitable format movie = new BlinkenMovie( this ); movie.resize( movie.height, movie.width, 1, 1 ); try { //write header line writer.write( "# BlinkenLights Movie " + movie.width + "x" + movie.height + "\n" ); //write information lines cnt = movie.getInfoCnt( ); for( i = 0; i < cnt; i++ ) writer.write( "# " + movie.getInfoType( i ) + " = " + movie.getInfoData( i ) + "\n" ); //write frames cnt = movie.getFrameCnt( ); for( i = 0; i < cnt; i++ ) { writer.write( "\n@" + movie.frames[i].getDuration( ) + "\n" ); for( y = 0; y < movie.height; y++ ) { line = ""; for( x = 0; x < movie.width; x++ ) { if( movie.frames[i].getPixel( y, x, 0 ) != 0 ) line = line + "1"; else line = line + "0"; } writer.write( line + "\n" ); } } //success return true; } catch( IOException e ) { } //some error return false; } public boolean saveBlm( String filename ) { try { BufferedWriter file = new BufferedWriter( new FileWriter( filename ) ); boolean ret = saveBlm( file ); file.close( ); return ret; } catch( IOException e ) { return false; } } public boolean saveBmm( BufferedWriter writer ) { BlinkenMovie movie; int cnt, i, y, x, val; String line; //convert movie to suitable format movie = new BlinkenMovie( this ); movie.resize( movie.height, movie.width, 1, 255 ); try { //write header line writer.write( "# BlinkenMini Movie " + movie.width + "x" + movie.height + "\n" ); //write information lines cnt = movie.getInfoCnt( ); for( i = 0; i < cnt; i++ ) writer.write( "# " + movie.getInfoType( i ) + " = " + movie.getInfoData( i ) + "\n" ); //write frames cnt = movie.getFrameCnt( ); for( i = 0; i < cnt; i++ ) { writer.write( "\n@" + movie.frames[i].getDuration( ) + "\n" ); for( y = 0; y < movie.height; y++ ) { line = ""; for( x = 0; x < movie.width; x++ ) { val = (int)movie.frames[i].getPixel( y, x, 0 ) & 0xFF; if( val < 0x10 ) line = line + " 0x0" + Integer.toHexString( val ).toUpperCase( ); else line = line + " 0x" + Integer.toHexString( val ).toUpperCase( ); } writer.write( line.substring( 1 ) + "\n" ); } } //success return true; } catch( IOException e ) { } //some error return false; } public boolean saveBmm( String filename ) { try { BufferedWriter file = new BufferedWriter( new FileWriter( filename ) ); boolean ret = saveBmm( file ); file.close( ); return ret; } catch( IOException e ) { return false; } } public boolean saveBml( BufferedWriter writer ) { BlinkenMovie movie; int bits, cnt, i, y, x, c, val; String infoType, infoData, line; //convert movie to suitable format movie = new BlinkenMovie( this ); val = movie.maxval; //get number of bits for( bits = 0; val != 0; val >>= 1, bits++ ); movie.resize( movie.height, movie.width, movie.channels, (1 << bits) - 1 ); try { //write header line writer.write( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ); //write blm start tag writer.write( "<blm width=\"" + movie.width + "\" height=\"" + movie.height + "\" bits=\"" + bits + "\" channels=\"" + movie.channels + "\">\n" ); //write information lines writer.write( "\t<header>\n" ); cnt = movie.getInfoCnt( ); for( i = 0; i < cnt; i++ ) { infoType = movie.getInfoType( i ); infoData = movie.getInfoData( i ); if( infoType.equals( "title" ) ) writer.write( "\t\t<title>" + infoData + "</title>\n" ); else if( infoType.equals( "description" ) ) writer.write( "\t\t<description>" + infoData + "</description>\n" ); else if( infoType.equals( "creator" ) ) writer.write( "\t\t<creator>" + infoData + "</creator>\n" ); else if( infoType.equals( "author" ) ) writer.write( "\t\t<author>" + infoData + "</author>\n" ); else if( infoType.equals( "email" ) ) writer.write( "\t\t<email>" + infoData + "</email>\n" ); else if( infoType.equals( "url" ) ) writer.write( "\t\t<url>" + infoData + "</url>\n" ); else writer.write( "\t\t<description>" + infoType + ": " + infoData + "</description>\n" ); } writer.write( "\t</header>\n" ); //write frames cnt = movie.getFrameCnt( ); for( i = 0; i < cnt; i++ ) { writer.write( "\n\t<frame duration=\"" + movie.frames[i].getDuration( ) + "\">\n" ); for( y = 0; y < movie.height; y++ ) { line = ""; for( x = 0; x < movie.width; x++ ) { for( c = 0; c < movie.channels; c++ ) { val = (int)movie.frames[i].getPixel( y, x, c ) & 0xFF; if( bits > 4 && val < 0x10 ) line = line + "0" + Integer.toHexString( val ).toUpperCase( ); else line = line + Integer.toHexString( val ).toUpperCase( ); } } writer.write( "\t\t<row>" + line + "</row>\n" ); } writer.write( "\t</frame>\n" ); } //write blm end tag writer.write( "</blm>\n" ); //success return true; } catch( IOException e ) { } //some error return false; } public boolean saveBml( String filename ) { try { BufferedWriter file = new BufferedWriter( new FileWriter( filename ) ); boolean ret = saveBml( file ); file.close( ); return ret; } catch( IOException e ) { return false; } } public boolean saveBbm( String filename ) { RandomAccessFile file; byte[] header, infoHeader, framePointer, frameStartMarker, frameData; int cnt, duration, i, j, len, y, x, c, val; String infoType, infoData, line; try { //open file file = new RandomAccessFile( filename, "rw" ); //truncate file file.setLength( 0 ); //write header header = new byte[24]; header[0] = 0x23; //magic header[1] = 0x54; header[2] = 0x26; header[3] = 0x66; header[4] = (byte)(this.height >> 8); header[5] = (byte)this.height; header[6] = (byte)(this.width >> 8); header[7] = (byte)this.width; header[8] = (byte)(this.channels >> 8); header[9] = (byte)this.channels; header[10] = (byte)(this.maxval >> 8); header[11] = (byte)this.maxval; cnt = this.getFrameCnt( ); header[12] = (byte)(cnt >> 24); header[13] = (byte)(cnt >> 16); header[14] = (byte)(cnt >> 8); header[15] = (byte)cnt; duration = 0; for( i = 0; i < cnt; i++ ) duration += this.frames[i].getDuration( ); header[16] = (byte)(duration >> 24); header[17] = (byte)(duration >> 16); header[18] = (byte)(duration >> 8); header[19] = (byte)duration; header[20] = 0; //frame pointer is written later header[21] = 0; header[22] = 0; header[23] = 0; file.write( header ); //write information cnt = this.getInfoCnt( ); for( i = 0; i < cnt; i++ ) { infoType = this.getInfoType( i ); if( infoType.length( ) > 32760 ) infoType = infoType.substring( 0, 32760 ); infoData = this.getInfoData( i ); if( infoData.length( ) > 32760 ) infoData = infoData.substring( 0, 32760 ); len = 8 + infoType.length( ) + infoData.length( ); infoHeader = new byte[6]; infoHeader[0] = 0x69; //'i' infoHeader[1] = 0x6E; //'n' infoHeader[2] = 0x66; //'f' infoHeader[3] = 0x6F; //'o' infoHeader[4] = (byte)(len >> 8); infoHeader[5] = (byte)len; file.write( infoHeader ); file.write( (infoType + "\000" + infoData + "\000").getBytes( ) ); } //write frame pointer framePointer = new byte[4]; val = (int)file.getFilePointer( ); framePointer[0] = (byte)(val >> 24); framePointer[1] = (byte)(val >> 16); framePointer[2] = (byte)(val >> 8); framePointer[3] = (byte)val; file.seek( 20 ); file.write( framePointer ); file.seek( val ); //write frame start marker frameStartMarker = new byte[4]; frameStartMarker[0] = 0x66; //'f' frameStartMarker[1] = 0x72; //'r' frameStartMarker[2] = 0x6D; //'m' frameStartMarker[3] = 0x73; //'s' file.write( frameStartMarker ); //write frames len = 2 + this.height * this.width * this.channels; frameData = new byte[len]; cnt = this.getFrameCnt( ); for( i = 0; i < cnt; i++ ) { val = this.frames[i].getDuration( ); frameData[0] = (byte)(val >> 8); frameData[1] = (byte)val; for( j = 2, y = 0; y < this.height; y++ ) for( x = 0; x < this.width; x++ ) for( c = 0; c < this.channels; c++, j++ ) frameData[j] = this.frames[i].getPixel( y, x, c ); file.write( frameData ); } //close file file.close( ); //success return true; } catch( IOException e ) { } //some error return false; } public boolean save( String filename ) { if( filename.endsWith( ".blm" ) ) return saveBlm( filename ); if( filename.endsWith( ".bmm" ) ) return saveBmm( filename ); if( filename.endsWith( ".bml" ) ) return saveBml( filename ); if( filename.endsWith( ".bbm" ) ) return saveBbm( filename ); return false; } } //public class BlinkenMovie