pngtile/render.py
changeset 103 1a6a6957197d
parent 92 e50ec4217fe6
child 105 30c091643f75
--- a/pngtile/render.py	Mon Jan 25 22:11:10 2010 +0200
+++ b/pngtile/render.py	Tue Jan 26 01:26:05 2010 +0200
@@ -52,20 +52,6 @@
         if ext == '.png' and os.path.exists(base + '.cache') :
             yield item
 
-def scale_by_zoom (val, zoom) :
-    """
-        Scale coordinates by zoom factor
-    """
-
-    if zoom > 0 :
-        return val << zoom
-
-    elif zoom > 0 :
-        return val >> -zoom
-
-    else :
-        return val
-
 
 ### Render HTML data
 def dir_html (prefix, name, path) :
@@ -157,19 +143,90 @@
         img_height      = img_height,
     )
 
+
+# threshold to cache images on - only images with a source data region *larger* than this are cached
+CACHE_THRESHOLD = 512 * 512
+
+def scale_by_zoom (val, zoom) :
+    """
+        Scale dimension by zoom factor
+    """
+
+    if zoom > 0 :
+        return val << zoom
+
+    elif zoom > 0 :
+        return val >> -zoom
+
+    else :
+        return val
+
+### Image caching
+def check_cache_threshold (width, height, zl) :
+    """
+        Checks if a tile with the given dimensions should be cached
+    """
+
+    return (scale_by_zoom(width, -zl) * scale_by_zoom(height, -zl)) > CACHE_THRESHOLD
+
+def render_raw (image, width, height, x, y, zl) :
+    """
+        Render and return tile
+    """
+
+    return image.tile_mem(
+            width, height,
+            x, y, zl
+    )
+
+def render_cache (cache, image, width, height, x, y, zl) :
+    """
+        Perform a cached render of the given tile
+    """
+    
+    if cache :
+        # cache key
+        # XXX: need a better id for the image..
+        key = "tl_%d:%d_%d:%d:%d_%s" % (x, y, width, height, zl, id(image))
+        
+        # lookup
+        data = cache.get(key)
+
+    else :
+        # oops, no cache
+        data = None
+
+    if not data :
+        # cache miss, render
+        data = render_raw(image, width, height, x, y, zl)
+        
+        if cache :
+            # store
+            cache.add(key, data)
+    
+    # ok
+    return data
+
 ### Render PNG Data
-def img_png_tile (image, x, y, zoom) :
+def img_png_tile (image, x, y, zoom, cache) :
     """
         Render given tile, returning PNG data
     """
 
-    return image.tile_mem(
-        TILE_WIDTH, TILE_HEIGHT,
-        scale_by_zoom(x, -zoom), scale_by_zoom(y, -zoom), 
-        zoom
-    )
+    # remap coordinates by zoom
+    x = scale_by_zoom(x, -zoom)
+    y = scale_by_zoom(y, -zoom)
 
-def img_png_region (image, cx, cy, zoom, width, height) :
+    # do we want to cache this?
+    if check_cache_threshold(TILE_WIDTH, TILE_HEIGHT, zoom) :
+        # go via the cache
+        return render_cache(cache, image, TILE_WIDTH, TILE_HEIGHT, x, y, zoom)
+
+    else :
+        # just go raw
+        return render_raw(image, TILE_WIDTH, TILE_HEIGHT, x, y, zoom)
+
+def img_png_region (image, cx, cy, zoom, width, height, cache) :
     """
         Render arbitrary tile, returning PNG data
     """
@@ -180,10 +237,7 @@
     # safely limit
     if width * height > MAX_PIXELS :
         raise ValueError("Image size: %d * %d > %d" % (width, height, MAX_PIXELS))
+    
+    # these images are always cached
+    return render_cache(cache, image, width, height, x, y, zoom)
 
-    return image.tile_mem(
-        width, height,
-        x, y,
-        zoom
-    )
-