mirror of
https://bitbucket.org/s_l_teichmann/mtsatellite
synced 2024-11-17 15:48:17 +01:00
Added som broken pyramid generation code.
This commit is contained in:
parent
bbd96172a3
commit
a6bbf4a8bd
@ -20,6 +20,7 @@ func main() {
|
|||||||
outDir string
|
outDir string
|
||||||
numWorkers int
|
numWorkers int
|
||||||
skipBaseLevel bool
|
skipBaseLevel bool
|
||||||
|
skipPyramid bool
|
||||||
)
|
)
|
||||||
|
|
||||||
flag.IntVar(&port, "port", 6379, "port to of mtredisalize server")
|
flag.IntVar(&port, "port", 6379, "port to of mtredisalize server")
|
||||||
@ -34,8 +35,10 @@ func main() {
|
|||||||
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, "worker", 1, "number of workers")
|
flag.IntVar(&numWorkers, "worker", 1, "number of workers")
|
||||||
flag.IntVar(&numWorkers, "w", 1, "number of workers (shorthand)")
|
flag.IntVar(&numWorkers, "w", 1, "number of workers (shorthand)")
|
||||||
flag.BoolVar(&skipBaseLevel, "skip-base-level", false, "Do not generate baselevel")
|
flag.BoolVar(&skipBaseLevel, "skip-base-level", false, "Do not generate base level tiles")
|
||||||
flag.BoolVar(&skipBaseLevel, "sb", false, "Do not generate baselevel (shorthand)")
|
flag.BoolVar(&skipBaseLevel, "sb", false, "Do not generate base level tiles (shorthand)")
|
||||||
|
flag.BoolVar(&skipPyramid, "skip-pyramid", false, "Do not generate pyramid tiles")
|
||||||
|
flag.BoolVar(&skipPyramid, "sp", false, "Do not generate pyramid tiles (shorthand)")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
@ -44,7 +47,12 @@ func main() {
|
|||||||
address := fmt.Sprintf("%s:%d", host, port)
|
address := fmt.Sprintf("%s:%d", host, port)
|
||||||
if err = createBaseLevel(
|
if err = createBaseLevel(
|
||||||
address, xMin, zMin, xMax, zMax, colorsFile, outDir, numWorkers); err != nil {
|
address, xMin, zMin, xMax, zMax, colorsFile, outDir, numWorkers); err != nil {
|
||||||
log.Fatalf("Creating base level failed: %s", err)
|
log.Fatalf("Creating base level tiles failed: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !skipPyramid {
|
||||||
|
if err = createPyramid(outDir, numWorkers); err != nil {
|
||||||
|
log.Fatalf("Creating pyramid tiles failed: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
233
cmd/mtseeder/pyramid.go
Normal file
233
cmd/mtseeder/pyramid.go
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
// Copyright 2014 by Sascha L. Teichmann
|
||||||
|
// Use of this source code is governed by the MIT license
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"image"
|
||||||
|
"image/draw"
|
||||||
|
"image/png"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"math"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/nfnt/resize"
|
||||||
|
)
|
||||||
|
|
||||||
|
func findMaxDir(files []os.FileInfo) (min, max int) {
|
||||||
|
min, max = math.MaxInt32, math.MinInt32
|
||||||
|
for _, file := range files {
|
||||||
|
if !file.Mode().IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if x, err := strconv.Atoi(file.Name()); err == nil {
|
||||||
|
if x > max {
|
||||||
|
max = x
|
||||||
|
}
|
||||||
|
if x < min {
|
||||||
|
min = x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func findMaxFile(files []os.FileInfo) (min, max int) {
|
||||||
|
min, max = math.MaxInt32, math.MinInt32
|
||||||
|
for _, file := range files {
|
||||||
|
if !file.Mode().IsRegular() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
name := file.Name()
|
||||||
|
name = strings.TrimSuffix(name, filepath.Ext(name))
|
||||||
|
if x, err := strconv.Atoi(name); err == nil {
|
||||||
|
if x > max {
|
||||||
|
max = x
|
||||||
|
}
|
||||||
|
if x < min {
|
||||||
|
min = x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type pyramidJob struct {
|
||||||
|
src [4]string
|
||||||
|
dst string
|
||||||
|
}
|
||||||
|
|
||||||
|
func createParentLevel(oldDir string, jobs chan pyramidJob) (newDir string, err error) {
|
||||||
|
oldName := filepath.Base(oldDir)
|
||||||
|
|
||||||
|
var oldLevel int
|
||||||
|
if oldLevel, err = strconv.Atoi(oldName); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if oldLevel <= 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var files []os.FileInfo
|
||||||
|
if files, err = ioutil.ReadDir(oldDir); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
xMin, xMax := findMaxDir(files)
|
||||||
|
if xMax == math.MinInt32 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
newLevel := oldLevel - 1
|
||||||
|
|
||||||
|
log.Printf("Generating tiles of level %d", newLevel)
|
||||||
|
|
||||||
|
parentDir := filepath.Dir(oldDir)
|
||||||
|
newDir = filepath.Join(parentDir, strconv.Itoa(newLevel))
|
||||||
|
|
||||||
|
if err = os.MkdirAll(newDir, os.ModePerm); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for ox, nx := xMin, xMin; ox <= xMax; ox += 2 {
|
||||||
|
|
||||||
|
ox1Dir := filepath.Join(oldDir, strconv.Itoa(ox))
|
||||||
|
ox2Dir := filepath.Join(oldDir, strconv.Itoa(ox+1))
|
||||||
|
|
||||||
|
if files, err = ioutil.ReadDir(ox1Dir); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
zMin, zMax := findMaxFile(files)
|
||||||
|
if zMax == math.MinInt32 {
|
||||||
|
nx++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
nxDir := filepath.Join(newDir, strconv.Itoa(nx))
|
||||||
|
if err = os.MkdirAll(nxDir, os.ModePerm); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for oz, nz := zMin, zMin; oz <= zMax; oz += 2 {
|
||||||
|
oz1 := fmt.Sprintf("%d.png", oz)
|
||||||
|
oz2 := fmt.Sprintf("%d.png", oz+1)
|
||||||
|
s1 := filepath.Join(ox1Dir, oz1)
|
||||||
|
s2 := filepath.Join(ox1Dir, oz2)
|
||||||
|
s3 := filepath.Join(ox2Dir, oz1)
|
||||||
|
s4 := filepath.Join(ox2Dir, oz2)
|
||||||
|
d := filepath.Join(nxDir, fmt.Sprintf("%d.png", nz))
|
||||||
|
jobs <- pyramidJob{src: [4]string{s1, s2, s3, s4}, dst: d}
|
||||||
|
nz++
|
||||||
|
}
|
||||||
|
|
||||||
|
nx++
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadImage(path string) image.Image {
|
||||||
|
var err error
|
||||||
|
var file *os.File
|
||||||
|
if file, err = os.Open(path); err != nil {
|
||||||
|
//log.Printf("WARN: %s", err)
|
||||||
|
return image.White
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
reader := bufio.NewReader(file)
|
||||||
|
var img image.Image
|
||||||
|
if img, err = png.Decode(reader); err != nil {
|
||||||
|
log.Printf("WARN: %s", err)
|
||||||
|
return image.White
|
||||||
|
}
|
||||||
|
return img
|
||||||
|
}
|
||||||
|
|
||||||
|
func fuseTile(scratch *image.RGBA, job *pyramidJob) (err error) {
|
||||||
|
|
||||||
|
var ofs = [4][2]int{
|
||||||
|
{0, 0},
|
||||||
|
{0, 256},
|
||||||
|
{256, 0},
|
||||||
|
{256, 256}}
|
||||||
|
|
||||||
|
for i, path := range job.src {
|
||||||
|
|
||||||
|
img := loadImage(path)
|
||||||
|
|
||||||
|
draw.Draw(scratch,
|
||||||
|
image.Rect(0, 0, 256, 256),
|
||||||
|
img, image.Pt(ofs[i][0], ofs[i][1]), draw.Src)
|
||||||
|
}
|
||||||
|
|
||||||
|
resized := resize.Resize(256, 256, scratch, resize.Bicubic)
|
||||||
|
|
||||||
|
var outFile *os.File
|
||||||
|
if outFile, err = os.Create(job.dst); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
out := bufio.NewWriter(outFile)
|
||||||
|
|
||||||
|
if err = png.Encode(out, resized); err != nil {
|
||||||
|
outFile.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
out.Flush()
|
||||||
|
err = outFile.Close()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func fuseTiles(jobs chan pyramidJob, done *sync.WaitGroup) {
|
||||||
|
defer done.Done()
|
||||||
|
scratch := image.NewRGBA(image.Rect(0, 0, 512, 512))
|
||||||
|
|
||||||
|
for job := range jobs {
|
||||||
|
if err := fuseTile(scratch, &job); err != nil {
|
||||||
|
log.Printf("WARN: Writing image failed: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createPyramid(outDir string, numWorker int) (err error) {
|
||||||
|
|
||||||
|
for oldDir := filepath.Join(outDir, baseLevelDir); oldDir != ""; {
|
||||||
|
if oldDir, err = createLevel(oldDir, numWorker); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func createLevel(oldDir string, numWorker int) (newDir string, err error) {
|
||||||
|
|
||||||
|
jobs := make(chan pyramidJob)
|
||||||
|
|
||||||
|
var done sync.WaitGroup
|
||||||
|
|
||||||
|
for i := 0; i < numWorker; i++ {
|
||||||
|
done.Add(1)
|
||||||
|
go fuseTiles(jobs, &done)
|
||||||
|
}
|
||||||
|
|
||||||
|
newDir, err = createParentLevel(oldDir, jobs)
|
||||||
|
close(jobs)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
done.Wait()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user