1 SVG - Scalable Vector Graphics

SVG is an XML-based, W3C approved graphics standard. It facilitates creation of vector graphics which can be incorporated into HTML files. All modern browsers (except Microsoft Internet Explorer) support SVG. If you are using Internet Explorer, you need to install a plugin (such as this one) or install a different browser (such as Firefox).

Below is an example of an SVG file, which draws a blue rectangle.

<?xml version="1.0" standalone="no"?> 
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> 

<svg width="100%" height="100%" version="1.1" 
xmlns="http://www.w3.org/2000/svg"> 

<rect width="300" height="100" fill="blue"/> 

</svg> 

1.1 Exercises

1) Save this as "example1.svg". Change the file so that the blue rectangle is a bit further in the middle of the page.
Hints: The first 5 lines of the example should not be changed. You can find details on the basic shapes here. (Don't read that whole page. Scroll down until you find an example of the shape you are looking for.)

2) Add a green circle and a yellow star to the example.

3) Add some text.

2 Embedding SVG into an HTML file

An SVG image can be embedded into an HTML page using either the <embed> or the <object> tag.
<embed src="example.svg" type="image/svg+xml" width="400" height="300" />
Or:
<object data="example.svg" type="image/svg+xml" width="400" height="300" />
Browsers need to create scrollbars for large SVG images. Some browsers have problems with that. Creating a large object area will force the browser to produce adequate scrollbars:
<object data="example.svg" type="image/svg+xml" width="200%" height="200%" />
In general, there can be incompatibilities between different browsers and different operating systems. Not all advanced features may work on all browsers.

2.1 Exercise

4) Create an HTML page which contains one of the images you created above.

3 Producing SVG from a script

The advantage of using a script is that SVG code can be dynamically generated. You can choose either the PHP or the Perl version of the following exercises.

In PHP:

PHP has a package for producing SVG images (XML_SVG package). But it is not necessary to use this package for basic SVG files. Even without using the XML_SVG package, any PHP script can produce SVG. It is important that the header says "image/svg+xml" at the very beginning of the file:
<?php
  header('Content-Type: image/svg+xml');
  echo '<?xml version="1.0" standalone="no"?>';
?>
This should be followed by the DOCTYPE and the svg tags as in the previous examples.

In Perl:

Perl has a module for producing SVG images ( SVG module) which can be downloaded via CPAN (running "perl -MCPAN -e 'install SVG'" on the command-line). But using this module probably does not make it much easier because all the attributes need to be produced in either case.

If a PHP or Perl/CGI script produces an SVG file, it is important that the header information is accurately produced. For Perl, don't use "print header();" but instead use this:

print "Content-type: image/svg+xml\n\n";
print '<?xml version="1.0" standalone="no"?>';
This should be followed by printing the DOCTYPE and svg tags.

3.1 Exercise

5) Create a form which asks a user for a colour and write a script that generates an SVG response page which shows a circle in that colour.

4 Using ImageMagick

Download this photograph onto your I-drive. Save it under the name "photo.jpg". ImageMagick can be used to print metadata for this photograph or to convert it into a different format.

4.1 Exercises

6) Print all of the metadata of the image file (identify -verbose photo.jpg).

7) Print selected values of the metadata. Try these:

8) Convert the file into other formats or sizes. Try these:

5 Using Graphviz

Graphviz is installed on DCS. If you use a different computer, check whether Graphviz is installed (by typing "dot" on the command-line). You can install Graphviz from here.

Graphviz has a number of command-line utilities for creating graph layouts: dot (for directed graphs), neato and fdp (for undirected graphs), and twopi and circo for different radial, circular layouts. The graph code is saved in files with a ".dot" extension.

digraph names { 
node0 [label="John"] 
node1 [label="Mary"] 
node2 [label="Paul"] 
node0 -> node1 
node0 -> node2 
node2 -> node1 
} 
An undirected graph uses the word "graph" instead of "digraph" and "--" instead of "->".

5.1 Exercises

9) Save the file as "example.dot".
Type dot -Tgif -o example.gif example.dot, then look at example.gif.
Type circo -Tgif -o example.gif example.dot, then look at example.gif. Try "twopi" instead of "circo".
Add a few more nodes and edges.
(There seems to be a problem with the PATH settings on DCS. If the commands above don't work, use
/usr/bin/dot -Tgif -o example.gif example.dot
/usr/bin/circo -Tgif -o example.gif example.dot
etc.)

10) Save the file as an undirected graph and use the "neato" and "fdp" layouts.

11) Have a look at the Graphviz gallery. Each of the examples shows both the picture and the Graphviz file that was used. (In some cases, you need to click on the picture to see the code.)

5.2 Using Graphviz from a script

There are libraries for PHP and Perl that can be installed in order to use Graphviz. Without installing these libraries it is still possible to use Graphviz via system calls. The code of the Graphviz file is produced by a script and then piped into the Graphviz process (dot, neato, ...). The output from the Graphviz process is sent to the browser as a gif file. The PHP and Perl code examples below show the details.

It should be noted that sending user data to system calls is a potential security risk. The user data needs to be carefully checked. This will be discussed in the Security lecture.

The following example shows a form that contains textfields for names of people and their friends. The script in the next section then draws a graph for the social network of these people.

<form action=" ... " method="post">
Enter the names of a people and their friends. <p>

Person: <input type="text" size =10 name="person1"> <br>
Friends: <input type="text" size=10 name="f11"><br>
      <input type="text" size=10 name="f12"> <br>
      <input type="text" size=10 name="f13"> <p>

Person: <input type="text" size=10 name="person2"> <br>
Friends: <input type="text" size=10 name="f21"><br>
      <input type="text" size=10 name="f22"> <br>
      <input type="text" size=10 name="f23"> <p>

Person: <input type="text" size=10 name="person3"> <br>
Friends: <input type="text" size=10 name="f31"><br>
      <input type="text" size=10 name="f32"> <br>
      <input type="text" size=10 name="f33"> <p>
<input type="submit" value="Draw it">

5.3 PHP/Graphviz example

(Use either the PHP or the Perl example below.)
<?php
error_reporting(E_ALL ^ E_NOTICE);
header("Content-type: image/svg+xml");

$graphcontent = "digraph G {".
"\"".$_REQUEST['person1']."\" -> \"".$_REQUEST['f11']."\"\n".
"\"".$_REQUEST['person1']."\" -> \"".$_REQUEST['f12']."\"\n".
"\"".$_REQUEST['person1']."\" -> \"".$_REQUEST['f13']."\"\n".
"\"".$_REQUEST['person2']."\" -> \"".$_REQUEST['f21']."\"\n".
"\"".$_REQUEST['person2']."\" -> \"".$_REQUEST['f22']."\"\n".
"\"".$_REQUEST['person2']."\" -> \"".$_REQUEST['f23']."\"\n".
"\"".$_REQUEST['person3']."\" -> \"".$_REQUEST['f31']."\"\n".
"\"".$_REQUEST['person3']."\" -> \"".$_REQUEST['f32']."\"\n".
"\"".$_REQUEST['person3']."\" -> \"".$_REQUEST['f33']."\"\n".
"}";

$descriptorspec = array(0 => array("pipe", "r"),1 => array("pipe", "w") );
$process = proc_open('/usr/bin/dot -Tsvg',$descriptorspec,$pipes);               

if (is_resource($process)) {

fwrite($pipes[0],  "$graphcontent");
fclose($pipes[0]);
while (! feof($pipes[1])) {$retval .= fgets($pipes[1]);}
echo $retval;
fclose($pipes[1]);
$return_value = proc_close($process);
}
?>

5.4 Perl/Graphviz example

#!/usr/bin/perl
use CGI;
my $cgi = new CGI;

$filetype = "svg";
$graphcontent = "digraph G {".
        "\"".$cgi->param('person1')."\" -> \"".$cgi->param('f11')."\"\n".
        "\"".$cgi->param('person1')."\" -> \"".$cgi->param('f12')."\"\n".
        "\"".$cgi->param('person1')."\" -> \"".$cgi->param('f13')."\"\n".
        "\"".$cgi->param('person2')."\" -> \"".$cgi->param('f21')."\"\n".
        "\"".$cgi->param('person2')."\" -> \"".$cgi->param('f22')."\"\n".
        "\"".$cgi->param('person2')."\" -> \"".$cgi->param('f23')."\"\n".
        "\"".$cgi->param('person3')."\" -> \"".$cgi->param('f31')."\"\n".
        "\"".$cgi->param('person3')."\" -> \"".$cgi->param('f32')."\"\n".
        "\"".$cgi->param('person3')."\" -> \"".$cgi->param('f33')."\"\n".
    "}";

if ($filetype eq "svg") {
    print "Content-type: image/svg+xml\n\n";
    open(PIPE, "| dot -Tsvg   2>Errors.log");
         print PIPE $graphcontent;
         close PIPE;
} else {
     print "Content-type: text/html\n\n";
     print $graphcontent;
}

5.5 Exercise

12) Implement the example. Add one more person and their friends. Change it from a directed to an undirected graph.