javafx中的任意形状是否有“填充”function?

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

不同部分的图像http://sofzh.miximages.com/java/image_2.jpg

我想将区域1蓝色,第二个红色,最后两个紫色。 如何在JavaFX中执行此操作? 是不是在Windows Paint中有某种function? (你知道,填充某个区域的绘画桶,边框之间有颜色)。

建议的方法

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

填充

示例代码

 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 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 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; } } } 

其他问题的答案

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

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

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

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

替代方法

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

 Shape circle = new Circle(x,y,r); Shape rect = new Rectangle(x,y,w,h); Shape region1 = Shape.subtract(circle, rect);// to "cut" the rect away from a circle. // You'll need to do this twice for each piece. region1 = Shape.subtract(region1,anotherRect); region1.setFill(Color.BLUE); // Then simply add your shape to a node and set it's translation. 

这种方式的工作方式是矩形与圆重叠,圆的那部分将被删除。