Codebase list twms / upstream/0.06y twms / drawing.py
upstream/0.06y

Tree @upstream/0.06y (Download .tar.gz)

drawing.py @upstream/0.06yraw · history · blame

# -*- coding: utf-8 -*-
#    This file is part of twms.

# This program is free software. It comes without any warranty, to
# the extent permitted by applicable law. You can redistribute it
# and/or modify it under the terms specified in COPYING.

try:
    from PIL import Image, ImageDraw, ImageColor, ImageFont
except ImportError:
    import Image, ImageDraw, ImageColor, ImageFont

import urllib
import os, sys
import array

import projections
import config
from gpxparse import GPXParser
import math


HAVE_CAIRO = True
try:
  import cairo
  import pango
  import pangocairo
except ImportError:
  HAVE_CAIRO = False

def wkt(wkt, img, bbox, srs, color, blend = 0.5):
    """
    Simple WKT renderer
    """
    wkt = wkt.replace("((","(")
    for obj in wkt.split("),"):

       canvas = img.copy()
       name, coords = obj.split("(")
       coords = coords.replace(")","")
       text = ""
       if name == "TEXT":
         text, coords = coords.split(",", 1)
       coords = coords.split(",")
       coords = [ [float(t) for t in x.split(" ")] for x in coords]
       canvas = render_vector(name, canvas, bbox, coords, srs, color, text=text)
       img = Image.blend(img, canvas, blend)
    return img

def gpx(track, img, bbox, srs, color, blend = 0.5):
    """
    Simple GPX renderer
    """
    for i in track.tracks.keys():
      coords = track.getTrack(i)
      canvas = img.copy()
      canvas = render_vector("LINESTRING", canvas, bbox, coords, srs, color)
      img = Image.blend(img, canvas, blend)
    return img


def render_vector(geometry, img, bbox, coords, srs, color=None, renderer=None,
        linestring_width=None, text=None, cairo_font=None, pil_font=None):
    """
    Renders a vector geometry on image.
    """
    if not color:
      color = config.geometry_color[geometry]
    if not renderer:
      renderer = config.default_vector_renderer
    if not linestring_width:
      if 'linestring_width' in dir(config):
        linestring_width = config.linestring_width
      else:
        linestring_width = 3
    if not cairo_font:
      if 'cairo_font' in dir(config):
        cairo_font = config.cairo_font
    if not pil_font:
      if 'pil_font' in dir(config):
        pil_font = config.pil_font
    bbox = projections.from4326(bbox, srs)
    lo1, la1, lo2, la2 = bbox
    coords = projections.from4326(coords, srs)
    W,H = img.size
    prevcoord = False
    coords = [((coord[0]-lo1)*(W-1)/abs(lo2-lo1), (la2-coord[1])*(H-1)/(la2-la1)) for coord in coords]

    if renderer == "cairo" and HAVE_CAIRO:
      "rendering as cairo"
      imgd = img.tostring()
      a = array.array('B',imgd)
      surface = cairo.ImageSurface.create_for_data (a, cairo.FORMAT_ARGB32, W, H, W*4)
      cr = cairo.Context(surface)
      cr.move_to(*coords[0])
      color = ImageColor.getrgb(color)
      cr.set_source_rgba(color[2]/255.0, color[1]/255.0, color[0]/255.0, 1)
      if geometry == "LINESTRING" or geometry == "POLYGON":
        for k in coords:
          cr.line_to(*k)
      if geometry == "LINESTRING":
        if linestring_width is not None:
          cr.set_line_width(linestring_width)
        cr.stroke()
      elif geometry == "POLYGON":
        cr.fill()
      elif geometry == "POINT":
        cr.arc(coords[0][0],coords[0][1],6,0,2*math.pi)
        cr.fill()
      elif geometry == "TEXT" and text and cairo_font:
        pcr = pangocairo.CairoContext(cr)
        pcr.set_antialias(cairo.ANTIALIAS_SUBPIXEL)
        layout = pcr.create_layout()
        font = pango.FontDescription(cairo_font)
        layout.set_font_description(font)
        layout.set_text(text)
        pcr.update_layout(layout)
        pcr.show_layout(layout)

      img = Image.frombuffer("RGBA",( W,H ),surface.get_data(),"raw","RGBA",0,1)
    
    else:
      "falling back to PIL"
      coord = [(int(coord[0]),int(coord[1])) for coord in coords]                 # PIL dislikes subpixels
      draw = ImageDraw.Draw(img)
      if geometry == "LINESTRING":
        draw.line (coords, fill=color, width=linestring_width)
      elif geometry == "POINT":
        draw.ellipse((coords[0][0]-3,coords[0][1]-3,coords[0][0]+3,coords[0][1]+3),fill=color,outline=color)
      elif geometry == "POLYGON":
        draw.polygon(coords, fill=color, outline=color)
      elif geometry == "TEXT" and text and pil_font:
        font = ImageFont.truetype(pil_font[0], pil_font[1])
        draw.text(coords[0], text, color, font=font)
    return img