Scalable Vector Graphics with Perl

Scalable Vector Graphics allows you to create images that can scale up and down without loss of quality.

I have already hear Tamir Lousky give two presentation on how to create SVG images using Perl, so I thought I should give it a try.

What is Scalable Vector Graphics?

When seeing an image, we basically see lots of colored pixels. The original picture can be stored either as those pixels, that's called a raster image or in can be saves as a series of commands to draw the picture.

Scalable Vector Graphics (SVG) is basically an XML file containing instructions how to draw an image.

Your browser can process that XML file and render it as a picture. (Well, assuming you have a modern web browser.)

There is a pure-perl module called SVG created by Ronan Oger, that allows you to create that XML file by calling Perl methods.

Let's see a few simple examples.

Draw circle


  #!/usr/bin/perl
  use strict;
  use warnings;

  use SVG;

  # create an SVG object with a size of 40x40 pixels
  my $svg = SVG->new(
    width  => 40,
    height => 40,
  );

  # add a circle
  $svg->circle(
    cx => 20,
    cy => 20,
    r  => 18,
  );


  # now render the SVG object, implicitly use svg namespace
  print $svg->xmlify;

First we create the background of the image with a size of 40 x 40 pixels. We only need this so we can add elements to it in a size relative to this size. By default the background is white.


  my $svg = SVG->new(
    width  => 40,
    height => 40,
  );

Then we add a circle, with a center at 20x20 and a radius of 18 pixels. By default the circle will be black.

Finally we call the xmlify method that returns the XML file.

If we run this script we'll see a small XML on our screen:


  <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
  <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
     "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
  <svg height="40" width="40" xmlns="http://www.w3.org/2000/svg" 
     xmlns:svg="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">
   <circle cx="20" cy="20" r="18" />
  <!-- 
    Generated using the Perl SVG Module V2.50
    by Ronan Oger
    Info: http://www.roitsystems.com/
 -->

We can save this by redirecting the output of the script to a file called


  perl circle.pl > black_circle.svg

Then we can open that file using our browser or by embedding in an html file using the img tag:


  <img src="/img/black_circle.svg" alt="black circle"/>

and make sure that your web server returns the file with Content-type: image/svg+xml.

black circle

Adding some style to the circle


  # add a circle with style
  #  fill is the color used tof fill the circle
  #  stroke is the color of the line used to draw the circle
  #     these both can be either a name of a color or an RGB triplet
  #  stroke-width is a non-negative integer, thw width of thr drawing line
  #  stroke-opacity and fill-opacity are floating point numbers between 0 and 1.
  #     1 means the line is totally opaque
  #     0 means the line is totally transparent
  $svg->circle(
      cx => 20,
      cy => 20,
      r  => 15,
      style => {
          'fill'           => 'rgb(255, 0, 0)',
          'stroke'         => 'blue',
          'stroke-width'   =>  5,
          'stroke-opacity' =>  1,
          'fill-opacity'   =>  1,
      },
  );

Add the following entry to the HTML


   <img src="/img/red_blue_circle.svg" alt="red and blue circle"/>

red and blue circle

While that SVG file has a default size of 20x20 we can tell the browser to display the same image at a larger size by setting the width and the height


  <img src="/img/red_blue_circle.svg" width="200" height="200" 
     alt="big red and blue circle"/>

big red and blue circle

Finally, I changed the 'fill-opacity' of the circle to 0.5. This made the red lighter:

big red and blue circle

Circle, Triangle and Square


  #!/usr/bin/perl
  use strict;
  use warnings;
  
  use SVG;
  
  # create an SVG object with a size of 100x100 pixels
  my $svg = SVG->new(
      width  => 100,
      height => 100,
  );
  
  # create a rectangle (actually square) with the top left
  # corner being at (40, 50)
  # (0, 0) would mean being in the top left corner of the image.
  # The width and the height of the rectangular are also given
  # in pixels and we can add style just asw we  did with the circle.
  $svg->rectangle(
      x => 40,
      y => 50,
      width  => 40,
      height => 40,
      style => {
          'fill'           => 'rgb(0, 255, 0)',
          'stroke'         => 'black',
          'stroke-width'   =>  0,
          'stroke-opacity' =>  1,
          'fill-opacity'   =>  1,
      },
  );
  
  $svg->circle(
      cx => 40,
      cy => 40,
      r  => 20,
      style => {
          'fill'           => 'rgb(255, 0, 0)',
          'stroke'         => 'black',
          'stroke-width'   =>  0,
          'stroke-opacity' =>  1,
          'fill-opacity'   =>  1,
      },
  );
  
  # In order to create a triangle we are going to create a polygon
  # To make it easy to create various path based constructs, SVG.pm
  # provides a "get_path" method that, give a series of coordinates
  # and a type, return the respective data structure that is needed
  # for SVG.
  my $path = $svg->get_path(
      x => [40, 60, 80],
      y => [40, 6, 40],
      -type => 'polygon');
  
  # Then we use that data structure to create a polygon
  $svg->polygon(
      %$path,
      style => {
          'fill'           => 'rgb(0,0,255)',
          'stroke'         => 'black',
          'stroke-width'   =>  0,
          'stroke-opacity' =>  1,
          'fill-opacity'   =>  1,
      },
  );
  
  # now render the SVG object, implicitly use svg namespace
  print $svg->xmlify;



Circle, Triangle and Square

Set the 'fill-opacity' of the circle and that of the polygon to 0.5.

Transparent Circle, Triangle and Square

More of SVG

Recently I got co-maintainership on the SVG module. Made some small documentation fixes and started to modernize the tests a little bit. The above examples will be included in the next release. If you have any bug reports or requests, please use RT. In case you'd like to contribute, use the github repository.

More Perl articles

That was basic introduction to SVG using Perl. If you'd like to read more articles on how to use Perl or how to improve your Perl programming skills, subscribe to my update list:

Published on 2012-03-31 by Gabor Szabo

In the comments, please wrap your code snippets within <pre> </pre> tags and use spaces for indentation.
blog comments powered by Disqus
EduMaven
Python, Dart, JavaScript, and more.


Google Plus Twitter RSS feed