Fix ColorExtensions math (#41717)
All of this was doing sRGB -> OkLAB conversions without linearizing the sRGB first, so it was broken. I could have sworn I pointed this out in review but I guess that got lost. Also, add a gamut clipping step since we have out-of-gamut colors and I don't want random negative values causing weird nightmare bugs somewhere. Shouldn't change anything in regular rendering.
This commit is contained in:
parent
091b7d98b6
commit
1c4806740c
|
|
@ -14,10 +14,10 @@ public static class ColorExtensions
|
|||
{
|
||||
DebugTools.Assert(lightness is >= 0.0f and <= 1.0f);
|
||||
|
||||
var oklab = Color.ToLab(c);
|
||||
var oklab = c.LabFromSrgb();
|
||||
oklab.X = lightness;
|
||||
|
||||
return Color.FromLab(oklab);
|
||||
return oklab.LabToSrgb();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -25,10 +25,10 @@ public static class ColorExtensions
|
|||
/// </summary>
|
||||
public static Color NudgeLightness(this Color c, float lightnessShift)
|
||||
{
|
||||
var oklab = Color.ToLab(c);
|
||||
var oklab = c.LabFromSrgb();
|
||||
oklab.X = Math.Clamp(oklab.X + lightnessShift, 0, 1);
|
||||
|
||||
return Color.FromLab(oklab);
|
||||
return oklab.LabToSrgb();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -39,12 +39,12 @@ public static class ColorExtensions
|
|||
/// </remarks>
|
||||
public static Color NudgeChroma(this Color c, float chromaShift)
|
||||
{
|
||||
var oklab = Color.ToLab(c);
|
||||
var oklab = c.LabFromSrgb();
|
||||
var oklch = Color.ToLch(oklab);
|
||||
|
||||
oklch.Y = Math.Clamp(oklch.Y + chromaShift, 0, 1);
|
||||
|
||||
return Color.FromLab(Color.FromLch(oklch));
|
||||
return Color.FromLch(oklch).LabToSrgb();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -54,10 +54,43 @@ public static class ColorExtensions
|
|||
{
|
||||
DebugTools.Assert(factor is >= 0.0f and <= 1.0f);
|
||||
|
||||
var okFrom = Color.ToLab(from);
|
||||
var okTo = Color.ToLab(to);
|
||||
var okFrom = from.LabFromSrgb();
|
||||
var okTo = to.LabFromSrgb();
|
||||
|
||||
var blended = Vector4.Lerp(okFrom, okTo, factor);
|
||||
return Color.FromLab(blended);
|
||||
return blended.LabToSrgb();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a nonlinear sRGB ("normal") color to OkLAB.
|
||||
/// </summary>
|
||||
public static Vector4 LabFromSrgb(this Color from)
|
||||
{
|
||||
return Color.ToLab(Color.FromSrgb(from));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts OkLAB to a nonlinear sRGB ("normal") color.
|
||||
/// </summary>
|
||||
public static Color LabToSrgb(this Vector4 from)
|
||||
{
|
||||
return Color.ToSrgb(Color.FromLab(from).SimpleClipGamut());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clips the gamut of the color so that all color channels are in the range 0 -> 1.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This uses no clever perceptual techniques, it literally just clamps the individual channels.
|
||||
/// </remarks>
|
||||
public static Color SimpleClipGamut(this Color from)
|
||||
{
|
||||
return new Color
|
||||
{
|
||||
R = Math.Clamp(from.R, 0, 1),
|
||||
G = Math.Clamp(from.G, 0, 1),
|
||||
B = Math.Clamp(from.B, 0, 1),
|
||||
A = from.A,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue