initial code
authorTero Marttila <terom@fixme.fi>
Tue, 05 May 2009 16:21:41 +0300
changeset 0 44c5c8c2ac66
child 1 71c7382994c4
initial code
logo.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/logo.py	Tue May 05 16:21:41 2009 +0300
@@ -0,0 +1,173 @@
+#!/usr/bin/python2.5
+import cgi, cgitb
+
+cgitb.enable()
+
+from PIL import Image, ImageDraw, ImageFont
+from cStringIO import StringIO
+import random
+
+
+# settings
+text = [
+    "aalto",
+    "unive",
+    "rsity"
+]
+
+random_chars = [ '"', '!', '?' ]
+
+line_colors = [
+    "#0469af",
+    "#fbc614",
+    "#e1313b",
+]
+
+fonts = {
+    'dejavu-sans-bold':     "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf",
+    'helvetica':            "HELR65W.TTF",
+}
+
+font_name = 'helvetica'
+font_size = 30
+
+def randomize (seq) :
+    """
+        Returns the given sequence in random order as a list
+    """
+    
+    # copy
+    l = list(seq)
+    
+    # rearrange
+    random.shuffle(l)
+
+    return l
+
+def build_data (text, chars, line_colors) :
+    """
+        Returns a matrix of (text, color) tuples representing the data to render
+
+        [ [ (str, str) ] ]
+
+            text        - list of lines
+            chars       - list of random chars to interpse
+            line_colors - list of colors to draw the chars in
+    """
+
+    data = []
+    
+    for line, char, color in zip(text, chars, line_colors) :
+        # pick position to place char
+        pos = random.randint(1, len(line) - 1)
+        
+        # split into three parts
+        data.append([
+                (line[:pos], "#000000"),
+                (char, color),
+                (line[pos:], "#000000"),
+            ])
+    
+    return data
+
+def load_font (font_name, font_size) :
+    """
+        Load a font by name
+    """
+    
+    # load font
+    font_path = fonts[font_name]
+    font = ImageFont.truetype(font_path, font_size)
+    
+    return font
+
+def render_img (data, font, background_color="#ffffff", line_spacing=0) :
+    """
+        Render the data (as from build_data) as an image, using the given PIL.ImageFont, and return the PIL Image object
+    """
+
+    img_width = img_height = 0
+
+    img_data = []
+    
+    # compute image width/height
+    for segments in data :
+        line_width = line_height = 0
+        
+        # build a new list of segments with additional info
+        line_segments = []
+        
+        for seg_text, seg_color in segments :
+            # compute rendered text size
+            seg_width, seg_height = font.getsize(seg_text)
+            
+            # update line_*
+            line_width += seg_width
+            line_height = max(line_height, seg_height)
+            
+            # build the new segments list
+            line_segments.append((seg_text, seg_color, seg_width))
+        
+        # update img_*
+        img_width = max(img_width, line_width)
+        img_height += line_height
+        img_data.append((line_segments, line_height))
+
+    # calculate height needed for line spacing
+    img_height += (len(img_data) - 1) * line_spacing
+
+    # create image
+    img = Image.new("RGB", (img_width, img_height), background_color)
+    draw = ImageDraw.Draw(img)
+
+    # draw text
+    img_y = 0
+    for segments, line_height in img_data :
+        img_x = 0
+        
+        # draw each segment build above, incremeing along img_x
+        for seg_text, seg_color, seg_width in segments :
+            draw.text((img_x, img_y), seg_text, font=font, fill=seg_color)
+
+            img_x += seg_width
+        
+        img_y += line_height + line_spacing
+    
+    return img
+
+def build_png (img) :
+    """
+        Write the given PIL.Image as a string, returning the raw binary data
+    """
+
+    # render PNG output
+    buf = StringIO()
+    img.save(buf, "png")
+    data = buf.getvalue()
+
+    return data
+
+def response (type, data) :
+    """
+        Write out the HTTP Response
+    """
+
+    from sys import stdout
+
+    stdout.write("Content-Type: %s\r\n" % type)
+    stdout.write("Content-Length: %d\r\n" % len(data))
+    stdout.write("\r\n")
+    stdout.write(data)
+
+def main () :
+    data = build_data(text, randomize(random_chars), line_colors)
+    font = load_font(font_name, font_size)
+
+    img = render_img(data, font)
+    png_data = build_png(img)
+
+    response("image/png", png_data)
+
+if __name__ == '__main__' :
+    main()
+