Skip to content

Commit

Permalink
Merge 06f0dc3 into d7db0ef
Browse files Browse the repository at this point in the history
  • Loading branch information
uvchik committed Jun 28, 2019
2 parents d7db0ef + 06f0dc3 commit 4b37411
Showing 1 changed file with 39 additions and 3 deletions.
42 changes: 39 additions & 3 deletions contextily/tile.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def bounds2raster(w, s, e, n, path, zoom='auto',


def bounds2img(w, s, e, n, zoom='auto',
url=sources.ST_TERRAIN, ll=False,
url=sources.ST_TERRAIN, path=None, ll=False,
wait=0, max_retries=2):
'''
Take bounding box and zoom and return an image with all the tiles
Expand Down Expand Up @@ -121,6 +121,11 @@ def bounds2img(w, s, e, n, zoom='auto',
ll : Boolean
[Optional. Default: False] If True, `w`, `s`, `e`, `n` are
assumed to be lon/lat as opposed to Spherical Mercator.
path : str
[Optional. Default: None] If a path is given the tiles will be
downloaded to this location. If the tile can be found in the
given path the local tile will be used instead of the server
tile. This is faster and will reduce server usage.
wait : int
[Optional. Default: 0]
if the tile API is rate-limited, the number of seconds to wait
Expand All @@ -147,9 +152,13 @@ def bounds2img(w, s, e, n, zoom='auto',
arrays = []
for t in mt.tiles(w, s, e, n, [zoom]):
x, y, z = t.x, t.y, t.z
tile_url = url.replace('tileX', str(x)).replace('tileY', str(y)).replace('tileZ', str(z))
tile_url = url.replace(
'tileX', str(x)).replace('tileY', str(y)).replace('tileZ', str(z))
# ---
image = _fetch_tile(tile_url, wait, max_retries)
if path is not None:
image = _fetch_tile_with_cache(tile_url, wait, max_retries, path)
else:
image = _fetch_tile(tile_url, wait, max_retries)
# ---
tiles.append(t)
arrays.append(image)
Expand All @@ -162,6 +171,33 @@ def bounds2img(w, s, e, n, zoom='auto',
return merged, extent


def _fetch_tile_with_cache(tile_url, wait, max_retries, path):
"""
Fetch local tile or try to download file if local file is not present.
Sometimes OSM servers deny requests via Python scripts but allows direct
downloads. In that case one can try to download the file manually using the
given url and filename.
"""

fn = tile_url.replace('https://', '').replace('http://', '')
fn = fn.replace('/', '_')
image_path = os.path.join(path, fn)

if not os.path.isfile(image_path):
request = _retryer(tile_url, wait, max_retries)
if request.status_code == 200:
with open(image_path, 'wb') as f:
for chunk in request:
f.write(chunk)
else:
request.raise_for_status()

image = Image.open(image_path).convert('RGB')
image = np.asarray(image)
return image


def _fetch_tile(tile_url, wait, max_retries):
request = _retryer(tile_url, wait, max_retries)
with io.BytesIO(request.content) as image_stream:
Expand Down

0 comments on commit 4b37411

Please sign in to comment.