javafx中的任意形状是否有"填充"功能?

n00*_*990 1 css java javafx paint javafx-8

我需要知道哪种方式可以使用JavaFX为下面的图像(PNG)着色.该图像目前包含在JavaFX的ImageView中:

不同部分的图像http://s12.postimg.org/wofhjvy2h/image_2.jpg

我想将区域1蓝色,第二个红色,最后两个紫色.我怎么能在JavaFX中做到这一点?是不是在Windows Paint中有某种功能?(你知道,填充某个区域的绘画桶,边框之间有颜色).

jew*_*sea 5

建议的方法

您可以使用泛洪填充算法.

填充

示例代码

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Point2D;
import javafx.scene.Scene;
import javafx.scene.image.*;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

import java.util.Stack;

public class UnleashTheKraken extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(final Stage stage) {
        Image original = new Image(
            "http://s12.postimg.org/wofhjvy2h/image_2.jpg"
        );

        WritableImage updateable = new WritableImage(
                original.getPixelReader(),
                (int) original.getWidth(),
                (int) original.getHeight()
        );

        Kraken kraken = new Kraken(updateable, Color.WHITE);
        kraken.unleash(new Point2D(40,   40), Color.BLUE);
        kraken.unleash(new Point2D(40,  100), Color.RED);
        kraken.unleash(new Point2D(100, 100), Color.GREEN);
        kraken.unleash(new Point2D(120,  40), Color.YELLOW);

        ImageView originalView = new ImageView(original);
        ImageView filledView   = new ImageView(updateable);

        HBox layout = new HBox(10, originalView, filledView);
        layout.setPadding(new Insets(10));
        stage.setScene(new Scene(layout));
        stage.show();
    }

    class Kraken {
        private final WritableImage image;
        private final Color colorToFill;

        // tolerance for color matching (on a scale of 0 to 1);
        private final double E = 0.3;

        public Kraken(WritableImage image, Color colorToFill) {
            this.image = image;
            this.colorToFill = colorToFill;
        }

        public void unleash(Point2D start, Color color) {
            PixelReader reader = image.getPixelReader();
            PixelWriter writer = image.getPixelWriter();

            Stack<Point2D> stack = new Stack<>();
            stack.push(start);

            while (!stack.isEmpty()) {
                Point2D point = stack.pop();
                int x = (int) point.getX();
                int y = (int) point.getY();
                if (filled(reader, x, y)) {
                    continue;
                }

                writer.setColor(x, y, color);

                push(stack, x - 1, y - 1);
                push(stack, x - 1, y    );
                push(stack, x - 1, y + 1);
                push(stack, x    , y + 1);
                push(stack, x + 1, y + 1);
                push(stack, x + 1, y    );
                push(stack, x + 1, y - 1);
                push(stack, x,     y - 1);
            }
        }

        private void push(Stack<Point2D> stack, int x, int y) {
            if (x < 0 || x > image.getWidth() ||
                y < 0 || y > image.getHeight()) {
                return;
            }

            stack.push(new Point2D(x, y));
        }

        private boolean filled(PixelReader reader, int x, int y) {
            Color color = reader.getColor(x, y);

            return !withinTolerance(color, colorToFill, E);
        }

        private boolean withinTolerance(Color a, Color b, double epsilon) {
            return
                    withinTolerance(a.getRed(),   b.getRed(),   epsilon) &&
                    withinTolerance(a.getGreen(), b.getGreen(), epsilon) &&
                    withinTolerance(a.getBlue(),  b.getBlue(),  epsilon);
        }

        private boolean withinTolerance(double a, double b, double epsilon) {
            return Math.abs(a - b) < epsilon;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

其他问题的答案

但是图像不是逐像素着色的吗?

是的,这就是重点,你需要遮挡像素.具有位图显示的计算机图形中的所有内容最终归结为着色像素.

这是一种有效的着色方式吗?

这是您提供的样本图像的瞬间(据我所知).它在空间方面占用了一些内存,但所有这些算法都会使用内存.我提供的示例代码不是可以设计的最有效的洪水填充着色算法(时间或空间方式).我链接的维基百科页面可以提供更高效(更复杂)的算法,如果需要,可以应用.

替代方法

如果每个区域都有一个切出的模板形状,您可以堆叠模板并对它们应用ColorAdjust效果(例如:如何在JavaFX中更改图像的颜色).ColorAdjust(可能)是硬件加速效果.这种替代方法不是一般方法,因为它需要您了解模板形状.