index.cgi
changeset 1 71c7382994c4
parent 0 44c5c8c2ac66
child 2 50d95ac19dfc
equal deleted inserted replaced
0:44c5c8c2ac66 1:71c7382994c4
       
     1 #!/usr/bin/python2.5
       
     2 import cgi, cgitb
       
     3 
       
     4 cgitb.enable()
       
     5 
       
     6 from PIL import Image, ImageDraw, ImageFont, ImageEnhance
       
     7 from cStringIO import StringIO
       
     8 import random
       
     9 
       
    10 
       
    11 # settings
       
    12 text = [
       
    13     "aalto",
       
    14     "unive",
       
    15     "rsity"
       
    16 ]
       
    17 
       
    18 random_chars = [ '"', '!', '?' ]
       
    19 
       
    20 line_colors = [
       
    21     "#0469af",
       
    22     "#fbc614",
       
    23     "#e1313b",
       
    24 ]
       
    25 
       
    26 fonts = {
       
    27     'dejavu-sans-bold':     "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf",
       
    28     'helvetica':            "HELR65W.TTF",
       
    29 }
       
    30 
       
    31 font_name = 'helvetica'
       
    32 font_size = 30
       
    33 
       
    34 def randomize (seq) :
       
    35     """
       
    36         Returns the given sequence in random order as a list
       
    37     """
       
    38     
       
    39     # copy
       
    40     l = list(seq)
       
    41     
       
    42     # rearrange
       
    43     random.shuffle(l)
       
    44 
       
    45     return l
       
    46 
       
    47 def build_data (text, chars, line_colors) :
       
    48     """
       
    49         Returns a matrix of (text, color) tuples representing the data to render
       
    50 
       
    51         [ [ (str, str) ] ]
       
    52 
       
    53             text        - list of lines
       
    54             chars       - list of random chars to interpse
       
    55             line_colors - list of colors to draw the chars in
       
    56     """
       
    57 
       
    58     data = []
       
    59     
       
    60     for line, char, color in zip(text, chars, line_colors) :
       
    61         # pick position to place char
       
    62         pos = random.randint(1, len(line) - 1)
       
    63         
       
    64         # split into three parts
       
    65         data.append([
       
    66                 (line[:pos], "#000000"),
       
    67                 (char, color),
       
    68                 (line[pos:], "#000000"),
       
    69             ])
       
    70     
       
    71     return data
       
    72 
       
    73 def load_font (font_name, font_size) :
       
    74     """
       
    75         Load a font by name
       
    76     """
       
    77     
       
    78     # load font
       
    79     font_path = fonts[font_name]
       
    80     font = ImageFont.truetype(font_path, font_size)
       
    81     
       
    82     return font
       
    83 
       
    84 def render_img (data, font, background_color="#ffffff", line_spacing=0) :
       
    85     """
       
    86         Render the data (as from build_data) as an image, using the given PIL.ImageFont, and return the PIL Image object
       
    87     """
       
    88 
       
    89     img_width = img_height = 0
       
    90 
       
    91     img_data = []
       
    92     
       
    93     # compute image width/height
       
    94     for segments in data :
       
    95         line_width = line_height = 0
       
    96         
       
    97         # build a new list of segments with additional info
       
    98         line_segments = []
       
    99         
       
   100         for seg_text, seg_color in segments :
       
   101             # compute rendered text size
       
   102             seg_width, seg_height = font.getsize(seg_text)
       
   103             
       
   104             # update line_*
       
   105             line_width += seg_width
       
   106             line_height = max(line_height, seg_height)
       
   107             
       
   108             # build the new segments list
       
   109             line_segments.append((seg_text, seg_color, seg_width))
       
   110         
       
   111         # update img_*
       
   112         img_width = max(img_width, line_width)
       
   113         img_height += line_height
       
   114         img_data.append((line_segments, line_height))
       
   115 
       
   116     # calculate height needed for line spacing
       
   117     img_height += (len(img_data) - 1) * line_spacing
       
   118 
       
   119     # create image
       
   120     img = Image.new("RGB", (img_width, img_height), background_color)
       
   121     draw = ImageDraw.Draw(img)
       
   122 
       
   123     # draw text
       
   124     img_y = 0
       
   125     for segments, line_height in img_data :
       
   126         img_x = 0
       
   127         
       
   128         # draw each segment build above, incremeing along img_x
       
   129         for seg_text, seg_color, seg_width in segments :
       
   130             draw.text((img_x, img_y), seg_text, font=font, fill=seg_color)
       
   131 
       
   132             img_x += seg_width
       
   133         
       
   134         img_y += line_height + line_spacing
       
   135     
       
   136     return img
       
   137 
       
   138 def effect_smooth (img, factor) :
       
   139     """
       
   140         De-sharpen the image by the given factor
       
   141     """
       
   142 
       
   143     return ImageEnhance.Sharpness(img).enhance(factor)
       
   144 
       
   145 def build_png (img) :
       
   146     """
       
   147         Write the given PIL.Image as a string, returning the raw binary data
       
   148     """
       
   149 
       
   150     # render PNG output
       
   151     buf = StringIO()
       
   152     img.save(buf, "png")
       
   153     data = buf.getvalue()
       
   154 
       
   155     return data
       
   156 
       
   157 def response (type, data) :
       
   158     """
       
   159         Write out the HTTP Response
       
   160     """
       
   161 
       
   162     from sys import stdout
       
   163 
       
   164     stdout.write("Content-Type: %s\r\n" % type)
       
   165     stdout.write("Content-Length: %d\r\n" % len(data))
       
   166     stdout.write("\r\n")
       
   167     stdout.write(data)
       
   168 
       
   169 def main () :
       
   170     data = build_data(text, randomize(random_chars), line_colors)
       
   171     font = load_font(font_name, font_size)
       
   172 
       
   173     img = render_img(data, font)
       
   174     img = effect_smooth(img, 0.6)
       
   175     png_data = build_png(img)
       
   176 
       
   177     response("image/png", png_data)
       
   178 
       
   179 if __name__ == '__main__' :
       
   180     main()
       
   181