如何在 JavaFX 渐变中插入颜色?
How are colors interpolated in a JavaFX gradient?
我正在尝试弄清楚如何在涉及透明度时复制 JavaFX 渐变 interpolated/blended。如果我尝试使用内置 Color#interpolate
方法在颜色之间进行插值的天真方法,我会得到完全不同的结果。如您所见:
两个渐变都是简单的 [red @ 0%, rgba(0, 0, 255, 0) @ 50%, green @ 100%],但是在 JavaFX 渐变中根本看不到蓝色 (顶部)并且在天真的方法中非常明显(底部)。在渐变中如何插入颜色的实际公式是什么,在哪里可以找到它(即什么方法 class)?
这是一个显示半透明的示例(从 rgba(255, 0, 0, 1) 到 rgba(0, 0, 255, 0.5)):
该图显示了最终颜色的采样分量(白色代表不透明度)。注意颜色通道是如何非线性插值的。我正在寻找可以如图所示调整曲线的方程式。
此答案归功于 @fabian
渲染渐变时,Prism uses pre-multiplied colors。
要获得相同的结果,您可以像这样手动预乘:
public Color interpolatePreMultiplied(double ratio, Color origin, Color target) {
var opacity = lerp(ratio, origin.getOpacity(), target.getOpacity());
return opacity == 0.0 ? Color.TRANSPARENT : Color.color(
lerp(ratio, origin.getRed() * origin.getOpacity(), target.getRed() * target.getOpacity()) / opacity,
lerp(ratio, origin.getRed() * origin.getOpacity(), target.getRed() * target.getOpacity()) / opacity,
lerp(ratio, origin.getBlue() * origin.getOpacity(), target.getBlue() * target.getOpacity()) / opacity,
opacity
);
}
public double lerp(double ratio, double origin, double target) {
return origin + (target - origin) * ratio;
}
或者您可以使用一些实用程序转换:
public Color interpolatePreMultiplied(double ratio, Color origin, Color target) {
var po = toPreMutliplied(origin);
var pt = toPreMultiplied(target);
return toStraightAlpha(po.interpolate(pt, ratio));
}
public Color toPreMultiplied(Color color) {
return Color.color(
color.getRed() * color.getOpacity(),
color.getGreen() * color.getOpacity(),
color.getBlue() * color.getOpacity(),
color.getOpacity()
);
}
public Color toStraightAlpha(Color color) {
return color.getOpacity() == 0.0 ? Color.TRANSPARENT : Color.color(
color.getRed() / color.getOpacity(),
color.getGreen() / color.getOpacity(),
color.getBlue() / color.getOpacity(),
color.getOpacity()
);
}
我正在尝试弄清楚如何在涉及透明度时复制 JavaFX 渐变 interpolated/blended。如果我尝试使用内置 Color#interpolate
方法在颜色之间进行插值的天真方法,我会得到完全不同的结果。如您所见:
两个渐变都是简单的 [red @ 0%, rgba(0, 0, 255, 0) @ 50%, green @ 100%],但是在 JavaFX 渐变中根本看不到蓝色 (顶部)并且在天真的方法中非常明显(底部)。在渐变中如何插入颜色的实际公式是什么,在哪里可以找到它(即什么方法 class)?
这是一个显示半透明的示例(从 rgba(255, 0, 0, 1) 到 rgba(0, 0, 255, 0.5)):
该图显示了最终颜色的采样分量(白色代表不透明度)。注意颜色通道是如何非线性插值的。我正在寻找可以如图所示调整曲线的方程式。
此答案归功于 @fabian
渲染渐变时,Prism uses pre-multiplied colors。
要获得相同的结果,您可以像这样手动预乘:
public Color interpolatePreMultiplied(double ratio, Color origin, Color target) {
var opacity = lerp(ratio, origin.getOpacity(), target.getOpacity());
return opacity == 0.0 ? Color.TRANSPARENT : Color.color(
lerp(ratio, origin.getRed() * origin.getOpacity(), target.getRed() * target.getOpacity()) / opacity,
lerp(ratio, origin.getRed() * origin.getOpacity(), target.getRed() * target.getOpacity()) / opacity,
lerp(ratio, origin.getBlue() * origin.getOpacity(), target.getBlue() * target.getOpacity()) / opacity,
opacity
);
}
public double lerp(double ratio, double origin, double target) {
return origin + (target - origin) * ratio;
}
或者您可以使用一些实用程序转换:
public Color interpolatePreMultiplied(double ratio, Color origin, Color target) {
var po = toPreMutliplied(origin);
var pt = toPreMultiplied(target);
return toStraightAlpha(po.interpolate(pt, ratio));
}
public Color toPreMultiplied(Color color) {
return Color.color(
color.getRed() * color.getOpacity(),
color.getGreen() * color.getOpacity(),
color.getBlue() * color.getOpacity(),
color.getOpacity()
);
}
public Color toStraightAlpha(Color color) {
return color.getOpacity() == 0.0 ? Color.TRANSPARENT : Color.color(
color.getRed() / color.getOpacity(),
color.getGreen() / color.getOpacity(),
color.getBlue() / color.getOpacity(),
color.getOpacity()
);
}