Mapnik 3.0.12 Release Sep 08, 2016 | Artem Pavlenko
Mapnik 3.0.10 Release Feb 29, 2016 | Artem Pavlenko
Node Mapnik 3.5.0 Release Feb 29, 2016 | Sam Matthews
Mapnik 3.0.9 Release Nov 26, 2015 | Artem Pavlenko
Mapnik 3.0.7 and 3.0.8 Releases Oct 26, 2015 | Artem Pavlenko
Mapnik 3.0.6 Release Oct 08, 2015 | Artem Pavlenko
Mapnik 3.0.5 Release Sep 17, 2015 | Artem Pavlenko
Mapnik 3.0.4 Release Aug 26, 2015 | Artem Pavlenko
Introducing a Color Blind Filter Aug 14, 2015 | Blake Thompson
Mapnik 3.0.3 Release Aug 12, 2015 | Artem Pavlenko
Mapnik 3.0.2 Release Jul 31, 2015 | Blake Thompson
Node Mapnik 3.4.1 Release Jul 31, 2015 | Blake Thompson

latest news

Cartographic trick of the day

Apr 20, 2012

This is a short post to share some techniques I came up with while implementing compositing and image filtering in Mapnik core.

The problem

Text rendered on top of a ‘busy’ map can become difficult to read, it can make colours appear heavy. One use-case would be place names on top of a dense road network, another text on top of height contours.

Consider the following map generated with :

python mapnik/demo/python/


(I modified text size to be 14px for clarity)

As you can see, dark text interferes with dark-ish minor roads and also casings on bigger roads.

One way to address this is to use text halos :

text halos

Now we have nice ‘punchy’ text but the rest of the features are getting overwhelmed. This is a sub-optimal solution, though, as halos saturate the image and attract far to much attention to the text items. What we really want is to punch-out the interfering layers around the text but leave the background intact.

smart halos

This is better - now we have a map that is lighter on the eye and the text is easier to read. After all, this is the main purpose of a map - to convey information to the user.

Note that province and water polygons are underneath halos, while roads have been removed.

So how can we achieve this in Mapnik?

The solution

This is a well known cartographic issue and the solution in the paleo-geo world is referred to as “variable-depth masking”. I call it ‘smart-halo’ but the principle is the same.

There are possibly multiple ways to solve this, but here is one solution based on recent ‘compositing’ work I was concentrating on in Mapnik.

So here are step-by-step maps demonstrating the process.

1) We start with an empty map with fully transparent background - ‘transparent’ named colour or rgba(0,0,0,0). Then we render roads in the usual way.

NOTE: black background is due to conversion to JPEG format which doesn’t support alpha channel. It should appear as white


2) Right after roads we insert ‘smart-halo’ layer with the following style

<Style name="smart-halo" comp-op="dst_out">
       <TextSymbolizer face-name="DejaVu Sans Book" halo-radius="3" halo-fill="white" fill="white"  size="14">[GEONAME]</TextSymbolizer>

We use ‘dst_out’ compositing mode on this style to ‘punch-out’ roads or any other previously rendered objects.


3) Now we add provinces and water polygons using “dst_over” compositing operator, e.g for water polygons:

<PolygonSymbolizer fill="rgb(153,204,255)" fill-opacity="1.0" smooth="0.7" comp-op="dst_over"/>

dst_over polygons

4) And finally we render text and there you have it - smart-halos :D

smart halos

Copyright © 2016 Artem Pavlenko | Downloads | License | Media