120 lines
2.2 KiB
Go
120 lines
2.2 KiB
Go
package main
|
|
|
|
import (
|
|
"crypto/md5"
|
|
"math"
|
|
"slices"
|
|
|
|
"github.com/fogleman/gg"
|
|
)
|
|
|
|
// Translated to Go from: https://github.com/dgraham/identicon
|
|
func GitHub(dc *gg.Context, userId string) {
|
|
hash := md5.Sum([]byte(userId))
|
|
w := 800
|
|
h := 800
|
|
cols := 5
|
|
rows := 5
|
|
pw := w / cols
|
|
ph := h / rows
|
|
|
|
// Background
|
|
dc.SetRGB255(240, 240, 240)
|
|
dc.DrawRectangle(0, 0, float64(w), float64(h))
|
|
dc.Fill()
|
|
|
|
dc.SetRGB255(foreground(hash[:]))
|
|
|
|
// Foreground
|
|
enabledVertices := make([]bool, 25)
|
|
for i := range 15 {
|
|
byte := hash[i/2]
|
|
var nibble uint8 // 4 bits are called a nibble
|
|
if i % 2 == 0 {
|
|
nibble = (byte & 0xf0) >> 4 // left side
|
|
} else {
|
|
nibble = byte & 0x0f // right side
|
|
}
|
|
painted := nibble % 2 == 0
|
|
|
|
rowIdx := i % 5
|
|
colIdx := 2 - i / 5
|
|
mirrColIdx := 2 + i / 5
|
|
|
|
enabledVertices[rowIdx * 5 + colIdx] = painted
|
|
enabledVertices[rowIdx * 5 + mirrColIdx] = painted
|
|
}
|
|
|
|
for row, pix := range slices.Collect(slices.Chunk(enabledVertices, 5)) {
|
|
for col, painted := range pix {
|
|
if painted {
|
|
x := col * pw
|
|
y := row * ph
|
|
|
|
dc.DrawRectangle(float64(x), float64(y), float64(pw), float64(ph))
|
|
dc.Fill()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
func hue_to_rgb(a float32, b float32, hue float32) float32 {
|
|
var h float32
|
|
if hue < 0.0 {
|
|
h = hue + 1.0
|
|
} else if hue > 1.0 {
|
|
h = hue - 1.0
|
|
} else {
|
|
h = hue
|
|
}
|
|
|
|
if h < 1.0 / 6.0 {
|
|
return a + (b - a) * 6.0 * h
|
|
}
|
|
|
|
if h < 1.0 / 2.0 {
|
|
return b
|
|
}
|
|
|
|
if h < 2.0 / 3.0 {
|
|
return a + (b - a) * (2.0 / 3.0 - h) * 6.0
|
|
}
|
|
|
|
return a
|
|
}
|
|
|
|
func foreground(source []uint8) (int, int, int) {
|
|
h1 := (uint16(source[12]) & 0x0f) << 8;
|
|
h2 := uint16(source[13])
|
|
|
|
h := uint32(h1 | h2)
|
|
s := uint32(source[14])
|
|
l := uint32(source[15])
|
|
|
|
hue := float32(h * 360) / float32(4095)
|
|
sat := float32(s * 20) / float32(255)
|
|
lum := float32(l * 20) / float32(255)
|
|
|
|
sat = 65.0 - sat
|
|
lum = 75.0 - lum
|
|
|
|
hue = hue / 360.0
|
|
sat = sat / 100.0
|
|
lum = lum / 100.0
|
|
|
|
var b float32
|
|
if lum <= 0.5 {
|
|
b = lum * (sat + 1.0)
|
|
} else {
|
|
b = lum + sat - lum * sat
|
|
}
|
|
a := lum * 2.0 - b
|
|
|
|
r := hue_to_rgb(a, b, hue + 1.0 / 3.0)
|
|
g := hue_to_rgb(a, b, hue)
|
|
b = hue_to_rgb(a, b, hue - 1.0 / 3.0)
|
|
|
|
return int(math.Round(float64(r * 255))), int(math.Round(float64(g * 255))), int(math.Round(float64(b * 255)))
|
|
}
|