2016-04-21 15 views
0

私は8ビットの画像にエフェクトを適用したいと思います。これは8ビットの入力カラーごとに出力32ビットカラーを関連付けます。エフェクトを適用すると、入力カラーが関連するものに置き換えられます。javafxでカラーマップ効果を作成するには?

プログラムでイメージビットマップの書き換えを実装できます。しかし、私はそれが効率を妨げるのではないかと心配しています。効果のような機能を実装するのが最善です。

どうすればいいですか?

+0

[カラーサイクリング](http://www.effectgames.com/demos/canvascycle/)をしようとしていますか? [Effect](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/effect/Effect.html)をサブクラス化しようとしていますか、またはこのコンテキストで他の何かを意味していますか? – jewelsea

+0

私はこのようなことをしようとしています。より正確にはサイクリングではありませんが、ユーザーの入力に反応するアニメーション – ayvango

答えて

2

を使用してWritableImageを使用することも可能です(ご希望のものを正しく理解している場合)。

ここでは、値が変わるたびにインデックスを更新し、毎回イメージのピクセルを設定する非常に単純なアニメーションの例を示します。これは非常に効率的ですが、あなたがしようとしていることを達成するためのより効率的な方法があるかもしれません。

import javafx.animation.Animation; 
import javafx.animation.KeyFrame; 
import javafx.animation.KeyValue; 
import javafx.animation.Timeline; 
import javafx.application.Application; 
import javafx.beans.property.DoubleProperty; 
import javafx.beans.property.SimpleDoubleProperty; 
import javafx.scene.Scene; 
import javafx.scene.image.ImageView; 
import javafx.scene.image.PixelFormat; 
import javafx.scene.image.WritableImage; 
import javafx.scene.layout.StackPane; 
import javafx.scene.paint.Color; 
import javafx.stage.Stage; 
import javafx.util.Duration; 

public class IndexedImage extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     int width = 600 ; 
     int height = 600 ; 
     WritableImage img = new WritableImage(width, height); 
     byte[] pixels = createPixels(width, height); 

     DoubleProperty hue = new SimpleDoubleProperty(); 
     hue.addListener((obs, oldValue, newValue) -> { 
      updateImage(img, pixels, newValue.doubleValue()); 
     }); 

     Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(3), new KeyValue(hue, 360))); 
     timeline.setCycleCount(Animation.INDEFINITE); 


     Scene scene = new Scene(new StackPane(new ImageView(img))); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 

     timeline.play(); 
    } 

    private void updateImage(WritableImage img, byte[] pixels, double hue) { 
     int[] colorIndex = new int[256]; 
     for (int i = 0 ; i < colorIndex.length; i++) { 
      Color c = Color.hsb(hue, 1.0*i/colorIndex.length, 1.0); 
      colorIndex[i] = getArgb(c); 
     } 
     int w = (int) img.getWidth(); 
     int h = (int) img.getHeight(); 
     img.getPixelWriter().setPixels(0, 0, w, h, PixelFormat.createByteIndexedInstance(colorIndex), pixels, 0, w); 
    } 

    private int getArgb(Color c) { 
     int a = (int) (255*c.getOpacity()); 
     int r = (int) (255*c.getRed()); 
     int g = (int) (255*c.getGreen()); 
     int b = (int) (255*c.getBlue()); 
     return (a << 24) | (r << 16) | (g << 8) | b ; 
    } 

    private byte[] createPixels(int width, int height) { 
     byte[] pixels = new byte[width * height]; 
     int d = width * width + height * height; 
     for (int i = 0 ; i < pixels.length; i++) { 
      int x = i % width ; 
      int y = i/width ; 
      pixels[i] = (byte) (256 * (height * y + width * x)/d); 
     } 
     return pixels ; 
    } 

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

は、キャンバスに直接書き込むよりもイメージを書き直す方が効率的でしょうか? – ayvango

+0

わかりません。実際のユースケースではおそらくかなり依存しています。 –

+0

ああ、それはクールです。数年前にこれを見ると、バイトインデックス形式は完全に実装されず、機能していませんでした。ニースは、この機能が最近のJREバージョンで動作することを確認しています。 – jewelsea

関連する問題