15
xdraw "golang.org/x/image/draw"
16
"xelbot.com/reprogl/container"
17
"xelbot.com/reprogl/models/repositories"
18
"xelbot.com/reprogl/utils/hashid"
22
iconsConfig = map[string]map[string]int{
40
validSizes = map[int]bool{
47
InvalidSize = errors.New("avatar: invalid size")
50
type dataDict map[string]string
52
func GenerateAvatar(hashData hashid.HashData, app *container.Application, size int) (image.Image, error) {
53
if _, ok := validSizes[size]; !ok {
54
return nil, InvalidSize
57
app.InfoLog.Printf("[IMG] avatar generation by %+v\n", hashData)
58
if hashData.IsUser() {
59
imageSrc, err := tryUserSource(hashData.ID, size)
60
if err == nil && imageSrc != nil {
61
app.InfoLog.Printf("[IMG] avatar %s found on public/data/pictures\n", hashData.Hash)
67
var object MaybeGravatar
69
if !hashData.IsUser() {
70
repository := repositories.CommentRepository{DB: app.DB}
71
object, err = repository.FindForGravatar(hashData.ID)
76
repository := repositories.UserRepository{DB: app.DB}
77
object, err = repository.Find(hashData.ID)
83
gravatar, err := tryGravatar(object, size, app.InfoLog)
85
app.InfoLog.Printf("[IMG] avatar %s found on gravatar.com\n", hashData.Hash)
90
return generate8BitIconAvatar(hashData.Hash, hashData.IsMale(), size, app.InfoLog)
93
func generate8BitIconAvatar(hash string, male bool, size int, logger *log.Logger) (image.Image, error) {
94
dict := dataByHash(hash, male)
95
logger.Printf("[IMG] details for %s: %+v\n", hash, dict)
97
baseImage := image.NewRGBA(image.Rect(0, 0, 400, 400))
99
bgImage, err := loadImage(filePath(dict, "background"))
103
faceImage, err := loadImage(filePath(dict, "face"))
107
clothesImage, err := loadImage(filePath(dict, "clothes"))
111
mouthImage, err := loadImage(filePath(dict, "mouth"))
116
var hairImage image.Image
118
hairImage, err = loadImage(filePath(dict, "hair"))
123
hairImage, err = loadImage(filePath(dict, "head"))
129
eyeImage, err := loadImage(filePath(dict, "eye"))
134
draw.Draw(baseImage, bgImage.Bounds(), bgImage, image.Point{}, draw.Src)
135
draw.Draw(baseImage, faceImage.Bounds(), faceImage, image.Point{}, draw.Over)
136
draw.Draw(baseImage, clothesImage.Bounds(), clothesImage, image.Point{}, draw.Over)
137
draw.Draw(baseImage, mouthImage.Bounds(), mouthImage, image.Point{}, draw.Over)
138
draw.Draw(baseImage, hairImage.Bounds(), hairImage, image.Point{}, draw.Over)
139
draw.Draw(baseImage, eyeImage.Bounds(), eyeImage, image.Point{}, draw.Over)
141
imageResult := image.NewRGBA(image.Rect(0, 0, size, size))
142
xdraw.NearestNeighbor.Scale(imageResult, imageResult.Bounds(), baseImage, baseImage.Bounds(), draw.Src, nil)
144
return imageResult, nil
147
func dataByHash(hash string, male bool) dataDict {
149
md5bytes := md5.Sum([]byte(hash))
157
facePart := int(md5bytes[0])
158
backgroundPart := (int(md5bytes[1]) << 16) + (int(md5bytes[2]) << 8) + int(md5bytes[3])
159
eyePart := (int(md5bytes[4]) << 16) + (int(md5bytes[5]) << 8) + int(md5bytes[6])
160
hairPart := (int(md5bytes[7]) << 16) + (int(md5bytes[8]) << 8) + int(md5bytes[9])
161
mouthPart := (int(md5bytes[10]) << 16) + (int(md5bytes[11]) << 8) + int(md5bytes[12])
162
clothesPart := (int(md5bytes[13]) << 16) + (int(md5bytes[14]) << 8) + int(md5bytes[15])
164
face := 1 + facePart%iconsConfig[gender]["face"]
165
eye := 1 + eyePart%iconsConfig[gender]["eye"]
166
mouth := 1 + mouthPart%iconsConfig[gender]["mouth"]
167
clothes := 1 + clothesPart%iconsConfig[gender]["clothes"]
168
background := 1 + backgroundPart%iconsConfig[gender]["background"]
172
"face": strconv.Itoa(face),
173
"eye": strconv.Itoa(eye),
174
"mouth": strconv.Itoa(mouth),
175
"clothes": strconv.Itoa(clothes),
176
"background": strconv.Itoa(background),
180
dict["hair"] = strconv.Itoa(1 + hairPart%iconsConfig[gender]["hair"])
182
dict["head"] = strconv.Itoa(1 + hairPart%iconsConfig[gender]["head"])
188
func filePath(dict dataDict, key string) string {
189
return fmt.Sprintf("./var/8biticon/%s/%s%s.png", dict["gender"], key, dict[key])
192
func loadImage(filePath string) (image.Image, error) {
193
imgFile, err := os.Open(filePath)
194
defer imgFile.Close()
200
img, _, err := image.Decode(imgFile)