Static maps are somewhat limited, e.g. they can only be up to 640x640 pixels in size, but they provide support for locations as lat/long coordinates, zip-codes and search terms, draw markers, lines and polygons and do not need a developers key. You need to dig into the the documentation to find out the specifics but I found it pretty easy do put together a (rather long) URL with query parameters in python, retrieve the image from google and either save the image to disk or show it via PIL and/or TKinter.
1) To get a hybrid street+satellite map around the Empire State Building (note the + instead of spaces inside the search term part), you'd have to assemble a request like this:
http://maps.google.com/maps/api/staticmap?center=Empire+State+Building&zoom=18&size=500x500&format=jpeg&maptype=hybrid&sensor=false&
2) For a a terrain map around latitude = 42.950827 (North) and Longitude = -122.108974 (East). Note that the actual extent around the center (the viewport) is a function of the zoom-level and the size of your image, zoom=0 shows all of the globe, zoom=20 is usually the limit for zooming in:
http://maps.google.com/maps/api/staticmap?center=42.950827,-122.108974&zoom=12&size=500x500&format=jpg&maptype=terrain&sensor=false&
3) You can also "plot" a bunch of locations as Markers or connect them into lines or polygons within this viewport. Instead of specifying a center and zoom factor, you could also specify a bunch of locations (again either as lat/long, search term or even as zip-code) and let google figure out what "envelope" is needed to show them all within a map. Here's a couple of marker at such locations:
http://maps.google.com/maps/api/staticmap?size=640x640&format=png&maptype=roadmap&markers=color:blue|label:S|11211|11206|11222&markers=size:tiny|label:B|color:0xFFFF00|40.702147,-74.015794|&markers=size:mid|color:red|label:6|Brooklyn+Bridge,New+York,NY&sensor=false&
Again, this is just a quick overview, the documentation actually walks you nicely through creating such URLs. To start you can just assemble the URL by hand (in a text editor), then copy and paste them into your browser and look at the image but why not use python to do the work for you?
Here's some code to create such a URL programmatically and, in the simplest case, save the image it gets back from google as local file. You can use PIL to make a image directly from google's image data, i.e. without saving it to disk first.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | import urllib import cStringIO import Image def get_static_google_map(filename_wo_extension, center=None, zoom=None, imgsize="500x500", imgformat="jpeg", maptype="roadmap", markers=None ): """retrieve a map (image) from the static google maps server See: http://code.google.com/apis/maps/documentation/staticmaps/ Creates a request string with a URL like this: http://maps.google.com/maps/api/staticmap?center=Brooklyn+Bridge,New+York,NY&zoom=14&size=512x512&maptype=roadmap &markers=color:blue|label:S|40.702147,-74.015794&sensor=false""" # assemble the URL request = "http://maps.google.com/maps/api/staticmap?" # base URL, append query params, separated by & # if center and zoom are not given, the map will show all marker locations if center != None: request += "center=%s&" % center #request += "center=%s&" % "40.714728, -73.998672" # latitude and longitude (up to 6-digits) #request += "center=%s&" % "50011" # could also be a zipcode, #request += "center=%s&" % "Brooklyn+Bridge,New+York,NY" # or a search term if center != None: request += "zoom=%i&" % zoom # zoom 0 (all of the world scale ) to 22 (single buildings scale) request += "size=%ix%i&" % (imgsize) # tuple of ints, up to 640 by 640 request += "format=%s&" % imgformat request += "maptype=%s&" % maptype # roadmap, satellite, hybrid, terrain # add markers (location and style) if markers != None: for marker in markers: request += "%s&" % marker #request += "mobile=false&" # optional: mobile=true will assume the image is shown on a small screen (mobile device) request += "sensor=false&" # must be given, deals with getting loction from mobile device print request urllib.urlretrieve(request, filename_wo_extension+"."+imgformat) # Option 1: save image directly to disk # Option 2: read into PIL web_sock = urllib.urlopen(request) imgdata = cStringIO.StringIO(web_sock.read()) # constructs a StringIO holding the image try: PIL_img = Image.open(imgdata) # if this cannot be read as image that, it's probably an error from the server, except IOError: print "IOError:", imgdata.read() # print error (or it may return a image showing the error" # show image else: PIL_img.show() #PIL_img.save(filename_wo_extension+".jpg", "JPEG") # save as jpeg if __name__ == '__main__': # define a series of location markers and their styles # syntax: markers=markerStyles|markerLocation1|markerLocation2|... etc. marker_list = [] marker_list.append("markers=color:blue|label:S|11211|11206|11222") # blue S at several zip code's centers marker_list.append("markers=size:tiny|label:B|color:0xFFFF00|40.702147,-74.015794|") # tiny yellow B at lat/long marker_list.append("markers=size:mid|color:red|label:6|Brooklyn+Bridge,New+York,NY") # mid-sized red 6 at search location # see http://code.google.com/apis/maps/documentation/staticmaps/#Markers # make a map around a center get_static_google_map("google_map_example1", center="42.950827,-122.108974", zoom=12, imgsize=(500,500), imgformat="jpg", maptype="terrain" ) get_static_google_map("google_map_example2", center="Empire+State+Building", zoom=18, imgsize=(500,500), maptype="hybrid") # make map that shows all the markers get_static_google_map("google_map_example3", imgsize=(640,640), imgformat="png", markers=marker_list ) |
So far, so good - but how would you show such a map (image) in a GUI? TkInter's canvas and label widgets can draw an image as a "background", however, I did run into a couple of strange issues when trying to do this inside a class. Luckily I did find this link: http://www.daniweb.com/forums/thread65288.html which let me put together a short and hopefully working example of reading a jpg image from disk and showing it inside a TkInter Frame.
This example uses a (pretty large) label to draw the image but it could be done with a canvas widget as well, in case you want to draw something "over" the map:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # thanks to: http://www.daniweb.com/forums/thread65288.html from Tkinter import * # order seems to matter: import Tkinter first import Image, ImageTk # then import ImageTk class MyFrame(Frame): def __init__(self, master, im): Frame.__init__(self, master) self.caption = Label(self, text="Some text about the map") self.caption.grid() self.image = ImageTk.PhotoImage(im) # <--- results of PhotoImage() must be stored self.image_label = Label(self, image=self.image, bd=0) # <--- will not work if 'image = ImageTk.PhotoImage(im)' self.image_label.grid() self.grid() im = Image.open("mymap.jpg") # read map from disk # or you could use the PIL image you created directly via option 2 from the URL request ... mainw = Tk() mainw.frame = MyFrame(mainw, im) mainw.mainloop() |
The google static map inside a TkInter Window |
4 comments:
This is great. Thanks for the example.
Congratulations for this post!!
It's amazing!! You helped me a lot!!
AMAZINNNGGGGG!!!
Thank for the examples and documentation!!
I'm new in Python but I understand everything because your explanation!
You deserve all the best!
Thank you very very very ... much
That was really helpful.
Fardo Campalo
Thank you so SO much! I have been trying to save static maps for far too long. Your post saved me :)
Post a Comment