pngtile/tile.py
author Tero Marttila <terom@paivola.fi>
Mon, 15 Sep 2014 00:49:15 +0300
changeset 144 5b2b866ad0a3
parent 140 a3bbecbd31e7
child 165 1dc09e81a4e2
permissions -rw-r--r--
pngtile.tile: fix render_region centering
135
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     1
"""
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     2
    Raw tile handling.
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     3
"""
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     4
138
59d61da2b64f pngtile.tile: split off BaseAppliation
Tero Marttila <terom@paivola.fi>
parents: 135
diff changeset
     5
from pngtile.application import BaseApplication
135
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     6
from werkzeug import Request, Response, exceptions
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     7
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     8
import pypngtile
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
     9
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    10
## Coordinates
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    11
# width of a tile
140
a3bbecbd31e7 pngtile.tile: limit zoom; fix tile row/col mixup with just x/y
Tero Marttila <terom@paivola.fi>
parents: 138
diff changeset
    12
TILE_SIZE = 256
a3bbecbd31e7 pngtile.tile: limit zoom; fix tile row/col mixup with just x/y
Tero Marttila <terom@paivola.fi>
parents: 138
diff changeset
    13
a3bbecbd31e7 pngtile.tile: limit zoom; fix tile row/col mixup with just x/y
Tero Marttila <terom@paivola.fi>
parents: 138
diff changeset
    14
# maximum zoom out
a3bbecbd31e7 pngtile.tile: limit zoom; fix tile row/col mixup with just x/y
Tero Marttila <terom@paivola.fi>
parents: 138
diff changeset
    15
MAX_ZOOM = 4
135
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    16
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    17
# max. output resolution to allow
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    18
MAX_PIXELS = 1920 * 1200
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    19
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    20
def scale (val, zoom):
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    21
    """
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    22
        Scale dimension by zoom factor
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    23
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    24
        zl > 0 -> bigger
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    25
        zl < 0 -> smaller
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    26
    """
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    27
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    28
    if zoom > 0:
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    29
        return val << zoom
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    30
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    31
    elif zoom < 0:
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    32
        return val >> -zoom
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    33
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    34
    else:
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    35
        return val
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    36
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    37
def scale_center (val, dim, zoom):
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    38
    """
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    39
        Scale value about center by zoom.
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    40
    """
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    41
144
5b2b866ad0a3 pngtile.tile: fix render_region centering
Tero Marttila <terom@paivola.fi>
parents: 140
diff changeset
    42
    return scale(val, zoom) - dim / 2
135
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    43
138
59d61da2b64f pngtile.tile: split off BaseAppliation
Tero Marttila <terom@paivola.fi>
parents: 135
diff changeset
    44
class TileApplication (BaseApplication):
59d61da2b64f pngtile.tile: split off BaseAppliation
Tero Marttila <terom@paivola.fi>
parents: 135
diff changeset
    45
    def __init__ (self, **opts):
59d61da2b64f pngtile.tile: split off BaseAppliation
Tero Marttila <terom@paivola.fi>
parents: 135
diff changeset
    46
        BaseApplication.__init__(self, **opts)
135
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    47
        
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    48
    def render_region (self, request, image):
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    49
        """
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    50
            Handle request for an image region
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    51
        """
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    52
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    53
        width = int(request.args['w'])
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    54
        height = int(request.args['h'])
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    55
        x = int(request.args['x'])
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    56
        y = int(request.args['y'])
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    57
        zoom = int(request.args.get('zoom', "0"))
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    58
140
a3bbecbd31e7 pngtile.tile: limit zoom; fix tile row/col mixup with just x/y
Tero Marttila <terom@paivola.fi>
parents: 138
diff changeset
    59
        # safety limit
135
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    60
        if width * height > MAX_PIXELS:
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    61
            raise exceptions.BadRequest("Image size: %d * %d > %d" % (width, height, MAX_PIXELS))
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    62
140
a3bbecbd31e7 pngtile.tile: limit zoom; fix tile row/col mixup with just x/y
Tero Marttila <terom@paivola.fi>
parents: 138
diff changeset
    63
        if zoom > MAX_ZOOM:
a3bbecbd31e7 pngtile.tile: limit zoom; fix tile row/col mixup with just x/y
Tero Marttila <terom@paivola.fi>
parents: 138
diff changeset
    64
            raise exceptions.BadRequest("Image zoom: %d > %d" % (zoom, MAX_ZOOM))
a3bbecbd31e7 pngtile.tile: limit zoom; fix tile row/col mixup with just x/y
Tero Marttila <terom@paivola.fi>
parents: 138
diff changeset
    65
144
5b2b866ad0a3 pngtile.tile: fix render_region centering
Tero Marttila <terom@paivola.fi>
parents: 140
diff changeset
    66
        x = scale_center(x, width, zoom)
5b2b866ad0a3 pngtile.tile: fix render_region centering
Tero Marttila <terom@paivola.fi>
parents: 140
diff changeset
    67
        y = scale_center(y, height, zoom)
135
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    68
        
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    69
        try:
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    70
            return image.tile_mem(width, height, x, y, zoom)
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    71
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    72
        except pypngtile.Error as error:
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    73
            raise exceptions.BadRequest(str(error))
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    74
        
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    75
    def render_tile (self, request, image):
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    76
        """
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    77
            Handle request for image tile
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    78
        """
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    79
140
a3bbecbd31e7 pngtile.tile: limit zoom; fix tile row/col mixup with just x/y
Tero Marttila <terom@paivola.fi>
parents: 138
diff changeset
    80
        width = TILE_SIZE
a3bbecbd31e7 pngtile.tile: limit zoom; fix tile row/col mixup with just x/y
Tero Marttila <terom@paivola.fi>
parents: 138
diff changeset
    81
        height = TILE_SIZE
a3bbecbd31e7 pngtile.tile: limit zoom; fix tile row/col mixup with just x/y
Tero Marttila <terom@paivola.fi>
parents: 138
diff changeset
    82
        x = int(request.args['x'])
a3bbecbd31e7 pngtile.tile: limit zoom; fix tile row/col mixup with just x/y
Tero Marttila <terom@paivola.fi>
parents: 138
diff changeset
    83
        y = int(request.args['y'])
135
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    84
        zoom = int(request.args.get('zoom', "0"))
140
a3bbecbd31e7 pngtile.tile: limit zoom; fix tile row/col mixup with just x/y
Tero Marttila <terom@paivola.fi>
parents: 138
diff changeset
    85
        
a3bbecbd31e7 pngtile.tile: limit zoom; fix tile row/col mixup with just x/y
Tero Marttila <terom@paivola.fi>
parents: 138
diff changeset
    86
        if zoom > MAX_ZOOM:
a3bbecbd31e7 pngtile.tile: limit zoom; fix tile row/col mixup with just x/y
Tero Marttila <terom@paivola.fi>
parents: 138
diff changeset
    87
            raise exceptions.BadRequest("Image zoom: %d > %d" % (zoom, MAX_ZOOM))
135
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    88
140
a3bbecbd31e7 pngtile.tile: limit zoom; fix tile row/col mixup with just x/y
Tero Marttila <terom@paivola.fi>
parents: 138
diff changeset
    89
        x = scale(x * width, zoom)
a3bbecbd31e7 pngtile.tile: limit zoom; fix tile row/col mixup with just x/y
Tero Marttila <terom@paivola.fi>
parents: 138
diff changeset
    90
        y = scale(y * height, zoom)
135
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    91
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    92
        try:
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    93
            return image.tile_mem(width, height, x, y, zoom)
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    94
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    95
        except pypngtile.Error as error:
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    96
            raise exceptions.BadRequest(str(error))
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    97
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    98
    def handle (self, request):
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    99
        """
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   100
            Handle request for an image
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   101
        """
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   102
        
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   103
        try:
138
59d61da2b64f pngtile.tile: split off BaseAppliation
Tero Marttila <terom@paivola.fi>
parents: 135
diff changeset
   104
            image, name = self.get_image(request.path)
135
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   105
        except pypngtile.Error as error:
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   106
            raise exceptions.BadRequest(str(error))
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   107
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   108
        if 'w' in request.args and 'h' in request.args and 'x' in request.args and 'y' in request.args:
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   109
            png = self.render_region(request, image)
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   110
140
a3bbecbd31e7 pngtile.tile: limit zoom; fix tile row/col mixup with just x/y
Tero Marttila <terom@paivola.fi>
parents: 138
diff changeset
   111
        elif 'x' in request.args and 'y' in request.args:
135
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   112
            png = self.render_tile(request, image)
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   113
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   114
        else:
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   115
            raise exceptions.BadRequest("Unknown args")
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   116
e99dd75afa15 pngtile.tile: separate Application dedicated to PNG serving
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
   117
        return Response(png, content_type='image/png')