Refactor avatar package, support default avatar fallback (#36788)

* Fix #34715
This commit is contained in:
wxiaoguang
2026-03-01 21:32:35 +08:00
committed by GitHub
parent 1592576fa5
commit 2c624d4deb
15 changed files with 205 additions and 276 deletions
+7 -10
View File
@@ -28,21 +28,18 @@ import (
// than the size after resizing.
const DefaultAvatarSize = 256
// RandomImageSize generates and returns a random avatar image unique to input data
// RandomImageWithSize generates and returns a random avatar image unique to input data
// in custom size (height and width).
func RandomImageSize(size int, data []byte) (image.Image, error) {
func RandomImageWithSize(size int, data []byte) image.Image {
// we use white as background, and use dark colors to draw blocks
imgMaker, err := identicon.New(size, color.White, identicon.DarkColors...)
if err != nil {
return nil, fmt.Errorf("identicon.New: %w", err)
}
return imgMaker.Make(data), nil
imgMaker := identicon.New(size, color.White, identicon.DarkColors)
return imgMaker.Make(data)
}
// RandomImage generates and returns a random avatar image unique to input data
// RandomImageDefaultSize generates and returns a random avatar image unique to input data
// in default size (height and width).
func RandomImage(data []byte) (image.Image, error) {
return RandomImageSize(DefaultAvatarSize*setting.Avatar.RenderedSizeFactor, data)
func RandomImageDefaultSize(data []byte) image.Image {
return RandomImageWithSize(DefaultAvatarSize*setting.Avatar.RenderedSizeFactor, data)
}
// processAvatarImage process the avatar image data, crop and resize it if necessary.
+15 -13
View File
@@ -15,19 +15,6 @@ import (
"github.com/stretchr/testify/assert"
)
func Test_RandomImageSize(t *testing.T) {
_, err := RandomImageSize(0, []byte("gitea@local"))
assert.Error(t, err)
_, err = RandomImageSize(64, []byte("gitea@local"))
assert.NoError(t, err)
}
func Test_RandomImage(t *testing.T) {
_, err := RandomImage([]byte("gitea@local"))
assert.NoError(t, err)
}
func Test_ProcessAvatarPNG(t *testing.T) {
setting.Avatar.MaxWidth = 4096
setting.Avatar.MaxHeight = 4096
@@ -134,3 +121,18 @@ func Test_ProcessAvatarImage(t *testing.T) {
_, err = processAvatarImage(origin, 262144)
assert.ErrorContains(t, err, "image width is too large: 10 > 5")
}
func BenchmarkRandomImage(b *testing.B) {
b.Run("size-48", func(b *testing.B) {
for b.Loop() {
// BenchmarkRandomImage/size-48-12 49549 22899 ns/op
RandomImageWithSize(48, []byte("test-content"))
}
})
b.Run("size-96", func(b *testing.B) {
for b.Loop() {
// BenchmarkRandomImage/size-96-12 13816 88187 ns/op
RandomImageWithSize(96, []byte("test-content"))
}
})
}
+12 -19
View File
@@ -8,13 +8,14 @@ package identicon
import (
"crypto/sha256"
"errors"
"fmt"
"image"
"image/color"
)
const minImageSize = 16
const (
minImageSize = 16
maxImageSize = 2048
)
// Identicon is used to generate pseudo-random avatars
type Identicon struct {
@@ -24,25 +25,17 @@ type Identicon struct {
rect image.Rectangle
}
// New returns an Identicon struct with the correct settings
// size image size
// back background color
// fore all possible foreground colors. only one foreground color will be picked randomly for one image
func New(size int, back color.Color, fore ...color.Color) (*Identicon, error) {
if len(fore) == 0 {
return nil, errors.New("foreground is not set")
}
if size < minImageSize {
return nil, fmt.Errorf("size %d is smaller than min size %d", size, minImageSize)
}
// New returns an Identicon struct.
// Only one foreground color will be picked randomly for one image.
func New(size int, backColor color.Color, foreColors []color.Color) *Identicon {
size = max(size, minImageSize)
size = min(size, maxImageSize)
return &Identicon{
foreColors: fore,
backColor: back,
foreColors: foreColors,
backColor: backColor,
size: size,
rect: image.Rect(0, 0, size, size),
}, nil
}
}
// Make generates an avatar by data
+1 -1
View File
@@ -23,7 +23,7 @@ func TestGenerate(t *testing.T) {
}
backColor := color.White
imgMaker, err := New(64, backColor, DarkColors...)
imgMaker, err := New(64, backColor, DarkColors)
assert.NoError(t, err)
for i := 0; i < 100; i++ {
s := strconv.Itoa(i)