Refactor avatar package, support default avatar fallback (#36788)
* Fix #34715
This commit is contained in:
@@ -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,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"))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user