[OSM-dev] NOT-saving empty Mapnik tiles

Igor Podolskiy igor.podolskiy at vwi-stuttgart.de
Mon Aug 15 19:56:10 BST 2011


Hi Markus,

now that I've had time to look into the mapnik code for more than 3 
minutes, it is somewhat clearer to me.

> 1. Mapnik internals
> I would guess that Mapnik stored every tile in an array of 256 x 256 Bytes. If you could check such an array's bytes if they all had the same value, this would indicate either strictly monochromacity or complete transparency. In my case there are no monochrome tiles, so I could conclude these tiles to be transparent.
Yes, it does something like that. It is an array of 256 * 256 * 4 bytes 
(one byte for each of R, G, B and A channels, so four bytes per pixel). 
This is known internally as mapnik::image_32 and is basically an array 
of 32-bit integers, one per pixel. Pretty straightforward. What you see 
on the Python side is the Python wrapper around this class which exposes 
some methods as the Python API. Sadly, no direct access to raw data 
(that integer array).

Those tostring() methods (there are two of them) give you access to a 
copy of the raw or encoded image data, though. After all, a "string" 
(str) is an array of bytes in Python, albeit Python pretends those are 
"characters" (as opposed to an "unicode string" which is an array of 
proper, possibly multibyte characters). Anyway, you can check for a 
fully transparent mapnik.Image with:

def is_transparent(mapnik_image_array):
     # starting with the fourth byte, every fourth byte
     # represents the alpha value of a pixel
     for i in xrange(3, len(mapnik_image_array), 4):
         if mapnik_image_array[i] != '\x00':
            return False
     return True

im = mapnik.Image(256, 256)
print(is_transparent(im.tostring())) # should print True here

Actually, mapnik _can_ save a PNG to a buffer. My accusation from the 
previous mail that it couldn't do it was totally wrong, sorry for that 
:( Here is how it works:

def is_empty_by_size(mapnik_image):
     return im.tostring('png256') == 116

mapnik.Image.tostring() is overloaded, and you can pass a parameter for 
the encoding.

Of course, you can go with tmpfs but the above way for storing a PNG in 
memory should be simpler (and now you don't need PIL any more).

Bye
Igor



More information about the dev mailing list