package main import ( "image" "image/color" "image/draw" "github.com/disintegration/gift" "golang.org/x/image/font" "golang.org/x/image/font/basicfont" "golang.org/x/image/math/fixed" "streamdeck-lets-go/internal/config" ) func RenderKeyToImage(k *config.KeyConfig, keySize int, showLabelBackground bool) image.Image { if k == nil { return blankImage(keySize, color.RGBA{0, 0, 0, 255}) } if k.Icon == "" && k.Label == "" { if k.Background != "" { if bg, err := parseHexColor(k.Background); err == nil { return blankImage(keySize, bg) } } return blankImage(keySize, color.RGBA{64, 64, 64, 255}) } faScale := 0.55 if k.IconScale != nil { faScale = *k.IconScale } if k.Icon != "" { img, err := loadImage(k.Icon, keySize, faScale) if err != nil { img = blankImage(keySize, color.RGBA{64, 64, 64, 255}) } if k.Background != "" { if bg, err := parseHexColor(k.Background); err == nil { img = applyBackground(img, bg) } } if k.Label != "" { fontSize := 10.0 if k.FontSize != nil { fontSize = *k.FontSize } return composeImageWithLabel(img, k.Label, keySize, fontSize, showLabelBackground) } g := gift.New(gift.Resize(keySize, keySize, gift.LanczosResampling)) rgba := image.NewRGBA(image.Rect(0, 0, keySize, keySize)) g.Draw(rgba, img) return rgba } if k.Background != "" { if bg, err := parseHexColor(k.Background); err == nil { if k.Label != "" { fontSize := 12.0 if k.FontSize != nil { fontSize = *k.FontSize } return renderUnicodeText(k.Label, fontSize, keySize, bg, color.White) } return blankImage(keySize, bg) } } fontSize := 12.0 if k.FontSize != nil { fontSize = *k.FontSize } return renderTextImage(k.Label, keySize, fontSize) } func blankImage(size int, c color.Color) image.Image { img := image.NewRGBA(image.Rect(0, 0, size, size)) draw.Draw(img, img.Bounds(), &image.Uniform{c}, image.Point{}, draw.Src) return img } func composeImageWithLabel(src image.Image, text string, keySize int, fontSize float64, showLabelBackground bool) image.Image { g := gift.New(gift.Resize(keySize, keySize, gift.LanczosResampling)) rgba := image.NewRGBA(image.Rect(0, 0, keySize, keySize)) g.Draw(rgba, src) barHeight := 20 if keySize < 72 { barHeight = 18 } barRect := image.Rect(0, keySize-barHeight, keySize, keySize) if showLabelBackground { draw.Draw(rgba, barRect, &image.Uniform{color.RGBA{0, 0, 0, 180}}, image.Point{}, draw.Over) } if text != "" { face, err := parseDisplayFace(fontSize) if err != nil { face = basicfont.Face7x13 } else { defer face.Close() } textW := font.MeasureString(face, text).Ceil() posX := (keySize - textW) / 2 if posX < 2 { posX = 2 } posY := keySize - barHeight/2 + face.Metrics().Height.Ceil()/2 if posY >= keySize { posY = keySize - 2 } d := &font.Drawer{ Dst: rgba, Src: image.NewUniform(color.White), Face: face, Dot: fixed.P(posX, posY), } d.DrawString(text) } return rgba } func renderTextImage(text string, keySize int, fontSize float64) image.Image { rgba := blankImage(keySize, color.RGBA{0, 0, 0, 255}).(*image.RGBA) if text != "" { face, err := parseDisplayFace(fontSize) if err != nil { face = basicfont.Face7x13 } else { defer face.Close() } textW := font.MeasureString(face, text).Ceil() posX := (keySize - textW) / 2 if posX < 2 { posX = 2 } posY := keySize/2 + face.Metrics().Height.Ceil()/2 d := &font.Drawer{ Dst: rgba, Src: image.NewUniform(color.White), Face: face, Dot: fixed.P(posX, posY), } d.DrawString(text) } return rgba }