【JavaFX】エフェクトをかけたImageを作成し、ファイル保存とかやってみる

2018年6月1日

ゲーム制作途中で、既存の画像の色をプログラム内で変更して使いたいと思い、エフェクトをかけて表示してみたのですが、カメラ使ってると表示がおかしくなるっぽい(Java9の時点)ので、エフェクト適用済みのNodeを純粋なImageオブジェクトに変換することにしました。

snapshotというメソッドがあるのですが、これはNodeに対して実行でき、表示している内容を画像化できます。こいつを使用して新しいImageを作成してみましょう。

今回使うサンプル画像はこれ

mogmol.png

下記がサンプルプログラムです。

package com.nompor.app;

import java.io.File;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.SnapshotParameters;
import javafx.scene.effect.ColorAdjust;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;


public class Test extends Application{

	public static void main(String[] args) {
		launch(args);
	}

	@Override
	public void start(Stage primaryStage) {
		View v = new View();
		Scene scene = new Scene(v, 400, 400);
		primaryStage.setScene(scene);
		primaryStage.show();
	}
}
class View extends Pane{
	public View() {
		//画像
		ImageView image = new ImageView(new File("mogmol.png").toURI().toString());

		//色相変更
		ColorAdjust ef = new ColorAdjust();
		ef.setHue(0.6);
		image.setEffect(ef);

		//新しい画像を作成する
		WritableImage newImage = new WritableImage((int)image.getImage().getWidth(), (int)image.getImage().getHeight());
		SnapshotParameters params = new SnapshotParameters();
		params.setFill(Color.TRANSPARENT);
		image.snapshot(params, newImage);
		ImageView newView = new ImageView(newImage);

		//位置を中心に移動
		newView.setTranslateX(200 - image.getLayoutBounds().getWidth()/2);
		newView.setTranslateY(200 - image.getLayoutBounds().getHeight()/2);

		//新しい画像を表示する
		getChildren().add(newView);
	}
}
実行結果

ゲームではまず使わないのですが、せっかくなのでファイル保存とかもやってみましょうか。

JavaFXとSwingの連携メソッドで画像変換をかけBufferedImageに変換します。あとはImageIOで画像の書き出しをします。

package com.nompor.app;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.SnapshotParameters;
import javafx.scene.effect.Bloom;
import javafx.scene.effect.ColorAdjust;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.paint.Color;
import javafx.stage.Stage;


public class Test extends Application{

	public static void main(String[] args) throws IOException {
		launch(args);
	}

	@Override
	public void start(Stage arg0) throws Exception {
		ImageView image = new ImageView(new File("mogmol.png").toURI().toString());

		//色相変更
		ColorAdjust ef = new ColorAdjust();
		ef.setHue(0.6);

		//さらにピッカピカのエフェクト
		Bloom b = new Bloom(0.1);
		b.setInput(ef);

		image.setEffect(b);

		//新しい画像を作成する
		WritableImage newImage = new WritableImage((int)image.getImage().getWidth(), (int)image.getImage().getHeight());
		SnapshotParameters params = new SnapshotParameters();
		params.setFill(Color.TRANSPARENT);
		image.snapshot(params, newImage);

		//BufferedImageへ変換
		BufferedImage resultImg = new BufferedImage((int)newImage.getWidth(), (int)newImage.getHeight(), BufferedImage.TYPE_INT_ARGB);
		SwingFXUtils.fromFXImage(newImage, resultImg);

		//ファイル書き出し
		ImageIO.write(resultImg, "png", new File("mogmol_blue.png"));
	}
}
実行結果

ライブラリにも今回紹介した内容のエフェクト適用メソッドを入れておくことにします。

JavaJavaFX

Posted by nompor