Stefan Schuermans commited on 2018-09-04 21:21:39
Showing 2 changed files, with 187 additions and 2 deletions.
... | ... |
@@ -1,11 +1,11 @@ |
1 | 1 |
# BlinkenLib |
2 |
-# Copyright (C) 2004-2011: Stefan Schuermans <stefan@schuermans.info> |
|
2 |
+# Copyright (C) 2004-2018: Stefan Schuermans <stefan@schuermans.info> |
|
3 | 3 |
# Copyleft: GNU public license - http://www.gnu.org/copyleft/gpl.html |
4 | 4 |
# a blinkenarea.org project |
5 | 5 |
|
6 | 6 |
VERSION_MAJOR=0 |
7 | 7 |
VERSION_MINOR=1 |
8 |
-VERSION_REVISION=5 |
|
8 |
+VERSION_REVISION=6 |
|
9 | 9 |
|
10 | 10 |
JAVAC=javac |
11 | 11 |
JAR=jar |
... | ... |
@@ -9,6 +9,12 @@ package org.blinkenarea.BlinkenLib; |
9 | 9 |
import java.util.*; |
10 | 10 |
import java.util.regex.*; |
11 | 11 |
import java.io.*; |
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.*; |
|
12 | 18 |
import org.blinkenarea.BlinkenLib.*; |
13 | 19 |
|
14 | 20 |
public class BlinkenMovie |
... | ... |
@@ -880,6 +886,183 @@ public class BlinkenMovie |
880 | 886 |
return false; |
881 | 887 |
} |
882 | 888 |
|
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; |
|
911 |
+ for( int chi = 0; chi < children.getLength(); ++chi ) |
|
912 |
+ { |
|
913 |
+ Node child = children.item( chi ); |
|
914 |
+ |
|
915 |
+ if( child.getNodeName( ).equals( "GlobalColorTable" ) ) |
|
916 |
+ { |
|
917 |
+ NamedNodeMap attr = child.getAttributes(); |
|
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 |
+ { |
|
929 |
+ NamedNodeMap entryAttr = entry.getAttributes(); |
|
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 |
+ { |
|
975 |
+ NamedNodeMap attr = child.getAttributes(); |
|
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 |
+ { |
|
987 |
+ NamedNodeMap attr = child.getAttributes(); |
|
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 |
+ { |
|
1022 |
+ Graphics g = backup.getGraphics(); |
|
1023 |
+ g.drawImage(canvas, 0, 0, null); |
|
1024 |
+ g.dispose(); |
|
1025 |
+ } |
|
1026 |
+ |
|
1027 |
+ // draw new image to canvas |
|
1028 |
+ Graphics g = canvas.getGraphics( ); |
|
1029 |
+ g.drawImage( img, left, top, null ); |
|
1030 |
+ g.dispose(); |
|
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 |
+ { |
|
1043 |
+ g = canvas.getGraphics(); |
|
1044 |
+ g.drawImage(backup, 0, 0, null); |
|
1045 |
+ g.dispose(); |
|
1046 |
+ } |
|
1047 |
+ if( restoreToBackgroundColor ) |
|
1048 |
+ { |
|
1049 |
+ Graphics2D g2d = canvas.createGraphics(); |
|
1050 |
+ g2d.setColor(bgColor); |
|
1051 |
+ g2d.fill(new Rectangle(left, top, width, height)); |
|
1052 |
+ g2d.dispose(); |
|
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 |
+ |
|
883 | 1066 |
public boolean load( String filename ) |
884 | 1067 |
{ |
885 | 1068 |
if( filename.endsWith( ".blm" ) ) |
... | ... |
@@ -890,6 +1073,8 @@ public class BlinkenMovie |
890 | 1073 |
return loadBml( filename ); |
891 | 1074 |
if( filename.endsWith( ".bbm" ) ) |
892 | 1075 |
return loadBbm( filename ); |
1076 |
+ if( filename.endsWith( ".gif" ) ) |
|
1077 |
+ return loadGif( filename ); |
|
893 | 1078 |
deleteFrames( ); |
894 | 1079 |
return false; |
895 | 1080 |
} |
896 | 1081 |