mapserver/server/tilerenderer/renderer.go

245 lines
5.1 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-28 15:31:48 +03:00
"mapserver/eventbus"
2019-01-21 13:13:00 +03:00
"mapserver/layer"
2019-01-18 11:13:37 +03:00
"mapserver/mapblockrenderer"
2019-02-09 20:05:40 +03:00
"mapserver/tiledb"
2019-01-18 11:13:37 +03:00
"time"
2019-02-15 10:36:48 +03:00
"strconv"
2019-01-20 23:03:58 +03:00
"github.com/disintegration/imaging"
"github.com/sirupsen/logrus"
2019-02-15 10:36:48 +03:00
"github.com/prometheus/client_golang/prometheus"
2019-01-11 18:00:40 +03:00
)
type TileRenderer struct {
2019-01-13 18:37:03 +03:00
mapblockrenderer *mapblockrenderer.MapBlockRenderer
2019-02-14 10:50:54 +03:00
layers []*layer.Layer
2019-02-09 20:05:40 +03:00
tdb *tiledb.TileDB
2019-01-18 11:13:37 +03:00
dba db.DBAccessor
2019-01-28 15:31:48 +03:00
Eventbus *eventbus.Eventbus
2019-01-11 18:00:40 +03:00
}
2019-01-17 13:20:03 +03:00
func NewTileRenderer(mapblockrenderer *mapblockrenderer.MapBlockRenderer,
2019-02-09 20:05:40 +03:00
tdb *tiledb.TileDB,
2019-01-17 17:14:13 +03:00
dba db.DBAccessor,
2019-02-14 10:50:54 +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-28 15:31:48 +03:00
Eventbus: eventbus.New(),
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-02-07 21:48:05 +03:00
func (tr *TileRenderer) Render(tc *coords.TileCoords) ([]byte, error) {
//No tile in db
img, data, err := tr.RenderImage(tc, 2)
2019-01-17 13:20:03 +03:00
if err != nil {
return nil, err
}
2019-02-07 21:48:05 +03:00
if img == nil {
//empty tile
return nil, nil
2019-01-17 13:20:03 +03:00
}
2019-02-07 21:48:05 +03:00
return data, nil
2019-01-17 13:20:03 +03:00
}
2019-01-22 14:53:36 +03:00
func (tr *TileRenderer) RenderImage(tc *coords.TileCoords, recursionDepth int) (*image.NRGBA, []byte, error) {
2019-01-17 13:20:03 +03:00
2019-02-07 21:48:05 +03:00
if recursionDepth < 2 {
cachedtile, err := tr.tdb.GetTile(tc)
2019-01-17 13:20:03 +03:00
if err != nil {
2019-01-22 14:53:36 +03:00
return nil, nil, err
2019-01-17 13:20:03 +03:00
}
2019-02-07 21:48:05 +03:00
if cachedtile != nil {
2019-02-09 20:05:40 +03:00
reader := bytes.NewReader(cachedtile)
2019-02-07 21:48:05 +03:00
cachedimg, err := png.Decode(reader)
if err != nil {
return nil, nil, err
}
rect := image.Rectangle{
image.Point{0, 0},
image.Point{IMG_SIZE, IMG_SIZE},
}
2019-01-21 15:27:36 +03:00
2019-02-07 21:48:05 +03:00
img := image.NewNRGBA(rect)
draw.Draw(img, rect, cachedimg, image.ZP, draw.Src)
2019-01-21 15:27:36 +03:00
2019-02-07 21:48:05 +03:00
log.WithFields(logrus.Fields{"x": tc.X, "y": tc.Y, "zoom": tc.Zoom}).Debug("Cached image")
2019-02-09 20:05:40 +03:00
return img, cachedtile, nil
2019-02-07 21:48:05 +03:00
}
2019-01-21 15:27:36 +03:00
}
2019-01-22 14:53:36 +03:00
if recursionDepth == 0 {
2019-01-21 22:13:38 +03:00
log.WithFields(logrus.Fields{"x": tc.X, "y": tc.Y, "zoom": tc.Zoom}).Debug("Skip image")
2019-01-22 14:53:36 +03:00
return nil, 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-02-15 10:36:48 +03:00
renderedTiles.With(prometheus.Labels{"zoom":strconv.Itoa(tc.Zoom)}).Inc()
timer := prometheus.NewTimer(renderDuration)
defer timer.ObserveDuration()
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 {
2019-02-14 10:50:54 +03:00
layer = l
2019-01-17 13:20:03 +03:00
}
}
if layer == nil {
2019-01-22 14:53:36 +03:00
return nil, nil, errors.New("No layer found")
2019-01-17 13:20:03 +03:00
}
2019-01-17 17:37:33 +03:00
if tc.Zoom > 13 || tc.Zoom < 1 {
2019-01-22 14:53:36 +03:00
return nil, nil, errors.New("Invalid zoom")
2019-01-17 17:37:33 +03:00
}
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
2019-01-22 14:53:36 +03:00
img, err := tr.mapblockrenderer.Render(mbr.Pos1, mbr.Pos2)
if err != nil {
return nil, nil, err
}
if img == nil {
return nil, nil, nil
}
buf := new(bytes.Buffer)
png.Encode(buf, img)
return img, buf.Bytes(), nil
2019-01-17 13:20:03 +03:00
}
//zoom 1-12
quads := tc.GetZoomedQuadrantsFromTile()
2019-01-21 22:13:38 +03:00
fields := logrus.Fields{
"UpperLeft": quads.UpperLeft,
"UpperRight": quads.UpperRight,
"LowerLeft": quads.LowerLeft,
"LowerRight": quads.LowerRight,
}
log.WithFields(fields).Debug("Quad image stats")
2019-01-22 15:17:30 +03:00
start := time.Now()
2019-01-22 14:53:36 +03:00
upperLeft, _, err := tr.RenderImage(quads.UpperLeft, recursionDepth-1)
2019-01-17 13:20:03 +03:00
if err != nil {
2019-01-22 15:17:30 +03:00
return nil, nil, err
2019-01-17 13:20:03 +03:00
}
2019-01-17 12:04:09 +03:00
2019-01-22 14:53:36 +03:00
upperRight, _, err := tr.RenderImage(quads.UpperRight, recursionDepth-1)
2019-01-17 13:20:03 +03:00
if err != nil {
2019-01-22 15:17:30 +03:00
return nil, nil, err
2019-01-17 12:04:09 +03:00
}
2019-01-22 14:53:36 +03:00
lowerLeft, _, err := tr.RenderImage(quads.LowerLeft, recursionDepth-1)
2019-01-17 13:20:03 +03:00
if err != nil {
2019-01-22 15:17:30 +03:00
return nil, nil, err
2019-01-17 13:20:03 +03:00
}
2019-01-22 14:53:36 +03:00
lowerRight, _, err := tr.RenderImage(quads.LowerRight, recursionDepth-1)
2019-01-17 13:20:03 +03:00
if err != nil {
2019-01-22 15:17:30 +03:00
return nil, nil, err
2019-01-17 13:20:03 +03:00
}
2019-01-22 15:17:30 +03:00
t := time.Now()
quadrender := t.Sub(start)
start = t
2019-01-17 13:20:03 +03:00
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-22 15:17:30 +03:00
t = time.Now()
quadresize := t.Sub(start)
start = t
2019-01-17 13:38:13 +03:00
buf := new(bytes.Buffer)
2019-01-21 22:13:38 +03:00
png.Encode(buf, img)
2019-01-17 13:38:13 +03:00
2019-01-22 15:17:30 +03:00
t = time.Now()
encode := t.Sub(start)
start = t
2019-02-09 20:05:40 +03:00
tile := buf.Bytes()
tr.tdb.SetTile(tc, tile)
2019-01-17 13:20:03 +03:00
2019-01-22 15:17:30 +03:00
t = time.Now()
cache := t.Sub(start)
fields = logrus.Fields{
"X": tc.X,
"Y": tc.Y,
"Zoom": tc.Zoom,
"LayerId": tc.LayerId,
2019-02-09 20:05:40 +03:00
"size": len(tile),
2019-01-22 15:17:30 +03:00
"quadrender": quadrender,
"quadresize": quadresize,
"encode": encode,
"cache": cache,
}
log.WithFields(fields).Debug("Cross stitch")
2019-01-28 15:31:48 +03:00
tr.Eventbus.Emit(eventbus.TILE_RENDERED, tc)
2019-01-22 17:25:33 +03:00
2019-01-22 14:53:36 +03:00
return img, buf.Bytes(), nil
2019-01-11 18:00:40 +03:00
}