diff options
Diffstat (limited to 'vendor/github.com/felix/go-staticmaps/tile_fetcher.go')
| -rw-r--r-- | vendor/github.com/felix/go-staticmaps/tile_fetcher.go | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/vendor/github.com/felix/go-staticmaps/tile_fetcher.go b/vendor/github.com/felix/go-staticmaps/tile_fetcher.go new file mode 100644 index 0000000..e02a71f --- /dev/null +++ b/vendor/github.com/felix/go-staticmaps/tile_fetcher.go @@ -0,0 +1,153 @@ +// Copyright 2016 Florian Pigorsch. All rights reserved. +// +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package sm + +import ( + "bytes" + "fmt" + "image" + _ "image/jpeg" // to be able to decode jpegs + _ "image/png" // to be able to decode pngs + "io" + "io/ioutil" + "log" + "net/http" + "os" + "path/filepath" + + "github.com/Wessie/appdirs" +) + +// TileFetcher downloads map tile images from a TileProvider +type TileFetcher struct { + tileProvider *TileProvider + cacheDir string + useCaching bool +} + +// NewTileFetcher creates a new Tilefetcher struct +func NewTileFetcher(tileProvider *TileProvider) *TileFetcher { + t := new(TileFetcher) + t.tileProvider = tileProvider + app := appdirs.New("go-staticmaps", "flopp.net", "0.1") + t.cacheDir = fmt.Sprintf("%s/%s", app.UserCache(), tileProvider.Name) + t.useCaching = true + return t +} + +func (t *TileFetcher) url(zoom, x, y int) string { + shard := "" + ss := len(t.tileProvider.Shards) + if len(t.tileProvider.Shards) > 0 { + shard = t.tileProvider.Shards[(x+y)%ss] + } + return t.tileProvider.getURL(shard, zoom, x, y) +} + +func (t *TileFetcher) cacheFileName(zoom int, x, y int) string { + return fmt.Sprintf("%s/%d/%d/%d", t.cacheDir, zoom, x, y) +} + +// ToggleCaching enables/disables caching +func (t *TileFetcher) ToggleCaching(enabled bool) { + t.useCaching = enabled +} + +// Fetch download (or retrieves from the cache) a tile image for the specified zoom level and tile coordinates +func (t *TileFetcher) Fetch(zoom, x, y int) (image.Image, error) { + if t.useCaching { + fileName := t.cacheFileName(zoom, x, y) + cachedImg, err := t.loadCache(fileName) + if err == nil { + return cachedImg, nil + } + } + + url := t.url(zoom, x, y) + data, err := t.download(url) + if err != nil { + return nil, err + } + + img, _, err := image.Decode(bytes.NewBuffer(data)) + if err != nil { + return nil, err + } + + if t.useCaching { + fileName := t.cacheFileName(zoom, x, y) + if err := t.storeCache(fileName, data); err != nil { + log.Printf("Failed to store map tile as '%s': %s", fileName, err) + } + } + + return img, nil +} + +func (t *TileFetcher) download(url string) ([]byte, error) { + resp, err := http.Get(url) + defer resp.Body.Close() + + if err != nil { + return nil, err + } + + contents, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + return contents, nil +} + +func (t *TileFetcher) loadCache(fileName string) (image.Image, error) { + file, err := os.Open(fileName) + if err != nil { + return nil, err + } + defer file.Close() + + img, _, err := image.Decode(file) + if err != nil { + return nil, err + } + + return img, nil +} + +func (t *TileFetcher) createCacheDir(path string) error { + src, err := os.Stat(path) + if err != nil { + if os.IsNotExist(err) { + return os.MkdirAll(path, 0777) + } + return err + } + if src.IsDir() { + return nil + } + return fmt.Errorf("File exists but is not a directory: %s", path) +} + +func (t *TileFetcher) storeCache(fileName string, data []byte) error { + dir, _ := filepath.Split(fileName) + + if err := t.createCacheDir(dir); err != nil { + return err + } + + file, err := os.Create(fileName) + if err != nil { + return err + } + defer file.Close() + + if _, err = io.Copy(file, bytes.NewBuffer(data)); err != nil { + return err + } + + return nil +} |
