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))) }