Skip to content

Instantly share code, notes, and snippets.

@willowiscool
Last active March 16, 2019 02:55
Show Gist options
  • Save willowiscool/f2997521d70991bbb6ed0ff6d1468e8c to your computer and use it in GitHub Desktop.
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
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