mirror of
https://codeberg.org/Codeberg/avatars.git
synced 2023-08-10 21:12:50 +03:00
split library & example
This commit is contained in:
parent
c02c75e2e3
commit
fd3ef77fa6
@ -1,32 +1,24 @@
|
|||||||
package main
|
package avatars
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"math/bits"
|
"math/bits"
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
// MakeAvatar create svg from seed
|
||||||
if len(os.Args) < 2 {
|
func MakeAvatar(seedString string) string {
|
||||||
fmt.Println("please specify a seed string")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fmt.Println(makeAvatar(os.Args[1]))
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeAvatar(seedString string) string {
|
|
||||||
var seed uint64
|
var seed uint64
|
||||||
for _, c := range []byte(seedString) {
|
for _, c := range []byte(seedString) {
|
||||||
seed = bits.RotateLeft64(seed, 8)
|
seed = bits.RotateLeft64(seed, 8)
|
||||||
seed ^= uint64(c)
|
seed ^= uint64(c)
|
||||||
}
|
}
|
||||||
if seed & 1 == 0 {
|
if seed&1 == 0 {
|
||||||
return femaleAvatar(seed)
|
return femaleAvatar(seed, "")
|
||||||
} else {
|
} else {
|
||||||
return maleAvatar(seed)
|
return maleAvatar(seed, "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,35 +28,35 @@ func makeAvatar(seedString string) string {
|
|||||||
* cf. https://github.com/DiceBear/avatars/blob/master/packages/avatars-male-sprites/src/index.ts
|
* cf. https://github.com/DiceBear/avatars/blob/master/packages/avatars-male-sprites/src/index.ts
|
||||||
*/
|
*/
|
||||||
|
|
||||||
type LCG struct {
|
type lcg struct {
|
||||||
seed uint64
|
seed uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *LCG) random() uint32 {
|
func (g *lcg) random() uint32 {
|
||||||
/* Linear Congruent Generator, POSIX/glibc [de]rand48 setting, bits [47..0] are output bits */
|
/* Linear Congruent Generator, POSIX/glibc [de]rand48 setting, bits [47..0] are output bits */
|
||||||
g.seed = (25214903917*g.seed + 11) % 281474976710656
|
g.seed = (25214903917*g.seed + 11) % 281474976710656
|
||||||
return uint32(g.seed)
|
return uint32(g.seed)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *LCG) binomial(p float64) bool {
|
func (g *lcg) binomial(p float64) bool {
|
||||||
/* Sample from Binomial distribution with probability p */
|
/* Sample from Binomial distribution with probability p */
|
||||||
var sample = float64(g.random()) * float64(1.0/4294967295.0)
|
var sample = float64(g.random()) * float64(1.0/4294967295.0)
|
||||||
return sample > p
|
return sample > p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *LCG) pickOne(s []string) string {
|
func (g *lcg) pickOne(s []string) string {
|
||||||
/* Pick one element from list */
|
/* Pick one element from list */
|
||||||
var N = uint32(len(s))
|
var N = uint32(len(s))
|
||||||
return s[g.random()%N]
|
return s[g.random()%N]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *LCG) pickOneFloat(s []float64) float64 {
|
func (g *lcg) pickOneFloat(s []float64) float64 {
|
||||||
/* Pick one element from list - float version*/
|
/* Pick one element from list - float version*/
|
||||||
var N = uint32(len(s))
|
var N = uint32(len(s))
|
||||||
return s[g.random()%N]
|
return s[g.random()%N]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *LCG) pickAorB(p float64, a string, b string) string {
|
func (g *lcg) pickAorB(p float64, a string, b string) string {
|
||||||
/* Pick a or b with probability p of picking a */
|
/* Pick a or b with probability p of picking a */
|
||||||
if g.binomial(p) {
|
if g.binomial(p) {
|
||||||
return a
|
return a
|
||||||
@ -72,28 +64,28 @@ func (g *LCG) pickAorB(p float64, a string, b string) string {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func LinearCongruentialGenerator(seed uint64) *LCG {
|
func linearCongruentialGenerator(seed uint64) *lcg {
|
||||||
g := new(LCG)
|
g := new(lcg)
|
||||||
g.seed = seed
|
g.seed = seed
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
type RGB struct {
|
type rgb struct {
|
||||||
r uint8
|
r uint8
|
||||||
g uint8
|
g uint8
|
||||||
b uint8
|
b uint8
|
||||||
a uint8
|
a uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
type HSV struct {
|
type hsv struct {
|
||||||
h float64
|
h float64
|
||||||
s float64
|
s float64
|
||||||
v float64
|
v float64
|
||||||
}
|
}
|
||||||
|
|
||||||
func f2rgb(r, g, b float64) *RGB {
|
func f2rgb(r, g, b float64) *rgb {
|
||||||
// make RGB from 3 floats
|
// make rgb from 3 floats
|
||||||
c := new(RGB)
|
c := new(rgb)
|
||||||
c.r = uint8(r * 1.0 / 255)
|
c.r = uint8(r * 1.0 / 255)
|
||||||
c.g = uint8(g * 1.0 / 255)
|
c.g = uint8(g * 1.0 / 255)
|
||||||
c.b = uint8(b * 1.0 / 255)
|
c.b = uint8(b * 1.0 / 255)
|
||||||
@ -101,23 +93,23 @@ func f2rgb(r, g, b float64) *RGB {
|
|||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func f2hsv(h, s, v float64) *HSV {
|
func f2hsv(h, s, v float64) *hsv {
|
||||||
// make HSV from 3 floats
|
// make hsv from 3 floats
|
||||||
c := new(HSV)
|
c := new(hsv)
|
||||||
c.h = h
|
c.h = h
|
||||||
c.s = s
|
c.s = s
|
||||||
c.v = v
|
c.v = v
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func rgb(s string) *RGB {
|
func to_rgb(s string) *rgb {
|
||||||
c := new(RGB)
|
c := new(rgb)
|
||||||
c.a = 255
|
c.a = 255
|
||||||
fmt.Sscanf(s, "#%02x%02x%02x", &c.r, &c.g, &c.b)
|
fmt.Sscanf(s, "#%02x%02x%02x", &c.r, &c.g, &c.b)
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RGB) to_hsv() *HSV {
|
func (c *rgb) to_hsv() *hsv {
|
||||||
var h float64
|
var h float64
|
||||||
var s float64
|
var s float64
|
||||||
var v float64
|
var v float64
|
||||||
@ -150,7 +142,7 @@ func (c *RGB) to_hsv() *HSV {
|
|||||||
return f2hsv(h, s, v)
|
return f2hsv(h, s, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *HSV) to_rgb() *RGB {
|
func (c *hsv) to_rgb() *rgb {
|
||||||
h := int((c.h / 60))
|
h := int((c.h / 60))
|
||||||
f := c.h/60 - float64(h)
|
f := c.h/60 - float64(h)
|
||||||
p := c.v * (1 - c.s)
|
p := c.v * (1 - c.s)
|
||||||
@ -174,7 +166,7 @@ func (c *HSV) to_rgb() *RGB {
|
|||||||
return f2rgb(0, 0, 0)
|
return f2rgb(0, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RGB) brighterThan(ref *RGB, delta float64) *RGB {
|
func (c *rgb) brighterThan(ref *rgb, delta float64) *rgb {
|
||||||
primary := c.to_hsv()
|
primary := c.to_hsv()
|
||||||
secondary := ref.to_hsv()
|
secondary := ref.to_hsv()
|
||||||
if primary.v >= secondary.v+delta {
|
if primary.v >= secondary.v+delta {
|
||||||
@ -187,7 +179,7 @@ func (c *RGB) brighterThan(ref *RGB, delta float64) *RGB {
|
|||||||
return primary.to_rgb()
|
return primary.to_rgb()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RGB) darkerThan(ref *RGB, delta float64) *RGB {
|
func (c *rgb) darkerThan(ref *rgb, delta float64) *rgb {
|
||||||
primary := c.to_hsv()
|
primary := c.to_hsv()
|
||||||
secondary := ref.to_hsv()
|
secondary := ref.to_hsv()
|
||||||
if primary.v <= secondary.v-delta {
|
if primary.v <= secondary.v-delta {
|
||||||
@ -200,7 +192,7 @@ func (c *RGB) darkerThan(ref *RGB, delta float64) *RGB {
|
|||||||
return primary.to_rgb()
|
return primary.to_rgb()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RGB) brighterOrDarkerThan(ref *RGB, delta float64) *RGB {
|
func (c *rgb) brighterOrDarkerThan(ref *rgb, delta float64) *rgb {
|
||||||
primary := c.to_hsv()
|
primary := c.to_hsv()
|
||||||
secondary := ref.to_hsv()
|
secondary := ref.to_hsv()
|
||||||
if primary.v <= secondary.v {
|
if primary.v <= secondary.v {
|
||||||
@ -210,32 +202,31 @@ func (c *RGB) brighterOrDarkerThan(ref *RGB, delta float64) *RGB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RGB) withAlpha(alpha float64) *RGB {
|
func (c *rgb) withAlpha(alpha float64) *rgb {
|
||||||
c.a = uint8(alpha * 255)
|
c.a = uint8(alpha * 255)
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RGB) html() string {
|
func (c *rgb) html() string {
|
||||||
if (c.a == 255) {
|
if c.a == 255 {
|
||||||
return fmt.Sprintf("#%02x%02x%02x", c.r, c.g, c.b)
|
return fmt.Sprintf("#%02x%02x%02x", c.r, c.g, c.b)
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("#%02x%02x%02x%02x", c.r, c.g, c.b, c.a)
|
return fmt.Sprintf("#%02x%02x%02x%02x", c.r, c.g, c.b, c.a)
|
||||||
}
|
}
|
||||||
|
|
||||||
func maleAvatar(seed uint64) string {
|
func maleAvatar(seed uint64, mood string) string {
|
||||||
var g = LinearCongruentialGenerator(seed)
|
var g = linearCongruentialGenerator(seed)
|
||||||
var skinColor = rgb(g.pickOne([]string{"#FFDBAC", "#F5CFA0", "#EAC393", "#E0B687", "#CB9E6E", "#B68655", "#A26D3D", "#8D5524"}))
|
var skinColor = to_rgb(g.pickOne([]string{"#FFDBAC", "#F5CFA0", "#EAC393", "#E0B687", "#CB9E6E", "#B68655", "#A26D3D", "#8D5524"}))
|
||||||
var hairColor = rgb(g.pickOne([]string{"#090806", "#2c222b", "#71635a", "#b7a69e", "#b89778", "#a56b46", "#b55239", "#8d4a43",
|
var hairColor = to_rgb(g.pickOne([]string{"#090806", "#2c222b", "#71635a", "#b7a69e", "#b89778", "#a56b46", "#b55239", "#8d4a43",
|
||||||
"#91553d", "#533d32", "#3b3024", "#554838", "#4e433f", "#504444", "#6a4e42", "#a7856a", "#977961"})).brighterOrDarkerThan(skinColor, 17)
|
"#91553d", "#533d32", "#3b3024", "#554838", "#4e433f", "#504444", "#6a4e42", "#a7856a", "#977961"})).brighterOrDarkerThan(skinColor, 17)
|
||||||
var eyesColor = rgb(g.pickOne([]string{"#76778b", "#697b94", "#647b90", "#5b7c8b", "#588387"}))
|
var eyesColor = to_rgb(g.pickOne([]string{"#76778b", "#697b94", "#647b90", "#5b7c8b", "#588387"}))
|
||||||
var eyebrowsColor = hairColor.darkerThan(skinColor, 7).darkerThan(hairColor, 10)
|
var eyebrowsColor = hairColor.darkerThan(skinColor, 7).darkerThan(hairColor, 10)
|
||||||
var mustacheColor = hairColor.darkerThan(skinColor, 7).withAlpha(g.pickOneFloat([]float64{1, 0.75, 0.5}))
|
var mustacheColor = hairColor.darkerThan(skinColor, 7).withAlpha(g.pickOneFloat([]float64{1, 0.75, 0.5}))
|
||||||
var mouthColor = rgb(g.pickOne([]string{"#eec1ad", "#dbac98", "#d29985"})).brighterOrDarkerThan(skinColor, 10)
|
var mouthColor = to_rgb(g.pickOne([]string{"#eec1ad", "#dbac98", "#d29985"})).brighterOrDarkerThan(skinColor, 10)
|
||||||
var glassesColor = rgb(g.pickOne([]string{"#5f705c", "#43677d", "#5e172d", "#ffb67a", "#a04b5d", "#191919", "#323232", "#4b4b4b"}))
|
var glassesColor = to_rgb(g.pickOne([]string{"#5f705c", "#43677d", "#5e172d", "#ffb67a", "#a04b5d", "#191919", "#323232", "#4b4b4b"}))
|
||||||
var clothesColor = rgb(g.pickOne([]string{"#5bc0de", "#5cb85c", "#428bca", "#03396c", "#005b96", "#6497b1", "#1b85b8", "#5a5255", "#559e83", "#ae5a41", "#c3cb71", "#666547", "#ffe28a"}))
|
var clothesColor = to_rgb(g.pickOne([]string{"#5bc0de", "#5cb85c", "#428bca", "#03396c", "#005b96", "#6497b1", "#1b85b8", "#5a5255", "#559e83", "#ae5a41", "#c3cb71", "#666547", "#ffe28a"}))
|
||||||
var hatColor = rgb(g.pickOne([]string{"#18293b", "#2e1e05", "#989789", "#3d6ba7", "#517459", "#a62116"}))
|
var hatColor = to_rgb(g.pickOne([]string{"#18293b", "#2e1e05", "#989789", "#3d6ba7", "#517459", "#a62116"}))
|
||||||
|
|
||||||
var mood = ""
|
|
||||||
if mood == "" {
|
if mood == "" {
|
||||||
mood = g.pickOne([]string{"sad", "happy", "surprised"})
|
mood = g.pickOne([]string{"sad", "happy", "surprised"})
|
||||||
}
|
}
|
||||||
@ -383,23 +374,22 @@ func maleAvatar(seed uint64) string {
|
|||||||
return strings.NewReplacer(m...).Replace(s)
|
return strings.NewReplacer(m...).Replace(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func femaleAvatar(seed uint64) string {
|
func femaleAvatar(seed uint64, mood string) string {
|
||||||
var g = LinearCongruentialGenerator(seed)
|
var g = linearCongruentialGenerator(seed)
|
||||||
|
|
||||||
var skinColor = rgb(g.pickOne([]string{"#FFDBAC", "#F5CFA0", "#EAC393", "#E0B687", "#CB9E6E", "#B68655", "#A26D3D", "#8D5524"}))
|
var skinColor = to_rgb(g.pickOne([]string{"#FFDBAC", "#F5CFA0", "#EAC393", "#E0B687", "#CB9E6E", "#B68655", "#A26D3D", "#8D5524"}))
|
||||||
var hairColor = rgb(g.pickOne([]string{"#090806", "#2c222b", "#71635a", "#b7a69e", "#d6c4c2", "#cabfb1", "#dcd0ba", "#fff5e1",
|
var hairColor = to_rgb(g.pickOne([]string{"#090806", "#2c222b", "#71635a", "#b7a69e", "#d6c4c2", "#cabfb1", "#dcd0ba", "#fff5e1",
|
||||||
"#e6cea8", "#e5c8a8", "#debc99", "#b89778", "#a56b46", "#b55239", "#8d4a43", "#91553d",
|
"#e6cea8", "#e5c8a8", "#debc99", "#b89778", "#a56b46", "#b55239", "#8d4a43", "#91553d",
|
||||||
"#533d32", "#3b3024", "#554838", "#4e433f", "#504444", "#6a4e42", "#a7856a", "#977961"})).brighterOrDarkerThan(skinColor, 17)
|
"#533d32", "#3b3024", "#554838", "#4e433f", "#504444", "#6a4e42", "#a7856a", "#977961"})).brighterOrDarkerThan(skinColor, 17)
|
||||||
var eyesColor = rgb(g.pickOne([]string{"#76778b", "#697b94", "#647b90", "#5b7c8b", "#588387"}))
|
var eyesColor = to_rgb(g.pickOne([]string{"#76778b", "#697b94", "#647b90", "#5b7c8b", "#588387"}))
|
||||||
var eyebrowsColor = hairColor.darkerThan(skinColor, 7).darkerThan(hairColor, 10)
|
var eyebrowsColor = hairColor.darkerThan(skinColor, 7).darkerThan(hairColor, 10)
|
||||||
var accessoriesColor = rgb(g.pickOne([]string{"#daa520", "#ffd700", "#eee8aa", "#fafad2", "#d3d3d3", "#a9a9a9"}))
|
var accessoriesColor = to_rgb(g.pickOne([]string{"#daa520", "#ffd700", "#eee8aa", "#fafad2", "#d3d3d3", "#a9a9a9"}))
|
||||||
var mouthColor = rgb(g.pickOne([]string{"#dbac98", "#d29985", "#c98276", "#e35d6a", "#e32153", "#de0f0d"})).brighterOrDarkerThan(skinColor, 10)
|
var mouthColor = to_rgb(g.pickOne([]string{"#dbac98", "#d29985", "#c98276", "#e35d6a", "#e32153", "#de0f0d"})).brighterOrDarkerThan(skinColor, 10)
|
||||||
var glassesColor = rgb(g.pickOne([]string{"#5f705c", "#43677d", "#5e172d", "#ffb67a", "#a04b5d", "#191919", "#323232", "#4b4b4b"}))
|
var glassesColor = to_rgb(g.pickOne([]string{"#5f705c", "#43677d", "#5e172d", "#ffb67a", "#a04b5d", "#191919", "#323232", "#4b4b4b"}))
|
||||||
var clothesColor = rgb(g.pickOne([]string{"#d11141", "#00b159", "#00aedb", "#f37735", "#ffc425", "#740001", "#ae0001", "#eeba30",
|
var clothesColor = to_rgb(g.pickOne([]string{"#d11141", "#00b159", "#00aedb", "#f37735", "#ffc425", "#740001", "#ae0001", "#eeba30",
|
||||||
"#96ceb4", "#ffeead", "#ff6f69", "#ffcc5c", "#88d8b0"}))
|
"#96ceb4", "#ffeead", "#ff6f69", "#ffcc5c", "#88d8b0"}))
|
||||||
var hatColor = rgb(g.pickOne([]string{"#cc6192", "#2663a3", "#a62116", "#3d8a6b", "#614f8a"}))
|
var hatColor = to_rgb(g.pickOne([]string{"#cc6192", "#2663a3", "#a62116", "#3d8a6b", "#614f8a"}))
|
||||||
|
|
||||||
var mood = ""
|
|
||||||
if mood == "" {
|
if mood == "" {
|
||||||
mood = g.pickOne([]string{"sad", "happy", "surprised"})
|
mood = g.pickOne([]string{"sad", "happy", "surprised"})
|
||||||
}
|
}
|
16
example/main.go
Normal file
16
example/main.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"codeberg.org/Codeberg/avatars"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if len(os.Args) < 2 {
|
||||||
|
fmt.Println("please specify a seed string")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println(avatars.MakeAvatar(os.Args[1]))
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user