source: subversion/sites/tile.openstreetmap.org/cgi-bin/export

Last change on this file was 20819, checked in by gslater, 9 years ago

Mapnik cgi export: Fix trailing newline on jpeg/png.

  • Property svn:executable set to *
File size: 4.5 KB
Line 
1#!/usr/bin/python -u
2# -*- coding: utf-8 -*-
3
4import cairo
5import cgi
6import mapnik
7import os
8import shutil
9import sys
10import tempfile
11import resource
12
13# Limit maximum CPU time
14# The Postscript output format can sometimes take hours
15resource.setrlimit(resource.RLIMIT_CPU,(90,90))
16
17# Limit memory usage
18# Some odd requests can cause extreme memory usage
19resource.setrlimit(resource.RLIMIT_AS,(4000000000, 4000000000))
20
21# Routine to output HTTP headers
22def output_headers(content_type, filename = "", length = 0):
23  print "Content-Type: %s" % content_type
24  if filename:
25    print "Content-Disposition: attachment; filename=\"%s\"" % filename
26  if length:
27    print "Content-Length: %d" % length
28  print ""
29
30# Routine to output the contents of a file
31def output_file(file):
32  file.seek(0)
33  shutil.copyfileobj(file, sys.stdout)
34
35# Routine to get the size of a file
36def file_size(file):
37  return os.fstat(file.fileno()).st_size
38
39# Routine to report an error
40def output_error(message):
41  output_headers("text/html")
42  print "<html>"
43  print "<head>"
44  print "<title>Error</title>"
45  print "</head>"
46  print "<body>"
47  print "<h1>Error</h1>"
48  print "<p>%s</p>" % message
49  print "</body>"
50  print "</html>"
51
52# Parse CGI parameters
53form = cgi.FieldStorage()
54
55
56# Abort if the load average on the machine is too high
57loadavg = float(open("/proc/loadavg").readline().split(" ")[0])
58if loadavg > 25.0:
59  print "Status: 503 Service Unavailable"
60  output_error("The load average on the server is too high at the moment. Please wait a few minutes before trying again.")
61 
62# Validate the parameters
63elif not form.has_key("bbox"):
64  # No bounding box specified
65  output_error("No bounding box specified")
66elif not form.has_key("scale"):
67  # No scale specified
68  output_error("No scale specified")
69elif not form.has_key("format"):
70  # No format specified
71  output_error("No format specified")
72else:
73  # Create projection object
74  prj = mapnik.Projection("+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs +over");
75
76  # Get the bounds of the area to render
77  bbox = [float(x) for x in form.getvalue("bbox").split(",")]
78
79  if bbox[0] >= bbox[2] or bbox[1] >= bbox[3]:
80    # Bogus bounding box
81    output_error("Invalid bounding box")
82  else:
83    # Project the bounds to the map projection
84    bbox = mapnik.forward_(mapnik.Envelope(*bbox), prj)
85
86    # Calculate the size of the final rendered image
87    scale = float(form.getvalue("scale"))
88    width = int(bbox.width() / scale / 0.00028)
89    height = int(bbox.height() / scale / 0.00028)
90
91    # Limit the size of map we are prepared to produce
92    if width * height > 4000000:
93      # Map is too large (limit is approximately A2 size)
94      output_error("Map too large")
95    else:
96      # Create map
97      map = mapnik.Map(width, height)
98
99      # Load map configuration
100      mapnik.load_map(map, "/home/jburgess/live/osm.xml")
101
102      # Zoom the map to the bounding box
103      map.zoom_to_box(bbox)
104
105      # Render the map
106      if form.getvalue("format") == "png":
107        image = mapnik.Image(map.width, map.height)
108        mapnik.render(map, image)
109        png = image.tostring("png") 
110        output_headers("image/png", "map.png", len(png))
111        sys.stdout.write(png)
112      elif form.getvalue("format") == "jpeg":
113        image = mapnik.Image(map.width, map.height)
114        mapnik.render(map, image)
115        jpeg = image.tostring("jpeg") 
116        output_headers("image/jpeg", "map.jpg", len(jpeg))
117        sys.stdout.write(jpeg)
118      elif form.getvalue("format") == "svg":
119        file = tempfile.NamedTemporaryFile()
120        surface = cairo.SVGSurface(file.name, map.width, map.height)
121        mapnik.render(map, surface)
122        surface.finish()
123        output_headers("image/svg+xml", "map.svg", file_size(file))
124        output_file(file)
125      elif form.getvalue("format") == "pdf":
126        file = tempfile.NamedTemporaryFile()
127        surface = cairo.PDFSurface(file.name, map.width, map.height)
128        mapnik.render(map, surface)
129        surface.finish()
130        output_headers("application/pdf", "map.pdf", file_size(file))
131        output_file(file)
132      elif form.getvalue("format") == "ps":
133        file = tempfile.NamedTemporaryFile()
134        surface = cairo.PSSurface(file.name, map.width, map.height)
135        mapnik.render(map, surface)
136        surface.finish()
137        output_headers("application/postscript", "map.ps", file_size(file))
138        output_file(file)
139      else:
140        output_error("Unknown format '%s'" % form.getvalue("format"))
Note: See TracBrowser for help on using the repository browser.