CUBは子供の白熊

Java SE 8 実践プログラミングの練習問題を解く

第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();
}

■ 実行結果 f:id:ClosedUnBounded:20150611185257p:plain