From: <cli...@us...> - 2006-01-09 22:31:58
|
Author: cliechti Date: 2006-01-09 23:31:51 +0100 (Mon, 09 Jan 2006) New Revision: 4279 Added: trunk/sandbox/cliechti/aafigure/pil.py Modified: trunk/sandbox/cliechti/aafigure/aafigure_directive.py Log: - add PIL backend for bitmap output - :format: option for aafigure directive (all PIL formats + 'SVG') - error handling if image format is not known or PIL not installed Modified: trunk/sandbox/cliechti/aafigure/aafigure_directive.py =================================================================== --- trunk/sandbox/cliechti/aafigure/aafigure_directive.py 2006-01-09 22:05:13 UTC (rev 4278) +++ trunk/sandbox/cliechti/aafigure/aafigure_directive.py 2006-01-09 22:31:51 UTC (rev 4279) @@ -3,7 +3,13 @@ """ import os, sys, tempfile, popen2 -import aafigure, svg +import aafigure +import svg +try: + import pil +except ImportError: + #no support for bitmaps + pil = None from docutils import nodes from docutils.parsers.rst.directives import register_directive @@ -16,37 +22,66 @@ global aafigure_counter aafigure_counter += 1 - output_name = 'aafigure-%i.svg' % aafigure_counter aaimg = aafigure.AsciiArtImage(text) #~ print text aaimg.recognize() + #ensure that options are present if not options.has_key('scale'): options['scale'] = 1 if not options.has_key('line_width'): options['line_width'] = 2 + if not options.has_key('format'): options['format'] = 'svg' - svgout = svg.SVGOutputVisitor( - file(output_name, 'w'), - scale = options['scale']*10, - line_width = options['line_width'], - debug = True - ) - svgout.visit(aaimg) - - # Return an image directive. - #~ options['uri'] = os.path.basename(output_name) - #~ return [nodes.image(output_name, **options)] - - attributes = {'format': 'html'} - return [nodes.raw('', '<embed src="%s" %s type="image/svg+xml"/>' % ( + if options['format'] == 'svg': + output_name = 'aafigure-%i.svg' % aafigure_counter + svgout = svg.SVGOutputVisitor( + file(output_name, 'w'), + scale = options['scale']*10, + line_width = options['line_width'], + debug = True + ) + svgout.visit(aaimg) + attributes = {'format': 'html'} + result = [nodes.raw('', '<embed src="%s" %s type="image/svg+xml"/>' % ( output_name, svgout.get_size_attrs() ), **attributes)] + elif pil is not None: + output_name = 'aafigure-%i.%s' % (aafigure_counter, options['format']) + pilout = pil.PILOutputVisitor( + file(output_name, 'wb'), + scale = options['scale']*10, + line_width = options['line_width'], + debug = True, + file_type = options['format'] + ) + try: + pilout.visit(aaimg) + except KeyError: + result = [state_machine.reporter.error( + 'No support for image format %r' % (options['format']), + nodes.literal_block(block_text, block_text), + line=lineno + )] + else: + # Return an image directive. + image_options = {} + image_options['uri'] = os.path.basename(output_name) + result = [nodes.image(output_name, **image_options)] + else: + result = [state_machine.reporter.error( + 'No support for image format %r (PIL not installed)' % (options['format']), + nodes.literal_block(block_text, block_text), + line=lineno + )] + + return result AAFigureDrective.content = True #~ AAFigureDrective.arguments = (1, 1, 1) AAFigureDrective.options = { 'scale': float, 'line_width': float, + 'format': str, } def register(): Added: trunk/sandbox/cliechti/aafigure/pil.py =================================================================== --- trunk/sandbox/cliechti/aafigure/pil.py 2006-01-09 22:05:13 UTC (rev 4278) +++ trunk/sandbox/cliechti/aafigure/pil.py 2006-01-09 22:31:51 UTC (rev 4279) @@ -0,0 +1,108 @@ +""" +Bitmap renderer with the help of the Python Imaging Library. + +(C) 2006 Chris Liechti <cli...@gm...> +""" + +import Image, ImageDraw, ImageFont + +class PILOutputVisitor: + """Render a list of shapes as ASCII art. + """ + + def __init__(self, file_like, scale = 1, line_width=1, debug=False, file_type='png'): + self.file_like = file_like + self.scale = scale + self.debug = debug + self.line_width = line_width + self.file_type = file_type + self.color = (0,0,0) + + def visit(self, aa_image): + """Process the gived ASCIIArtFigure and output the shapes in + the SVG file + """ + self.aa_image = aa_image #save fore later XXX not optimal to do it here + self.width = (aa_image.width+1)*aa_image.nominal_size + self.height = (aa_image.height+1)*aa_image.nominal_size + + image = Image.new( + 'RGB', + (int(self.width*self.scale), int(self.height*self.scale)), + (255,255,255) + ) + self.draw = ImageDraw.Draw(image) + + #~ if self.debug: + #~ #draw a rectangle around entire image + #~ self._rectangle( + #~ 0,0, + #~ aa_image.width, aa_image.height, + #~ style = 'fill:none;', + #~ ) + + for shape in aa_image.shapes: + shape_name = shape.__class__.__name__.lower() + visitor_name = 'visit_%s' % shape_name + if hasattr(self, visitor_name): + getattr(self, visitor_name)(shape) + else: + print "WARNING: don't know how to handle shape %r" % shape + + del self.draw + image.save(self.file_like, self.file_type) + + # - - - - - - SVG drawing helpers - - - - - - - + def _line(self, x1, y1, x2, y2): + """Draw a line, coordinates given as four decimal numbers""" + self.draw.line((x1, y1, x2, y2), fill=self.color) #self.line_width + + def _rectangle(self, x1, y1, x2, y2): + """Draw a rectange, coordinates given as four decimal numbers. + ``style`` is inserted in the SVG. It could be e.g. "fill:yellow" + """ + self.draw.rectangle((x1, y1, x2, y2), fill=self.color, outline=self.color) #self.line_width + + # - - - - - - visitor function for the different shape types - - - - - - - + + def visit_point(self, point): + dotsize = 2 + self.draw.ellipse( + ( + point.x*self.scale-dotsize, point.y*self.scale-dotsize, + point.x*self.scale+dotsize, point.y*self.scale+dotsize + ), + fill=self.color + ) + + def visit_line(self, line): + x1, x2 = line.start.x, line.end.x + y1, y2 = line.start.y, line.end.y + self._line(x1*self.scale, y1*self.scale, x2*self.scale, y2*self.scale) + + def visit_rectangle(self, rectangle): + self._rectangle( + rectangle.p1.x*self.scale, rectangle.p1.y*self.scale, + rectangle.p2.x*self.scale, rectangle.p2.y*self.scale, + fill=self.color + ) + + + def visit_circle(self, circle): + self.draw.ellipse( + ( + (circle.center.x-circle.radius)*self.scale, (circle.center.y-circle.radius)*self.scale, + (circle.center.x+circle.radius)*self.scale, (circle.center.y+circle.radius)*self.scale + ), + fill=self.color + ) + + def visit_label(self, label): + # font-weight="bold" + self.draw.text( + (label.position.x*self.scale, (label.position.y-self.aa_image.nominal_size*1.1)*self.scale), + label.text, + fill=self.color, + font=ImageFont.truetype('arial.ttf', int(self.aa_image.nominal_size*self.scale)) + ) + Property changes on: trunk/sandbox/cliechti/aafigure/pil.py ___________________________________________________________________ Name: svn:keywords + Author Date Id Revision Name: svn:eol-style + native |