93 lines
1.8 KiB
Go
93 lines
1.8 KiB
Go
package utils
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
)
|
|
|
|
const (
|
|
Pred float64 = 0.299
|
|
Pgreen float64 = 0.587
|
|
Pblue float64 = 0.114
|
|
)
|
|
|
|
var (
|
|
DarkAltFallback = []uint8{0x1c, 0x10, 0x10}
|
|
LightAltFallback = []uint8{0xf2, 0xef, 0xef}
|
|
)
|
|
|
|
func IntToRgb(color uint32) (uint8, uint8, uint8) {
|
|
b := color % 256
|
|
g := color / 256 % 256
|
|
r := color / (256 * 256) % 256
|
|
|
|
return uint8(r), uint8(g), uint8(b)
|
|
}
|
|
|
|
func RgbToString(r, g, b uint8) string {
|
|
return fmt.Sprintf("#%02x%02x%02x", r, g, b)
|
|
}
|
|
|
|
func AltColor(r, g, b uint8) (uint8, uint8, uint8) {
|
|
l1 := Luminance(r, g, b)
|
|
isDark := l1 <= 0.5098
|
|
|
|
brightnessAmount := -0.6
|
|
if isDark { // color is dark
|
|
brightnessAmount = 0.85
|
|
}
|
|
|
|
r2, g2, b2 := Brighten(r, g, b, brightnessAmount)
|
|
|
|
l2 := Luminance(r2, g2, b2)
|
|
ratio := WCAGRatio(l1, l2)
|
|
|
|
// log.Printf("isDark=%v, ratio: %f, l1(%f)=%s, l2(%f)=%s", isDark, ratio, l1, RgbToString(r, g, b), l2, RgbToString(r2, g2, b2))
|
|
|
|
if ratio >= 3 {
|
|
return r2, g2, b2
|
|
}
|
|
|
|
if isDark {
|
|
return LightAltFallback[0], LightAltFallback[1], LightAltFallback[2]
|
|
} else {
|
|
return DarkAltFallback[0], DarkAltFallback[1], DarkAltFallback[3]
|
|
}
|
|
}
|
|
|
|
func Brighten(r, g, b uint8, amount float64) (uint8, uint8, uint8) {
|
|
return multiply(r, amount), multiply(g, amount), multiply(b, amount)
|
|
}
|
|
|
|
func multiply(i uint8, amount float64) uint8 {
|
|
iF := float64(i)
|
|
return uint8(
|
|
math.Max(
|
|
0,
|
|
math.Min(
|
|
255, iF+255*amount,
|
|
),
|
|
),
|
|
)
|
|
}
|
|
|
|
func sRGB(c uint8) float64 {
|
|
cf := float64(c) / 255
|
|
if cf <= 0.03928 {
|
|
return cf / 12.92
|
|
} else {
|
|
return math.Pow((cf+0.055)/1.055, 2.4)
|
|
}
|
|
}
|
|
|
|
func Luminance(r, g, b uint8) float64 {
|
|
rC := Pred * math.Pow(sRGB(r), 2)
|
|
gC := Pgreen * math.Pow(sRGB(g), 2)
|
|
bC := Pblue * math.Pow(sRGB(b), 2)
|
|
|
|
return math.Sqrt(rC + gC + bC)
|
|
}
|
|
|
|
func WCAGRatio(l1, l2 float64) float64 {
|
|
return (math.Max(l1, l2) + 0.05) / (math.Min(l1, l2) + 0.05)
|
|
}
|