Compare commits
2 Commits
v0.5.0
...
c3b2036713
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c3b2036713 | ||
![]() |
a95b833004 |
8
Makefile
Normal file
8
Makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
.PHONY: build, clean
|
||||
|
||||
build:
|
||||
go build -v
|
||||
|
||||
clean:
|
||||
rm -f barnsley-fern-go barnsley-fern.png
|
||||
|
108
barnsley-fern.go
108
barnsley-fern.go
@@ -1,78 +1,12 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/png"
|
||||
"math/rand"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
func createImage(h, v int) *image.RGBA {
|
||||
rect := image.Rectangle{
|
||||
image.Point{0, 0},
|
||||
image.Point{h, v},
|
||||
}
|
||||
return image.NewRGBA(rect)
|
||||
}
|
||||
|
||||
func fillBackground(img *image.RGBA, c color.Color) {
|
||||
rect := img.Bounds()
|
||||
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:
|
||||
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
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
func drawBarnsleyFern(img *image.RGBA, colorfunc func(float64, float64) color.Color, dots int) {
|
||||
func drawBarnsleyFern(img *image.RGBA, colorfunc colorFunc, dots int) {
|
||||
var (
|
||||
x, y, tmpx, tmpy, r, maxy, maxx, scale, yoffset, xoffset float64
|
||||
)
|
||||
@@ -107,45 +41,15 @@ func drawBarnsleyFern(img *image.RGBA, colorfunc func(float64, float64) color.Co
|
||||
// рисуем точку
|
||||
x, y = tmpx, tmpy
|
||||
|
||||
color := colorfunc(x, y)
|
||||
color := colorfunc(x, y, time.Now())
|
||||
|
||||
img.Set(int(xoffset+x*scale), int(maxy-yoffset-y*scale), color)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
var (
|
||||
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, "привязка к координатам")
|
||||
filename = flag.String("out", "barnsley-fern.png", "полный путь файла для записи изображения")
|
||||
)
|
||||
|
||||
flag.Parse()
|
||||
|
||||
img := createImage(*h, *v)
|
||||
|
||||
fillBackground(img, color.White)
|
||||
|
||||
colorfunc := newColorFunc(*rand, *timed, *rainbow)
|
||||
|
||||
drawBarnsleyFern(img, colorfunc, *dots)
|
||||
|
||||
f, err := os.Create(*filename)
|
||||
if err != nil {
|
||||
fmt.Printf("не удалось создать файл %s: %v", *filename, err)
|
||||
return
|
||||
func min(a, b float64) float64 {
|
||||
if a > b {
|
||||
a = b
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
|
||||
if err = png.Encode(f, img); err != nil {
|
||||
fmt.Printf("не удалось сохранить изображение: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("done...")
|
||||
return a
|
||||
}
|
||||
|
47
color.go
Normal file
47
color.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"image/color"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
type colorFunc func(float64, float64, time.Time) color.Color
|
||||
|
||||
func newColorFunc(c colormode) colorFunc {
|
||||
start := time.Now()
|
||||
return func(x, y float64, t time.Time) color.Color {
|
||||
var (
|
||||
r, g, b, a uint8
|
||||
)
|
||||
|
||||
switch c {
|
||||
case crandom:
|
||||
r = uint8(rand.Intn(256))
|
||||
g = uint8(rand.Intn(256))
|
||||
b = uint8(rand.Intn(256))
|
||||
a = 255
|
||||
|
||||
case ctimed:
|
||||
n := time.Since(start).Nanoseconds()
|
||||
|
||||
r = uint8(n % 256)
|
||||
g = uint8((n + 128) % 256)
|
||||
//b = uint8((n + 1) % 256)
|
||||
|
||||
a = 255
|
||||
|
||||
case crainbow:
|
||||
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}
|
||||
}
|
||||
}
|
2
go.mod
2
go.mod
@@ -1,3 +1,5 @@
|
||||
module code.uint32.ru/dmitry/barnsley-fern-go
|
||||
|
||||
go 1.24.1
|
||||
|
||||
require github.com/AlexEidt/Vidio v1.5.1 // indirect
|
||||
|
2
go.sum
Normal file
2
go.sum
Normal file
@@ -0,0 +1,2 @@
|
||||
github.com/AlexEidt/Vidio v1.5.1 h1:tovwvtgQagUz1vifiL9OeWkg1fP/XUzFazFKh7tFtaE=
|
||||
github.com/AlexEidt/Vidio v1.5.1/go.mod h1:djhIMnWMqPrC3X6nB6ymGX6uWWlgw+VayYGKE1bNwmI=
|
49
image.go
Normal file
49
image.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/png"
|
||||
"io"
|
||||
)
|
||||
|
||||
var erreEcnodePng = errors.New("не удалось создать png изображение")
|
||||
|
||||
func createBarnsleyFernPng(s *settings, w io.Writer) error {
|
||||
img := newImageWithBackGround(s.X, s.Y, s.BG)
|
||||
|
||||
drawBarnsleyFern(img, newColorFunc(s.CM), s.Dots)
|
||||
|
||||
if err := png.Encode(w, img); err != nil {
|
||||
return errors.Join(erreEcnodePng, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func newImageWithBackGround(x, y int, background color.Color) *image.RGBA {
|
||||
img := createImage(x, y)
|
||||
|
||||
fillBackground(img, background)
|
||||
|
||||
return img
|
||||
}
|
||||
|
||||
func createImage(x, y int) *image.RGBA {
|
||||
rect := image.Rectangle{
|
||||
image.Point{0, 0},
|
||||
image.Point{x, y},
|
||||
}
|
||||
|
||||
return image.NewRGBA(rect)
|
||||
}
|
||||
|
||||
func fillBackground(img *image.RGBA, c color.Color) {
|
||||
rect := img.Bounds()
|
||||
for x := range rect.Max.X {
|
||||
for y := range rect.Max.Y {
|
||||
img.Set(x, y, c)
|
||||
}
|
||||
}
|
||||
}
|
29
main.go
Normal file
29
main.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
filename, settings := parseSettings()
|
||||
|
||||
file, err := os.Create(filename)
|
||||
if err != nil {
|
||||
fmt.Println("ошибка открытия файла", err)
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err := file.Close(); err != nil {
|
||||
fmt.Println("ошибка закрытия файла", err)
|
||||
}
|
||||
}()
|
||||
|
||||
if err := createBarnsleyFernPng(settings, file); err != nil {
|
||||
fmt.Println("ошибка создания изображения:", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("done...")
|
||||
}
|
56
settings.go
Normal file
56
settings.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"image/color"
|
||||
)
|
||||
|
||||
type colormode int
|
||||
|
||||
const (
|
||||
cdefault colormode = iota
|
||||
crandom
|
||||
ctimed
|
||||
crainbow
|
||||
)
|
||||
|
||||
type outputmode int
|
||||
|
||||
const (
|
||||
outputpng outputmode = iota
|
||||
outputvideo
|
||||
)
|
||||
|
||||
type settings struct {
|
||||
X, Y int // image size
|
||||
Dots int // dots to draw for single image
|
||||
BG color.Color // background color
|
||||
CM colormode // settings for colorFunc
|
||||
}
|
||||
|
||||
func parseSettings() (string, *settings) {
|
||||
var (
|
||||
x, y int
|
||||
dots int
|
||||
cmode int
|
||||
fname string
|
||||
)
|
||||
|
||||
flag.IntVar(&x, "x", 1920, "размер картинки по горизонтали")
|
||||
flag.IntVar(&y, "y", 1080, "размер картинки по вертикали")
|
||||
flag.IntVar(&dots, "d", 100000, "сколько точек рисовать")
|
||||
flag.IntVar(&cmode, "color", 0, "color mode: 0 - default green, 1 - random, 2 - timed, 3 - rainbow")
|
||||
flag.StringVar(&fname, "out", "barnsley-fern.png", "полный путь файла для записи изображения")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
s := &settings{
|
||||
X: x,
|
||||
Y: y,
|
||||
Dots: dots,
|
||||
BG: color.White,
|
||||
CM: colormode(cmode),
|
||||
}
|
||||
|
||||
return fname, s
|
||||
}
|
Reference in New Issue
Block a user