mirror of
https://bitbucket.org/s_l_teichmann/mtsatellite
synced 2024-12-23 16:50:18 +01:00
Implement fetaure request issue #17
mtseeder and mtwebmapper got an option to set the background color where no nodes are generated, yet.
This commit is contained in:
parent
0030f7bc02
commit
0db9b519a6
@ -5,6 +5,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"image/color"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -39,7 +40,7 @@ func createBaseLevel(
|
|||||||
address string,
|
address string,
|
||||||
xMin, yMin, zMin, xMax, yMax, zMax int,
|
xMin, yMin, zMin, xMax, yMax, zMax int,
|
||||||
transparent bool, transparentDim float32,
|
transparent bool, transparentDim float32,
|
||||||
colorsFile, outDir string,
|
colorsFile string, bg color.RGBA, outDir string,
|
||||||
numWorkers int) (err error) {
|
numWorkers int) (err error) {
|
||||||
|
|
||||||
var colors *common.Colors
|
var colors *common.Colors
|
||||||
@ -65,7 +66,7 @@ func createBaseLevel(
|
|||||||
}
|
}
|
||||||
done.Add(1)
|
done.Add(1)
|
||||||
btc := common.NewBaseTileCreator(
|
btc := common.NewBaseTileCreator(
|
||||||
client, colors,
|
client, colors, bg,
|
||||||
int16(yMin), int16(yMax),
|
int16(yMin), int16(yMax),
|
||||||
transparent, baseDir, false)
|
transparent, baseDir, false)
|
||||||
go createTiles(btc, jobs, &done)
|
go createTiles(btc, jobs, &done)
|
||||||
|
@ -7,6 +7,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"image/color"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"bitbucket.org/s_l_teichmann/mtsatellite/common"
|
"bitbucket.org/s_l_teichmann/mtsatellite/common"
|
||||||
@ -19,6 +20,7 @@ func main() {
|
|||||||
xMin, yMin, zMin int
|
xMin, yMin, zMin int
|
||||||
xMax, yMax, zMax int
|
xMax, yMax, zMax int
|
||||||
colorsFile string
|
colorsFile string
|
||||||
|
bgColor string
|
||||||
outDir string
|
outDir string
|
||||||
numWorkers int
|
numWorkers int
|
||||||
skipBaseLevel bool
|
skipBaseLevel bool
|
||||||
@ -28,6 +30,8 @@ func main() {
|
|||||||
version bool
|
version bool
|
||||||
)
|
)
|
||||||
|
|
||||||
|
defaultBgColor := common.ColorToHex(common.BackgroundColor)
|
||||||
|
|
||||||
flag.IntVar(&port, "port", 6379, "port to of mtredisalize server")
|
flag.IntVar(&port, "port", 6379, "port to of mtredisalize server")
|
||||||
flag.IntVar(&port, "p", 6379, "port to of mtredisalize server (shorthand)")
|
flag.IntVar(&port, "p", 6379, "port to of mtredisalize server (shorthand)")
|
||||||
flag.StringVar(&host, "host", "localhost", "host to mtredisalize server")
|
flag.StringVar(&host, "host", "localhost", "host to mtredisalize server")
|
||||||
@ -38,6 +42,8 @@ func main() {
|
|||||||
flag.IntVar(&zMin, "zmin", -1933, "z min of the area to tile")
|
flag.IntVar(&zMin, "zmin", -1933, "z min of the area to tile")
|
||||||
flag.IntVar(&zMax, "zmax", 1932, "z max of the area to tile")
|
flag.IntVar(&zMax, "zmax", 1932, "z max of the area to tile")
|
||||||
flag.StringVar(&colorsFile, "colors", "colors.txt", "definition of colors")
|
flag.StringVar(&colorsFile, "colors", "colors.txt", "definition of colors")
|
||||||
|
flag.StringVar(&bgColor, "background", defaultBgColor, "background color")
|
||||||
|
flag.StringVar(&bgColor, "bg", defaultBgColor, "background color (shorthand)")
|
||||||
flag.StringVar(&outDir, "output-dir", "map", "directory with the resulting image tree")
|
flag.StringVar(&outDir, "output-dir", "map", "directory with the resulting image tree")
|
||||||
flag.StringVar(&outDir, "o", "map", "directory with the resulting image tree")
|
flag.StringVar(&outDir, "o", "map", "directory with the resulting image tree")
|
||||||
flag.IntVar(&numWorkers, "workers", 1, "number of workers")
|
flag.IntVar(&numWorkers, "workers", 1, "number of workers")
|
||||||
@ -62,6 +68,13 @@ func main() {
|
|||||||
common.PrintVersionAndExit()
|
common.PrintVersionAndExit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var bg color.RGBA
|
||||||
|
var err error
|
||||||
|
if bg, err = common.ParseColor(bgColor); err != nil {
|
||||||
|
log.Printf("WARN: Cannot parse background color '%s': %s\n", bgColor, err)
|
||||||
|
bg = common.BackgroundColor
|
||||||
|
}
|
||||||
|
|
||||||
if !skipBaseLevel {
|
if !skipBaseLevel {
|
||||||
td := common.Clamp32f(float32(transparentDim/100.0), 0.0, 1.0)
|
td := common.Clamp32f(float32(transparentDim/100.0), 0.0, 1.0)
|
||||||
address := fmt.Sprintf("%s:%d", host, port)
|
address := fmt.Sprintf("%s:%d", host, port)
|
||||||
@ -69,14 +82,15 @@ func main() {
|
|||||||
address,
|
address,
|
||||||
xMin, yMin, zMin, xMax, yMax, zMax,
|
xMin, yMin, zMin, xMax, yMax, zMax,
|
||||||
transparent, td,
|
transparent, td,
|
||||||
colorsFile,
|
colorsFile, bg,
|
||||||
outDir,
|
outDir,
|
||||||
numWorkers); err != nil {
|
numWorkers); err != nil {
|
||||||
log.Fatalf("Creating base level tiles failed: %s", err)
|
log.Fatalf("Creating base level tiles failed: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !skipPyramid {
|
if !skipPyramid {
|
||||||
if err := createPyramid(outDir, numWorkers); err != nil {
|
pc := pyramidCreator{numWorkers: numWorkers, outDir: outDir, bg: bg}
|
||||||
|
if err := pc.create(); err != nil {
|
||||||
log.Fatalf("Creating pyramid tiles failed: %s", err)
|
log.Fatalf("Creating pyramid tiles failed: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"image"
|
"image"
|
||||||
|
"image/color"
|
||||||
"image/draw"
|
"image/draw"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
@ -21,6 +22,12 @@ import (
|
|||||||
"github.com/bamiaux/rez"
|
"github.com/bamiaux/rez"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type pyramidCreator struct {
|
||||||
|
numWorkers int
|
||||||
|
outDir string
|
||||||
|
bg color.RGBA
|
||||||
|
}
|
||||||
|
|
||||||
func findMaxDir(files []os.FileInfo) (min, max int) {
|
func findMaxDir(files []os.FileInfo) (min, max int) {
|
||||||
min, max = math.MaxInt32, math.MinInt32
|
min, max = math.MaxInt32, math.MinInt32
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
@ -64,7 +71,10 @@ type pyramidJob struct {
|
|||||||
dst string
|
dst string
|
||||||
}
|
}
|
||||||
|
|
||||||
func createParentLevel(oldDir string, jobs chan pyramidJob) (newDir string, err error) {
|
func (pc *pyramidCreator) createParentLevel(
|
||||||
|
oldDir string,
|
||||||
|
jobs chan pyramidJob) (newDir string, err error) {
|
||||||
|
|
||||||
oldName := filepath.Base(oldDir)
|
oldName := filepath.Base(oldDir)
|
||||||
|
|
||||||
var oldLevel int
|
var oldLevel int
|
||||||
@ -155,11 +165,14 @@ var dps = [4]image.Point{
|
|||||||
image.Pt(256, 256),
|
image.Pt(256, 256),
|
||||||
image.Pt(256, 0)}
|
image.Pt(256, 0)}
|
||||||
|
|
||||||
func fuseTile(scratch, resized *image.RGBA, conv rez.Converter, job *pyramidJob) error {
|
func (pc *pyramidCreator) fuseTile(
|
||||||
|
scratch, resized *image.RGBA,
|
||||||
|
conv rez.Converter,
|
||||||
|
job *pyramidJob) error {
|
||||||
|
|
||||||
for i, path := range job.src {
|
for i, path := range job.src {
|
||||||
|
|
||||||
img := common.LoadPNG(path)
|
img := common.LoadPNG(path, pc.bg)
|
||||||
|
|
||||||
sr := clipRect(img.Bounds())
|
sr := clipRect(img.Bounds())
|
||||||
r := sr.Sub(sr.Min).Add(dps[i])
|
r := sr.Sub(sr.Min).Add(dps[i])
|
||||||
@ -176,7 +189,7 @@ func fuseTile(scratch, resized *image.RGBA, conv rez.Converter, job *pyramidJob)
|
|||||||
return common.SaveAsPNG(job.dst, resized)
|
return common.SaveAsPNG(job.dst, resized)
|
||||||
}
|
}
|
||||||
|
|
||||||
func fuseTiles(jobs chan pyramidJob, done *sync.WaitGroup) {
|
func (pc *pyramidCreator) fuseTiles(jobs chan pyramidJob, done *sync.WaitGroup) {
|
||||||
defer done.Done()
|
defer done.Done()
|
||||||
scratch := image.NewRGBA(image.Rect(0, 0, 512, 512))
|
scratch := image.NewRGBA(image.Rect(0, 0, 512, 512))
|
||||||
resized := image.NewRGBA(image.Rect(0, 0, 256, 256))
|
resized := image.NewRGBA(image.Rect(0, 0, 256, 256))
|
||||||
@ -194,41 +207,41 @@ func fuseTiles(jobs chan pyramidJob, done *sync.WaitGroup) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for job := range jobs {
|
for job := range jobs {
|
||||||
if err := fuseTile(scratch, resized, conv, &job); err != nil {
|
if err := pc.fuseTile(scratch, resized, conv, &job); err != nil {
|
||||||
log.Printf("WARN: Writing image failed: %s\n", err)
|
log.Printf("WARN: Writing image failed: %s\n", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createPyramid(outDir string, numWorker int) (err error) {
|
func (pc *pyramidCreator) create() (err error) {
|
||||||
|
|
||||||
for oldDir := filepath.Join(outDir, baseLevelDir); oldDir != ""; {
|
for oldDir := filepath.Join(pc.outDir, baseLevelDir); oldDir != ""; {
|
||||||
if oldDir, err = createLevel(oldDir, numWorker); err != nil {
|
if oldDir, err = pc.createLevel(oldDir); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func createLevel(oldDir string, numWorker int) (newDir string, err error) {
|
func (pc *pyramidCreator) createLevel(oldDir string) (string, error) {
|
||||||
|
|
||||||
jobs := make(chan pyramidJob)
|
jobs := make(chan pyramidJob)
|
||||||
|
|
||||||
var done sync.WaitGroup
|
var done sync.WaitGroup
|
||||||
|
|
||||||
for i := 0; i < numWorker; i++ {
|
for i := 0; i < pc.numWorkers; i++ {
|
||||||
done.Add(1)
|
done.Add(1)
|
||||||
go fuseTiles(jobs, &done)
|
go pc.fuseTiles(jobs, &done)
|
||||||
}
|
}
|
||||||
|
|
||||||
newDir, err = createParentLevel(oldDir, jobs)
|
newDir, err := pc.createParentLevel(oldDir, jobs)
|
||||||
close(jobs)
|
close(jobs)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return newDir, err
|
||||||
}
|
}
|
||||||
|
|
||||||
done.Wait()
|
done.Wait()
|
||||||
|
|
||||||
return
|
return newDir, err
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ func main() {
|
|||||||
x, y, z int
|
x, y, z int
|
||||||
width, height, depth int
|
width, height, depth int
|
||||||
colorsfile string
|
colorsfile string
|
||||||
|
bgColor string
|
||||||
outfile string
|
outfile string
|
||||||
shaded bool
|
shaded bool
|
||||||
transparent bool
|
transparent bool
|
||||||
@ -31,6 +32,8 @@ func main() {
|
|||||||
version bool
|
version bool
|
||||||
)
|
)
|
||||||
|
|
||||||
|
defaultBgColor := common.ColorToHex(common.BackgroundColor)
|
||||||
|
|
||||||
flag.IntVar(&port, "port", 6379, "port to of mtredisalize server")
|
flag.IntVar(&port, "port", 6379, "port to of mtredisalize server")
|
||||||
flag.IntVar(&port, "p", 6379, "port to of mtredisalize server (shorthand)")
|
flag.IntVar(&port, "p", 6379, "port to of mtredisalize server (shorthand)")
|
||||||
flag.StringVar(&host, "host", "localhost", "host to mtredisalize server")
|
flag.StringVar(&host, "host", "localhost", "host to mtredisalize server")
|
||||||
@ -44,6 +47,8 @@ func main() {
|
|||||||
flag.IntVar(&height, "h", 16, "height of query cuboid (shorthand)")
|
flag.IntVar(&height, "h", 16, "height of query cuboid (shorthand)")
|
||||||
flag.IntVar(&depth, "d", 150, "depth of query cuboid (shorthand)")
|
flag.IntVar(&depth, "d", 150, "depth of query cuboid (shorthand)")
|
||||||
flag.StringVar(&colorsfile, "colors", "colors.txt", "definition of colors")
|
flag.StringVar(&colorsfile, "colors", "colors.txt", "definition of colors")
|
||||||
|
flag.StringVar(&bgColor, "background", defaultBgColor, "background color")
|
||||||
|
flag.StringVar(&bgColor, "bg", defaultBgColor, "background color (shorthand)")
|
||||||
flag.StringVar(&outfile, "output", "out.png", "image file of result")
|
flag.StringVar(&outfile, "output", "out.png", "image file of result")
|
||||||
flag.StringVar(&outfile, "o", "out.png", "image file of result (shorthand)")
|
flag.StringVar(&outfile, "o", "out.png", "image file of result (shorthand)")
|
||||||
flag.BoolVar(&shaded, "shaded", true, "draw relief")
|
flag.BoolVar(&shaded, "shaded", true, "draw relief")
|
||||||
@ -60,6 +65,13 @@ func main() {
|
|||||||
common.PrintVersionAndExit()
|
common.PrintVersionAndExit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var bg color.RGBA
|
||||||
|
var err error
|
||||||
|
if bg, err = common.ParseColor(bgColor); err != nil {
|
||||||
|
log.Printf("WARN: Cannot parse background color '%s': %s\n", bgColor, err)
|
||||||
|
bg = common.BackgroundColor
|
||||||
|
}
|
||||||
|
|
||||||
if cpuProfile != "" {
|
if cpuProfile != "" {
|
||||||
f, err := os.Create(cpuProfile)
|
f, err := os.Create(cpuProfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -69,9 +81,7 @@ func main() {
|
|||||||
defer pprof.StopCPUProfile()
|
defer pprof.StopCPUProfile()
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
|
||||||
var colors *common.Colors
|
var colors *common.Colors
|
||||||
|
|
||||||
if colors, err = common.ParseColors(colorsfile); err != nil {
|
if colors, err = common.ParseColors(colorsfile); err != nil {
|
||||||
log.Fatalf("Cannot open color file: %s", err)
|
log.Fatalf("Cannot open color file: %s", err)
|
||||||
}
|
}
|
||||||
@ -134,10 +144,9 @@ func main() {
|
|||||||
if shaded {
|
if shaded {
|
||||||
image = renderer.CreateShadedImage(
|
image = renderer.CreateShadedImage(
|
||||||
16, 16, (width-2)*16, (height-2)*16,
|
16, 16, (width-2)*16, (height-2)*16,
|
||||||
colors, color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff})
|
colors, bg)
|
||||||
} else {
|
} else {
|
||||||
image = renderer.CreateImage(
|
image = renderer.CreateImage(colors.Colors, bg)
|
||||||
colors.Colors, color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = common.SaveAsPNG(outfile, image); err != nil {
|
if err = common.SaveAsPNG(outfile, image); err != nil {
|
||||||
|
@ -7,6 +7,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"image/color"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -25,6 +26,7 @@ func main() {
|
|||||||
redisPort int
|
redisPort int
|
||||||
redisHost string
|
redisHost string
|
||||||
colorsFile string
|
colorsFile string
|
||||||
|
bgColor string
|
||||||
workers int
|
workers int
|
||||||
transparent bool
|
transparent bool
|
||||||
transparentDim float64
|
transparentDim float64
|
||||||
@ -35,6 +37,9 @@ func main() {
|
|||||||
yMin int
|
yMin int
|
||||||
yMax int
|
yMax int
|
||||||
)
|
)
|
||||||
|
|
||||||
|
defaultBgColor := common.ColorToHex(common.BackgroundColor)
|
||||||
|
|
||||||
flag.IntVar(&webPort, "web-port", 8808, "port of the web server")
|
flag.IntVar(&webPort, "web-port", 8808, "port of the web server")
|
||||||
flag.IntVar(&webPort, "p", 8808, "port of the web server (shorthand)")
|
flag.IntVar(&webPort, "p", 8808, "port of the web server (shorthand)")
|
||||||
flag.StringVar(&webHost, "web-host", "localhost", "address to bind web server")
|
flag.StringVar(&webHost, "web-host", "localhost", "address to bind web server")
|
||||||
@ -54,6 +59,8 @@ func main() {
|
|||||||
flag.IntVar(&workers, "workers", 1, "number of workers to render tiles")
|
flag.IntVar(&workers, "workers", 1, "number of workers to render tiles")
|
||||||
flag.StringVar(&colorsFile, "colors", "colors.txt", "colors used to render map tiles.")
|
flag.StringVar(&colorsFile, "colors", "colors.txt", "colors used to render map tiles.")
|
||||||
flag.StringVar(&colorsFile, "c", "colors.txt", "colors used to render map tiles (shorthand).")
|
flag.StringVar(&colorsFile, "c", "colors.txt", "colors used to render map tiles (shorthand).")
|
||||||
|
flag.StringVar(&bgColor, "background", defaultBgColor, "background color")
|
||||||
|
flag.StringVar(&bgColor, "bg", defaultBgColor, "background color (shorthand)")
|
||||||
flag.BoolVar(&transparent, "transparent", false, "Render transparent blocks.")
|
flag.BoolVar(&transparent, "transparent", false, "Render transparent blocks.")
|
||||||
flag.BoolVar(&transparent, "t", false, "Render transparent blocks (shorthand).")
|
flag.BoolVar(&transparent, "t", false, "Render transparent blocks (shorthand).")
|
||||||
flag.Float64Var(&transparentDim,
|
flag.Float64Var(&transparentDim,
|
||||||
@ -76,9 +83,16 @@ func main() {
|
|||||||
common.PrintVersionAndExit()
|
common.PrintVersionAndExit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var bg color.RGBA
|
||||||
|
var err error
|
||||||
|
if bg, err = common.ParseColor(bgColor); err != nil {
|
||||||
|
log.Printf("WARN: Cannot parse background color '%s': %s\n", bgColor, err)
|
||||||
|
bg = common.BackgroundColor
|
||||||
|
}
|
||||||
|
|
||||||
router := mux.NewRouter()
|
router := mux.NewRouter()
|
||||||
|
|
||||||
subBaseLine := newSubBaseLine(mapDir)
|
subBaseLine := newSubBaseLine(mapDir, bg)
|
||||||
router.Path("/map/{z:[0-9]+}/{x:[0-9]+}/{y:[0-9]+}.png").Handler(subBaseLine)
|
router.Path("/map/{z:[0-9]+}/{x:[0-9]+}/{y:[0-9]+}.png").Handler(subBaseLine)
|
||||||
|
|
||||||
var btu baseTilesUpdates
|
var btu baseTilesUpdates
|
||||||
@ -116,7 +130,7 @@ func main() {
|
|||||||
mapDir,
|
mapDir,
|
||||||
redisAddress,
|
redisAddress,
|
||||||
allowedUpdateIps,
|
allowedUpdateIps,
|
||||||
colors,
|
colors, bg,
|
||||||
yMin, yMax,
|
yMin, yMax,
|
||||||
transparent,
|
transparent,
|
||||||
workers,
|
workers,
|
||||||
|
@ -7,6 +7,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
|
"image/color"
|
||||||
"image/png"
|
"image/png"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -21,10 +22,11 @@ import (
|
|||||||
|
|
||||||
type subBaseLine struct {
|
type subBaseLine struct {
|
||||||
mapDir string
|
mapDir string
|
||||||
|
bg color.RGBA
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSubBaseLine(mapDir string) *subBaseLine {
|
func newSubBaseLine(mapDir string, bg color.RGBA) *subBaseLine {
|
||||||
return &subBaseLine{mapDir: mapDir}
|
return &subBaseLine{mapDir: mapDir, bg: bg}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sb *subBaseLine) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
func (sb *subBaseLine) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||||
@ -77,7 +79,7 @@ func (sb *subBaseLine) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
|||||||
xo := w * rx
|
xo := w * rx
|
||||||
yo := w * (parts - 1 - ry)
|
yo := w * (parts - 1 - ry)
|
||||||
|
|
||||||
img := common.LoadPNG(baseTile)
|
img := common.LoadPNG(baseTile, sb.bg)
|
||||||
|
|
||||||
type subImage interface {
|
type subImage interface {
|
||||||
SubImage(image.Rectangle) image.Image
|
SubImage(image.Rectangle) image.Image
|
||||||
|
@ -7,6 +7,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"image"
|
"image"
|
||||||
|
"image/color"
|
||||||
"image/draw"
|
"image/draw"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
@ -34,6 +35,7 @@ type tileUpdater struct {
|
|||||||
redisAddress string
|
redisAddress string
|
||||||
ips []net.IP
|
ips []net.IP
|
||||||
colors *common.Colors
|
colors *common.Colors
|
||||||
|
bg color.RGBA
|
||||||
yMin, yMax int16
|
yMin, yMax int16
|
||||||
workers int
|
workers int
|
||||||
transparent bool
|
transparent bool
|
||||||
@ -71,6 +73,7 @@ func newTileUpdater(
|
|||||||
mapDir, redisAddress string,
|
mapDir, redisAddress string,
|
||||||
ips []net.IP,
|
ips []net.IP,
|
||||||
colors *common.Colors,
|
colors *common.Colors,
|
||||||
|
bg color.RGBA,
|
||||||
yMin, yMax int,
|
yMin, yMax int,
|
||||||
transparent bool,
|
transparent bool,
|
||||||
workers int,
|
workers int,
|
||||||
@ -83,6 +86,7 @@ func newTileUpdater(
|
|||||||
ips: ips,
|
ips: ips,
|
||||||
changes: map[xz]bool{},
|
changes: map[xz]bool{},
|
||||||
colors: colors,
|
colors: colors,
|
||||||
|
bg: bg,
|
||||||
yMin: int16(yMin),
|
yMin: int16(yMin),
|
||||||
yMax: int16(yMax),
|
yMax: int16(yMax),
|
||||||
transparent: transparent,
|
transparent: transparent,
|
||||||
@ -171,11 +175,11 @@ func (tu *tileUpdater) doUpdates() {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
btc := common.NewBaseTileCreator(
|
btc := common.NewBaseTileCreator(
|
||||||
client, tu.colors,
|
client, tu.colors, tu.bg,
|
||||||
tu.yMin, tu.yMax,
|
tu.yMin, tu.yMax,
|
||||||
tu.transparent, baseDir, true)
|
tu.transparent, baseDir, true)
|
||||||
done.Add(1)
|
done.Add(1)
|
||||||
go updateBaseTiles(jobs, btc, &done)
|
go tu.updateBaseTiles(jobs, btc, &done)
|
||||||
}
|
}
|
||||||
|
|
||||||
parentJobs := make(map[xz]uint16)
|
parentJobs := make(map[xz]uint16)
|
||||||
@ -193,7 +197,7 @@ func (tu *tileUpdater) doUpdates() {
|
|||||||
pJobs := make(chan xzm)
|
pJobs := make(chan xzm)
|
||||||
for i, n := 0, common.Min(len(parentJobs), tu.workers); i < n; i++ {
|
for i, n := 0, common.Min(len(parentJobs), tu.workers); i < n; i++ {
|
||||||
done.Add(1)
|
done.Add(1)
|
||||||
go updatePyramidTiles(level, tu.mapDir, pJobs, &done)
|
go tu.updatePyramidTiles(level, pJobs, &done)
|
||||||
}
|
}
|
||||||
ppJobs := make(map[xz]uint16)
|
ppJobs := make(map[xz]uint16)
|
||||||
for c, mask := range parentJobs {
|
for c, mask := range parentJobs {
|
||||||
@ -212,13 +216,15 @@ func (tu *tileUpdater) doUpdates() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updatePyramidTiles(level int, baseDir string, jobs chan xzm, done *sync.WaitGroup) {
|
func (tu *tileUpdater) updatePyramidTiles(
|
||||||
|
level int, jobs chan xzm, done *sync.WaitGroup) {
|
||||||
|
|
||||||
defer done.Done()
|
defer done.Done()
|
||||||
scratch := image.NewRGBA(image.Rect(0, 0, 256, 256))
|
scratch := image.NewRGBA(image.Rect(0, 0, 256, 256))
|
||||||
resized := image.NewRGBA(image.Rect(0, 0, 128, 128))
|
resized := image.NewRGBA(image.Rect(0, 0, 128, 128))
|
||||||
|
|
||||||
for job := range jobs {
|
for job := range jobs {
|
||||||
if err := updatePyramidTile(scratch, resized, level, baseDir, job); err != nil {
|
if err := tu.updatePyramidTile(scratch, resized, level, job); err != nil {
|
||||||
log.Printf("Updating pyramid tile failed: %s\n", err)
|
log.Printf("Updating pyramid tile failed: %s\n", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -244,28 +250,29 @@ var ofs = [4][2]int{
|
|||||||
|
|
||||||
var windowSize = image.Pt(128, 128)
|
var windowSize = image.Pt(128, 128)
|
||||||
|
|
||||||
func updatePyramidTile(scratch, resized *image.RGBA, level int, baseDir string, j xzm) error {
|
func (tu *tileUpdater) updatePyramidTile(scratch, resized *image.RGBA, level int, j xzm) error {
|
||||||
|
|
||||||
var orig image.Image
|
var orig image.Image
|
||||||
|
|
||||||
origPath := filepath.Join(
|
origPath := filepath.Join(
|
||||||
baseDir,
|
tu.mapDir,
|
||||||
strconv.Itoa(level),
|
strconv.Itoa(level),
|
||||||
strconv.Itoa(int(j.P.X)),
|
strconv.Itoa(int(j.P.X)),
|
||||||
strconv.Itoa(int(j.P.Z))+".png")
|
strconv.Itoa(int(j.P.Z))+".png")
|
||||||
|
|
||||||
sr := resized.Bounds()
|
sr := resized.Bounds()
|
||||||
|
levelDir := strconv.Itoa(level + 1)
|
||||||
for i := uint16(0); i < 4; i++ {
|
for i := uint16(0); i < 4; i++ {
|
||||||
if j.Mask&(1<<i) != 0 {
|
if j.Mask&(1<<i) != 0 {
|
||||||
//log.Printf("level %d: modified %d\n", level, i)
|
//log.Printf("level %d: modified %d\n", level, i)
|
||||||
o := ofs[i]
|
o := ofs[i]
|
||||||
bx, bz := int(2*j.P.X), int(2*j.P.Z)
|
bx, bz := int(2*j.P.X), int(2*j.P.Z)
|
||||||
path := filepath.Join(
|
path := filepath.Join(
|
||||||
baseDir,
|
tu.mapDir,
|
||||||
strconv.Itoa(level+1),
|
levelDir,
|
||||||
strconv.Itoa(bx+o[0]),
|
strconv.Itoa(bx+o[0]),
|
||||||
strconv.Itoa(bz+o[1])+".png")
|
strconv.Itoa(bz+o[1])+".png")
|
||||||
img := common.LoadPNG(path)
|
img := common.LoadPNG(path, tu.bg)
|
||||||
if err := rez.Convert(resized, img, common.ResizeFilter); err != nil {
|
if err := rez.Convert(resized, img, common.ResizeFilter); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -274,7 +281,7 @@ func updatePyramidTile(scratch, resized *image.RGBA, level int, baseDir string,
|
|||||||
} else {
|
} else {
|
||||||
// Load lazy
|
// Load lazy
|
||||||
if orig == nil {
|
if orig == nil {
|
||||||
orig = common.LoadPNG(origPath)
|
orig = common.LoadPNG(origPath, tu.bg)
|
||||||
}
|
}
|
||||||
//log.Printf("level %d: copied %d\n", level, i)
|
//log.Printf("level %d: copied %d\n", level, i)
|
||||||
min := orig.Bounds().Min.Add(dps[i])
|
min := orig.Bounds().Min.Add(dps[i])
|
||||||
@ -286,7 +293,10 @@ func updatePyramidTile(scratch, resized *image.RGBA, level int, baseDir string,
|
|||||||
return common.SaveAsPNGAtomic(origPath, scratch)
|
return common.SaveAsPNGAtomic(origPath, scratch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateBaseTiles(jobs chan xz, btc *common.BaseTileCreator, done *sync.WaitGroup) {
|
func (tu *tileUpdater) updateBaseTiles(
|
||||||
|
jobs chan xz,
|
||||||
|
btc *common.BaseTileCreator, done *sync.WaitGroup) {
|
||||||
|
|
||||||
defer btc.Close()
|
defer btc.Close()
|
||||||
defer done.Done()
|
defer done.Done()
|
||||||
for job := range jobs {
|
for job := range jobs {
|
||||||
|
@ -59,11 +59,13 @@ type BaseTileCreator struct {
|
|||||||
baseDir string
|
baseDir string
|
||||||
update bool
|
update bool
|
||||||
emptyImage []byte
|
emptyImage []byte
|
||||||
|
bg color.RGBA
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBaseTileCreator(
|
func NewBaseTileCreator(
|
||||||
client *RedisClient,
|
client *RedisClient,
|
||||||
colors *Colors,
|
colors *Colors,
|
||||||
|
bg color.RGBA,
|
||||||
yMin, yMax int16,
|
yMin, yMax int16,
|
||||||
transparent bool,
|
transparent bool,
|
||||||
baseDir string,
|
baseDir string,
|
||||||
@ -73,6 +75,7 @@ func NewBaseTileCreator(
|
|||||||
return &BaseTileCreator{
|
return &BaseTileCreator{
|
||||||
client: client,
|
client: client,
|
||||||
colors: colors,
|
colors: colors,
|
||||||
|
bg: bg,
|
||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
yOrder: NewYOrder(renderer, yOrderCapacity),
|
yOrder: NewYOrder(renderer, yOrderCapacity),
|
||||||
yMin: yMin,
|
yMin: yMin,
|
||||||
@ -141,7 +144,7 @@ func (btc *BaseTileCreator) CreateTile(x, z int16, i, j int) error {
|
|||||||
// To avoid redundant encoding cache the resulting empty image.
|
// To avoid redundant encoding cache the resulting empty image.
|
||||||
if btc.emptyImage == nil {
|
if btc.emptyImage == nil {
|
||||||
var err error
|
var err error
|
||||||
m := BackgroundImage((tileWidth-2)*16, (tileHeight-2)*16, BackgroundColor)
|
m := BackgroundImage((tileWidth-2)*16, (tileHeight-2)*16, btc.bg)
|
||||||
if btc.emptyImage, err = EncodeToMem(m); err != nil {
|
if btc.emptyImage, err = EncodeToMem(m); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -152,7 +155,7 @@ func (btc *BaseTileCreator) CreateTile(x, z int16, i, j int) error {
|
|||||||
|
|
||||||
image := btc.renderer.CreateShadedImage(
|
image := btc.renderer.CreateShadedImage(
|
||||||
16, 16, (tileWidth-2)*16, (tileHeight-2)*16,
|
16, 16, (tileWidth-2)*16, (tileHeight-2)*16,
|
||||||
btc.colors, BackgroundColor)
|
btc.colors, btc.bg)
|
||||||
|
|
||||||
log.Printf("Writing (%d, %d) to file %s\n", x, z, path)
|
log.Printf("Writing (%d, %d) to file %s\n", x, z, path)
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"image/color"
|
"image/color"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -121,3 +122,20 @@ func (colors *Colors) BlendColors(span *Span, col color.RGBA, pos int32) color.R
|
|||||||
}
|
}
|
||||||
return col
|
return col
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ParseColor(col string) (color.RGBA, error) {
|
||||||
|
col = strings.TrimLeft(col, "#")
|
||||||
|
rgb, err := strconv.ParseUint(col, 16, 32)
|
||||||
|
if err != nil {
|
||||||
|
return color.RGBA{}, err
|
||||||
|
}
|
||||||
|
return color.RGBA{
|
||||||
|
R: uint8(rgb >> 16),
|
||||||
|
G: uint8(rgb >> 8),
|
||||||
|
B: uint8(rgb),
|
||||||
|
A: 0xff}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ColorToHex(col color.RGBA) string {
|
||||||
|
return fmt.Sprintf("#%02x%02x%02x", col.R, col.G, col.B)
|
||||||
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"image"
|
"image"
|
||||||
|
"image/color"
|
||||||
"image/png"
|
"image/png"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
@ -94,18 +95,18 @@ func SaveAsPNGAtomic(path string, img image.Image) (err error) {
|
|||||||
return os.Rename(tmpPath, path)
|
return os.Rename(tmpPath, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadPNG(path string) image.Image {
|
func LoadPNG(path string, bg color.RGBA) image.Image {
|
||||||
var err error
|
var err error
|
||||||
var file *os.File
|
var file *os.File
|
||||||
if file, err = os.Open(path); err != nil {
|
if file, err = os.Open(path); err != nil {
|
||||||
return image.White
|
return image.NewUniform(bg)
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
reader := bufio.NewReader(file)
|
reader := bufio.NewReader(file)
|
||||||
var img image.Image
|
var img image.Image
|
||||||
if img, err = png.Decode(reader); err != nil {
|
if img, err = png.Decode(reader); err != nil {
|
||||||
log.Printf("WARN: decoding '%s' failed: %s\n", path, err)
|
log.Printf("WARN: decoding '%s' failed: %s\n", path, err)
|
||||||
return image.White
|
return image.NewUniform(bg)
|
||||||
}
|
}
|
||||||
return img
|
return img
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user