package rgb import ( "fmt" "math" "strconv" ) // LEDParam defines QMK rgblight parameter indices. type LEDParam uint8 const ( Brightness LEDParam = 1 EffectID LEDParam = 2 Speed LEDParam = 3 ColorValue LEDParam = 4 Mode LEDParam = EffectID Enable LEDParam = EffectID ) // Color represents an RGB color. type Color struct { R uint8 G uint8 B uint8 } // ParseHexColor parses a 6-digit hex color string (e.g. "ff0000"). func ParseHexColor(s string) (Color, error) { if len(s) != 6 { return Color{}, fmt.Errorf("invalid hex color: %s", s) } r, err := strconv.ParseUint(s[0:2], 16, 8) if err != nil { return Color{}, fmt.Errorf("invalid hex color: %s", s) } g, err := strconv.ParseUint(s[2:4], 16, 8) if err != nil { return Color{}, fmt.Errorf("invalid hex color: %s", s) } b, err := strconv.ParseUint(s[4:6], 16, 8) if err != nil { return Color{}, fmt.Errorf("invalid hex color: %s", s) } return Color{R: uint8(r), G: uint8(g), B: uint8(b)}, nil } // HSV converts the color to HSV (QMK rgblight uses 0-255 ranges for H, S, V). func (c Color) HSV() (h, s, v uint8) { r, g, b := float64(c.R), float64(c.G), float64(c.B) max := math.Max(r, math.Max(g, b)) min := math.Min(r, math.Min(g, b)) v = uint8(max) d := max - min if d == 0 { return 0, 0, v } if max > 0 { s = uint8((d / max) * 255) } else { return 0, 0, 0 } var hFloat float64 switch { case max == r: hFloat = ((g - b) / d) * 60.0 case max == g: hFloat = ((b-r)/d)*60.0 + 120.0 case max == b: hFloat = ((r-g)/d)*60.0 + 240.0 } if hFloat < 0 { hFloat += 360.0 } h = uint8((hFloat / 360.0) * 255.0) if h >= 255 { h = 254 } return h, s, v }