官网地址:GitHub - disintegration/letteravatar: Letter avatar generation for Go
我对其中函数改了一下,支持多个字符,效果如下:
func TestCreateAvatar(t *testing.T) {GenerateAvatar("Bird Fish", 0, "Bird.png")GenerateAvatar("飞鸟真人", 1, "飞鸟.png")GenerateAvatar("Жозефина", 1, "1.png")GenerateAvatar("Ярослав", 1, "2.png")GenerateAvatar("ちびまる子ちゃん", 1, "日语.png")}
其中把源码放到自己目录下,改其中的函数,将rune类型参数改为string,
然后自己加个蒙版:
package utilsimport ("birdtalk/server/utils/myavatar""fmt""github.com/fogleman/gg""github.com/golang/freetype/truetype""image""image/color""image/draw""image/png""os""unicode/utf8"
)func GenerateAvatar(name string, gender int, saveFilePath string) error {onceShort.Do(func() {initFont()})// 生成圆形图标avatar, err := generateAvatar(name, 100, gender)if err != nil {return err}// 创建相同尺寸的圆形蒙版mask := createCircularMask(avatar.Bounds())// 创建一个新的透明背景图像bgImg := image.NewRGBA(avatar.Bounds())// 使用圆形蒙版将文字图标覆盖到透明背景图像上draw.DrawMask(bgImg, bgImg.Bounds(), avatar, image.Point{}, mask, image.Point{}, draw.Over)// 保存图像到文件file, err := os.Create(saveFilePath)if err != nil {return err}defer file.Close()err = png.Encode(file, bgImg)if err != nil {return err}//fmt.Println("Avatar saved as avatar.png")return nil
}// LoadFontToMemory 加载字体文件到内存中,返回一个粗体
func loadFontToMemory(fontPath string) (*truetype.Font, error) {// Read the font file into memoryfontBytes, err := os.ReadFile(fontPath)if err != nil {return nil, err}// Parse the font filefont, err := truetype.Parse(fontBytes)if err != nil {return nil, err}return font, nil
}var defaultFont *truetype.Font = nilfunc initFont() {strFilePath := "D:\\GBuild\\\utils\\SourceHanSans-VF.ttf"//strFilePath = "C:\\Windows\\Fonts\\simfang.ttf"font, err := loadFontToMemory(strFilePath)if err != nil {return}defaultFont = font
}// createCircularMask 创建一个圆形蒙版,与指定的边界大小相同
func createCircularMask(bounds image.Rectangle) *image.Alpha {dc := gg.NewContext(bounds.Dx(), bounds.Dy())dc.DrawCircle(float64(bounds.Dx())/2, float64(bounds.Dy())/2, float64(bounds.Dx())/2)dc.Fill()mask := image.NewAlpha(bounds)for y := bounds.Min.Y; y < bounds.Max.Y; y++ {for x := bounds.Min.X; x < bounds.Max.X; x++ {_, _, _, a := dc.Image().At(x, y).RGBA()mask.Set(x, y, color.Alpha{A: uint8(a >> 8)})}}return mask
}func generateAvatar(name string, sz int, gender int) (image.Image, error) {if defaultFont == nil {// 汉语会出错}myColor := color.RGBA{0x7f, 0xd3, 0xfa, 0xff} // 蓝色if gender == 0 {myColor = color.RGBA{0xf6, 0xa1, 0xbe, 0xff} // 粉色}options := &myavatar.Options{Font: defaultFont,Palette: []color.Color{myColor,},}first6Letter := TakeFirstCharacters(name)fmt.Println("返回:", first6Letter)avatar, err := myavatar.Draw(sz, first6Letter, options)if err != nil {return nil, err}return avatar, nil
}// TakeFirstNRunes 返回字符串的前N个字符,确保总字节数不超过4个字节
// TakeFirstCharacters 根据字符类型取字符串的前N个字符
func TakeFirstCharacters(str string) string {result := ""count := 0for len(str) > 0 {r, size := utf8.DecodeRuneInString(str)//fmt.Printf("字符: %c, 字节数: %d\n", r, size)if (count + size) > 6 {break} else {result += string(r)count += size}str = str[size:] // 将已解码的字符从字符串中去除}return result
}func TakeFirstNRunes(str string, n int) string {var result stringvar bytesCount intfor _, runeValue := range str {runeSize := utf8.RuneLen(runeValue)if bytesCount+runeSize > 4 {break}bytesCount += runeSizeresult += string(runeValue)if bytesCount == 4 {break}}return result
}
其中字体是从如下地址找的开源字体:Releases · adobe-fonts/source-han-sans · GitHub