2016-04-21 18 views
0

Ich möchte einen Effekt auf 8-Bit-Bild anwenden, die mit jeder 8-Bit-Eingabefarbe eine Ausgabe 32-Bit-Farbe zuordnen. Durch das Anwenden der Effekte werden die Eingabefarben durch die zugehörigen Farben ersetzt.Wie mache ich Colormap-Effekt in Javafx?

Ich könnte programmgesteuert das Bild Bitmap neu schreiben implementieren. Aber ich befürchte, es würde die Effizienz beeinträchtigen. Es wäre am besten, diese Funktionalität als Effekt zu implementieren.

Wie könnte das getan werden?

+0

Versuchen Sie [color cycling] (http://www.effectgames.com/demos/canvascycle/)? Versuchen Sie, [Effect] (https://docs.oracle.com/javase/effect/Effect.html) zu unterklassifizieren oder bedeutet Effekt in diesem Kontext etwas anderes? – jewelsea

+0

Ich versuche so etwas zu tun. Genauer gesagt nicht Radfahren, aber Animation, die auf Benutzereingabe reagiert – ayvango

Antwort

2

Eine Möglichkeit (wenn ich richtig verstehe, was Sie suchen) ist die Verwendung eines WritableImage mit einem indexed pixel format.

Hier ist ein Beispiel für eine sehr einfache Animation, die den Index aktualisiert, wenn sich ein Wert ändert, und jedes Mal die Pixel des Bildes setzt. Dies scheint ziemlich effizient zu sein, auch wenn es möglicherweise effizientere Wege gibt, um das zu erreichen, was Sie tun möchten.

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

wäre das Umschreiben von Bildern effizienter als direkt auf Leinwand schreiben? – ayvango

+0

Nicht sicher. Es hängt wahrscheinlich ziemlich viel von Ihrem tatsächlichen Anwendungsfall ab. –

+0

Oh, das ist cool. Als ich das vor ein paar Jahren angeschaut habe, war das byte-indizierte Format nicht vollständig implementiert und funktionierte. Es ist schön zu sehen, dass das Feature jetzt auf neueren JRE-Versionen funktioniert. – jewelsea