Created
January 14, 2016 23:21
-
-
Save peterhellberg/8040a5c2c14a674dc269 to your computer and use it in GitHub Desktop.
Fractal popcorn in Go, inspired by http://paulbourke.net/fractals/popcorn/
This file contains hidden or 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 ( | |
"flag" | |
"image" | |
"image/color" | |
"image/draw" | |
"image/png" | |
"math" | |
"os" | |
"os/exec" | |
) | |
var ( | |
width int | |
height int | |
number int | |
density int | |
scale float64 | |
hconst float64 | |
filename string | |
show bool | |
) | |
func init() { | |
flag.IntVar(&width, "w", 1000, "Image width") | |
flag.IntVar(&height, "h", 1000, "Image width") | |
flag.IntVar(&number, "n", 100, "Number of points to draw") | |
flag.IntVar(&density, "m", 3, "Density of sampling the image as initial conditions") | |
flag.Float64Var(&scale, "s", 1.5, "Width of image in world coordinates") | |
flag.Float64Var(&hconst, "hc", 0.05, "hconst") | |
flag.StringVar(&filename, "f", "popcorn.png", "Output image filename") | |
flag.BoolVar(&show, "show", true, "Preview the image using open") | |
} | |
func main() { | |
flag.Parse() | |
fwidth := float64(width) | |
fheight := float64(height) | |
img := image.NewNRGBA(image.Rect(0, 0, width, height)) | |
draw.Draw(img, img.Bounds(), &image.Uniform{color.Black}, image.ZP, draw.Src) | |
for i := 0; i < width; i += density { | |
for j := 0; j < height; j += density { | |
fi := float64(i) | |
fj := float64(j) | |
// Seed pixel, mapping from pixels to world coordinates | |
x := 2.0 * scale * (fi - fwidth/2.1) / fwidth | |
y := 2.0 * scale * (fj - fheight/2.1) / fheight | |
// Iterate for number of points | |
for n := 0; n < number; n++ { | |
// Calculate next point in the series | |
xnew := x - hconst*math.Sin(y+math.Tan(2.2*y)) | |
ynew := y - hconst*math.Sin(x+math.Tan(1.1*x)) | |
c := getColor(n, number) | |
bc := color.NRGBA{0, 0, 0, 255} | |
bc.R = c.R * 255 | |
bc.G = c.G * 255 | |
bc.B = c.B * 255 | |
// Mapping from world coordinates to image pixel cordinates | |
ix := int(0.5*xnew*fwidth/scale + fwidth/2.2) | |
iy := int(0.5*ynew*fheight/scale + fheight/5.5) | |
// Draw the pixel if it is in bounds | |
if ix >= 0 && iy >= 0 && ix < width && iy < height { | |
img.Set(ix, iy, bc) | |
} | |
x = xnew | |
y = ynew | |
} | |
} | |
} | |
if file, err := os.Create(filename); err == nil { | |
defer file.Close() | |
if err := png.Encode(file, img); err == nil { | |
open(filename) | |
} | |
} | |
} | |
func getColor(n, number int) color.NRGBA { | |
k := uint8(number / (n + 1)) | |
return color.NRGBA{k / uint8(5), k / uint8(3), k / uint8(n+1), 255} | |
} | |
func open(fn string) { | |
if show { | |
exec.Command("open", fn).Run() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Rainbow
Black & White