What you are Doing Wrong
差异运算符不是基于是否设置像素而不是RGB分量的差异的二进制差异,因此代替实心红色叠加,您将获得多色叠加,因为RGB组件的差异混合图像在像素之间不同 .
Background
您正在尝试使用混合模式执行与masked bit-blit operation类似的操作(基本上是OR,然后是基于黑色蒙版上的白色的像素数据的AND) . JavaFX 8中的内置混合可能有点棘手 .
您可以在混合API中为bit-blt样式基础创建一个功能请求,以及公开Swing has这样的完整porter duff compositing实现,以便底层混合引擎具有更强大的功能,并且可能更容易使用 .
Alternatives
首选的方法是在像photoshop这样的图像编辑器中预处理你的蒙版,将黑色部分转换为alpha通道 - 然后你可以将你的蒙版层叠在原始图像上,默认的合成模式将采用它 .
要使支持alpha的蒙版成为红色,您可以使用 mask.setBlendMode(BlendMode.RED) (或者您可以在图像编辑器中对蒙版进行预着色,然后再在程序中使用它) .
另一种选择是您在问题中使用的PixelReader解决方案(如果您无法预先将掩码转换为使用alpha,我认为这很好) .
混合操作可以在适当的硬件上进行硬件加速 . 因此,如果您经常使用混合可能会更快(但是您必须在大图像上快速运行许多混合才能真正注意到任何类型的性能差异) .
Sample Solution Using Blend Operations
样本输出
输入图像
original.jpg
stencil.jpg
码
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.*;
import javafx.scene.effect.BlendMode;
import javafx.scene.image.*;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
public class Blended extends Application {
@Override
public void start(Stage stage) {
Image original = new Image(
getClass().getResourceAsStream("original.jpg")
);
Image stencil = new Image(
getClass().getResourceAsStream("stencil.jpg")
);
// first invert the stencil so that it is black on white rather than white on black.
Rectangle whiteRect = new Rectangle(stencil.getWidth(), stencil.getHeight());
whiteRect.setFill(Color.WHITE);
whiteRect.setBlendMode(BlendMode.DIFFERENCE);
Group inverted = new Group(
new ImageView(stencil),
whiteRect
);
// overlay the black portions of the inverted mask onto the image.
inverted.setBlendMode(BlendMode.MULTIPLY);
Group overlaidBlack = new Group(
new ImageView(original),
inverted
);
// create a new mask with a red tint (red on black).
Rectangle redRect = new Rectangle(stencil.getWidth(), stencil.getHeight());
redRect.setFill(Color.RED);
redRect.setBlendMode(BlendMode.MULTIPLY);
Group redStencil = new Group(
new ImageView(stencil),
redRect
);
// overlay the red mask on to the image.
redStencil.setBlendMode(BlendMode.ADD);
Group overlaidRed = new Group(
overlaidBlack,
redStencil
);
// display the original, composite image and stencil.
HBox layout = new HBox(10);
layout.getChildren().addAll(
new ImageView(original),
overlaidRed,
new ImageView(stencil)
);
layout.setPadding(new Insets(10));
stage.setScene(new Scene(layout));
stage.show();
}
public static void main(String[] args) {
launch();
}
}