Improved LCH support
This commit is contained in:
65
LCH.go
65
LCH.go
@ -4,24 +4,51 @@ import (
|
||||
"math"
|
||||
)
|
||||
|
||||
// LCH represents a color using lightness, chroma and hue (oklch).
|
||||
// LCH represents a color using lightness, chroma and hue.
|
||||
func LCH(lightness Value, chroma Value, hue Value) Color {
|
||||
hue *= math.Pi / 180.0
|
||||
a := chroma * math.Cos(hue)
|
||||
b := chroma * math.Sin(hue)
|
||||
lightness = min(max(lightness, 0), 1)
|
||||
hue *= math.Pi / 180
|
||||
a := math.Cos(hue)
|
||||
b := math.Sin(hue)
|
||||
|
||||
r, g, b := labToRGB(lightness, a, b)
|
||||
if !inSRGB(lightness, a, b, chroma) {
|
||||
chroma = findChromaInSRGB(chroma, lightness, a, b, 0.01)
|
||||
}
|
||||
|
||||
r = gammaCorrection(r)
|
||||
g = gammaCorrection(g)
|
||||
b = gammaCorrection(b)
|
||||
a *= chroma
|
||||
b *= chroma
|
||||
|
||||
r, g, b := oklabToLinearRGB(lightness, a, b)
|
||||
|
||||
r = sRGB(r)
|
||||
g = sRGB(g)
|
||||
b = sRGB(b)
|
||||
|
||||
return Color{r, g, b}
|
||||
}
|
||||
|
||||
// LAB to linear sRGB
|
||||
// findChromaInSRGB tries to find the closest chroma that can be represented in sRGB color space.
|
||||
func findChromaInSRGB(chroma Value, lightness Value, a Value, b Value, precision Value) Value {
|
||||
high := chroma
|
||||
low := 0.0
|
||||
chroma *= 0.5
|
||||
|
||||
for high-low > precision {
|
||||
if inSRGB(lightness, a, b, chroma) {
|
||||
low = chroma
|
||||
} else {
|
||||
high = chroma
|
||||
}
|
||||
|
||||
chroma = (high + low) * 0.5
|
||||
}
|
||||
|
||||
return chroma
|
||||
}
|
||||
|
||||
// OKLAB to linear RGB.
|
||||
// Source: https://bottosson.github.io/posts/oklab/
|
||||
func labToRGB(lightness Value, a Value, b Value) (Value, Value, Value) {
|
||||
func oklabToLinearRGB(lightness Value, a Value, b Value) (Value, Value, Value) {
|
||||
l := lightness + 0.3963377773761749*a + 0.21580375730991364*b
|
||||
m := lightness - 0.10556134581565857*a - 0.0638541728258133*b
|
||||
s := lightness - 0.08948418498039246*a - 1.2914855480194092*b
|
||||
@ -36,21 +63,3 @@ func labToRGB(lightness Value, a Value, b Value) (Value, Value, Value) {
|
||||
|
||||
return red, green, blue
|
||||
}
|
||||
|
||||
// Gamma correction
|
||||
// Source: IEC 61966-2-2
|
||||
func gammaCorrection(x Value) Value {
|
||||
if x < 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
if x <= 0.0031308 {
|
||||
return 12.92 * x
|
||||
}
|
||||
|
||||
if x < 1.0 {
|
||||
return 1.055*math.Pow(x, 1/2.4) - 0.055
|
||||
}
|
||||
|
||||
return 1.0
|
||||
}
|
||||
|
Reference in New Issue
Block a user