diff --git a/.gitignore b/.gitignore index 8f6a2e4..c45b969 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ barnsley-fern +barnsley-fern-go +barnsley_fern.png diff --git a/README.md b/README.md index 6262d14..a1253ab 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,8 @@ Implementation of Barnsley Fern in Go From the root of the repository ```bash -go build barnsley-fern.go -./barnsley-fern +go build +./barnsley-fern-go ``` or simply ``` @@ -15,3 +15,5 @@ go run barnsley-fern.go This will generate an image in current directory. See **./barnsley-fern --help** for available flags. + +Image on this page was generated with **./barnsley-fern-go -h 500 -v 500 -rainbow** diff --git a/barnsley-fern.go b/barnsley-fern.go index ff39457..8eb97cd 100644 --- a/barnsley-fern.go +++ b/barnsley-fern.go @@ -8,6 +8,7 @@ import ( "image/png" "math/rand" "os" + "time" ) func createImage(h, v int) *image.RGBA { @@ -20,13 +21,61 @@ func createImage(h, v int) *image.RGBA { func fillBackground(img *image.RGBA, c color.Color) { rect := img.Bounds() - for x := 0; x < rect.Max.X; x++ { - for y := 0; y < rect.Max.Y; y++ { + for x := range rect.Max.X { + for y := range rect.Max.Y { img.Set(x, y, c) } } } +func newColorFunc(random bool, timed bool, rainbow bool) func(float64, float64) color.Color { + return func(x, y float64) color.Color { + var ( + r, g, b, a uint8 + ) + + switch { + case random: + // n := rand.Intn(3) + + // switch n { + // case 0: + // r = 255 + // case 1: + // g = 255 + // case 2: + // b = 255 + // } + + r = uint8(rand.Intn(256)) + g = uint8(rand.Intn(256)) + b = uint8(rand.Intn(256)) + a = 255 + + case timed: + n := time.Now().Nanosecond() % 256 // Nanosecond returns range [0, 999999999] + + r = uint8((n + 256) % 256) + g = uint8((n + 128) % 256) + b = uint8(n % 256) + + a = 255 + + case rainbow: + r = uint8(y * 256) + g = uint8(x * 256) + b = uint8(((y - x) - min(x, y)) * 256) + + a = 255 + + default: + r, g, b, a = 0, 153, 0, 255 + } + + return color.RGBA{r, g, b, a} + } +} + func min(a, b float64) float64 { if a > b { a = b @@ -34,7 +83,7 @@ func min(a, b float64) float64 { return a } -func drawBarnsleyFern(img *image.RGBA, c color.Color, dots int) { +func drawBarnsleyFern(img *image.RGBA, colorfunc func(float64, float64) color.Color, dots int) { var ( x, y, tmpx, tmpy, r, maxy, maxx, scale, yoffset, xoffset float64 ) @@ -43,7 +92,7 @@ func drawBarnsleyFern(img *image.RGBA, c color.Color, dots int) { scale = min(maxx, maxy) yoffset = scale / 10 // отступы 10% сверху и снизу scale = scale - yoffset*2 // масштаб самого папоротника - xoffset = (maxx - scale) / 2 // равные отступы с двух сторон + xoffset = (maxx - scale) / 2 // равные отступы по сторонам x, y = 0.5, 0.0 for dots > 0 { @@ -68,7 +117,10 @@ func drawBarnsleyFern(img *image.RGBA, c color.Color, dots int) { } // рисуем точку x, y = tmpx, tmpy - img.Set(int(xoffset+x*scale), int(maxy-yoffset-y*scale), c) + + color := colorfunc(x, y) + + img.Set(int(xoffset+x*scale), int(maxy-yoffset-y*scale), color) } } @@ -78,6 +130,9 @@ func main() { h = flag.Int("h", 1920, "размер картинки по горизонтали") v = flag.Int("v", 1080, "размер картинки по вертикали") dots = flag.Int("d", 100000, "сколько точек рисовать") + rand = flag.Bool("rand", false, "использовать случайные цвета") + timed = flag.Bool("timed", false, "привязка к наносекундам времени исполнения") + rainbow = flag.Bool("rainbow", false, "привязка к координатам") img *image.RGBA f *os.File err error @@ -87,7 +142,10 @@ func main() { img = createImage(*h, *v) fillBackground(img, color.White) - drawBarnsleyFern(img, color.RGBA{0, 153, 0, 255}, *dots) + + colorfunc := newColorFunc(*rand, *timed, *rainbow) + + drawBarnsleyFern(img, colorfunc, *dots) f, err = os.Create(filename) if err != nil { diff --git a/barnsley_fern.png b/barnsley_fern.png index 12f3979..1e906d9 100644 Binary files a/barnsley_fern.png and b/barnsley_fern.png differ