identicon

Profile Image Generator
git clone git://git.lair.cx/identicon
Log | Files | Refs | README | LICENSE

identicon.go (1815B)


      1 package identicon
      2 
      3 import (
      4 	"image"
      5 	"image/color"
      6 
      7 	"github.com/segmentio/fasthash/fnv1a"
      8 	"golang.org/x/image/draw"
      9 )
     10 
     11 const (
     12 	iconWidth     = 5
     13 	iconWidthHalf = 3
     14 	iconHeight    = 5
     15 )
     16 
     17 var defaultPalette = [...]color.RGBA{
     18 	{0xFF, 0x40, 0x00, 0xFF},
     19 	{0xFF, 0x93, 0x51, 0xFF},
     20 	{0xFF, 0xE2, 0x72, 0xFF},
     21 	{0x9D, 0xE1, 0x6F, 0xFF},
     22 	{0x53, 0xAF, 0xFF, 0xFF},
     23 	{0x41, 0x47, 0x96, 0xFF},
     24 	{0xDE, 0x6F, 0xFF, 0xFF},
     25 	{0xFF, 0x74, 0xBC, 0xFF},
     26 }
     27 
     28 type Factory struct {
     29 	// Palette
     30 	palette []color.RGBA
     31 }
     32 
     33 func NewFactory() *Factory {
     34 	return &Factory{
     35 		palette: defaultPalette[:],
     36 	}
     37 }
     38 
     39 // SetPalette sets the palette.
     40 func (f *Factory) SetPalette(palette []color.RGBA) {
     41 	f.palette = palette
     42 }
     43 
     44 // Generate generates a identicon.
     45 func (f *Factory) Generate(src []byte) (image.Image, error) {
     46 	// Hash the source.
     47 	hash := fnv1a.HashBytes64(src)
     48 
     49 	// Choose color from palette.
     50 	markColor := f.palette[int(hash&0xFF)%len(f.palette)]
     51 	hash = hash >> 8
     52 
     53 	// Prepare canvas.
     54 	canvas := image.NewRGBA(image.Rect(0, 0, iconWidth, iconHeight))
     55 	draw.Draw(canvas, canvas.Bounds(), &image.Uniform{C: color.White}, image.Point{}, draw.Src)
     56 
     57 	// Draw to canvas.
     58 	for y := 0; y < iconHeight; y++ {
     59 		for x := 0; x < iconWidthHalf; x++ {
     60 			if hash>>(8*y+x)&1 > 0 {
     61 				canvas.SetRGBA(x, y, markColor)
     62 				canvas.SetRGBA(4-x, y, markColor)
     63 			}
     64 		}
     65 	}
     66 
     67 	return canvas, nil
     68 }
     69 
     70 func WrapImage(img image.Image, cw, ch, ix int) image.Image {
     71 	var (
     72 		w  = iconWidth * ix
     73 		h  = iconHeight * ix
     74 		x1 = (cw - w) / 2
     75 		y1 = (ch - h) / 2
     76 		x2 = x1 + w
     77 		y2 = y1 + h
     78 	)
     79 	wrapper := image.NewRGBA(image.Rect(0, 0, cw, ch))
     80 	draw.Draw(wrapper, wrapper.Bounds(), &image.Uniform{C: color.White}, image.Point{}, draw.Src)
     81 	draw.NearestNeighbor.Scale(wrapper, image.Rect(x1, y1, x2, y2), img, img.Bounds(), draw.Src, nil)
     82 	return wrapper
     83 }