第3章 ラムダ式を使ったプログラミング : 問題 12 : 遅延画像クラス LatentImage の拡張
問題
本文に出てきた色変換を遅延実行する画像 LatentImage クラスをUnaryOperator<Color>
とColorTransformer
の両方をサポートするように拡張せよ
■ LatentImage クラスの概要
public class LatentImage { /** 変換対象の画像 */ private final Image in; /** 適用する色変換 */ private List<UnaryOperator<Color>> pendingOperations; /** オブジェクトの生成 */ public static LatentImage from(Image in) { … } /** 色変換の適用 */ public LatentImage transform(UnaryOperator<Color> f) { … } /** 色変換適用済みの画像の取得 */ public Image toImage() { … } }
解答
ここでは、問題 11 で実装した static メソッドColorTransformer.onlyColor
を使う
public class LatentImage { /** 変換対象の画像 */ private final Image in; /** 適用する色変換 */ private List<ColorTransformer> pendingOperations; /** コンストラクタ */ private LatentImage(Image in) { this.in = in; pendingOperations = new ArrayList<ColorTransformer>(); } /** オブジェクトの生成 */ public static LatentImage from(Image in) { return new LatentImage(in); } /** 座標を無視した色変換の適用 */ public LatentImage transform(UnaryOperator<Color> f) { pendingOperations.add(ColorTransformer.onlyColor(f)); return this; } /** 色変換の適用 */ public LatentImage transform(ColorTransformer f) { pendingOperations.add(f); return this; } /** 色変換適用済みの画像の取得 */ public Image toImage() { int width = (int)in.getWidth(); int height = (int)in.getHeight(); WritableImage out = new WritableImage(width, height); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { Color c = in.getPixelReader().getColor(x, y); for (ColorTransformer f : pendingOperations) { c = f.apply(x, y, c); } out.getPixelWriter().setColor(x, y, c); } } } }
例えば
- グレイスケール
- 明度アップ
- 青い枠
の色変換を合成する場合は、以下のように呼び出す
public void start(Stage stage) throws Exception { Image image = new Image("queen-mary.png"); int width = (int)image.getWidth(); int height = (int)image.getHeight(); Image image2; ColorTransformer frame = (x, y, c) -> x < 15 || y < 15 || x >= width - 15 || y >= height - 15 ? Color.AQUAMARINE : c; image2 = LatentImage.from(image) .transform(Color::grayscale) .transform(Color::brighter) .transform(frame) .toImage(); stage.setScene(new Scene(new HBox(new ImageView(image), new ImageView(image2)))); stage.show(); }
■ 実行結果