status-go/protocol/identity/ring/ring.go

88 lines
2.6 KiB
Go
Raw Normal View History

2022-06-25 07:20:02 +00:00
package ring
import (
"bytes"
"errors"
"fmt"
"image"
"image/png"
"math"
"github.com/fogleman/gg"
"github.com/status-im/status-go/images"
)
type Theme int
const (
LightTheme Theme = 1
DarkTheme Theme = 2
)
var (
lightThemeIdenticonRingColors = []string{"#000000", "#726F6F", "#C4C4C4", "#E7E7E7", "#FFFFFF", "#00FF00", "#009800", "#B8FFBB", "#FFC413", "#9F5947", "#FFFF00", "#A8AC00", "#FFFFB0", "#FF5733", "#FF0000", "#9A0000", "#FF9D9D", "#FF0099", "#C80078", "#FF00FF", "#900090", "#FFB0FF", "#9E00FF", "#0000FF", "#000086", "#9B81FF", "#3FAEF9", "#9A6600", "#00FFFF", "#008694", "#C2FFFF", "#00F0B6"}
darkThemeIdenticonRingColors = []string{"#000000", "#726F6F", "#C4C4C4", "#E7E7E7", "#FFFFFF", "#00FF00", "#009800", "#B8FFBB", "#FFC413", "#9F5947", "#FFFF00", "#A8AC00", "#FFFFB0", "#FF5733", "#FF0000", "#9A0000", "#FF9D9D", "#FF0099", "#C80078", "#FF00FF", "#900090", "#FFB0FF", "#9E00FF", "#0000FF", "#000086", "#9B81FF", "#3FAEF9", "#9A6600", "#00FFFF", "#008694", "#C2FFFF", "#00F0B6"}
)
type DrawRingParam struct {
Theme Theme `json:"theme"`
ColorHash [][]int `json:"colorHash"`
ImageBytes []byte `json:"imageBytes"`
ImageUri string `json:"uri"`
Height int `json:"height"`
Width int `json:"width"`
}
func DrawRing(param *DrawRingParam) ([]byte, error) {
var colors []string
switch param.Theme {
case LightTheme:
colors = lightThemeIdenticonRingColors
case DarkTheme:
colors = darkThemeIdenticonRingColors
default:
return nil, errors.New(fmt.Sprintf("unknown theme"))
}
dc := gg.NewContext(param.Width, param.Height)
if param.ImageUri != "" {
imageBytes, err := images.DecodeFromB64Uri(param.ImageUri)
if err != nil {
return nil, err
}
param.ImageBytes = imageBytes
}
img, _, err := image.Decode(bytes.NewReader(param.ImageBytes))
if err != nil {
return nil, err
}
dc.DrawImage(img, 0, 0)
ringPxSize := math.Max(1.5, float64(param.Width/24.0))
radius := (float64(param.Height) - ringPxSize) / 2
arcPos := 0.0
totalRingUnits := 0
for i := 0; i < len(param.ColorHash); i++ {
totalRingUnits += param.ColorHash[i][0]
}
unitRadLen := 2 * math.Pi / float64(totalRingUnits)
for i := 0; i < len(param.ColorHash); i++ {
dc.SetHexColor(colors[param.ColorHash[i][1]])
dc.DrawArc(float64(param.Width/2), float64(param.Height/2), radius, arcPos, arcPos+unitRadLen*float64(param.ColorHash[i][0]))
dc.SetLineWidth(ringPxSize)
dc.Stroke()
arcPos += unitRadLen * float64(param.ColorHash[i][0])
}
buf := new(bytes.Buffer)
err = png.Encode(buf, dc.Image())
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}