terom@92: """
terom@92: Rendering output
terom@92: """
terom@92:
terom@92: import os, os.path
terom@92:
terom@92: ## Settings
terom@92: # width of a tile
terom@92: TILE_WIDTH = 256
terom@92: TILE_HEIGHT = 256
terom@92:
terom@92: # max. output resolution to allow
terom@92: MAX_PIXELS = 1920 * 1200
terom@92:
terom@92: def dir_url (prefix, name, item) :
terom@92: """
terom@92: Join together an absolute URL prefix, an optional directory name, and a directory item
terom@92: """
terom@92:
terom@92: url = prefix
terom@92:
terom@92: if name :
terom@92: url += '/' + name
terom@92:
terom@92: url += '/' + item
terom@92:
terom@92: return url
terom@92:
terom@92: def dir_list (dir_path) :
terom@92: """
terom@92: Yield a series of directory items to show for the given dir
terom@92: """
terom@92:
terom@92: # link to parent
terom@92: yield '..'
terom@92:
terom@92: for item in os.listdir(dir_path) :
terom@92: path = os.path.join(dir_path, item)
terom@92:
terom@92: # skip dotfiles
terom@92: if item.startswith('.') :
terom@92: continue
terom@92:
terom@92: # show dirs
terom@92: if os.path.isdir(path) :
terom@92: yield item
terom@92:
terom@92: # examine ext
terom@92: base, ext = os.path.splitext(path)
terom@92:
terom@92: # show .png files with a .cache file
terom@92: if ext == '.png' and os.path.exists(base + '.cache') :
terom@92: yield item
terom@92:
terom@92:
terom@92: ### Render HTML data
terom@92: def dir_html (prefix, name, path) :
terom@92: """
terom@92: Directory index
terom@92: """
terom@92:
terom@92: name = name.rstrip('/')
terom@92:
terom@92: return """\
terom@92:
terom@92:
terom@92: Index of %(dir)s
terom@92:
terom@92:
terom@92:
terom@92: Index of %(dir)s
terom@92:
terom@92:
terom@92: %(listing)s
terom@92:
terom@92:
terom@92: """ % dict(
terom@92: prefix = prefix,
terom@92: dir = '/' + name,
terom@92:
terom@92: listing = "\n".join(
terom@92: # link
terom@92: """%(name)s""" % dict(
terom@92: # URL to dir
terom@92: url = dir_url(prefix, name, item),
terom@92:
terom@92: # item name
terom@92: name = item,
terom@92: ) for item in dir_list(path)
terom@92: ),
terom@92: )
terom@92:
terom@92: def img_html (prefix, name, image) :
terom@92: """
terom@92: HTML for image
terom@92: """
terom@92:
terom@92: # a little slow, but not so bad - two stats(), heh
terom@92: info = image.info()
terom@92: img_width, img_height = info['img_width'], info['img_height']
terom@92:
terom@92: return """\
terom@92:
terom@92:
terom@92: %(title)s
terom@92:
terom@92:
terom@92:
terom@92:
terom@92:
terom@92:
terom@92:
terom@92:
terom@92:
terom@92:
terom@92:
terom@92:
terom@92:
terom@92:
terom@92: Loading...
terom@92:
terom@92:
terom@92:
terom@92:
terom@92:
terom@92:
terom@92: """ % dict(
terom@92: title = name,
terom@92: prefix = prefix,
terom@92: tile_url = prefix + '/' + name,
terom@92:
terom@92: tile_width = TILE_WIDTH,
terom@92: tile_height = TILE_HEIGHT,
terom@92:
terom@92: img_width = img_width,
terom@92: img_height = img_height,
terom@92: )
terom@92:
terom@103:
terom@103: # threshold to cache images on - only images with a source data region *larger* than this are cached
terom@103: CACHE_THRESHOLD = 512 * 512
terom@103:
terom@103: def scale_by_zoom (val, zoom) :
terom@103: """
terom@103: Scale dimension by zoom factor
terom@127:
terom@127: zl > 0 -> bigger
terom@127: zl < 0 -> smaller
terom@103: """
terom@103:
terom@103: if zoom > 0 :
terom@103: return val << zoom
terom@103:
terom@103: elif zoom > 0 :
terom@103: return val >> -zoom
terom@103:
terom@103: else :
terom@103: return val
terom@103:
terom@103: ### Image caching
terom@103: def check_cache_threshold (width, height, zl) :
terom@103: """
terom@103: Checks if a tile with the given dimensions should be cached
terom@103: """
terom@103:
terom@127: return (scale_by_zoom(width, zl) * scale_by_zoom(height, zl)) > CACHE_THRESHOLD
terom@103:
terom@103: def render_raw (image, width, height, x, y, zl) :
terom@103: """
terom@103: Render and return tile
terom@103: """
terom@103:
terom@103: return image.tile_mem(
terom@103: width, height,
terom@103: x, y, zl
terom@103: )
terom@103:
terom@103: def render_cache (cache, image, width, height, x, y, zl) :
terom@103: """
terom@103: Perform a cached render of the given tile
terom@103: """
terom@103:
terom@103: if cache :
terom@103: # cache key
terom@105: key = "tl_%d:%d_%d:%d:%d_%s" % (x, y, width, height, zl, image.path)
terom@103:
terom@103: # lookup
terom@103: data = cache.get(key)
terom@103:
terom@103: else :
terom@103: # oops, no cache
terom@103: data = None
terom@103:
terom@103: if not data :
terom@103: # cache miss, render
terom@103: data = render_raw(image, width, height, x, y, zl)
terom@103:
terom@103: if cache :
terom@103: # store
terom@103: cache.add(key, data)
terom@103:
terom@103: # ok
terom@103: return data
terom@103:
terom@92: ### Render PNG Data
terom@103: def img_png_tile (image, x, y, zoom, cache) :
terom@92: """
terom@92: Render given tile, returning PNG data
terom@92: """
terom@92:
terom@103: # do we want to cache this?
terom@103: if check_cache_threshold(TILE_WIDTH, TILE_HEIGHT, zoom) :
terom@103: # go via the cache
terom@103: return render_cache(cache, image, TILE_WIDTH, TILE_HEIGHT, x, y, zoom)
terom@103:
terom@103: else :
terom@103: # just go raw
terom@103: return render_raw(image, TILE_WIDTH, TILE_HEIGHT, x, y, zoom)
terom@103:
terom@103: def img_png_region (image, cx, cy, zoom, width, height, cache) :
terom@92: """
terom@92: Render arbitrary tile, returning PNG data
terom@92: """
terom@92:
terom@128: x = cx - width / 2
terom@128: y = cy - height / 2
terom@92:
terom@92: # safely limit
terom@92: if width * height > MAX_PIXELS :
terom@92: raise ValueError("Image size: %d * %d > %d" % (width, height, MAX_PIXELS))
terom@103:
terom@103: # these images are always cached
terom@103: return render_cache(cache, image, width, height, x, y, zoom)
terom@92: