diff --git a/common/color.go b/common/color.go index 04459b5..8082dd5 100644 --- a/common/color.go +++ b/common/color.go @@ -1,6 +1,10 @@ package common -import "image/color" +import ( + "fmt" + "image/color" + "strings" +) var ( MistyRose = color.RGBA{R: 0xFF, G: 0xE4, B: 0xE1, A: 0xFF} @@ -114,3 +118,56 @@ var ( {R: 0xD2, G: 0xFD, B: 0xFF, A: 0xFF}, } ) + +// ParseHexColor parses color string likes #FFFFFF or #2398EFFF +func ParseHexColor(s string) (color.RGBA, error) { + s = strings.TrimSpace(strings.ToLower(s)) + + if !strings.HasPrefix(s, "#") { + return Black, fmt.Errorf("invalid hex color string %v", s) + } + + if c, ok := parseHex(s); ok { + return c, nil + } + return Black, fmt.Errorf("invalid hex color string %v", s) +} + +// parseHex returns a color.RGBA by parsing a hex string +// Reference: https://stackoverflow.com/questions/54197913/parse-hex-string-to-image-color +func parseHex(s string) (color.RGBA, bool) { + c := color.RGBA{} + c.A = 1 + ok := true + + hexToByte := func(b byte) byte { + switch { + case b >= '0' && b <= '9': + return b - '0' + case b >= 'a' && b <= 'f': + return b - 'a' + 10 + } + ok = false + return 0 + } + + n := len(s) + if n == 6 || n == 8 { + c.R = hexToByte(s[0])<<4+hexToByte(s[1]) + c.G = hexToByte(s[2])<<4+hexToByte(s[3]) + c.B = hexToByte(s[4])<<4+hexToByte(s[5]) + if n == 8 { + c.A = hexToByte(s[6])<<4+hexToByte(s[7]) + } + } else if n == 3 || n == 4 { + c.R = hexToByte(s[0])*17 + c.G = hexToByte(s[1])*17 + c.B = hexToByte(s[2])*17 + if n == 4 { + c.A = hexToByte(s[3])*17 + } + } else { + ok = false + } + return c, ok +} \ No newline at end of file