#!/usr/bin/perl -w ############################################## # Create a png image a user defined function # on the fly with the GD.pm module. ############################################# use strict; use CGI; my $func = CGI->new->param("f"); unless ($func) { # --- send user a form asking for the function --- print "Content-type: text/html\n\n"; print "

Enter a function

"; return; } else { # -- create and output png image of the function -- my $img = PlotFunction::makeImage($func); print "Content-type: image/png\n\n"; print $img->png; } # ===================================== { package PlotFunction; use GD; use constant XPixBorder => 10; use constant YPixBorder => 10; use constant Epsilon => 1e-6; use constant XMax => 8.0 + Epsilon; use constant XMin => -8.0; use constant YMax => 1.5 + Epsilon; use constant YMin => -1.5; use constant XPixSize => 384; use constant YPixSize => 256; use constant DX => (XMax - XMin)/(XPixSize/2); use constant XConvert => XPixSize/(XMax - XMmin); use constant YConvert => YPixSize/(YMax - YMin); # allocate new GD.pm Image. our $im = GD::Image->new(XPixSize+2*XPixBorder, YPixSize+2*YPixBorder); # allocate some colors. First allocated is background. use constant White => $im->colorAllocate(255,255,255); use constant Black => $im->colorAllocate( 0, 0, 0); use constant Grey => $im->colorAllocate(172,172,172); use constant DarkBlue => $im->colorAllocate( 0, 0,128); our $xpixpen; # current pen x coord our $ypixpen; # current pen y coord our $pencolor; # current pen color our $f; # function to be plotted. # make the background transparent and the image interlaced. $im->transparent(White); $im->interlaced('true'); # input: function f(x) to be plotted as a string, i.e. "sin(x)". sub makeImage { ($f) = @_; # convert function in form "exp(x)" to "exp($x)". for ($f) { s/exp/~~~/g; s/x/\$x/g; s/~~~/exp/g; } # draw axes $pencolor = Grey; pendown(XMin,0); lineto(XMax,0); pendown(0,YMin); lineto(0,YMax); # draw function $pencolor = Black; my $x = XMin; my $y = f($x); my ($lastx, $lasty); pendown($x,$y); while ($xstring(gdLargeFont, XPixBorder*2, YPixBorder*2, "f(x) = $func", DarkBlue); return $im; } # function to be plotted sub f { my ($x) = @_; return eval $f; } # convert x coords to pix sub xx { my ($x) = @_; return XPixBorder + ($x-XMin)*XConvert; } # convert x coords to pix sub yy { my ($y) = @_; return YPixborder + (YMax-$y)*YConvert; } # input: (x,y) coords to place pen sub pendown { my ($x,$y) = @_; $xpixpen = xx($x); $ypixpen = yy($y); return; } # input: (x,y) coords # draw line from last pendown position to (x,y) sub lineto { my ($x, $y) = @_; my ($xpixnew, $ypixnew) = ( xx($x), yy($y) ); $im->line($xpixpen, $ypixpen, $xpixnew, $ypixnew, $pencolor); ($xpixpen, $ypixpen) = ($xpixnew, $ypixnew); return; } } # end PlotFunction package