log_formatter_pil.py
author Tero Marttila <terom@fixme.fi>
Sat, 14 Feb 2009 20:09:08 +0200
changeset 127 5746705a2719
parent 124 4bc4de14f006
permissions -rw-r--r--
improve LogSearchIndex error handling, add explicit close() method, and modify get_index to not keep the index open persistently
"""
    Use of PIL to render the image formatting stuff
"""

from PIL import Image, ImageDraw, ImageFont

from cStringIO import StringIO

class PILImageFormatter (object) :
    """
        Mixin for LogFormatter that implements the basic image-rendering operations on top of format_txt
    """
    
    # the font we load
    font = None

    # line spacing in pixels
    LINE_SPACING = 1

    def _load_font (self) :
        """
            Use the configured img_ttf_path for a TrueType font, or a default one
        """

        if self.font :
            pass
        
        elif self.img_ttf_path :
            # load truetype with configured size
            self.font = ImageFont.truetype(self.img_ttf_path, self.img_font_size)

        else :
            # default
            self.font = ImageFont.load_default()

        return self.font

    def format_png (self, lines, **kwargs) :
        """
            Build and return a PNG image of the given lines, using format_txt
        """

        # load font
        font = self._load_font()

        # build list of plain-text line data
        lines = list(data for line, data in self.format_txt(lines, **kwargs))
        
        # lines sizes
        line_sizes = [font.getsize(line) for line in lines]

        # figure out how wide/high the image will be
        width = max(width for width, height in line_sizes)
        height = sum(height + self.LINE_SPACING for width, height in line_sizes)

        # create new B/W image
        img = Image.new('L', (width, height), 0xff)

        # drawer
        draw = ImageDraw.Draw(img)
        
        # starting offset
        offset_y = 0

        # draw the lines
        for line, (width, height) in zip(lines, line_sizes) :
            # draw
            draw.text((0, offset_y), line, font=font)

            # next offset
            offset_y += height + self.LINE_SPACING
        
        # output buffer
        buf = StringIO()

        # save
        img.save(buf, 'png')

        # return data
        return buf.getvalue()