如何在 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()
    );
}