I'm making heavy use of OpenLayers in my latest project and with this came the need for a wide range of map markers in terms of symbols and colors. Luckily there is the Map Icons Collection from Nicolas Mollet which provides an excellent set of markers sorted by various topics. You can even choose your own RGB colorization and download the markers for a single topic in a ZIP file.

This would have been sufficient if I were to use only a single color or a small set of colors for all my markers. But I wanted to be able to generate each marker with a specifyable color on the fly. So i downloaded all the markers as ZIPs with the color set to black (#000000, this is mandatory if you plan to duplicate my efforts) and the the iOS style applied (just a personal preference).

As I'm using Django to power my GIS web-application I wanted to have a view where I could specify the marker and it's color in the URL, so that I could use http://server/marker/star/ff0000 to get the start marker with a pure red (#ff0000) colorization. The colorization is done using PIL's ImageOps.colorize() function which calculates a color wedge that is then used to colorize a gray-scale image. The alpha channel of the original image is preserved and then reapplied to the newly colorized image.

The Django view looks like this:

def marker(request, marker, color):
    # open original image which serves as a staturation map
    image = Image.open(os.path.abspath(os.path.join(os.path.dirname(__file__), 
        'static/marker/%s.png' % (marker))))
    # convert image to gray scale format
    saturation = image.convert('L')
    # apply colorization which yield a RBG image without an alpha channel
    marker = ImageOps.colorize(saturation, ImageColor.getrgb('#%s' % (color)), (255, 255, 255))
    # convert ba to RGBA so we can apply the original alpha channel in the next step
    marker = marker.convert('RGBA')
    # apply original alpha channel to colorized image
    marker.putalpha(image.split()[3])
    # construct HttpResponse and send to browser
    response = HttpResponse(content_type='image/png')
    marker.save(response, 'PNG')
    return response

In my production code I have also added caching to this view so that the whole image processing has to be done only once for each color/marker combination.

The accompaning URL mapping for the view is like this:

urlpatterns = patterns('views',
    url(r'^marker/(?P\w+)/(?P[0-9a-fA-F]{6})$', 'marker'),
)

I unpacked the downloaded ZIP archive into static/marker/ so they can be found on a path relativ to the views.py file where the marker view is defined.
That's it, I hope this helps some of the people out there who have more dynamic requirements on their markers regarding colorization.