2

JavaFXのCanvasのGraphicsContextに、パス内のすべてのピクセルをオーバーライドして、再び透明になる方法があるかどうか疑問に思っています。clearRect 関数と同様ですが、任意のパスに対応します。

さまざまな BlendModes と Effects を見てきましたが、実際に達成できるアルファ値を実際にオーバーライドする方法はないようです。

  • Porter/Duff Src オペレーターを使用して透明色をレンダリングする
  • HTML5 で globalCompositeOperation destination-out を使用して非透明色をレンダリングする

誰かがパスをテッセレーションせずに複数の clearRect 呼び出しを使用せずにこれを達成する方法を知っていれば、とてもうれしいです。ありがとうございました。

http://docs.oracle.com/javase/8/javafx/api/javafx/scene/canvas/GraphicsContext.html


最初のコメントへの追加: Path ノードを使用する代わりに、Canvas ノードを使用して GraphicsContext を使用してレンダリングを実行しているため、以前にレンダリングされたパスの色を変更することはできません。私は次のようなことをしようとしています

Canvas canvas = …;
final GraphicsContext context = canvas.getGraphicsContext();
context.setFill(Color.BLUE);
context.fillRect(0,0,100,100);
…
…

後で、パス内のピクセルを透明にリセットしたい

context.setStroke(Color.TRANSPARENT);
context.beginPath();
context.moveTo(0, 0);
context.lineTo(10,10);
…
context.stroke();

ただし、ブレンドが適用されると、これは機能しません。他のレンダリング ライブラリでは、たとえば上記のブレンディング/合成方法の 1 つを使用してこれを実現することができますが、これまで javafx でそのような機能を特定できませんでした。

4

2 に答える 2

2

パスに応じてキャンバスをクリアするメカニズムが見つかりませんでした。ただし、手動で行う方法は次のとおりです。

  • パスを描くマスクを作成する
  • 画像とマスクを手動でブレンドする

パス付きのマスクが適用された青い四角形の例:

public class ManualBlendWithMask extends Application {

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

    @Override
    public void start(Stage primaryStage) {

        Group root = new Group();

        // create canvas
        Canvas canvas = new Canvas(200, 200);
        canvas.setTranslateX(100);
        canvas.setTranslateY(100);

        // create canvas with blue rectangle
        GraphicsContext canvasGC = canvas.getGraphicsContext2D();
        canvasGC.setFill(Color.BLUE);
        canvasGC.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());

        // create mask
        Canvas mask = new Canvas( canvas.getWidth(), canvas.getHeight());
        GraphicsContext maskGC = mask.getGraphicsContext2D();
        maskGC.setFill(Color.WHITE);
        maskGC.fillRect(0, 0, mask.getWidth(), mask.getHeight());

        // draw path
        maskGC.setStroke(Color.BLACK);
        maskGC.setLineWidth(20);
        maskGC.beginPath();
        maskGC.moveTo(0, 0);
        maskGC.lineTo(400, 400);
        maskGC.stroke();

        // get image from canvas
        WritableImage srcImage = new WritableImage((int) canvas.getWidth(), (int) canvas.getHeight());
        srcImage = canvas.snapshot(null, srcImage);

        // get image from mask
        WritableImage srcMask = new WritableImage((int) mask.getWidth(), (int) mask.getHeight());
        srcMask = mask.snapshot(null, srcMask);

        PixelReader maskReader = srcMask.getPixelReader();
        PixelReader imageReader = srcImage.getPixelReader();

        int width = (int) srcMask.getWidth();
        int height = (int) srcMask.getHeight();

        // create dest image
        WritableImage dest = new WritableImage(width, height);
        PixelWriter writer = dest.getPixelWriter();

        // blend image and mask
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {

                Color maskColor = maskReader.getColor(x, y);
                Color imageColor = imageReader.getColor(x, y);

                if (maskColor.equals(Color.WHITE)) {
                    writer.setColor(x, y, imageColor);
                }

            }
        }

        // clear canvas and fill it with the blended image
        canvasGC = canvas.getGraphicsContext2D();
        canvasGC.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());
        canvasGC.drawImage(dest, 0, 0);

        // draw background with gradient
        Rectangle rect = new Rectangle(400, 400);
        rect.setFill(new LinearGradient(0, 0, 1, 1, true, CycleMethod.REFLECT, new Stop(0, Color.RED), new Stop(1, Color.YELLOW)));

        // show nodes
        root.getChildren().addAll(rect, canvas);

        primaryStage.setScene(new Scene(root, 400, 400));
        primaryStage.show();

    }

}

もちろん、誰かが BlendModes を使った例を思いつくことができればもっと良いでしょう。 ここに画像の説明を入力

于 2015-03-04T08:19:47.097 に答える
0

このような 2015 年以降の投稿をいくつか見た後、これがまだ に追加されていないことに驚きましたjavaFX。私が言えることから、「DST-OUT」ブレンディングオプションがAWTにあったので、なぜではないのjavaFXですか?!

とにかく..私は自分の解決策を見つけた後にここに戻ってきたので、私の解決策を共有し、答えを求めてここにやってくる次の落ち着きのない魂を助けることができれば幸いです.

私の特定の必要性は、に基づく領域でキャンバスを透明にすることでしたSVGPath。だからここに私の解決策があります:

private void clearPath(GraphicsContext gc, SVGPath path) {
    int xstart = (int) path.getLayoutX();
    int xend = (int) (xstart + path.getLayoutBounds().getMaxX());
    int ystart = (int) path.getLayoutY();
    int yend = (int) (ystart + path.getLayoutBounds().getMaxY());

    PixelWriter pw = gc.getPixelWriter();
    for (int x = xstart; x <= xend; x++) {
        for (int y = ystart; y <= yend; y++) {
            if(path.contains(new Point2D(x, y))) {
                pw.setColor(x, y, Color.TRANSPARENT);
            }
        }
    }
}
于 2020-01-16T13:57:18.853 に答える