gitea/vendor/github.com/issue9/identicon/identicon.go
6543 792b4dba2c
[Vendor] Update directly used dependencys (#15593)
* update github.com/blevesearch/bleve v2.0.2 -> v2.0.3

* github.com/denisenkom/go-mssqldb v0.9.0 -> v0.10.0

* github.com/editorconfig/editorconfig-core-go v2.4.1 -> v2.4.2

* github.com/go-chi/cors v1.1.1 -> v1.2.0

* github.com/go-git/go-billy v5.0.0 -> v5.1.0

* github.com/go-git/go-git v5.2.0 -> v5.3.0

* github.com/go-ldap/ldap v3.2.4 -> v3.3.0

* github.com/go-redis/redis v8.6.0 -> v8.8.2

* github.com/go-sql-driver/mysql v1.5.0 -> v1.6.0

* github.com/go-swagger/go-swagger v0.26.1 -> v0.27.0

* github.com/lib/pq v1.9.0 -> v1.10.1

* github.com/mattn/go-sqlite3 v1.14.6 -> v1.14.7

* github.com/go-testfixtures/testfixtures v3.5.0 -> v3.6.0

* github.com/issue9/identicon v1.0.1 -> v1.2.0

* github.com/klauspost/compress v1.11.8 -> v1.12.1

* github.com/mgechev/revive v1.0.3 -> v1.0.6

* github.com/microcosm-cc/bluemonday v1.0.7 -> v1.0.8

* github.com/niklasfasching/go-org v1.4.0 -> v1.5.0

* github.com/olivere/elastic v7.0.22 -> v7.0.24

* github.com/pelletier/go-toml v1.8.1 -> v1.9.0

* github.com/prometheus/client_golang v1.9.0 -> v1.10.0

* github.com/xanzy/go-gitlab v0.44.0 -> v0.48.0

* github.com/yuin/goldmark v1.3.3 -> v1.3.5

* github.com/6543/go-version v1.2.4 -> v1.3.1

* do github.com/lib/pq v1.10.0 -> v1.10.1 again ...
2021-04-22 20:08:53 -04:00

137 lines
3.8 KiB
Go
Vendored
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// SPDX-License-Identifier: MIT
package identicon
import (
"crypto/md5"
"fmt"
"image"
"image/color"
"math/rand"
)
const (
minSize = 16 // 图片的最小尺寸
maxForeColors = 32 // 在New()函数中可以指定的最大颜色数量
)
// Identicon 用于产生统一尺寸的头像
//
// 可以根据用户提供的数据,经过一定的算法,自动产生相应的图案和颜色。
type Identicon struct {
foreColors []color.Color
backColor color.Color
size int
rect image.Rectangle
}
// New 声明一个 Identicon 实例
//
// size 表示整个头像的大小;
// back 表示前景色;
// fore 表示所有可能的前景色,会为每个图像随机挑选一个作为其前景色。
func New(size int, back color.Color, fore ...color.Color) (*Identicon, error) {
if len(fore) == 0 || len(fore) > maxForeColors {
return nil, fmt.Errorf("前景色数量必须介于[1]~[%d]之间,当前为[%d]", maxForeColors, len(fore))
}
if size < minSize {
return nil, fmt.Errorf("参数 size 的值(%d)不能小于 %d", size, minSize)
}
return &Identicon{
foreColors: fore,
backColor: back,
size: size,
// 画布坐标从0开始其长度应该是 size-1
rect: image.Rect(0, 0, size, size),
}, nil
}
// Make 根据 data 数据产生一张唯一性的头像图片
func (i *Identicon) Make(data []byte) image.Image {
h := md5.New()
h.Write(data)
sum := h.Sum(nil)
b1 := int(sum[0]+sum[1]+sum[2]) % len(blocks)
b2 := int(sum[3]+sum[4]+sum[5]) % len(blocks)
c := int(sum[6]+sum[7]+sum[8]) % len(centerBlocks)
b1Angle := int(sum[9]+sum[10]) % 4
b2Angle := int(sum[11]+sum[12]) % 4
color := int(sum[11]+sum[12]+sum[15]) % len(i.foreColors)
return i.render(c, b1, b2, b1Angle, b2Angle, color)
}
// Rand 随机生成图案
func (i *Identicon) Rand(r *rand.Rand) image.Image {
b1 := r.Intn(len(blocks))
b2 := r.Intn(len(blocks))
c := r.Intn(len(centerBlocks))
b1Angle := r.Intn(4)
b2Angle := r.Intn(4)
color := r.Intn(len(i.foreColors))
return i.render(c, b1, b2, b1Angle, b2Angle, color)
}
func (i *Identicon) render(c, b1, b2, b1Angle, b2Angle, foreColor int) image.Image {
p := image.NewPaletted(i.rect, []color.Color{i.backColor, i.foreColors[foreColor]})
drawBlocks(p, i.size, centerBlocks[c], blocks[b1], blocks[b2], b1Angle, b2Angle)
return p
}
// Make 根据 data 数据产生一张唯一性的头像图片
//
// size 头像的大小。
// back, fore头像的背景和前景色。
func Make(size int, back, fore color.Color, data []byte) (image.Image, error) {
i, err := New(size, back, fore)
if err != nil {
return nil, err
}
return i.Make(data), nil
}
// 将九个方格都填上内容。
// p 为画板;
// c 为中间方格的填充函数;
// b1、b2 为边上 8 格的填充函数;
// b1Angle 和 b2Angle 为 b1、b2 的起始旋转角度。
func drawBlocks(p *image.Paletted, size int, c, b1, b2 blockFunc, b1Angle, b2Angle int) {
incr := func(a int) int {
if a >= 3 {
a = 0
} else {
a++
}
return a
}
padding := (size % 6) / 2 // 不能除尽的,边上留白。
blockSize := size / 3
twoBlockSize := 2 * blockSize
c(p, blockSize+padding, blockSize+padding, blockSize, 0)
b1(p, 0+padding, 0+padding, blockSize, b1Angle)
b2(p, blockSize+padding, 0+padding, blockSize, b2Angle)
b1Angle = incr(b1Angle)
b2Angle = incr(b2Angle)
b1(p, twoBlockSize+padding, 0+padding, blockSize, b1Angle)
b2(p, twoBlockSize+padding, blockSize+padding, blockSize, b2Angle)
b1Angle = incr(b1Angle)
b2Angle = incr(b2Angle)
b1(p, twoBlockSize+padding, twoBlockSize+padding, blockSize, b1Angle)
b2(p, blockSize+padding, twoBlockSize+padding, blockSize, b2Angle)
b1Angle = incr(b1Angle)
b2Angle = incr(b2Angle)
b1(p, 0+padding, twoBlockSize+padding, blockSize, b1Angle)
b2(p, 0+padding, blockSize+padding, blockSize, b2Angle)
}