I hereby claim:
- I am sausheong on github.
- I am sausheong (https://keybase.io/sausheong) on keybase.
- I have a public key whose fingerprint is E86E 9A36 EF67 3777 3F86 88D3 3592 C89F 5903 A846
To claim this, I am signing this object:
I hereby claim:
To claim this, I am signing this object:
| // find the average color of the picture | |
| func averageColor(img image.Image) [3]float64 { | |
| bounds := img.Bounds() | |
| r, g, b := 0.0, 0.0, 0.0 | |
| for y := bounds.Min.Y; y < bounds.Max.Y; y++ { | |
| for x := bounds.Min.X; x < bounds.Max.X; x++ { | |
| r1, g1, b1, _ := img.At(x, y).RGBA() | |
| r, g, b = r+float64(r1), g+float64(g1), b+float64(b1) | |
| } | |
| } |
| // resize an image to its new width | |
| func resize(in image.Image, newWidth int) image.NRGBA { | |
| bounds := in.Bounds() | |
| width := bounds.Max.X - bounds.Min.X | |
| ratio := width / newWidth | |
| out := image.NewNRGBA(image.Rect(bounds.Min.X/ratio, bounds.Min.X/ratio, bounds.Max.X/ratio, bounds.Max.Y/ratio)) | |
| for y, j := bounds.Min.Y, bounds.Min.Y; y < bounds.Max.Y; y, j = y+ratio, j+1 { | |
| for x, i := bounds.Min.X, bounds.Min.X; x < bounds.Max.X; x, i = x+ratio, i+1 { | |
| r, g, b, a := in.At(x, y).RGBA() | |
| out.SetNRGBA(i, j, color.NRGBA{uint8(r), uint8(g), uint8(b), uint8(a)}) |
| // populate a tiles database in memory | |
| func tilesDB() map[string][3]float64 { | |
| fmt.Println("Start populating tiles db ...") | |
| db := make(map[string][3]float64) | |
| files, _ := ioutil.ReadDir("tiles") | |
| for _, f := range files { | |
| name := "tiles/" + f.Name() | |
| file, err := os.Open(name) | |
| if err == nil { | |
| img, _, err := image.Decode(file) |
| // find the nearest matching image | |
| func nearest(target [3]float64, db *map[string][3]float64) string { | |
| var filename string | |
| smallest := 1000000.0 | |
| for k, v := range *db { | |
| dist := distance(target, v) | |
| if dist < smallest { | |
| filename, smallest = k, dist | |
| } | |
| } |
| // find the Eucleadian distance between 2 points | |
| func distance(p1 [3]float64, p2 [3]float64) float64 { | |
| return math.Sqrt(sq(p2[0]-p1[0]) + sq(p2[1]-p1[1]) + sq(p2[2]-p1[2])) | |
| } | |
| // find the square | |
| func sq(n float64) float64 { | |
| return n * n | |
| } |
| var TILESDB map[string][3]float64 | |
| // clone the tile database each time we generate the photo mosaic | |
| func cloneTilesDB() map[string][3]float64 { | |
| db := make(map[string][3]float64) | |
| for k, v := range TILESDB { | |
| db[k] = v | |
| } | |
| return db | |
| } |
| package main | |
| import ( | |
| "fmt" | |
| "html/template" | |
| "net/http" | |
| "bytes" | |
| "encoding/base64" | |
| "image" | |
| "image/draw" |
| // get the content from the POSTed form | |
| r.ParseMultipartForm(10485760) // max body in memory is 10MB | |
| file, _, _ := r.FormFile("image") | |
| defer file.Close() | |
| tileSize, _ := strconv.Atoi(r.FormValue("tile_size")) |
| // decode and get original image | |
| original, _, _ := image.Decode(file) | |
| bounds := original.Bounds() | |
| // create a new image for the mosaic | |
| newimage := image.NewNRGBA(image.Rect(bounds.Min.X, bounds.Min.X, bounds.Max.X, bounds.Max.Y)) |