Re-arrange function ordering

This commit is contained in:
Steven Polley 2018-08-04 17:32:50 -06:00
parent 4ec1823f2c
commit 9384d8f12e
2 changed files with 85 additions and 131 deletions

View File

@ -1,4 +1,4 @@
FROM deadbeef.codes:5000/raspberrypi3-alpine:3.7 FROM deadbeef.codes:5000/raspberrypi3-alpine:3.7
COPY mandelmapper /usr/bin COPY mandelmapper /usr/bin
EXPOSE 6161:6161 EXPOSE 6161:6161
CMD mandelmapper CMD mandelmapper

220
render.go
View File

@ -1,7 +1,6 @@
package main package main
import ( import (
"fmt"
"image" "image"
"image/color" "image/color"
"image/png" "image/png"
@ -24,22 +23,9 @@ const (
var ( var (
colors []color.RGBA colors []color.RGBA
queue = make(chan pixel)
) )
func mandelbrot(c complex128) uint16 {
var z complex128
for i := 0; i < Iterations; i++ {
z = z*z + c
if cmplx.IsNaN(z) {
return uint16(i)
}
}
return Iterations
}
type pixel struct { type pixel struct {
out *image.RGBA out *image.RGBA
x, y int x, y int
@ -48,7 +34,22 @@ type pixel struct {
wg *sync.WaitGroup wg *sync.WaitGroup
} }
var queue = make(chan pixel) func init() {
http.HandleFunc("/mandelbrot/", renderTile)
}
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
for i := 0; i < runtime.GOMAXPROCS(0); i++ {
go computeThread()
}
colorStep := float64(Iterations)
colors = interpolateColors("Plan9", colorStep)
log.Fatal(http.ListenAndServe(":6161", nil))
}
func computeThread() { func computeThread() {
for p := range queue { for p := range queue {
@ -63,18 +64,70 @@ func computeThread() {
} }
} }
func main() { //interpolateColors accepts a color palette and number of desired colors and builds a slice of colors by interpolating the gaps
runtime.GOMAXPROCS(runtime.NumCPU()) func interpolateColors(paletteCode string, numberOfColors float64) []color.RGBA {
var factor float64
for i := 0; i < runtime.GOMAXPROCS(0); i++ { steps := []float64{}
go computeThread() cols := []uint32{}
interpolated := []uint32{}
interpolatedColors := []color.RGBA{}
for _, v := range palette.ColorPalettes {
factor = 1.0 / numberOfColors
switch v.Keyword {
case paletteCode:
if paletteCode != "" {
for index, col := range v.Colors {
if col.Step == 0.0 && index != 0 {
stepRatio := float64(index+1) / float64(len(v.Colors))
step := float64(int(stepRatio*100)) / 100 // truncate to 2 decimal precision
steps = append(steps, step)
} else {
steps = append(steps, col.Step)
} }
r, g, b, a := col.Color.RGBA()
r /= 0xff
g /= 0xff
b /= 0xff
a /= 0xff
uintColor := uint32(r)<<24 | uint32(g)<<16 | uint32(b)<<8 | uint32(a)
cols = append(cols, uintColor)
}
var min, max, minColor, maxColor float64
if len(v.Colors) == len(steps) && len(v.Colors) == len(cols) {
for i := 0.0; i <= 1; i += factor {
for j := 0; j < len(v.Colors)-1; j++ {
if i >= steps[j] && i < steps[j+1] {
min = steps[j]
max = steps[j+1]
minColor = float64(cols[j])
maxColor = float64(cols[j+1])
uintColor := cosineInterpolation(maxColor, minColor, (i-min)/(max-min))
interpolated = append(interpolated, uint32(uintColor))
}
}
}
}
for _, pixelValue := range interpolated {
r := pixelValue >> 24 & 0xff
g := pixelValue >> 16 & 0xff
b := pixelValue >> 8 & 0xff
a := 0xff
colorStep := float64(Iterations) interpolatedColors = append(interpolatedColors, color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)})
colors = interpolateColors("Plan9", colorStep) }
fmt.Println(len(colors)) }
}
}
return interpolatedColors
}
log.Fatal(http.ListenAndServe(":6161", nil)) func cosineInterpolation(c1, c2, mu float64) float64 {
mu2 := (1 - math.Cos(mu*math.Pi)) / 2.0
return c1*(1-mu2) + c2*mu2
}
func linearInterpolation(c1, c2, mu uint32) uint32 {
return c1*(1-mu) + c2*mu
} }
func renderTile(w http.ResponseWriter, r *http.Request) { func renderTile(w http.ResponseWriter, r *http.Request) {
@ -103,9 +156,7 @@ func renderTile(w http.ResponseWriter, r *http.Request) {
} }
var wg sync.WaitGroup var wg sync.WaitGroup
wg.Add(Size * Size) wg.Add(Size * Size)
img := image.NewRGBA(image.Rect(0, 0, Size, Size)) img := image.NewRGBA(image.Rect(0, 0, Size, Size))
for x := 0; x < Size; x++ { for x := 0; x < Size; x++ {
@ -116,114 +167,17 @@ func renderTile(w http.ResponseWriter, r *http.Request) {
} }
wg.Wait() wg.Wait()
/*
ip := GetOutboundIP()
addLabel(img, 20, 30, fmt.Sprintf("rendered by \n%s", ip.String()))
addLabel(img, 20, 30, fmt.Sprintf("%s/%s/%s.png", components[1], components[2], components[3]))
*/
w.Header().Set("Content-Type", "image/png") w.Header().Set("Content-Type", "image/png")
png.Encode(w, img) png.Encode(w, img)
} }
func init() { func mandelbrot(c complex128) uint16 {
http.HandleFunc("/mandelbrot/", renderTile) var z complex128
for i := 0; i < Iterations; i++ {
z = z*z + c
if cmplx.IsNaN(z) {
return uint16(i)
}
}
return Iterations
} }
func interpolateColors(paletteCode string, numberOfColors float64) []color.RGBA {
var factor float64
steps := []float64{}
cols := []uint32{}
interpolated := []uint32{}
interpolatedColors := []color.RGBA{}
for _, v := range palette.ColorPalettes {
factor = 1.0 / numberOfColors
switch v.Keyword {
case paletteCode:
if paletteCode != "" {
for index, col := range v.Colors {
if col.Step == 0.0 && index != 0 {
stepRatio := float64(index+1) / float64(len(v.Colors))
step := float64(int(stepRatio*100)) / 100 // truncate to 2 decimal precision
steps = append(steps, step)
} else {
steps = append(steps, col.Step)
}
r, g, b, a := col.Color.RGBA()
r /= 0xff
g /= 0xff
b /= 0xff
a /= 0xff
uintColor := uint32(r)<<24 | uint32(g)<<16 | uint32(b)<<8 | uint32(a)
cols = append(cols, uintColor)
}
var min, max, minColor, maxColor float64
if len(v.Colors) == len(steps) && len(v.Colors) == len(cols) {
for i := 0.0; i <= 1; i += factor {
for j := 0; j < len(v.Colors)-1; j++ {
if i >= steps[j] && i < steps[j+1] {
min = steps[j]
max = steps[j+1]
minColor = float64(cols[j])
maxColor = float64(cols[j+1])
uintColor := cosineInterpolation(maxColor, minColor, (i-min)/(max-min))
interpolated = append(interpolated, uint32(uintColor))
}
}
}
}
for _, pixelValue := range interpolated {
r := pixelValue >> 24 & 0xff
g := pixelValue >> 16 & 0xff
b := pixelValue >> 8 & 0xff
a := 0xff
interpolatedColors = append(interpolatedColors, color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)})
}
}
}
}
return interpolatedColors
}
func cosineInterpolation(c1, c2, mu float64) float64 {
mu2 := (1 - math.Cos(mu*math.Pi)) / 2.0
return c1*(1-mu2) + c2*mu2
}
func linearInterpolation(c1, c2, mu uint32) uint32 {
return c1*(1-mu) + c2*mu
}
//Adds a text label to an image
/*
func addLabel(img *image.RGBA, x, y int, label string) {
col := color.RGBA{255, 255, 255, 255}
point := fixed.Point26_6{fixed.Int26_6(x * 64), fixed.Int26_6(y * 64)}
d := &font.Drawer{
Dst: img,
Src: image.NewUniform(col),
Face: basicfont.Face7x13,
Dot: point,
}
d.DrawString(label)
}
func GetOutboundIP() net.IP {
conn, err := net.Dial("udp", "8.8.8.8:80")
if err != nil {
log.Fatal(err)
}
defer conn.Close()
localAddr := conn.LocalAddr().(*net.UDPAddr)
return localAddr.IP
}
*/