mapserver/tilerenderer/renderer.go

196 lines
3.9 KiB
Go
Raw Normal View History

2019-01-11 18:00:40 +03:00
package tilerenderer
import (
2019-01-18 11:13:37 +03:00
"bytes"
2019-01-17 13:20:03 +03:00
"errors"
2019-01-13 18:37:03 +03:00
"image"
2019-01-17 13:20:03 +03:00
"image/draw"
2019-01-18 11:13:37 +03:00
"image/png"
2019-01-13 18:37:03 +03:00
"mapserver/coords"
2019-01-18 11:13:37 +03:00
"mapserver/db"
2019-01-21 13:13:00 +03:00
"mapserver/layer"
2019-01-18 11:13:37 +03:00
"mapserver/mapblockrenderer"
2019-01-17 13:20:03 +03:00
"mapserver/tiledb"
2019-01-18 11:13:37 +03:00
"time"
2019-01-20 23:03:58 +03:00
"github.com/disintegration/imaging"
"github.com/sirupsen/logrus"
2019-01-11 18:00:40 +03:00
)
type TileRenderer struct {
2019-01-13 18:37:03 +03:00
mapblockrenderer *mapblockrenderer.MapBlockRenderer
2019-01-21 13:13:00 +03:00
layers []layer.Layer
2019-01-18 11:13:37 +03:00
tdb tiledb.DBAccessor
dba db.DBAccessor
2019-01-11 18:00:40 +03:00
}
2019-01-17 13:20:03 +03:00
func NewTileRenderer(mapblockrenderer *mapblockrenderer.MapBlockRenderer,
tdb tiledb.DBAccessor,
2019-01-17 17:14:13 +03:00
dba db.DBAccessor,
2019-01-21 13:13:00 +03:00
layers []layer.Layer) *TileRenderer {
2019-01-17 13:20:03 +03:00
2019-01-13 18:37:03 +03:00
return &TileRenderer{
mapblockrenderer: mapblockrenderer,
2019-01-18 11:13:37 +03:00
layers: layers,
tdb: tdb,
dba: dba,
2019-01-13 18:37:03 +03:00
}
2019-01-11 18:00:40 +03:00
}
2019-01-17 13:20:03 +03:00
const (
2019-01-18 11:13:37 +03:00
IMG_SIZE = 256
2019-01-17 13:20:03 +03:00
)
2019-01-21 15:27:36 +03:00
func (tr *TileRenderer) Render(tc *coords.TileCoords) ([]byte, error) {
2019-01-17 13:20:03 +03:00
//Check cache
tile, err := tr.tdb.GetTile(tc)
if err != nil {
return nil, err
}
if tile == nil {
//No tile in db
2019-01-21 15:27:36 +03:00
img, err := tr.RenderImage(tc, false)
2019-01-17 13:20:03 +03:00
if err != nil {
return nil, err
}
2019-01-17 17:37:33 +03:00
if img == nil {
//empty tile
return nil, nil
}
2019-01-17 13:20:03 +03:00
buf := new(bytes.Buffer)
png.Encode(buf, img)
return buf.Bytes(), nil
}
return tile.Data, nil
}
2019-01-21 15:27:36 +03:00
func (tr *TileRenderer) RenderImage(tc *coords.TileCoords, cachedOnly bool) (*image.NRGBA, error) {
2019-01-17 13:20:03 +03:00
cachedtile, err := tr.tdb.GetTile(tc)
if err != nil {
return nil, err
}
if cachedtile != nil {
reader := bytes.NewReader(cachedtile.Data)
cachedimg, err := png.Decode(reader)
if err != nil {
return nil, err
}
2019-01-21 15:27:36 +03:00
rect := image.Rectangle{
image.Point{0, 0},
image.Point{IMG_SIZE, IMG_SIZE},
}
img := image.NewNRGBA(rect)
draw.Draw(img, rect, cachedimg, image.ZP, draw.Src)
return img, nil
}
if cachedOnly {
return nil, nil
2019-01-17 13:20:03 +03:00
}
2019-01-17 13:27:31 +03:00
log.WithFields(logrus.Fields{"x": tc.X, "y": tc.Y, "zoom": tc.Zoom}).Debug("RenderImage")
2019-01-21 13:13:00 +03:00
var layer *layer.Layer
2019-01-17 13:20:03 +03:00
2019-01-18 11:13:37 +03:00
for _, l := range tr.layers {
2019-01-17 13:20:03 +03:00
if l.Id == tc.LayerId {
layer = &l
}
}
if layer == nil {
return nil, errors.New("No layer found")
}
2019-01-17 17:37:33 +03:00
if tc.Zoom > 13 || tc.Zoom < 1 {
return nil, errors.New("Invalid zoom")
}
2019-01-17 12:04:09 +03:00
if tc.Zoom == 13 {
//max zoomed in on mapblock level
2019-01-17 13:20:03 +03:00
mbr := coords.GetMapBlockRangeFromTile(tc, 0)
mbr.Pos1.Y = layer.From
mbr.Pos2.Y = layer.To
return tr.mapblockrenderer.Render(mbr.Pos1, mbr.Pos2)
}
//zoom 1-12
quads := tc.GetZoomedQuadrantsFromTile()
2019-01-21 15:27:36 +03:00
recursiveCachedOnly := tc.Zoom < 12
upperLeft, err := tr.RenderImage(quads.UpperLeft, recursiveCachedOnly)
2019-01-17 13:20:03 +03:00
if err != nil {
return nil, err
}
2019-01-17 12:04:09 +03:00
2019-01-21 15:27:36 +03:00
upperRight, err := tr.RenderImage(quads.UpperRight, recursiveCachedOnly)
2019-01-17 13:20:03 +03:00
if err != nil {
return nil, err
2019-01-17 12:04:09 +03:00
}
2019-01-21 15:27:36 +03:00
lowerLeft, err := tr.RenderImage(quads.LowerLeft, recursiveCachedOnly)
2019-01-17 13:20:03 +03:00
if err != nil {
return nil, err
}
2019-01-21 15:27:36 +03:00
lowerRight, err := tr.RenderImage(quads.LowerRight, recursiveCachedOnly)
2019-01-17 13:20:03 +03:00
if err != nil {
return nil, err
}
img := image.NewNRGBA(
image.Rectangle{
image.Point{0, 0},
image.Point{IMG_SIZE, IMG_SIZE},
},
)
rect := image.Rect(0, 0, 128, 128)
2019-01-17 13:27:31 +03:00
if upperLeft != nil {
2019-01-20 23:03:58 +03:00
resizedImg := imaging.Resize(upperLeft, 128, 128, imaging.Lanczos)
draw.Draw(img, rect, resizedImg, image.ZP, draw.Src)
2019-01-17 13:27:31 +03:00
}
2019-01-17 13:20:03 +03:00
rect = image.Rect(128, 0, 256, 128)
2019-01-17 13:27:31 +03:00
if upperRight != nil {
2019-01-20 23:03:58 +03:00
resizedImg := imaging.Resize(upperRight, 128, 128, imaging.Lanczos)
draw.Draw(img, rect, resizedImg, image.ZP, draw.Src)
2019-01-17 13:27:31 +03:00
}
2019-01-17 13:20:03 +03:00
rect = image.Rect(0, 128, 128, 256)
2019-01-17 13:27:31 +03:00
if lowerLeft != nil {
2019-01-20 23:03:58 +03:00
resizedImg := imaging.Resize(lowerLeft, 128, 128, imaging.Lanczos)
draw.Draw(img, rect, resizedImg, image.ZP, draw.Src)
2019-01-17 13:27:31 +03:00
}
2019-01-17 13:20:03 +03:00
rect = image.Rect(128, 128, 256, 256)
2019-01-17 13:27:31 +03:00
if lowerRight != nil {
2019-01-20 23:03:58 +03:00
resizedImg := imaging.Resize(lowerRight, 128, 128, imaging.Lanczos)
draw.Draw(img, rect, resizedImg, image.ZP, draw.Src)
2019-01-17 13:27:31 +03:00
}
2019-01-17 13:20:03 +03:00
2019-01-17 13:38:13 +03:00
buf := new(bytes.Buffer)
if img != nil {
png.Encode(buf, img)
}
tile := tiledb.Tile{Pos: tc, Data: buf.Bytes(), Mtime: time.Now().Unix()}
tr.tdb.SetTile(&tile)
2019-01-17 13:20:03 +03:00
return img, nil
2019-01-11 18:00:40 +03:00
}