Last active
March 16, 2019 02:55
-
-
Save willowiscool/f2997521d70991bbb6ed0ff6d1468e8c to your computer and use it in GitHub Desktop.
Program creates a voronoi diagram using random sites, then colors in each site with the average color of all of the pixels contained in the site. https://blog.victor.computer/article/3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"math/rand" | |
"image/draw" | |
"image/png" | |
"image/color" | |
"strconv" | |
"os" | |
"time" | |
) | |
func genSites(width, height int) ([][]int) { | |
rand.Seed(time.Now().Unix()) | |
l, err := strconv.Atoi(os.Args[len(os.Args)-2]) | |
if err != nil { | |
panic(err) | |
} | |
sites := make([][]int, l) | |
for i := range sites { | |
sites[i] = make([]int, 2) | |
sites[i][0] = rand.Intn(width) | |
sites[i][1] = rand.Intn(height) | |
} | |
return sites | |
} | |
func main() { | |
inputF, err := os.Open(os.Args[len(os.Args)-3]) | |
if err != nil { | |
panic(err) | |
} | |
defer inputF.Close() | |
inputR, err := png.Decode(inputF) | |
if err != nil { | |
panic(err) | |
} | |
input := inputR.(draw.Image) | |
minx, miny := input.Bounds().Min.X, input.Bounds().Min.Y | |
maxx, maxy := input.Bounds().Max.X-1, input.Bounds().Max.Y-1 | |
sites := genSites(maxx-minx, maxy-miny) | |
siteColors := make([][]color.Color, len(sites)) | |
//todo: figure out something better than this | |
for i := range siteColors { | |
siteColors[i] = make([]color.Color, 0, (maxx-minx)*(maxy-miny)) | |
} | |
siteBelongs := make([][]int, maxx - minx) | |
for x := range siteBelongs { | |
siteBelongs[x] = make([]int, maxy - miny) | |
for y := range siteBelongs[x] { | |
dmin := (maxx-minx)*(maxx-minx) + (maxy-miny)*(maxy-miny) | |
var smin int | |
for i, s := range sites { | |
d := (s[0]-x)*(s[0]-x) + (s[1]-y)*(s[1]-y) | |
if d < dmin { | |
smin = i | |
dmin = d | |
} | |
} | |
siteBelongs[x][y] = smin | |
siteColors[smin] = append(siteColors[smin], input.At(x+minx, y+miny)) | |
} | |
} | |
siteAvgColors := make([]color.Color, len(sites)) | |
for i := range siteAvgColors { | |
if len(siteColors[i]) == 0 { | |
siteAvgColors[i] = color.RGBA{0, 0, 0, 0} | |
} else { | |
var sR, sG, sB, sA int = 0, 0, 0, 0 | |
for _, val := range siteColors[i] { | |
r, g, b, a := val.RGBA() | |
sR += int(r)/255 | |
sG += int(g)/255 | |
sB += int(b)/255 | |
sA += int(a) | |
} | |
//siteAvgColors[i] = siteColors[i][0] | |
siteAvgColors[i] = color.RGBA{ | |
uint8(sR/len(siteColors[i])), | |
uint8(sG/len(siteColors[i])), | |
uint8(sB/len(siteColors[i])), | |
uint8(sA/len(siteColors[i]))} | |
} | |
} | |
for x := range siteBelongs { | |
for y := range siteBelongs[x] { | |
input.Set(minx + x, miny + y, siteAvgColors[siteBelongs[x][y]]) | |
} | |
} | |
output, err := os.Create(os.Args[len(os.Args)-1]) | |
if err != nil { | |
panic(err) | |
} | |
defer output.Close() | |
err = png.Encode(output, input) | |
if err != nil { | |
panic(err) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment