Last active
August 29, 2015 14:22
-
-
Save dividuum/2ee993f037c9e0cb3376 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# fw@dividuum.de wrote this file. As long as you retain this notice you | |
# can do whatever you want with this stuff. If we meet some day, and you think | |
# this stuff is worth it, you can buy me a beer in return | |
import math | |
import traceback | |
import json | |
from cStringIO import StringIO | |
from PIL import Image | |
import requests | |
class Tileset(object): | |
def __init__(self, overviewer, config): | |
self._overviewer = overviewer | |
self._config = config | |
self._tilepath = config['path'] | |
self._maxzoom = config['maxZoom'] | |
self._imgext = config['imgextension'] | |
self._northdir = config['north_direction'] | |
def tile_path(self, tile_x, tile_y, zoom): | |
path = "" | |
tile_x, tile_y = int(tile_x), int(tile_y) | |
if zoom == 0: | |
path += "/base" | |
else: | |
for z in xrange(zoom - 1, -1, -1): | |
x = int(math.floor(tile_x / (2 ** z)) % 2) | |
y = int(math.floor(tile_y / (2 ** z)) % 2) | |
path += "/" + str(x + 2 * y) | |
return '/' + self._tilepath + path + "." + self._imgext + "?c=" + self._overviewer._cachetag | |
def world_to_pixel(self, x, y, z): | |
x, z = -z, x | |
x /= 16.0 # to chunk coord | |
z /= 16.0 | |
col = x + z | |
row = z - x | |
return 192 * col, 96 * row + 12 * (256 - y) | |
def pixel_coord(self, x, y, z, zoom): | |
x, y = self.world_to_pixel(x, y, z) | |
x /= 2 ** (self._maxzoom - zoom) | |
y /= 2 ** (self._maxzoom - zoom) | |
return x, y | |
def pixel_to_tile(self, x, y, zoom): | |
x = x / 384. + (2 ** (zoom-1)) | |
y = y / 384. + (2 ** (zoom-1)) | |
return x, y | |
def surrounding_tiles(self, x, y, z, zoom, radius=1): | |
x, y = self.pixel_coord(x, y, z, zoom) | |
tx, ty = self.pixel_to_tile(x, y, zoom) | |
cx, cy = int(tx), int(ty) | |
def get_tiles(): | |
for xx in xrange(radius*2+1): | |
for yy in xrange(radius*2+1): | |
yield xx, yy, self.tile_path(cx + -radius + xx, cy + -radius + yy, zoom) | |
return 384 * (radius + (tx - math.floor(tx))), 384 * (radius + (ty - math.floor(ty))), get_tiles() | |
def adjust_north(self, x, z): | |
if self._northdir == 0: | |
return z, -x | |
elif self._northdir == 1: | |
return x, z | |
elif self._northdir == 2: | |
return -z, x | |
elif self._northdir == 3: | |
return -x, -z | |
def snapshot(self, x, y, z, zoom=0, radius=2): | |
x, z = self.adjust_north(x, z) | |
center_x, center_y, tiles = self.surrounding_tiles(x, y, z, self._maxzoom + zoom, radius) | |
im = Image.new("RGB", (384 * (radius*2+1), 384 * (radius*2+1)), "#000") | |
for off_x, off_y, path in tiles: | |
tile = self._overviewer.get(path) | |
try: | |
tile_img = Image.open(StringIO(tile.content)) | |
im.paste(tile_img, (384*off_x, 384*off_y)) | |
except Exception: | |
traceback.print_exc() | |
im = im.crop(( | |
int(center_x - radius*384), | |
int(center_y - radius*384), | |
int(center_x + radius*384), | |
int(center_y + radius*384), | |
)) | |
return im | |
class Overviewer(object): | |
def __init__(self, base_url, proxy=None): | |
self._proxy = proxy | |
self._base_url = base_url | |
self._config = self.get_config() | |
self._cachetag = self._config['map']['cacheTag'] | |
def get_config(self): | |
config = self.get("/overviewerConfig.js").content | |
prefix = 'var overviewerConfig = ' | |
if not config.startswith(prefix): | |
raise ValueError("couldn't parse overviewerConfig.js") | |
return json.loads(config[len(prefix):-2]) | |
def get_tileset(self, name): | |
for ts in self._config.get('tilesets', ()): | |
if ts['path'] == name: | |
return Tileset(self, ts) | |
def get(self, path): | |
print 'fetching ' + self._base_url + path | |
# implement caching here, if required. Or just use a proxy | |
return requests.get(self._base_url + path, | |
proxies = self._proxy, | |
) | |
if __name__ == "__main__": | |
ov = Overviewer('http://hcfactions.net/map') | |
ts = ov.get_tileset('normalrender') | |
ts.snapshot(0, 100, 0, radius=2, zoom=-1).save("spawn.jpg") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment