I'm using mapnik (python api) to render a very simple map where land polygons are black and water is white. There are no other features on the map. I'd like to detect if my tile is completely solid (ie. either black or white) so I can mark the tile as being 'fully land' or 'fully water'... this would help me save a ton of space later on when I pack the tiles together.

I know you can call the painted() function on an image in mapnik, but I don't think this works if a feature gets painted.

>>> im = Image(256,256)
>>> im.background = Color('white')
>>> m = Map(256,256)
>>> render(m,im)
>>> im.painted() # should be False

There are a couple of options that might help you get the result you're after:

You could do this with the Python Imaging Libary (PIL) using the getcolors method on a image. For example:

from PIL import Image

im = Image.open(tile_path)
max_colors = 2 #if max colors is exceded in getcolors it returns None

if not im.getcolors(max_colors):
    #mark solid

Alternately if you're looking to save space by not storing identical tiles you could take the hash of the file contents and compare them. If the contents are the same then the hash will be the same. Since tiles don't store geographic information they will be the same if they are the same block colour. For example using the inbuilt Python hashlib:

from hashlib import md5

m1 = md5(open("tile.png", "rb").read())
#Note that reading the contents of an image _MUST_ be binary
m2 = md5(open("other_tile.png", "rb").read())

if m1.digest() == m2.digest():
    #both tiles are the same
  • Your idea of comparing the hash of the files is pretty slick. Though that seems like it could expensive. (Maybe not as much as storage though?) Since the tile needs to be rendered before you can get it's hash---is it better to write a post-processing method to followup with, deleting the bandits, or to modify generate_tiles.py to tackle the extra step on the fly. To me it seems more organized as a followup step, but then again, that's an extra loop over all the tiles. – elrobis Apr 13 '13 at 0:31

In Mapnik the im.painted() method is meant to be used alongside an im.is_solid() method and im.get_pixel() method. However, it looks like I forgot to expose this in the Mapnik python bindings. It has been added to the javascript bindings: https://github.com/mapnik/node-mapnik/blob/6a63a5c2d09acab5db29a67c9490ec4af292c670/src/mapnik_image_view.cpp#L200-L222.

If you create an issue at the mapnik github site requesting the is_solid method be exposed I will implement this next week.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.