-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmain.go
153 lines (119 loc) · 3.46 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package main
import (
"fmt"
"image"
"image/color"
"image/gif"
"log"
"os"
"github.com/KEINOS/go-noise"
"github.com/pkg/errors"
)
const (
// Image size. The max X and Y value for looping.
width = 250
height = 250
// depth is the Z-axis which is the number of frames of the animation.
depth = 50
)
// These values should be adjusted to obtain the appropriate dispersion for
// the image size.
const (
// Create noise generator with seed 100. Same seed will generate the same
// noise pattern.
seed = 100
// The bigger the zoom and less randomness in the range.
zoomIn = 25
// The smaller the smoother and little difference between frames.
smoothness = 5
)
// ----------------------------------------------------------------------------
// Main
// ----------------------------------------------------------------------------
func main() {
{
fmt.Println("Creating Perlin noise image ...")
gen, err := noise.New(noise.Perlin, seed)
if err != nil {
log.Fatal(err)
}
if err := GenNoiseImage(gen, "animation_perlin.gif"); err != nil {
log.Fatal(err)
}
fmt.Printf("\nPerlin Noise image created.\n")
}
{
fmt.Println("Creating OpenSimplex noise image ...")
gen, err := noise.New(noise.OpenSimplex, seed)
if err != nil {
log.Fatal(err)
}
if err := GenNoiseImage(gen, "animation_opensimplex.gif"); err != nil {
log.Fatal(err)
}
fmt.Printf("\nOpenSimplex Noise image created.\n")
}
fmt.Printf("\nDone!\n")
}
// ----------------------------------------------------------------------------
// Functions
// ----------------------------------------------------------------------------
// CreatePaletteGray creates a color.Palette of 256 gray-scale colors.
func CreatePaletteGray() color.Palette {
grayPalet := make(color.Palette, 256)
for c := 0; c < 256; c++ {
grayPalet[c] = color.Gray{Y: uint8(c)}
}
return grayPalet
}
// GenNoiseImage is the actual function which generates the image with the provided
// noise generator.
func GenNoiseImage(gen noise.Noise, pathFile string) error {
// Define boundary of image
myBound := image.Rectangle{Max: image.Point{X: width, Y: height}}
// Create a color palette
grayPalet := CreatePaletteGray()
// Create a new image
outGif := &gif.GIF{}
// Z-axis is the frame number
for z := 0; z < depth; z++ {
zz := float64(z) / smoothness
canvas := image.NewPaletted(myBound, grayPalet)
// Create frame image
for y := 0; y < height; y++ {
yy := float64(y) / zoomIn
for x := 0; x < width; x++ {
xx := float64(x) / zoomIn
// Generate noise at xx, yy of layer zz
grayC := NoiseToUint8(
gen.Eval64(xx, yy, zz),
)
canvas.SetColorIndex(x, y, grayC) // Plot the pixel
}
}
fmt.Printf("Frame: %d\r", z+1)
outGif.Image = append(outGif.Image, canvas)
outGif.Delay = append(outGif.Delay, 0)
}
// Export image
if err := SaveImgGIF(outGif, pathFile); err != nil {
return errors.Wrap(err, "failed to save image")
}
return nil
}
// NoiseToUint8 converts the "in" value to uint8.
//
// The "in" is the noise value which is between -1 and 1 of float64. This function
// converts it to a range of 0 to 255.
func NoiseToUint8(in float64) uint8 {
out := ((1. - in) / 2.) * 255. // in: [-1, 1] --> out: [0, 255]
return uint8(out)
}
func SaveImgGIF(img *gif.GIF, pathFile string) error {
f, _ := os.OpenFile(pathFile, os.O_WRONLY|os.O_CREATE, 0600)
defer f.Close()
if err := gif.EncodeAll(f, img); err != nil {
return errors.Wrap(err, "failed to save image")
}
return nil
}