mirror of
https://bitbucket.org/s_l_teichmann/mtsatellite
synced 2024-11-17 23:58:17 +01:00
Moved sub baseline tile generation into separate file.
This commit is contained in:
parent
cf0aec6fa5
commit
29845a259d
@ -7,71 +7,12 @@ package main
|
|||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
|
||||||
"image/color"
|
|
||||||
"image/png"
|
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"bitbucket.org/s_l_teichmann/mtredisalize/common"
|
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
func blowUp(src image.Image) *image.RGBA {
|
|
||||||
|
|
||||||
// TODO: Fast path for image.RGBA
|
|
||||||
|
|
||||||
dst := image.NewRGBA(image.Rect(0, 0, 256, 256))
|
|
||||||
|
|
||||||
// fix point numbers x:8
|
|
||||||
dx, dy := src.Bounds().Dx(), src.Bounds().Dy()
|
|
||||||
|
|
||||||
bx, by := src.Bounds().Min.X<<8, src.Bounds().Min.Y<<8
|
|
||||||
|
|
||||||
py := by
|
|
||||||
for y := 0; y < 256; y++ {
|
|
||||||
sy := (py >> 8) & 0xff
|
|
||||||
ox := -1
|
|
||||||
px := bx
|
|
||||||
var col color.Color
|
|
||||||
for x := 0; x < 256; x++ {
|
|
||||||
sx := (px >> 8) & 0xff
|
|
||||||
if sx != ox { // Minimize interface indirection access.
|
|
||||||
ox = sx
|
|
||||||
col = src.At(sx, sy)
|
|
||||||
}
|
|
||||||
dst.Set(x, y, col)
|
|
||||||
px += dx
|
|
||||||
}
|
|
||||||
py += dy
|
|
||||||
}
|
|
||||||
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
func toUint(s string) uint {
|
|
||||||
var err error
|
|
||||||
var x int
|
|
||||||
if x, err = strconv.Atoi(s); err != nil {
|
|
||||||
log.Printf("WARN: Cannot convert to int: %s", err)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return uint(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func createETag(path string) (etag string, err error) {
|
|
||||||
var fi os.FileInfo
|
|
||||||
if fi, err = os.Stat(path); err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
etag = fmt.Sprintf("%x-%x", fi.ModTime().Unix(), fi.Size())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var (
|
var (
|
||||||
port int
|
port int
|
||||||
@ -91,92 +32,9 @@ func main() {
|
|||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
r := mux.NewRouter()
|
r := mux.NewRouter()
|
||||||
r.HandleFunc("/map/{z:[0-9]+}/{x:[0-9]+}/{y:[0-9]+}.png", func(rw http.ResponseWriter, r *http.Request) {
|
r.HandleFunc("/map/{z:[0-9]+}/{x:[0-9]+}/{y:[0-9]+}.png",
|
||||||
|
func(rw http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
createTiles(rw, r, mapDir)
|
||||||
xs := vars["x"]
|
|
||||||
ys := vars["y"]
|
|
||||||
zs := vars["z"]
|
|
||||||
|
|
||||||
x, y, z := toUint(xs), toUint(ys), toUint(zs)
|
|
||||||
if z < 9 {
|
|
||||||
filename := fmt.Sprintf("%d/%d/%d.png", z, x, y)
|
|
||||||
http.ServeFile(rw, r, filepath.Join(mapDir, filename))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if z > 16 {
|
|
||||||
z = 16
|
|
||||||
}
|
|
||||||
tx := x >> (z - 8)
|
|
||||||
ty := y >> (z - 8)
|
|
||||||
|
|
||||||
baseTile := filepath.Join(mapDir, fmt.Sprintf("8/%d/%d.png", tx, ty))
|
|
||||||
|
|
||||||
var etag string
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if ifNoneMatch := r.Header.Get("If-None-Match"); ifNoneMatch != "" {
|
|
||||||
if etag, err = createETag(baseTile); err != nil {
|
|
||||||
http.NotFound(rw, r)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if ifNoneMatch == etag {
|
|
||||||
http.Error(rw, http.StatusText(http.StatusNotModified), http.StatusNotModified)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
img := common.LoadPNG(baseTile)
|
|
||||||
|
|
||||||
type subImage interface {
|
|
||||||
SubImage(image.Rectangle) image.Image
|
|
||||||
}
|
|
||||||
var si subImage
|
|
||||||
var ok bool
|
|
||||||
if si, ok = img.(subImage); !ok {
|
|
||||||
// Should not happen.
|
|
||||||
http.Error(rw,
|
|
||||||
http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
rx := x & ^(^uint(0) << (z - 8))
|
|
||||||
ry := y & ^(^uint(0) << (z - 8))
|
|
||||||
|
|
||||||
parts := uint(1) << (z - 8)
|
|
||||||
|
|
||||||
w := uint(256) / parts
|
|
||||||
xo := w * rx
|
|
||||||
yo := w * (parts - 1 - ry)
|
|
||||||
//fmt.Printf("x %d\n", x)
|
|
||||||
//fmt.Printf("y %d\n", y)
|
|
||||||
//fmt.Printf("z %d\n", z)
|
|
||||||
//fmt.Printf("z %d\n", z)
|
|
||||||
//fmt.Printf("parts %d\n", parts)
|
|
||||||
//fmt.Printf("w %d\n", w)
|
|
||||||
//fmt.Printf("xo %d\n", xo)
|
|
||||||
//fmt.Printf("yo %d\n", yo)
|
|
||||||
//fmt.Printf("rx %d\n", rx)
|
|
||||||
//fmt.Printf("ry %d\n", ry)
|
|
||||||
|
|
||||||
img = si.SubImage(image.Rect(int(xo), int(yo), int(xo+w), int(yo+w)))
|
|
||||||
img = blowUp(img)
|
|
||||||
|
|
||||||
rw.Header().Set("Content-Type", "image/png")
|
|
||||||
if etag == "" {
|
|
||||||
if etag, err = createETag(baseTile); err != nil {
|
|
||||||
log.Printf("Cannot create ETag: %s", baseTile)
|
|
||||||
} else {
|
|
||||||
rw.Header().Set("ETag", etag)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
rw.Header().Set("ETag", etag)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = png.Encode(rw, img); err != nil {
|
|
||||||
log.Printf("WARN: encoding image failed: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
r.PathPrefix("/").Handler(http.FileServer(http.Dir(webDir)))
|
r.PathPrefix("/").Handler(http.FileServer(http.Dir(webDir)))
|
||||||
|
158
cmd/mtwebmapper/subbaseline.go
Normal file
158
cmd/mtwebmapper/subbaseline.go
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
// 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 (
|
||||||
|
"fmt"
|
||||||
|
"image"
|
||||||
|
"image/color"
|
||||||
|
"image/png"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"bitbucket.org/s_l_teichmann/mtredisalize/common"
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
)
|
||||||
|
|
||||||
|
func blowUp(src image.Image) *image.RGBA {
|
||||||
|
|
||||||
|
// TODO: Fast path for image.RGBA
|
||||||
|
|
||||||
|
dst := image.NewRGBA(image.Rect(0, 0, 256, 256))
|
||||||
|
|
||||||
|
// fix point numbers x:8
|
||||||
|
dx, dy := src.Bounds().Dx(), src.Bounds().Dy()
|
||||||
|
|
||||||
|
bx, by := src.Bounds().Min.X<<8, src.Bounds().Min.Y<<8
|
||||||
|
|
||||||
|
py := by
|
||||||
|
for y := 0; y < 256; y++ {
|
||||||
|
sy := (py >> 8) & 0xff
|
||||||
|
ox := -1
|
||||||
|
px := bx
|
||||||
|
var col color.Color
|
||||||
|
for x := 0; x < 256; x++ {
|
||||||
|
sx := (px >> 8) & 0xff
|
||||||
|
if sx != ox { // Minimize interface indirection access.
|
||||||
|
ox = sx
|
||||||
|
col = src.At(sx, sy)
|
||||||
|
}
|
||||||
|
dst.Set(x, y, col)
|
||||||
|
px += dx
|
||||||
|
}
|
||||||
|
py += dy
|
||||||
|
}
|
||||||
|
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
func createTiles(rw http.ResponseWriter, r *http.Request, mapDir string) {
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
xs := vars["x"]
|
||||||
|
ys := vars["y"]
|
||||||
|
zs := vars["z"]
|
||||||
|
|
||||||
|
x, y, z := toUint(xs), toUint(ys), toUint(zs)
|
||||||
|
if z < 9 {
|
||||||
|
filename := fmt.Sprintf("%d/%d/%d.png", z, x, y)
|
||||||
|
http.ServeFile(rw, r, filepath.Join(mapDir, filename))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if z > 16 {
|
||||||
|
z = 16
|
||||||
|
}
|
||||||
|
tx := x >> (z - 8)
|
||||||
|
ty := y >> (z - 8)
|
||||||
|
|
||||||
|
baseTile := filepath.Join(mapDir, fmt.Sprintf("8/%d/%d.png", tx, ty))
|
||||||
|
|
||||||
|
var etag string
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if ifNoneMatch := r.Header.Get("If-None-Match"); ifNoneMatch != "" {
|
||||||
|
if etag, err = createETag(baseTile); err != nil {
|
||||||
|
http.NotFound(rw, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ifNoneMatch == etag {
|
||||||
|
http.Error(rw, http.StatusText(http.StatusNotModified), http.StatusNotModified)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
img := common.LoadPNG(baseTile)
|
||||||
|
|
||||||
|
type subImage interface {
|
||||||
|
SubImage(image.Rectangle) image.Image
|
||||||
|
}
|
||||||
|
var si subImage
|
||||||
|
var ok bool
|
||||||
|
if si, ok = img.(subImage); !ok {
|
||||||
|
// Should not happen.
|
||||||
|
http.Error(rw,
|
||||||
|
http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rx := x & ^(^uint(0) << (z - 8))
|
||||||
|
ry := y & ^(^uint(0) << (z - 8))
|
||||||
|
|
||||||
|
parts := uint(1) << (z - 8)
|
||||||
|
|
||||||
|
w := uint(256) / parts
|
||||||
|
xo := w * rx
|
||||||
|
yo := w * (parts - 1 - ry)
|
||||||
|
//fmt.Printf("x %d\n", x)
|
||||||
|
//fmt.Printf("y %d\n", y)
|
||||||
|
//fmt.Printf("z %d\n", z)
|
||||||
|
//fmt.Printf("z %d\n", z)
|
||||||
|
//fmt.Printf("parts %d\n", parts)
|
||||||
|
//fmt.Printf("w %d\n", w)
|
||||||
|
//fmt.Printf("xo %d\n", xo)
|
||||||
|
//fmt.Printf("yo %d\n", yo)
|
||||||
|
//fmt.Printf("rx %d\n", rx)
|
||||||
|
//fmt.Printf("ry %d\n", ry)
|
||||||
|
|
||||||
|
img = si.SubImage(image.Rect(int(xo), int(yo), int(xo+w), int(yo+w)))
|
||||||
|
img = blowUp(img)
|
||||||
|
|
||||||
|
rw.Header().Set("Content-Type", "image/png")
|
||||||
|
if etag == "" {
|
||||||
|
if etag, err = createETag(baseTile); err != nil {
|
||||||
|
log.Printf("Cannot create ETag: %s", baseTile)
|
||||||
|
} else {
|
||||||
|
rw.Header().Set("ETag", etag)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rw.Header().Set("ETag", etag)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = png.Encode(rw, img); err != nil {
|
||||||
|
log.Printf("WARN: encoding image failed: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createETag(path string) (etag string, err error) {
|
||||||
|
var fi os.FileInfo
|
||||||
|
if fi, err = os.Stat(path); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
etag = fmt.Sprintf("%x-%x", fi.ModTime().Unix(), fi.Size())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func toUint(s string) uint {
|
||||||
|
var err error
|
||||||
|
var x int
|
||||||
|
if x, err = strconv.Atoi(s); err != nil {
|
||||||
|
log.Printf("WARN: Cannot convert to int: %s", err)
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return uint(x)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user