Skip to content

Instantly share code, notes, and snippets.

@torao
Last active November 18, 2017 12:26
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save torao/47e011e583f98b38c22bad37548e7e03 to your computer and use it in GitHub Desktop.
How to Build Animation by Image I/O in Java
/* **************************************************************************
* Copyright(C) 2008 BJORFUAN. All Rights Reserved.
* **************************************************************************
* This module, contains source code, binary and documentation, is in the
* Apache License 2.0, and comes with NO WARRANTY.
* ToRA. <torao@mars.dti.ne.jp>
* http://lab.moyo.biz/
* $Id: GifRecipes.java,v 1.1 2008/01/27 08:57:16 torao Exp $
*/
package biz.moyo.lab.experiment.gifanime;
import javax.imageio.metadata.IIOMetadataNode;
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// GifRecipe: GIF 画像作成用ユーティリティクラス
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/**
* Java SE 6 から Image I/O でサポートされた GIF の出力処理を使用してアニメー
* ション GIF を作成するためのユーティリティクラスです。
* <p>
* パラメータの入力値確認はアサーションで行っています。テスト時にはアサーショ
* ンを有効にして (<code>-ea</code> オプション) 実行してください。
* <p>
* @version $Revision: 1.1 $ $Date: 2008/01/27 08:57:16 $
* @author torao
* @since Java SE 6 2008/01/24
* @see <a href="http://java.sun.com/javase/ja/6/docs/ja/api/javax/imageio/metadata/doc-files/gif_metadata.html">GIF Metadata Format Specification</a>
*/
public final class GifRecipes {
// ======================================================================
// コンストラクタ
// ======================================================================
/**
* コンストラクタはクラス内に隠蔽されています。
* <p>
*/
private GifRecipes() {
return;
}
// ======================================================================
// Netscape ループ用アプリケーション拡張ブロックの参照
// ======================================================================
/**
* アニメーション画像を作成する時のループ回数を指定するアプリケーション
* 拡張ブロックを参照するためのユーティリティメソッドです。
* <p>
* @param count ループ回数 (0の場合は無限)
* @return アプリケーション拡張ブロックのメタデータノード
*/
public static IIOMetadataNode getNetscapeLoop(int count){
assert(count == (count & 0xFFFF));
byte[] data = {
0x01,
(byte)((count >> 0) & 0xFF),
(byte)((count >> 8) & 0xFF)
};
return getApplicationExtension("NETSCAPE", "2.0", data);
}
// ======================================================================
// GIF ヘッダの参照
// ======================================================================
/**
* GIF ヘッダに相当するメタデータを参照します。
* <p>
* @param version バージョン
* @param disposalMethod 画像描画後の破棄方法
* @param userInput 画像表示後にユーザ入力 (マウスクリックなど) を待つかどうか
* @param transparentColor 透過色を使用するかどうか
* @param transparentIndex 透過色に使用する色のインデックス (0~255)
* @param delay 表示後の遅延時間 (1/100秒; 0~65535)
* @return グラフィック制御ブロックのメタデータノード
*/
// public static IIOMetadataNode getLogicalScreenDescriptor(
// Version version, int width, int height, int resolution, int ratio){
// assert(delay == (delay & 0xFFFF));
// assert(transparentIndex == (transparentIndex & 0xFF));
// IIOMetadataNode child = new IIOMetadataNode("GraphicControlExtension");
// child.setAttribute("disposalMethod", disposalMethod.getValue());
// child.setAttribute("userInputFlag", userInput? "TRUE": "FALSE");
// child.setAttribute("transparentColorFlag", transparentColor? "TRUE": "FALSE");
// child.setAttribute("delayTime", String.valueOf(delay));
// child.setAttribute("transparentColorIndex", String.valueOf(transparentIndex));
// return child;
// }
// ======================================================================
// グラフィック制御ブロックの参照
// ======================================================================
/**
* アプリケーション拡張ブロックに相当するメタデータを参照します。
* <p>
* @param disposalMethod 画像描画後の破棄方法
* @param userInput 画像表示後にユーザ入力 (マウスクリックなど) を待つかどうか
* @param transparentColor 透過色を使用するかどうか
* @param transparentIndex 透過色に使用する色のインデックス (0~255)
* @param delay 表示後の遅延時間 (1/100秒; 0~65535)
* @return グラフィック制御ブロックのメタデータノード
*/
public static IIOMetadataNode getGraphicControlExtension(DisposalMethod disposalMethod, boolean userInput, boolean transparentColor, int transparentIndex, int delay){
assert(delay == (delay & 0xFFFF));
assert(transparentIndex == (transparentIndex & 0xFF));
IIOMetadataNode node = new IIOMetadataNode("GraphicControlExtension");
node.setAttribute("disposalMethod", disposalMethod.getValue());
node.setAttribute("userInputFlag", userInput? "TRUE": "FALSE");
node.setAttribute("transparentColorFlag", transparentColor? "TRUE": "FALSE");
node.setAttribute("delayTime", String.valueOf(delay));
node.setAttribute("transparentColorIndex", String.valueOf(transparentIndex));
return node;
}
// ======================================================================
// プレーンテキストブロックの参照
// ======================================================================
/**
* プレーンテキストブロックに相当するメタデータを参照します。
* <p>
* @param textGridLeft テキスト表示領域のX位置
* @param textGridTop テキスト表示領域Y位置
* @param textGridWidth テキスト表示領域幅
* @param textGridHeight テキスト表示領域高さ
* @param charCellWidth 1文字の幅
* @param charCellHeight 1文字の高さ
* @param textForeground 前景色インデックス
* @param textBackground 背景色インデックス
* @param text テキスト
* @return プレーンテキスト拡張ブロックのメタデータノード
*/
public static IIOMetadataNode getPlainTextExtension(
int textGridLeft, int textGridTop, int textGridWidth, int textGridHeight,
int charCellWidth, int charCellHeight, int textForeground, int textBackground, String text){
assert(textGridLeft == (textGridLeft & 0xFFFF));
assert(textGridTop == (textGridTop & 0xFFFF));
assert(textGridWidth == (textGridWidth & 0xFFFF));
assert(textGridHeight == (textGridHeight & 0xFFFF));
assert(charCellWidth == (charCellWidth & 0xFF));
assert(charCellHeight == (charCellHeight & 0xFF));
assert(textForeground == (textForeground & 0xFF));
assert(textBackground == (textBackground & 0xFF));
IIOMetadataNode node = new IIOMetadataNode("PlainTextExtension");
node.setAttribute("textGridLeft", String.valueOf(textGridLeft));
node.setAttribute("textGridTop", String.valueOf(textGridTop));
node.setAttribute("textGridWidth", String.valueOf(textGridWidth));
node.setAttribute("textGridHeight", String.valueOf(textGridHeight));
node.setAttribute("characterCellWidth", String.valueOf(charCellWidth));
node.setAttribute("characterCellHeight", String.valueOf(charCellHeight));
node.setAttribute("textForegroundColor", String.valueOf(textForeground));
node.setAttribute("textBackgroundColor", String.valueOf(textBackground));
node.setAttribute("text", text);
node.setUserObject(text.getBytes());
return node;
}
// ======================================================================
// アプリケーション拡張ブロックの参照
// ======================================================================
/**
* アプリケーション拡張ブロックに相当するメタデータノードを参照します。
* <p>
* @param appId アプリケーション ID
* @param authCode アプリケーションコード
* @param data アプリケーションデータ
* @return アプリケーション拡張ブロックのメタデータノード
*/
public static IIOMetadataNode getApplicationExtension(String appId, String authCode, byte[] data){
assert(appId.length() == 8);
assert(authCode.length() == 3);
IIOMetadataNode list = new IIOMetadataNode("ApplicationExtensions");
IIOMetadataNode node = new IIOMetadataNode("ApplicationExtension");
node.setAttribute("applicationID", appId);
node.setAttribute("authenticationCode", authCode);
node.setUserObject(data);
list.appendChild(node);
return list;
}
// ======================================================================
// コメント拡張ブロックの参照
// ======================================================================
/**
* コメント拡張ブロックに相当するメタデータノードを参照します。複数の文字
* 列が指定された場合は、それぞれ個別のコメントブロックに格納されます。
* <p>
* @param comment コメントの内容
* @param comments 追加のコメント
* @return コメント拡張ブロックのメタデータノード
*/
public static IIOMetadataNode getCommentExtension(String comment, String... comments){
assert(comment != null);
IIOMetadataNode list = new IIOMetadataNode("CommentExtensions");
// コメントを追加
IIOMetadataNode node = new IIOMetadataNode("CommentExtension");
node.setAttribute("value", comment);
list.appendChild(node);
// 残りのコメントを追加
for(String cmt: comments){
node = new IIOMetadataNode("CommentExtension");
node.setAttribute("value", cmt);
list.appendChild(node);
}
return list;
}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Version: バージョン
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/**
* 画像を描画し終え、次の画像を表示する前に行う動作です。
* <p>
*/
public enum Version{
// ==================================================================
// 未指定
// ==================================================================
/**
* 破棄方法を特に指定しません。
* <p>
*/
GIF87A("GIF87a"),
// ==================================================================
// 破棄しない
// ==================================================================
/**
* 描画した状態から何もせず次の画像を描画します。新しく描画する画像に
* 透過色が含まれている場合はオーバーレイされた状態になります。
* <p>
*/
GIF89A("GIF89a");
// ==================================================================
// 値
// ==================================================================
/**
* 値です。
* <p>
*/
private final String value;
// ==================================================================
// コンストラクタ
// ==================================================================
/**
* コンストラクタは何も行いません。
* <p>
* @param value 値
*/
private Version(String value) {
this.value = value;
return;
}
// ==================================================================
// 値の参照
// ==================================================================
/**
* 値を参照します。
* <p>
* @return 値
*/
public String getValue(){
return value;
}
}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// DisposalMethod: 破棄方法
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/**
* 画像を描画し終え、次の画像を表示する前に行う動作です。
* <p>
*/
public enum DisposalMethod{
// ==================================================================
// 未指定
// ==================================================================
/**
* 破棄方法を特に指定しません。
* <p>
*/
NONE("none"),
// ==================================================================
// 破棄しない
// ==================================================================
/**
* 描画した状態から何もせず次の画像を描画します。新しく描画する画像に
* 透過色が含まれている場合はオーバーレイされた状態になります。
* <p>
*/
DO_NOT_DISPOSE("doNotDispose"),
// ==================================================================
// 背景色で塗りつぶし
// ==================================================================
/**
* 背景色に指定されている色で塗りつぶしてから次の画像を描画します。
* <p>
*/
RESTORE_TO_BACKGROUND_COLOR("restoreToBackgroundColor"),
// ==================================================================
// 直前の画像に戻す
// ==================================================================
/**
* 画像の描画前の状態に戻します。
* <p>
*/
RESTORE_TO_PREVIOUS("restoreToPrevious");
// ==================================================================
// 値
// ==================================================================
/**
* 値です。
* <p>
*/
private final String value;
// ==================================================================
// コンストラクタ
// ==================================================================
/**
* コンストラクタは何も行いません。
* <p>
* @param value 値
*/
private DisposalMethod(String value) {
this.value = value;
return;
}
// ==================================================================
// 値の参照
// ==================================================================
/**
* 値を参照します。
* <p>
* @return 値
*/
public String getValue(){
return value;
}
}
}
package biz.moyo.lab.experiment.gifanime;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.util.*;
import javax.imageio.*;
import javax.imageio.metadata.*;
import javax.imageio.stream.*;
public class GIFPlainText {
public static void main(String[] args) throws IOException{
BufferedImage image = new BufferedImage(100, 16, BufferedImage.TYPE_4BYTE_ABGR);
Graphics g = image.getGraphics();
g.setColor(Color.WHITE); g.fillRect(0, 0, 100, 16);
g.setColor(Color.BLACK); g.drawString("hello, world", 3, 14);
ImageOutputStream out = ImageIO.createImageOutputStream(new File("foo.gif"));
Iterator<ImageWriter> it = ImageIO.getImageWritersByFormatName("GIF");
ImageWriter writer = it.next();
writer.setOutput(out);
IIOMetadataNode node = new IIOMetadataNode("PlainTextExtension");
node.setAttribute("textGridLeft", "0");
node.setAttribute("textGridTop", "0");
node.setAttribute("textGridWidth", "100");
node.setAttribute("textGridHeight", "16");
node.setAttribute("characterCellWidth", "100"); // *1
node.setAttribute("characterCellHeight", "16"); // *2
node.setAttribute("textForegroundColor", "0");
node.setAttribute("textBackgroundColor", "1");
ImageWriteParam param = writer.getDefaultWriteParam();
IIOMetadata meta = writer.getDefaultImageMetadata(
ImageTypeSpecifier.createFromRenderedImage(image), param);
String format = meta.getNativeMetadataFormatName();
IIOMetadataNode root = (IIOMetadataNode)meta.getAsTree(format);
root.appendChild(node);
meta.setFromTree(format, root);
writer.prepareWriteSequence(null);
writer.writeToSequence(new IIOImage(image, null, meta), param);
writer.endWriteSequence();
out.close();
}
}
/* **************************************************************************
* Copyright(C) 2008 BJORFUAN. All Rights Reserved.
* **************************************************************************
* This module, contains source code, binary and documentation, is in the
* Apache License 2.0, and comes with NO WARRANTY.
* ToRA. <torao@mars.dti.ne.jp>
* http://lab.moyo.biz/
* $Id: GifRecipes.java,v 1.1 2008/01/27 08:57:16 torao Exp $
*/
package biz.moyo.lab.experiment.gifanime;
import javax.imageio.metadata.IIOMetadataNode;
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// GifRecipe: GIF 画像作成用ユーティリティクラス
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/**
* Java SE 6 から Image I/O でサポートされた GIF の出力処理を使用してアニメー
* ション GIF を作成するためのユーティリティクラスです。
* <p>
* パラメータの入力値確認はアサーションで行っています。テスト時にはアサーショ
* ンを有効にして (<code>-ea</code> オプション) 実行してください。
* <p>
* @version $Revision: 1.1 $ $Date: 2008/01/27 08:57:16 $
* @author torao
* @since Java SE 6 2008/01/24
* @see <a href="http://java.sun.com/javase/ja/6/docs/ja/api/javax/imageio/metadata/doc-files/gif_metadata.html">GIF Metadata Format Specification</a>
*/
public final class GifRecipes {
// ======================================================================
// コンストラクタ
// ======================================================================
/**
* コンストラクタはクラス内に隠蔽されています。
* <p>
*/
private GifRecipes() {
return;
}
// ======================================================================
// Netscape ループ用アプリケーション拡張ブロックの参照
// ======================================================================
/**
* アニメーション画像を作成する時のループ回数を指定するアプリケーション
* 拡張ブロックを参照するためのユーティリティメソッドです。
* <p>
* @param count ループ回数 (0の場合は無限)
* @return アプリケーション拡張ブロックのメタデータノード
*/
public static IIOMetadataNode getNetscapeLoop(int count){
assert(count == (count & 0xFFFF));
byte[] data = {
0x01,
(byte)((count >> 0) & 0xFF),
(byte)((count >> 8) & 0xFF)
};
return getApplicationExtension("NETSCAPE", "2.0", data);
}
// ======================================================================
// GIF ヘッダの参照
// ======================================================================
/**
* GIF ヘッダに相当するメタデータを参照します。
* <p>
* @param version バージョン
* @param disposalMethod 画像描画後の破棄方法
* @param userInput 画像表示後にユーザ入力 (マウスクリックなど) を待つかどうか
* @param transparentColor 透過色を使用するかどうか
* @param transparentIndex 透過色に使用する色のインデックス (0~255)
* @param delay 表示後の遅延時間 (1/100秒; 0~65535)
* @return グラフィック制御ブロックのメタデータノード
*/
// public static IIOMetadataNode getLogicalScreenDescriptor(
// Version version, int width, int height, int resolution, int ratio){
// assert(delay == (delay & 0xFFFF));
// assert(transparentIndex == (transparentIndex & 0xFF));
// IIOMetadataNode child = new IIOMetadataNode("GraphicControlExtension");
// child.setAttribute("disposalMethod", disposalMethod.getValue());
// child.setAttribute("userInputFlag", userInput? "TRUE": "FALSE");
// child.setAttribute("transparentColorFlag", transparentColor? "TRUE": "FALSE");
// child.setAttribute("delayTime", String.valueOf(delay));
// child.setAttribute("transparentColorIndex", String.valueOf(transparentIndex));
// return child;
// }
// ======================================================================
// グラフィック制御ブロックの参照
// ======================================================================
/**
* アプリケーション拡張ブロックに相当するメタデータを参照します。
* <p>
* @param disposalMethod 画像描画後の破棄方法
* @param userInput 画像表示後にユーザ入力 (マウスクリックなど) を待つかどうか
* @param transparentColor 透過色を使用するかどうか
* @param transparentIndex 透過色に使用する色のインデックス (0~255)
* @param delay 表示後の遅延時間 (1/100秒; 0~65535)
* @return グラフィック制御ブロックのメタデータノード
*/
public static IIOMetadataNode getGraphicControlExtension(DisposalMethod disposalMethod, boolean userInput, boolean transparentColor, int transparentIndex, int delay){
assert(delay == (delay & 0xFFFF));
assert(transparentIndex == (transparentIndex & 0xFF));
IIOMetadataNode node = new IIOMetadataNode("GraphicControlExtension");
node.setAttribute("disposalMethod", disposalMethod.getValue());
node.setAttribute("userInputFlag", userInput? "TRUE": "FALSE");
node.setAttribute("transparentColorFlag", transparentColor? "TRUE": "FALSE");
node.setAttribute("delayTime", String.valueOf(delay));
node.setAttribute("transparentColorIndex", String.valueOf(transparentIndex));
return node;
}
// ======================================================================
// プレーンテキストブロックの参照
// ======================================================================
/**
* プレーンテキストブロックに相当するメタデータを参照します。
* <p>
* @param textGridLeft テキスト表示領域のX位置
* @param textGridTop テキスト表示領域Y位置
* @param textGridWidth テキスト表示領域幅
* @param textGridHeight テキスト表示領域高さ
* @param charCellWidth 1文字の幅
* @param charCellHeight 1文字の高さ
* @param textForeground 前景色インデックス
* @param textBackground 背景色インデックス
* @param text テキスト
* @return プレーンテキスト拡張ブロックのメタデータノード
*/
public static IIOMetadataNode getPlainTextExtension(
int textGridLeft, int textGridTop, int textGridWidth, int textGridHeight,
int charCellWidth, int charCellHeight, int textForeground, int textBackground, String text){
assert(textGridLeft == (textGridLeft & 0xFFFF));
assert(textGridTop == (textGridTop & 0xFFFF));
assert(textGridWidth == (textGridWidth & 0xFFFF));
assert(textGridHeight == (textGridHeight & 0xFFFF));
assert(charCellWidth == (charCellWidth & 0xFF));
assert(charCellHeight == (charCellHeight & 0xFF));
assert(textForeground == (textForeground & 0xFF));
assert(textBackground == (textBackground & 0xFF));
IIOMetadataNode node = new IIOMetadataNode("PlainTextExtension");
node.setAttribute("textGridLeft", String.valueOf(textGridLeft));
node.setAttribute("textGridTop", String.valueOf(textGridTop));
node.setAttribute("textGridWidth", String.valueOf(textGridWidth));
node.setAttribute("textGridHeight", String.valueOf(textGridHeight));
node.setAttribute("characterCellWidth", String.valueOf(charCellWidth));
node.setAttribute("characterCellHeight", String.valueOf(charCellHeight));
node.setAttribute("textForegroundColor", String.valueOf(textForeground));
node.setAttribute("textBackgroundColor", String.valueOf(textBackground));
node.setAttribute("text", text);
node.setUserObject(text.getBytes());
return node;
}
// ======================================================================
// アプリケーション拡張ブロックの参照
// ======================================================================
/**
* アプリケーション拡張ブロックに相当するメタデータノードを参照します。
* <p>
* @param appId アプリケーション ID
* @param authCode アプリケーションコード
* @param data アプリケーションデータ
* @return アプリケーション拡張ブロックのメタデータノード
*/
public static IIOMetadataNode getApplicationExtension(String appId, String authCode, byte[] data){
assert(appId.length() == 8);
assert(authCode.length() == 3);
IIOMetadataNode list = new IIOMetadataNode("ApplicationExtensions");
IIOMetadataNode node = new IIOMetadataNode("ApplicationExtension");
node.setAttribute("applicationID", appId);
node.setAttribute("authenticationCode", authCode);
node.setUserObject(data);
list.appendChild(node);
return list;
}
// ======================================================================
// コメント拡張ブロックの参照
// ======================================================================
/**
* コメント拡張ブロックに相当するメタデータノードを参照します。複数の文字
* 列が指定された場合は、それぞれ個別のコメントブロックに格納されます。
* <p>
* @param comment コメントの内容
* @param comments 追加のコメント
* @return コメント拡張ブロックのメタデータノード
*/
public static IIOMetadataNode getCommentExtension(String comment, String... comments){
assert(comment != null);
IIOMetadataNode list = new IIOMetadataNode("CommentExtensions");
// コメントを追加
IIOMetadataNode node = new IIOMetadataNode("CommentExtension");
node.setAttribute("value", comment);
list.appendChild(node);
// 残りのコメントを追加
for(String cmt: comments){
node = new IIOMetadataNode("CommentExtension");
node.setAttribute("value", cmt);
list.appendChild(node);
}
return list;
}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Version: バージョン
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/**
* 画像を描画し終え、次の画像を表示する前に行う動作です。
* <p>
*/
public enum Version{
// ==================================================================
// 未指定
// ==================================================================
/**
* 破棄方法を特に指定しません。
* <p>
*/
GIF87A("GIF87a"),
// ==================================================================
// 破棄しない
// ==================================================================
/**
* 描画した状態から何もせず次の画像を描画します。新しく描画する画像に
* 透過色が含まれている場合はオーバーレイされた状態になります。
* <p>
*/
GIF89A("GIF89a");
// ==================================================================
// 値
// ==================================================================
/**
* 値です。
* <p>
*/
private final String value;
// ==================================================================
// コンストラクタ
// ==================================================================
/**
* コンストラクタは何も行いません。
* <p>
* @param value 値
*/
private Version(String value) {
this.value = value;
return;
}
// ==================================================================
// 値の参照
// ==================================================================
/**
* 値を参照します。
* <p>
* @return 値
*/
public String getValue(){
return value;
}
}
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// DisposalMethod: 破棄方法
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/**
* 画像を描画し終え、次の画像を表示する前に行う動作です。
* <p>
*/
public enum DisposalMethod{
// ==================================================================
// 未指定
// ==================================================================
/**
* 破棄方法を特に指定しません。
* <p>
*/
NONE("none"),
// ==================================================================
// 破棄しない
// ==================================================================
/**
* 描画した状態から何もせず次の画像を描画します。新しく描画する画像に
* 透過色が含まれている場合はオーバーレイされた状態になります。
* <p>
*/
DO_NOT_DISPOSE("doNotDispose"),
// ==================================================================
// 背景色で塗りつぶし
// ==================================================================
/**
* 背景色に指定されている色で塗りつぶしてから次の画像を描画します。
* <p>
*/
RESTORE_TO_BACKGROUND_COLOR("restoreToBackgroundColor"),
// ==================================================================
// 直前の画像に戻す
// ==================================================================
/**
* 画像の描画前の状態に戻します。
* <p>
*/
RESTORE_TO_PREVIOUS("restoreToPrevious");
// ==================================================================
// 値
// ==================================================================
/**
* 値です。
* <p>
*/
private final String value;
// ==================================================================
// コンストラクタ
// ==================================================================
/**
* コンストラクタは何も行いません。
* <p>
* @param value 値
*/
private DisposalMethod(String value) {
this.value = value;
return;
}
// ==================================================================
// 値の参照
// ==================================================================
/**
* 値を参照します。
* <p>
* @return 値
*/
public String getValue(){
return value;
}
}
}
/* **************************************************************************
* Copyright(C) 2008 BJORFUAN. All Rights Reserved.
* **************************************************************************
* This module, contains source code, binary and documentation, is in the
* Apache License 2.0, and comes with NO WARRANTY.
* ToRA. <torao@mars.dti.ne.jp>
* http://lab.moyo.biz/
* $Id: NumberAnime.java,v 1.1 2008/01/27 08:57:16 torao Exp $
*/
package biz.moyo.lab.experiment.gifanime;
import java.awt.*;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import javax.imageio.*;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataNode;
import javax.imageio.stream.ImageOutputStream;
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// NumberAnime: 数値アニメーション作成クラス
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/**
* Java SE 6 から Image I/O でサポートされた GIF の出力処理を使用してアニメー
* ション GIF を作成するためのサンプルです。
* <p>
* @version $Revision: 1.1 $ $Date: 2008/01/27 08:57:16 $
* @author torao
* @since Java SE 6 2008/01/24
*/
public class NumberAnime {
// ======================================================================
// アプリケーションの実行
// ======================================================================
/**
* 0~9 までの数値を 0.5 秒おきに切り替える GIF アニメーションを作成しま
* す。
* <p>
* @param args コマンドライン引数
* @throws IOException
*/
public static void main(String[] args) throws IOException{
// 出力先のファイル名
File file = new File("anime.gif");
if(args.length > 0){
file = new File(args[0]);
}
// サンプル出力用の画像を作成
BufferedImage[] image = getAnimationFrames();
ImageOutputStream out = ImageIO.createImageOutputStream(file);
try{
// GIF 出力用の画像 Writer の参照
Iterator<ImageWriter> it = ImageIO.getImageWritersByFormatName("GIF");
if(! it.hasNext()){
System.err.println("GIF フォーマットの書き込みをサポートしていません");
return;
}
ImageWriter writer = it.next();
writer.setOutput(out);
// GIF ヘッダの設定
/*
// ヘッダを明示的に指定する場合
IIOMetadata meta = writer.getDefaultStreamMetadata(null);
String format = meta.getNativeMetadataFormatName();
IIOMetadataNode root = (IIOMetadataNode)meta.getAsTree(format);
IIOMetadataNode node = new IIOMetadataNode("Version");
node.setAttribute("value", "87a");
root.appendChild(node);
node = new IIOMetadataNode("LogicalScreenDescriptor");
node.setAttribute("logicalScreenWidth", "200");
node.setAttribute("logicalScreenHeight", "200");
node.setAttribute("colorResolution", "8");
node.setAttribute("pixelAspectRatio", "0");
root.appendChild(node);
meta.setFromTree(format, root);
writer.prepareWriteSequence(meta);
*/
writer.prepareWriteSequence(null);
for(int i=0; i<image.length; i++){
// メタデータ (GIF における画像以外の拡張ブロック) を参照
IIOMetadata meta = writer.getDefaultImageMetadata(
ImageTypeSpecifier.createFromRenderedImage(image[i]), null);
String format = meta.getNativeMetadataFormatName();
IIOMetadataNode root = (IIOMetadataNode)meta.getAsTree(format);
// この画像のグラフィック制御 (待ち時間など) を設定
root.appendChild(
GifRecipes.getGraphicControlExtension(
GifRecipes.DisposalMethod.NONE, false, false, 0, 50));
// 最初の画像の場合はループ回数とコメントも追加
if(i == 0){
root.appendChild(GifRecipes.getNetscapeLoop(0));
root.appendChild(GifRecipes.getCommentExtension("MOYO Laboratory Number Animation Sample"));
}
if(i+1 == image.length){
root.appendChild(GifRecipes.getPlainTextExtension(0, 0, 100, 16, 256, 256, 0, 1, "hello, world"));
}
// メタデータと画像を出力
meta.setFromTree(format, root);
writer.writeToSequence(new IIOImage(image[i], null, meta), null);
}
// 書き込みの終了
writer.endWriteSequence();
} finally {
out.close();
}
return;
}
// ======================================================================
// アニメーション画像の作成
// ======================================================================
/**
* アニメーションに使用する各フレームのサンプル画像を作成します。緑色の
* 背景に 0~9 の数字を描いた画像を返します。
* <p>
* @return アニメーションのフレーム画像
*/
private static BufferedImage[] getAnimationFrames(){
BufferedImage[] image = new BufferedImage[10];
for(int i=0; i<image.length; i++){
image[i] = new BufferedImage(10, 16, BufferedImage.TYPE_4BYTE_ABGR);
Graphics g = image[i].getGraphics();
g.setColor(new Color(0x9ACD32));
g.drawRect(0, 0, 8, 16);
g.setColor(Color.WHITE);
g.setFont(new Font("Dialog", Font.BOLD, 12));
FontMetrics fm = g.getFontMetrics();
g.drawString(String.valueOf(i), 2, fm.getAscent());
}
return image;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment