diff --git a/color.go b/color.go new file mode 100644 index 0000000..6db9412 --- /dev/null +++ b/color.go @@ -0,0 +1,14 @@ +package generativeart + +import "image/color" + +var MistyRose = color.RGBA{0xFF, 0xE4, 0xE1, 0xFF} +var DarkSalmon = color.RGBA{0xE9, 0x96, 0x7A, 0xFF} +var Tan = color.RGBA{0xD2, 0xB4, 0x8C, 0xFF} +var Bisque = color.RGBA{0xFF, 0xE4, 0xC4, 0xFF} +var Mintcream = color.RGBA{0xF5, 0xFF, 0xFA, 0xFF} +var Aquamarine = color.RGBA{0x7F, 0xFF, 0xD4, 0xFF} +var Azure = color.RGBA{0xF0, 0xFF, 0xFF, 0xFF} +var Lavender = color.RGBA{0xE6, 0xE6, 0xFA, 0xFF} +var Plum = color.RGBA{0xDD, 0xA0, 0xDD, 0xFF} +var AntiqueWhite = color.RGBA{0xFA, 0xEB, 0xD7, 0xFF} diff --git a/example/example.go b/example/example.go new file mode 100644 index 0000000..2425cda --- /dev/null +++ b/example/example.go @@ -0,0 +1,19 @@ +package main + +import ( + "generativeart" + "math" +) + +func formula1(x, y float64) (float64, float64) { + return -0.13*x*x - math.Sin(y*y) + math.Cos(x*y), + -0.96*y*y*y - math.Cos(x*x) +} + +func main() { + c := generativeart.NewCanva(800, 800, 4, 4) + c.FillBackgroud(generativeart.AntiqueWhite) + g := generativeart.NewWave(formula1) + g.GenerativePolar(c, generativeart.DarkSalmon) + c.ToPng("g1.png") +} diff --git a/generativeart.go b/generativeart.go new file mode 100644 index 0000000..5c49d5a --- /dev/null +++ b/generativeart.go @@ -0,0 +1,70 @@ +package generativeart + +import ( + "image" + "image/color" + "image/draw" + "image/jpeg" + "image/png" + "os" +) + +type Engine interface { + Generative(c *canva) +} + +type canva struct { + height, width int + xaixs, yaixs float64 + img *image.RGBA +} + +func NewCanva(h, w int, x, y float64) *canva { + return &canva{ + height: h, + width: w, + xaixs: x, + yaixs: y, + img: image.NewRGBA(image.Rect(0, 0, h, w)), + } +} + +func (c *canva) FillBackgroud(rgba color.RGBA) { + draw.Draw(c.img, c.img.Bounds(), &image.Uniform{rgba}, image.ZP, draw.Src) +} + +// ToPng saves the image to local with PNG format. +func (c *canva) ToPng(fpath string) error { + f, err := os.Create(fpath) + if err != nil { + return err + } + if err := png.Encode(f, c.img); err != nil { + f.Close() + return err + } + + if err := f.Close(); err != nil { + return err + } + + return nil +} + +// ToJpeg saves the image to local with Jpeg format. +func (c *canva) ToJpeg(path string) error { + f, err := os.Create(path) + if err != nil { + return err + } + if err := jpeg.Encode(f, c.img, nil); err != nil { + f.Close() + return err + } + + if err := f.Close(); err != nil { + return err + } + + return nil +} diff --git a/utils.go b/utils.go new file mode 100644 index 0000000..24d275d --- /dev/null +++ b/utils.go @@ -0,0 +1,53 @@ +package generativeart + +import "math" + +func ConvertCartesianToPixel(x, y, xaixs, yaixs float64, h, w int) (int, int) { + xr, yr := x/xaixs, y/yaixs + var i, j int + if xr > 0 { + i = w/2 + int(float64(w)/2*xr) + } else { + i = w/2 + int(float64(w)/2*xr) + } + + if yr > 0 { + j = h/2 + int(float64(h)/2*yr) + } else { + j = h/2 + int(float64(h)/2*yr) + } + + return i, j +} + +func ConvertCartesianToPolarPixel(x, y, xaixs, yaixs float64, h, w int) (int, int) { + r, theta := ConvertCartesianToPolar(x, y) + return ConvertPolarToPixel(r, theta, xaixs, yaixs, h, w) +} + +func ConvertCartesianToPolar(x, y float64) (float64, float64) { + r := math.Sqrt(x*x + y*y) + theta := math.Atanh(y / x) + + return r, theta +} + +func ConvertPolarToPixel(r, theta, xaixs, yaixs float64, h, w int) (int, int) { + x, y := r*math.Cos(theta), r*math.Sin(theta) + + xr, yr := x/xaixs, y/yaixs + var i, j int + if xr > 0 { + i = w/2 + int(float64(w)/2*xr) + } else { + i = w/2 + int(float64(w)/2*xr) + } + + if yr > 0 { + j = h/2 + int(float64(h)/2*yr) + } else { + j = h/2 + int(float64(h)/2*yr) + } + + return i, j +} diff --git a/wave.go b/wave.go new file mode 100644 index 0000000..f1d69eb --- /dev/null +++ b/wave.go @@ -0,0 +1,42 @@ +package generativeart + +import ( + "image/color" + "math" +) + +type Formula func(x, y float64) (float64, float64) + +type wave struct { + fn Formula +} + +func NewWave(fn Formula) *wave { + return &wave{fn: fn} +} + +func (w *wave) GenerativePolar(c *canva, rgba color.RGBA) { + for x := -math.Pi; x <= math.Pi; x += 0.01 { + for y := -math.Pi; y <= math.Pi; y += 0.01 { + xi, yi := w.fn(x, y) + i, j := ConvertCartesianToPolarPixel(xi, yi, c.xaixs, c.yaixs, c.height, c.width) + if i < 0 || i > c.width-1 || j < 0 || j > c.height-1 { + continue + } + c.img.Set(i, j, rgba) + } + } +} + +func (w *wave) Generative(c *canva, rgba color.RGBA) { + for x := -math.Pi; x <= math.Pi; x += 0.008 { + for y := -math.Pi; y <= math.Pi; y += 0.008 { + xi, yi := w.fn(x, y) + i, j := ConvertCartesianToPixel(xi, yi, c.xaixs, c.yaixs, c.height, c.width) + if i < 0 || i > c.width-1 || j < 0 || j > c.height-1 { + continue + } + c.img.Set(i, j, rgba) + } + } +}