-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
159 lines (142 loc) · 4.04 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
154
155
156
157
158
159
package main
import (
// "bufio"
"flag"
"fmt"
"image"
"image/color"
"image/png"
"math/cmplx"
"os"
"runtime"
"time"
)
// Constants for the image size.
const XSIZE = 4 * 2560
const YSIZE = 4 * 2048
// Constant for the number of iterations to perform.
const MAX_ITER = 255
// Parameters for generating the image.
const xLeft = -2.0
const xRight = 1.0
const yCenter = 0.0
// The y axis parameter have to be computed depending on the size of the image.
var yUpper, yLower float64
// Flag to obtain the number of goroutines to use in the generation
var NRoutines = flag.Int("n", 1, "number of goroutines to launch")
func main() {
flag.Parse()
runtime.GOMAXPROCS(*NRoutines)
start := time.Now()
fractal := MandelbrotLines(*NRoutines)
end := time.Now()
fmt.Printf("Generation took: %s\n", end.Sub(start))
SaveImage(fractal)
}
// ComputeIterations returns how many iterations took the complex n to diverge.
func ComputeIterations(n complex128) (iterations uint8) {
z := n
for cmplx.Abs(z) < 4 && iterations < MAX_ITER {
z = z*z + n
iterations += 1
}
return iterations
}
// ComputeStep returns the imaginary step from a pixel to another.
func ComputeStep() float64 {
return (xRight - xLeft) / XSIZE
}
// ComputeYBounds sets the global y-axis boundaries for a given step.
func ComputeYBounds(step float64) {
yUpper = yCenter + (step*YSIZE)/2
yLower = yCenter - (step*YSIZE)/2
}
// ComplexAt returns the associate complex to a i-j iteration and a step.
func ComplexAt(i, j int, step float64) (n complex128) {
return complex(xLeft+float64(j)*step, yUpper-float64(i)*step)
}
// SaveImage saves the created fractal representations
func SaveImage(fractal *image.RGBA) {
f, _ := os.Create("mandelbrot.png")
defer f.Close()
if err := png.Encode(f, fractal); err != nil {
panic(err)
}
}
func FancyColour(iter uint8) color.RGBA {
switch {
case iter == MAX_ITER:
return color.RGBA{0, 0, 0, 255}
case iter < 8:
return color.RGBA{128 + (iter * 16), 0, 0, 255}
case iter < 24:
return color.RGBA{255, (iter - 8) * 16, (iter - 8) * 16, 255}
case iter < 160:
return color.RGBA{255 - (iter-24)*2, 255 - (iter-24)*2, 255, 255}
default:
return color.RGBA{(iter - 160) * 2, (iter - 160) * 2,
255 - (iter-160)*2, 255}
}
}
// SimpleColor is a function used in NTNU to draw a BMP image of the Mandelbrot
// fractal.
func SimpleColor(iter uint8) color.RGBA {
switch {
case iter == MAX_ITER:
return color.RGBA{0, 0, 0, 255}
case iter < 8:
return color.RGBA{128 + (iter * 16), 0, 0, 255}
case iter < 24:
return color.RGBA{255, (iter - 8) * 16, (iter - 8) * 16, 255}
case iter < 160:
return color.RGBA{255 - (iter-24)*2, 255 - (iter-24)*2, 255, 255}
default:
return color.RGBA{(iter - 160) * 2, (iter - 160) * 2,
255 - (iter-160)*2, 255}
}
}
// FancyColor tries to mimic the interpolation used to generate the Mandelbrot
// image in Wikipedia linearly. As found in StackOverflow, this color palette
// is defined by these control points:
// Position = 0.0 Color = (0, 7, 100)
// Position = 0.16 Color = (32, 107, 203)
// Position = 0.42 Color = (237, 255, 255)
// Position = 0.6425 Color = (255, 170, 0)
// Position = 0.8575 Color = (0, 2, 0)
func FancyColor(iter uint8) color.RGBA {
position := float64(iter) / float64(MAX_ITER)
switch {
case position == 1.0:
return color.RGBA{0, 0, 0, 255}
case position < 0.16:
offset := position / 0.16
return color.RGBA{
uint8(0 + 32*offset),
uint8(7 + 100*offset),
uint8(100 + 103*offset),
255}
case position < 0.42:
offset := (position - 0.16) / 0.26
return color.RGBA{
uint8(32 + 205*offset),
uint8(107 + 148*offset),
uint8(203 + 52*offset),
255}
case position < 0.6425:
offset := (position - 0.42) / 0.2225
return color.RGBA{
uint8(237 + 18*offset),
uint8(255 - 85*offset),
uint8(255 - 255*offset),
255}
case position < 0.8575:
offset := (position - 0.6425) / 0.2150
return color.RGBA{
uint8(255 - 255*offset),
uint8(170 - 168*offset),
0, 255}
default:
offset := (position - 0.8575) / 0.1425
return color.RGBA{0, 0, uint8(0 + 2*offset), 255}
}
}