アニメを見てると「いまの作画かっこいいなー」と思い、コマ送りで原画・動画を確認したくなることが時々ある。今回は唐突にゲームのOPのコマ送り画像が見たくなったため、連続で画面キャプチャを行い、コマ撮り画像を取得するプログラムを作ってみた。
◇コード
package application;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.image.WritableImage;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.robot.Robot;
import javafx.stage.Stage;
public class Main extends Application {
private Stage primaryStage;
private TextField text = new TextField();
private Robot robot = new Robot();
private double xOffset = 0;
private double yOffset = 0;
@Override
public void start(Stage primaryStage) {
// 退避
this.primaryStage = primaryStage;
try {
// Pane
StackPane root = new StackPane();
HBox hbox1 = new HBox();
HBox hbox2 = new HBox();
root.getChildren().add( hbox2 );
root.getChildren().add( hbox1 );
root.setStyle("-fx-background-color: rgba(0,0,0,0.3);");
// 開始ボタン
Button btn1 = new Button("キャプチャ");
EventHandler<ActionEvent> btn1Handler = ( event ) -> {
try {
this.capture();
} catch (IOException e) {
e.printStackTrace();
}
};
btn1.addEventHandler( ActionEvent.ANY , btn1Handler );
hbox1.getChildren().add( btn1 );
// テキストフィールド
text.setText( "20" );
hbox1.getChildren().add( text );
// 範囲選択
EventHandler<MouseEvent> pressHandler = ( event ) -> {
xOffset = event.getSceneX();
yOffset = event.getSceneY();
};
root.addEventHandler( MouseEvent.MOUSE_PRESSED , pressHandler );
EventHandler<MouseEvent> dragHandler = ( event ) -> {
primaryStage.setX(event.getScreenX() - xOffset);
primaryStage.setY(event.getScreenY() - yOffset);
};
root.addEventHandler( MouseEvent.MOUSE_DRAGGED , dragHandler );
// Scene
Scene scene = new Scene(root,400,400, Color.TRANSPARENT);
// Stage
primaryStage.setScene(scene);
primaryStage.setOpacity( 0.75 );
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
private void capture() throws IOException
{
// キャプチャ準備
int time = Integer.parseInt( text.getText() );
this.primaryStage.hide();
// 画面サイズを取得
BufferedImage bImg = new BufferedImage((int)this.primaryStage.getWidth(), (int)this.primaryStage.getHeight(), BufferedImage.TYPE_INT_RGB);
int x = (int) primaryStage.getX();
int y = (int) primaryStage.getY();
int width = (int) primaryStage.getWidth();
int height = (int) primaryStage.getHeight();
// アニメーション取得
List<WritableImage> list = new ArrayList<WritableImage>();
for( int i = 0 ; i < time ; i++ )
{
// キャプチャ
WritableImage img = robot.getScreenCapture(null, x,y,width,height);
list.add( img );
}
// ファイル出力
for( int i = 0 ; i < list.size() ; i++ )
{
// ファイル名
String fileName = String.format( "result/output%03d.png" , i );
// 画像出力
SwingFXUtils.fromFXImage( list.get(i) , bImg );
ImageIO.write( bImg , "png" , new File( fileName ) );
}
// ウィンドウを復元
primaryStage.show();
primaryStage.setX( x );
primaryStage.setY( y );
primaryStage.setWidth( width );
primaryStage.setHeight( height );
}
}
◇実行結果
画面上でキャプチャ対象の動画を再生し、上記プログラムで「キャプチャ」ボタンを押下した際の実行結果は以下の通り。
ウィンドウのイメージ
出力画像サンプル
「
テイルズオブデスティニー」よりOP
◇解説
プログラムはJavaFXで作成している。JavaFXでのライブラリ設定と起動引数については、
こちらを参照。 半透明のウィンドウを表示し、「キャプチャ」ボタンを押下するとウィンドウの背面の画像を取得することができる。画面キャプチャはテキスト・フィールドに入力したコマ数分だけ取得し、Robotクラスで取得している。