Annotation of loncom/cgi/plot.gif, revision 1.1
1.1 ! matthew 1: #!/usr/bin/perl
! 2: #
! 3: # $Id$
! 4: #
! 5: # Copyright Michigan State University Board of Trustees
! 6: #
! 7: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
! 8: #
! 9: # LON-CAPA is free software; you can redistribute it and/or modify
! 10: # it under the terms of the GNU General Public License as published by
! 11: # the Free Software Foundation; either version 2 of the License, or
! 12: # (at your option) any later version.
! 13: #
! 14: # LON-CAPA is distributed in the hope that it will be useful,
! 15: # but WITHOUT ANY WARRANTY; without even the implied warranty of
! 16: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 17: # GNU General Public License for more details.
! 18: #
! 19: # You should have received a copy of the GNU General Public License
! 20: # along with LON-CAPA; if not, write to the Free Software
! 21: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
! 22: #
! 23: # /home/httpd/cgi-bin/plot.gif
! 24: #
! 25: # http://www.lon-capa.org/
! 26: #
! 27: # CGI-BIN interface to GD, used for making mathematical plots.
! 28: #
! 29: # User specifies the following variables (given are defaults):
! 30: # height = "100"
! 31: # width = "100"
! 32: # xmin = "-10.0"
! 33: # xmax = " 10.0"
! 34: # ymin = "-10.0"
! 35: # ymax = " 10.0"
! 36: # frame
! 37: # drawaxes
! 38: # drawtics
! 39: # vtic_every = "1.0"
! 40: # htic_every = "1.0"
! 41: # xseries1 = "x1,x2,x3,x4,x5,...,xn"
! 42: # yseries1 = "y1,y2,y3,y4,y5,...,yn"
! 43: # xseries2 = ..
! 44: # yseries2 = ..
! 45: # ...
! 46: # label1 = "x,y,size,text"
! 47: # label2 = "x,y,size,text"
! 48: # label3 = "x,y,size,text"
! 49: # ...
! 50: #
! 51: # size of a labelN is one of :
! 52: # giant, large, medium, small, tiny
! 53: #
! 54: use GD;
! 55:
! 56: my @inputs = split(/&/,$ENV{'QUERY_STRING'});
! 57: foreach $input (@inputs) {
! 58: ($var,$val) = split /\=/,$input,2;
! 59: if (! defined($val)) {
! 60: $val = 1;
! 61: }
! 62: $In{lc($var)}=$val;
! 63: }
! 64:
! 65: $height = &grab('height',100,\%In);
! 66: $width = &grab('width',100,\%In);
! 67: $axis->{'xmin'} = &grab('xmin',-10,\%In);
! 68: $axis->{'xmax'} = &grab('xmax', 10,\%In);
! 69: $axis->{'ymin'} = &grab('ymin',-10,\%In);
! 70: $axis->{'ymax'} = &grab('ymax', 10,\%In);
! 71: $axis->{'xlen'} = $axis->{'xmax'} - $axis->{'xmin'};
! 72: $axis->{'ylen'} = $axis->{'ymax'} - $axis->{'ymin'};
! 73: $vtic_every = &grab('vtic_every',1.0,\%In);
! 74: $htic_every = &grab('htic_every',1.0,\%In);
! 75:
! 76: my $image = new GD::Image($height,$width);
! 77:
! 78: # allocate standard colors
! 79: my $white = $image->colorAllocate(255,255,255);
! 80: my $black = $image->colorAllocate( 0, 0, 0);
! 81:
! 82: # Draw a black frame around the picture
! 83: &drawtics($htic_every,$vtic_every) if (exists($In{"drawtics"}));
! 84: &drawaxes($axis) if (exists($In{"drawaxis"}));
! 85: &frame(1) if (exists($In{'frame'}));
! 86:
! 87: ## Take care of labels and data series
! 88: foreach (keys %In) {
! 89: if (/^label/) {
! 90: my ($x,$y,$size,$text) = split/,/,$In{$_};
! 91: &drawstring($text,$x,$y,$black,$size);
! 92: delete ($In{$_});
! 93: next;
! 94: } elsif (/^xseries/) {
! 95: $xname = $_;
! 96: $yname = $xname;
! 97: $yname =~ s/^x/y/;
! 98: (@X)=split/,/,$In{$xname};
! 99: (@Y)=split/,/,$In{$yname};
! 100: delete ($In{$xname});
! 101: delete ($In{$yname});
! 102: if ($#X != $#Y) {
! 103: &drawstring("size of $xname and $yname do not match",
! 104: 10,10,$black,"giant");
! 105: next;
! 106: }
! 107: &drawcurve(\@X,\@Y);
! 108: }
! 109: }
! 110:
! 111: # make the background transparent and interlaced
! 112: $image->transparent($white);
! 113:
! 114: # make sure we are writing to a binary stream
! 115: binmode STDOUT;
! 116:
! 117: # Convert the image to PNG and print it on standard output
! 118: print <<END;
! 119: Content-type: image/png
! 120:
! 121: END
! 122:
! 123: my $BinaryData=$image->plot(\@data)->png;
! 124: undef $image;
! 125: binmode(STDOUT);
! 126: open IMG,"|pngtopnm|ppmtogif 2>/dev/null"; # convert into a gif image
! 127: print IMG $BinaryData; # output image
! 128: $|=1; # be sure to flush before closing
! 129: close IMG;
! 130:
! 131:
! 132: #--------------------------------------------------------------------
! 133:
! 134: sub grab{
! 135: my ($name,$default,$h) = @_;
! 136: my $value = $h->{$name};
! 137: if (defined($value)) {
! 138: delete ($h->{$name}) ;
! 139: } else {
! 140: $value = $default;
! 141: }
! 142: return $value;
! 143: }
! 144:
! 145: # transformPoint(x,y) where x,y are in the coordinates of axis will return
! 146: # the coordinates transformed to the image coordinate system.
! 147: sub transformPoint{
! 148: my ($x,$y) = @_;
! 149: my ($width,$height) = $image->getBounds();
! 150: $x = ( $x - $axis->{"xmin"}) * $width / ( $axis->{"xlen"});
! 151: $y = ( ( $axis->{"ylen"} ) - ($y - $axis->{"ymin"}))
! 152: * $height / ( $axis->{"ylen"} );
! 153: return($x,$y);
! 154: }
! 155:
! 156: sub drawaxes{
! 157: ($x1,$y1) = &transformPoint($axis->{"xmin"},0,$image,$axis);
! 158: ($x2,$y2) = &transformPoint($axis->{"xmax"},0,$image,$axis);
! 159: $image->line($x1,$y1,$x2,$y2,$black);
! 160: ($x1,$y1) = &transformPoint(0,$axis->{"ymin"},$image,$axis);
! 161: ($x2,$y2) = &transformPoint(0,$axis->{"ymax"},$image,$axis);
! 162: $image->line($x1,$y1,$x2,$y2,$black);
! 163: }
! 164:
! 165: sub drawtics{
! 166: my ($htic_every,$vtic_every) = @_;
! 167: my ($width,$height) = $image->getBounds();
! 168:
! 169: $ticwidth = ($width > 99 ? 10 : int($width /10) + 1);
! 170: $ticheight = ($height > 99 ? 10 : int($height/10));
! 171:
! 172: # Do tics along y-axis
! 173: for ($ntic = 0; $ntic <=int($axis->{"ylen"}/$vtic_every); $ntic++){
! 174: my ($x1,$y1) = &transformPoint(0,$axis->{"ymin"}+$ntic*$vtic_every);
! 175: my ($x2,$y2) = &transformPoint(0,$axis->{"ymin"}+$ntic*$vtic_every);
! 176: $x1 -= $ticwidth;
! 177: $x2 += $ticwidth;
! 178: $image->line($x1,$y1,$x2,$y2,$black);
! 179: }
! 180: # Do tics along x-axis
! 181: for ($ntic = 0; $ntic <=int($axis->{"xlen"}/$htic_every); $ntic++){
! 182: my ($x1,$y1) = &transformPoint( $axis->{"xmin"}+$ntic*$htic_every,0);
! 183: my ($x2,$y2) = &transformPoint( $axis->{"xmin"}+$ntic*$htic_every,0);
! 184: $y1 -= $ticheight;
! 185: $y2 += $ticheight;
! 186: $image->line($x1,$y1,$x2,$y2,$black);
! 187: }
! 188: }
! 189:
! 190: sub drawcurve{
! 191: my ($X,$Y) = @_;
! 192: for($i=0;$i< (@$X-1);$i++) {
! 193: ($x1,$y1) = &transformPoint($X->[$i ],$Y->[$i ]);
! 194: ($x2,$y2) = &transformPoint($X->[$i+1],$Y->[$i+1]);
! 195: $image->line($x1,$y1,$x2,$y2,$black);
! 196: }
! 197: }
! 198:
! 199: sub frame{
! 200: # Draw a frame around the picture.
! 201: my ($xoffset,$yoffset) = @_;
! 202: $xoffset = $xoffset || 1;
! 203: $yoffset = $yoffset || $xoffset;
! 204: my ($width,$height) = $image->getBounds();
! 205: $image->rectangle($xoffset-1,$yoffset-1,$width-$xoffset,$height-$yoffset,$black);
! 206: }
! 207:
! 208: sub drawstring{
! 209: # Write some text on the image.
! 210: my ($text,$x,$y,$color,$fontName) = @_;
! 211: $font = gdGiantFont if (lc($fontName) eq "giant" ||
! 212: lc($fontName) eq "huge" );
! 213: $font = gdLargeFont if (lc($fontName) eq "large");
! 214: $font = gdMediumBoldFont if (lc($fontName) eq "medium");
! 215: $font = gdSmallFont if (lc($fontName) eq "small");
! 216: $font = gdTinyFont if (lc($fontName) eq "tiny");
! 217: if (! defined($font)) {
! 218: $font = gdGiantFont;
! 219: $text = "Font size error!";
! 220: }
! 221: ($x,$y) = &transformPoint($x,$y);
! 222: $image->string($font,$x,$y,$text,$color);
! 223: }
! 224:
! 225:
! 226:
! 227:
! 228:
! 229:
! 230:
! 231:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>