提交 de9bf5bb 编写于 作者: A Andrew Janke 提交者: Mislav Marohnić

Improve contrast ratio for label text coloring

上级 8ba932b6
......@@ -600,13 +600,44 @@ func formatLabel(label github.IssueLabel, colorize bool) string {
func colorizeLabel(label github.IssueLabel, color *utils.Color) string {
bgColorCode := utils.RgbToTermColorCode(color)
return fmt.Sprintf("\033[38;5;%d;48;%sm %s \033[m",
getSuitableLabelTextColor(color), bgColorCode, label.Name)
fgColor := pickHighContrastTextColor(color)
fgColorCode := utils.RgbToTermColorCode(fgColor)
return fmt.Sprintf("\033[38;%s;48;%sm %s \033[m",
fgColorCode, bgColorCode, label.Name)
}
func getSuitableLabelTextColor(color *utils.Color) int {
if color.Brightness() < 0.65 {
return 15 // white text
func pickHighContrastTextColor(color *utils.Color) *utils.Color {
var candidates [12]*utils.Color
hsl := color.ToHsl()
a := hsl.ScaleLightness(0.5)
candidates[0] = a.ToRgb()
candidates[1] = a.ScaleLightness(0.25).ToRgb()
candidates[2] = a.ScaleSaturation(-0.25).ToRgb()
b := hsl.ScaleSaturation(0.75)
candidates[3] = b.ToRgb()
candidates[4] = b.ScaleLightness(0.25).ToRgb()
candidates[5] = b.ScaleSaturation(-0.25).ToRgb()
c := hsl.ScaleLightness(-0.5)
candidates[6] = c.ToRgb()
candidates[7] = c.ScaleLightness(-0.25).ToRgb()
candidates[8] = c.ScaleSaturation(-0.25).ToRgb()
d := hsl.ScaleSaturation(-0.75)
candidates[9] = d.ToRgb()
candidates[10] = d.ScaleLightness(-0.25).ToRgb()
candidates[11] = d.ScaleSaturation(-0.25).ToRgb()
foundContrastRatio := -999.0
ix := -1
for i := 0; i < 12; i++ {
contrastRatio := color.ContrastRatio(candidates[i])
if contrastRatio > foundContrastRatio {
ix = i
foundContrastRatio = contrastRatio
}
}
if foundContrastRatio >= 7.0 {
return candidates[ix]
} else {
return candidates[11]
}
return 16 // black text
}
......@@ -50,6 +50,106 @@ func (c *Color) Distance(other *Color) float64 {
math.Pow(float64(c.Blue-other.Blue), 2)))
}
func rgbComponentToBoldValue(component int64) float64 {
srgb := float64(component) / 255
if srgb <= 0.03928 {
return srgb / 12.92
} else {
return math.Pow(((srgb + 0.055) / 1.055), 2.4)
}
}
func (c *Color) Luminance() float64 {
return 0.2126*rgbComponentToBoldValue(c.Red) +
0.7152*rgbComponentToBoldValue(c.Green) +
0.0722*rgbComponentToBoldValue(c.Blue)
}
func (c *Color) ContrastRatio(other *Color) float64 {
L := c.Luminance()
otherL := other.Luminance()
var L1, L2 float64
if L > otherL {
L1, L2 = L, otherL
} else {
L1, L2 = otherL, L
}
ratio := (L1 + 0.05) / (L2 + 0.05)
return ratio
}
type HslColor struct {
Hue float64
Saturation float64
Lightness float64
}
func (c *Color) ToHsl() *HslColor {
rPrime := float64(c.Red) / 255
gPrime := float64(c.Green) / 255
bPrime := float64(c.Blue) / 255
cMax := math.Max(rPrime, math.Max(gPrime, bPrime))
cMin := math.Min(rPrime, math.Min(gPrime, bPrime))
delta := cMax - cMin
var H float64
if delta == 0 {
H = 0
} else if cMax == rPrime {
H = 60 * math.Mod((gPrime-bPrime)/delta, 6)
} else if cMax == gPrime {
H = 60 * (((bPrime - rPrime) / delta) + 2)
} else {
H = 60 * (((rPrime - gPrime) / delta) + 4)
}
var L float64
L = (cMax + cMin) / 2
var S float64
if delta == 0 {
S = 0
} else {
S = delta / (1 - math.Abs((2*L)-1))
}
return &HslColor{H, S, L}
}
func (c *HslColor) ToRgb() *Color {
C := (1 - math.Abs(2*c.Lightness-1)) * c.Saturation
X := C * (1 - math.Abs(math.Mod(c.Hue/60, 2)-1))
m := c.Lightness - (C / 2)
var rPrime, gPrime, bPrime float64
switch {
case c.Hue < 60.0:
rPrime, gPrime, bPrime = C, X, 0
case c.Hue < 120.0:
rPrime, gPrime, bPrime = X, C, 0
case c.Hue < 180.0:
rPrime, gPrime, bPrime = 0, C, X
case c.Hue < 240.0:
rPrime, gPrime, bPrime = 0, X, C
case c.Hue < 300.0:
rPrime, gPrime, bPrime = X, 0, C
case c.Hue < 360.0:
rPrime, gPrime, bPrime = C, 0, X
}
R := int64((rPrime + m) * 255)
G := int64((gPrime + m) * 255)
B := int64((bPrime + m) * 255)
return &Color{R, G, B}
}
func (c *HslColor) ScaleLightness(x float64) *HslColor {
newLightness := math.Round(math.Min(math.Max(0, c.Lightness*(1.0+x)), 1.0))
return &HslColor{c.Hue, c.Saturation, newLightness}
}
func (c *HslColor) ScaleSaturation(x float64) *HslColor {
newSaturation := math.Round(math.Min(math.Max(0, c.Lightness*(1.0+x)), 1.0))
return &HslColor{c.Hue, newSaturation, c.Lightness}
}
var x6colorIndexes = [6]int64{0, 95, 135, 175, 215, 255}
var x6colorCube [216]Color
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册