官网地址: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 utils
import (
"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 memory
fontBytes, err := os.ReadFile(fontPath)
if err != nil {
return nil, err
}
// Parse the font file
font, err := truetype.Parse(fontBytes)
if err != nil {
return nil, err
}
return font, nil
}
var defaultFont *truetype.Font = nil
func 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 := 0
for 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 string
var bytesCount int
for _, runeValue := range str {
runeSize := utf8.RuneLen(runeValue)
if bytesCount+runeSize > 4 {
break
}
bytesCount += runeSize
result += string(runeValue)
if bytesCount == 4 {
break
}
}
return result
}
其中字体是从如下地址找的开源字体:Releases · adobe-fonts/source-han-sans · GitHub