N342 Dynamic Server Graphics

Modified

Generating Graphics on the Fly

Overview

Graphics generated from dynamic data or user input is an effective means of communicating. There are two main approaches:

Most commonly, graphic files are generated on the server in some standard format and sent to the browser for rendering. The standard format of an image file is:

For example, the image at right would be sent to the browser as:

Content-type: image/png

‰PNG

IHDR @ FMY )PLTE     € @ €@ €€@ € ` `€`€ € @€0`€€` @@@@€ €€` €``€`€ ` @€` ` ` € € €` €``` @@ @€`€ `€``€€€€@ € €€€     €€` €`€ €`@ @@€€`€€  €  `` €   €       € € €@ €@€€`€`€€ €@ @ ` p €T&s tIDATxœٺ‚0 „ ”–.I…™ 4Oq!" A A A 4ֵw sk @‘V@ K `tŸ/BS{j_ Z )R‹6’ D{ Qš%r*7; s€EC*/bб› 20xE‰ѥs9T ~ H zŠM l #W4 N4) 0‹ƒ^z X€?~[* Hœx @†#cz-d‚ n=!5Ž{}f M ~$ #} †!C' y ˜…7z¼ 8 @#c̲o}; 2'9č &F '-ˆ ( = –  ߫Gb‰  6 @ 0k…qQYl‡! ȫ‰ Ž% 8 ” ‘ ‘24 ? {QI– Ž‹=-&D @Ž €:9u h4< ; 1L p h - –,B ‡ q €cL€‚š .[qj ` xZŠ\€_Ej"B€Ž<X šˆ=…$… X‰ PJœ PP JV3D €‡5 3 Ph   €B 2 Ot ϣ qG€ @mCkˆ 9 P C \ ‰ †ž ` 0' M †e%W!k €^5 € Gb=S5 ]X   f€_nf y x-† #-„CMD/YSƒ „ P( j@€e
C  0 * @o Ov ™Gz €BǨ ‰ X:OD•G'ƒ5o' €”u Œ* g€…
j"AU8 Zˆ vD €u] 9OV•G׏1Ÿ ƒt& €2 œ‹W9E s9@œ Pp €5Y €B
(4 ™V † @a MC3O'ر٣ ˏG €z 0'-€VX
(:k4Pr<t @+ƒKNZ cF’“ڏ‹ P" K Ph  " f
7   P“9Bh < )\Od@€ 9)‹ €? `r sy" 3< †B)(j‰cg p y"M ϶ ˜:O)6ºi iŠx6  g P— ,<Š  r X_ €Нx  0
C<  J 6  0.><” 5‘%>"} €‰Z ™ `%%G€—‹ oI k"‰‰(6\k $^O$Y I]Oq _j/k^' €–AMdY 3P;ٹ ֯' €4e'b P! “ S œ&@9 rs;@œ Ph˜ ` ` Ph @'@d 0 k D vš ?‰ ^{ ˜‰„€c %ƒvMq _R} b &B h1:)@œšk"1 HR&rG€Uƒ7 d/m ^œ R s ] G7 HJ ^ iZ€FčC   €Bt }‘*zM u ‚2@Y XŽš’‰œ"Z$d ;k" €fmC˜CŒ!„nM `H&r7€ ƒnMD 9 ǡM › x<   B  Ž …†.  l C d4#O[ C č šŽ   —0 u[ † Œ CŰF| ’(ˆ 9;0l p ˜4” nv < )5? —A3†Bn UF —EqR 5 … @‘ ‚ ‚ŒB.N~5uGLŽ8TžˆPďk2 qIm‚ң—Y( 19P
gƒ_še-‰`Š]… U“ › 5 B|qŽƒ cy"z 4 Z q‚ D vaI@ձDhŽ: A A A U  L.$~ IENDB`‚

 

gd - The gd library can produce png files that most current browsers can render. The gd library is callable from C programs allowing incorporation of dynamically generated graphics into CGI programs. The following is a simple example of a program that draws a white diagonal line on a black background. Note that HTTP header files are included to inform the browser as to the format of the image file.

Further information - The source for the gd library is at http://www.boutell.com/gd/ along with details of its use. The following example includes a zip file with all the necessary files to use the gd library from C or C++.
 
gd Library use in C
simplegd.c

#include "gd.h"
#include <stdio.h>
#include <io.h>
#include <fcntl.h>

int main() {

 gdImagePtr im;          /* Declare the image */

 int white, black;         /* Declare color indexes */

 im = gdImageCreate(64, 64);                                  /* Allocate the image: 64 pixels across by 64 pixels tall */

 black = gdImageColorAllocate(im, 0, 0, 0);             /* Allocate the color black (red, green and blue all minimum).
                                                                                    Since this is the first color in a new image, it will
                                                                                    be the background color. */
 white = gdImageColorAllocate(im, 255, 255, 255); /* Allocate the color white (red, green and blue all maximum). */

 gdImageLine(im, 0, 0, 63, 63, white);                      /* Draw a line from the upper left to the lower right,
                                                                                   using white color index. */

 printf( "Content-type: image/png\r\n\r\n");         /* Print HTTP header */

 _setmode( _fileno( stdout ), _O_BINARY );           /* Setmode for stdout to binary, necessary for 
                                                                                   Windows not to convert \n to \r\n */

 gdImagePng(im, stdout);                                          /* Output the image to stdout in PNG format. */

 gdImageDestroy(im);                                               /* Destroy the image in memory. */
}


Exercise -1 - gd 

  1. Download zip file with libraries, simplegd.c, and project file for VC++
  2. Unzip to any directory, say gd.
  3. Point Windows Explorer to the gd.dsw file to use as project file in VC++.
  4. In VC++ enter: Build | gd.exe
  5. Move the \gd\Debug\gd.exe to a virtual drive, say Graphics.
  6. In a browser enter URL: http://localhost/Graphics/gd.exe


Command line compiling, linking and running simplegd.cpp
 
C:\"Program Files\Microsoft Visual Studio\VC98\Bin\Vcvars32.bat" 
cl /c simplegd.c /Fogd.obj
link /NODEFAULTLIB:msvcrt gd.obj gd.lib libpng.lib zlib.lib
gd

URL - http://localhost/Graphics/gd.exe assuming gd.exe in virtual directory Graphics.

Controlling Programs from Perl

Perl can control other programs that execute at the command line using standard input and output.  Essentially the Perl executes the program, supplying input and receiving output back using pipes or redirection. For example, using the Environment.Cpp program to print environment variables to standard output:
 
Environment.cpp 

#include <iostream.h> 

void main(int argc, char *args[], char *envp[]) { 
  cout << "Content-type: text/html\n\n"; 

  for (int i=0; envp[i] != NULL; i++) 
      cout << envp[i] << "<br>\n"; 
  }
It can be executed and output piped to a Perl program by: open(FILE,"environment.exe |");. The complete program to execute and print the output from Environment.Exe is:
 
Pipe.pl 

open(FILE,"environment.exe |");

while ( <FILE> ) {
        print;
}
The | is the pipe operator, in this case piping output of Environment.exe to FILE. Placed in front of a program (e.g. open(FILE,"| environment.exe");), input is piped to the program from FILE. Though this example is trivial, it does illustrate how another program, Environment.Exe in this case, can be executed and output captured (or input given) for another program. In this example the Environment.Exe output is input by the Perl program and can be used as any other string input to the Perl program. As a more useful example, the following illustrates how a Perl CGI program can control a graphics program to send dynamic graphics to a browser.

Fly - A simple graphics language called Fly has been implemented using an earlier version of the gd library, hence the use of GIF encoding of graphics files rather the PNG. The language name comes from on the fly graphics. The Fly language programs can be run from the command prompt to produce a GIF file or a. A more interesting application for us is to wrap a Fly program inside of a Perl program to produce a CGI program that generates graphics on the fly back to a browser.

The Perl example below creates a GIF graphic, writes the HTTP header Content-type: image/gif and the binary GIF to standard output. The browser receives the header and interprets the following data as a GIF image. Fly is not very useful as a CGI directly since it does not have any control or data structures. The Perl program serves as a wrapper for the Fly program and can do the program control. The Perl program first writes all the Fly statements to a file named c:\temp\fly.$$ then invokes the Fly interpreter on that file using the statement open(FOO,"$flyprog -q -i $infile |"); which pipes the Fly output to the file FOO. Because DOS (Win95, etc.) automatically converts \n to \r\n all \r\n in the FOO file must be converted back to \n before sending to the browser.

Further information - The complete Fly can be downloaded from http://www.unimelb.edu.au/fly/ . If you plan to get very serious about producing on the fly graphics either use the gd library in C++ or get the GD.pm for Perl.
 
Fly graphics
Fly in Perl cgiGIF.pl
 
 $flyprog = "c:\\Fly\\fly";

 $infile = "c:\\temp\\fly.$$";

 open(FLY,"> $infile");

 # Output the following to the FLY c:\\temp\\fly.$$ file
 print FLY << "End";
new
size 256,256
fill 1,1,255,255,255
circle 128,128,180,0,0,0
fill 128,128,255,255,0
arc 128,128,120,120,0,180,0,0,0
circle 96,96,10,0,0,0
circle 160,96,10,0,0,0
fill 96,96,0,0,0
fill 160,96,0,0,0
string 0,0,0,10,240,giant,Hello, World!
string 0,0,0,100,10,medium,Don't worry, be Happy!
End

 close(FLY);

 open(FOO,"$flyprog -q -i $infile |");# Execute FLY on above to
                                      # capture graphics to FOO
 binmode(STDOUT);
 binmode(FOO);

 print "Content-type: image/gif\n\n";

 while ( $status = read(FOO, $data, 4096)){# Write graphics file
  $_ = $data;                              # back to client
  s/\r\n/"\n"/eg;                          # after \r\n to \n
  print;
 }
 close(FOO);
URL - http://localhost/Graphics/cgiGIF.pl

    Assumptions:
          cgiGIF.pl in real directory c:\Graphics
          Fly interpreter in real directory c:\Fly




DOS.Fly program - Reads dos.fly program and writes to hello.gif

c:> fly -q -o hello.gif < dos.fly

new
size 256,256
fill 1,1,255,255,255
circle 128,128,180,0,0,0
fill 128,128,255,255,0
arc 128,128,120,120,0,180,0,0,0
circle 96,96,10,0,0,0
circle 160,96,10,0,0,0
fill 96,96,0,0,0
fill 160,96,0,0,0
string 0,0,0,10,240,giant,Hello, World!
string 0,0,0,100,10,medium,Don't worry, be Happy!

Exercise 0 - Controlling Fly in Perl

  1. Download the Fly program to directory Fly.
  2. Copy and paste the Perl program to a virual drive.
  3. Execute the Perl program from a browser.
  4. Consult the Fly documentation.
  5. Modify the Fly program embedded in the Perl to draw a 100x100 square.
  6. Plot the {x,y}pairs as a line graph within the 100x100 square of: {10, 10}, {30,40}, {50, 90}, {70, 20}, {90, 80}.
  7. Where is the point on the screen {0,0}?
Graphing Data - A common use of graphics is for visual presentation of data, for example, when demonstrating a relationship between two sets of numbers an xy data plot is often used. The following uses the gd library to implement a basic xy data plot. A library of the xy plot function can be downloaded and used to easily implement PNG graphics as CGI programs as described below.
 
XY Data Plotter C++ CGI
xy Data Plotter

#include "gd.h"
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <math.h>
#include <string.h>
#include "gdfontt.h"
#include "gdfonts.h"

int  MINX=0, MINY=0, MAXX=250, MAXY=150;                // Default graphic size
double     Wxl, Wxr, Wyb, Wyt, Vxl, Vxr, Vyb, Vyt;
double     WVxm,WVxa,WVym,WVya;
gdImagePtr im;                                             // Declare the image 
int     green, black;                                      // Declare color indexes 

void SetSize(int minx, int miny, int maxx, int maxy) {     // Set size of graphics in pixels
 MINX=minx; MINY=miny; MAXX=maxx; MAXY=maxy;
}

void SetWindowViewport() {                                 // Determine constants for
  if (Wxr != Wxl)                                          // WorldtoScreen transform
  WVxm = (Vxr-Vxl)/(Wxr-Wxl);
  else WVxm = 0.0;
  WVxa = Vxl-Wxl*WVxm;
  if (Wyt != Wyb)
  WVym = (Vyt-Vyb)/(Wyt-Wyb);
  else WVym = 0.0;
  WVya = Vyb-Wyb*WVym;
}

double xWorldToScreen(double x){                            // Transform x World to x Screen
  return WVxm*x+WVxa;
}

double yWorldToScreen(double y){                            // Transform y World to y Screen
  return WVym*y+WVya;
}

void SetViewPort(int x1, int y1, int x2, int y2){           // Define screen viewport
//                          Adjust y1 & y2 to (0,0) bottom left from screen (0,0) at top left }
  Vxl=x1;  Vxr=x2;  Vyb=MAXY-y1;  Vyt=MAXY-y2;
  SetWindowViewport();
}

void SetWindow(double x1, double y1, double x2, double y2) {// Define real-world window
  Wxl=x1;  Wxr=x2;   Wyb=y1;   Wyt=y2;
  SetWindowViewport();
}

void ShowLine(double x1, double y1, double x2, double y2){  // Display line on device
 gdImageLine(im,(int)xWorldToScreen(x1), (int)yWorldToScreen(y1),
       (int)xWorldToScreen(x2), (int)yWorldToScreen(y2), black);
}

void initializeGraphics() {
 SetViewPort(0,0,MAXX,MAXY);
 im = gdImageCreate(MAXX+MINX+5, MAXY-MINY+2*gdFontTiny->h);  /* Allocate the image */

 green = gdImageColorAllocate(im, 0, 255, 255);         /* Allocate the color green 
                                                           (red, green and blue all minimum).
                                                           Since this is the first color in 
                                                           a new image, it will
                                                           be the background color. */
 black = gdImageColorAllocate(im, 0, 0, 0);             /* Allocate the color black (red, 
                                                           green and blue all maximum). */
}

void close() {
 printf( "Content-type: image/png\r\n\r\n");             /* Print HTTP header */

 _setmode( _fileno( stdout ), _O_BINARY );               /* Setmode for stdout to binary, necessary for 
                                                            Windows not to convert \n to \r\n */

 gdImagePng(im, stdout);                                 /* Output the image to stdout in PNG format. */

 gdImageDestroy(im);                                     /* Destroy the image in memory. */
}

void xyPlot(double x[], double y[], int nValues, char xaxis[], char yaxis[]) {
 const int NINTERVALS=10;
 unsigned char *buffer = (unsigned char *)(new char[20]);
 double xmin, ymin, xmax, ymax;
 double xinterval, yinterval;
 int i;

 xmin=x[0]; xmax=xmin; ymin=y[0]; ymax=ymin;
 for (i=0; i<nValues; i++) {
  xmin = x[i] < xmin ? x[i] : xmin;
  ymin = y[i] < ymin ? y[i] : ymin;
  xmax = x[i] > xmax ? x[i] : xmax;
  ymax = y[i] > ymax ? y[i] : ymax;
 }

 xinterval = fabs(xmax-xmin)/(NINTERVALS-1);
 yinterval = fabs(ymax-ymin)/(NINTERVALS-1);

 initializeGraphics();

 SetWindow(xmin,ymin,xmax,ymax);                      // Graph region in world coordinates
 SetViewPort(MAXX/6 , MAXY/5, MAXX, MAXY);

 for (i=0; i<nValues-1; i++) 
  ShowLine(x[i],y[i],x[i+1],y[i+1]);
 for (i=0; i<nValues; i++)
  gdImageRectangle(im, (int) xWorldToScreen(x[i])-2, (int) yWorldToScreen(y[i])-2,
        (int) xWorldToScreen(x[i])+2, (int) yWorldToScreen(y[i])+2, black);

 ShowLine(xmin,ymax,xmin,ymin);
 ShowLine(xmin,ymin,xmax,ymin);                       // Axis

 SetWindow(xmin,ymin,xmax,ymin+yinterval);
 SetViewPort(MAXX/6,0,MAXX,MAXY/5);

 for (i=0; i<NINTERVALS; i++) {                                   // X tics
  sprintf( (char *)buffer, "%.2f", xmin+xinterval*i );
  gdImageStringUp(im, gdFontTiny, (int) xWorldToScreen(xmin+xinterval*i) - gdFontSmall->h/2, 
           (int) yWorldToScreen(ymin+yinterval)
           +(strlen((const char *)buffer) * gdFontTiny->w), 
           buffer, black);
 }

 SetWindow(xmin,ymin,xmin+xinterval,ymax);
 SetViewPort(0,MAXY/5,MAXX/6,MAXY);

 strcpy((char *) buffer, xaxis);
 gdImageString(im, gdFontTiny, 
          (int) xWorldToScreen(xmax/2)-(gdFontTiny->h*strlen((const char *) buffer)),
          (int) yWorldToScreen(ymin)+4*(gdFontTiny->h), buffer, black);
 strcpy((char *) buffer, yaxis);
 gdImageStringUp(im, gdFontTiny, (int) xWorldToScreen(xmin),
                     (int) yWorldToScreen(ymax/2)+2*(gdFontTiny->h), buffer, black);
 for (i=0; i<NINTERVALS; i++) {                                    // Y tics
  ShowLine(xmin+xinterval/4,ymin+yinterval*i,xmin+xinterval,ymin+yinterval*i);
  sprintf( (char *)buffer, "%.2f", ymin+yinterval*i );
  gdImageString(im, gdFontTiny, (int) xWorldToScreen(xmin+xinterval/4), 
           (int) yWorldToScreen(ymin+yinterval*i-yinterval/nValues),
           buffer, black);
 }
 close();
}

void main() {
 double x[12] = { 1,2,3,4,5,6,7,8,9,10,11,12};
 double y[12] = { 1,2,3,4,5,6,-6,-5,-4,-3,-2,-1};

 xyPlot(x,y, 12, "X-Axis", "Y-Axis");
}

URL - http://localhost/Graphics/xy.exe

Example using XY data plotter in an HTML Document

Using the HTML IMG tag the CGI graphic can be placed anywhere that a regular image would within 
an HTML document. Assuming the xy data plotter CGI were on virtual 
drive Graphics the following tag would display the data plot produced by xy.exe within an HTML document:

<img SRC="http://localhost/graphics/xy.exe">
 

Use - A simple xy plot library xy.lib can be used to generate xy data plots by calling the xyPlot function. In the current version, the main function must be written to specify:

  • x data
  • y data
  • number of data points to plot
  • label for x-axis
  • label for y-axis
The following plotted the above examples:
void xyPlot(double x[], double y[], int nValues, char xaxis[], char yaxis[]);
void SetSize(int minxx, int miny, int maxx, int maxy);

void main() {
  double x[12] = { 1,2,3,4,5,6,7,8,9,10,11,12};
  double y[12] = { 1,2,3,4,5,6,-6,-5,-4,-3,-2,-1};

  SetSize(0, 0, 250, 150);
  xyPlot(x,y, 12, "X-Axis", "Y-Axis");
 }



Example - To run the above example:
  1. Download zip file with xy library, test.cpp, and project file for VC++
  2. Unzip to any virtual directory with execute rights, perhaps Graphics.
  3. In a browser enter URL: http://localhost/Graphics/Debug/xyPlot.exe
Compiling
  1. Download zip file with xy library, test.cpp, and project file for VC++
  2. Unzip to any virtual directory, perhaps Graphics.
  3. Point Windows Explorer to the xyPlot.dsw file to use as project file in VC++.
  4. Make any changes to the test.cpp file.
  5. In VC++ enter: Build | xyPlot.exe
  6. In a browser enter URL: http://localhost/Graphics/Debug/xyPlot.exe
Command line compiling, linking and running test.cpp as xyPlot.exe
 
C:\"Program Files\Microsoft Visual Studio\VC98\Bin\Vcvars32.bat"
cl /c test.cpp /FoxyPlot.obj 
link /NODEFAULTLIB:"MSVCRT" /NODEFAULTLIB:"LIBC" /out:Debug/xyPlot.exe test.obj gd.lib libpng.lib zlib.lib xy.lib
debug\xyPlot

Hints

  • Because a box is placed at each data point (x,y) pair, large data sets will run the boxes together creating an unsightly, fat line. You're welcome to change the xy source to not do boxes.
  • In VC++, if the linker complains about multiply defined functions, follow its advice and enter: 
    • Profile | Settings | Link 
    then add to the Project Options
        /NODEFAULTLIB:MSVCRT /NODEFAULTLIB:LIBC
  • Larger or smaller PNG images can be produced by changing the program line:
      •  
        SetSize(0, 0, 250, 150);
  • The browser must be told by the server (the xyPlot CGI in this case) that the file its receiving is an image/png. This is done in the C++ program before the graphics file is written to standard output by:
      • printf( "Content-type: image/png\r\n\r\n"); 

Exercise 1 - Dynamic Graphics

  1. Download zip file with xy library, test.cpp, and project file for VC++
  2. Unzip to any virtual directory with execute rights, perhaps Graphics.
  3. Then to test, in a browser enter URL: http://localhost/Graphics/Debug/xyPlot.exe
  4. Create an HTML file with an image link to the xyPlot.exe file as in: <img SRC="http://localhost/graphics/xyPlot.exe">
  5. In Visual C++, open xyPlot.dsw and edit the C++ test.cpp file.
  6. Change the graph size and data, rebuild, and test again in the browser.
  7. Make the image a link to the URL of this page.
Example URL Data - The following uses the xy.lib to take y-axis data from the URL and plot.
 
Plotting URL data
test.cpp

#include <stdlib.h>

void xyPlot(double x[], double y[], int nValues, 
            char xaxis[], char yaxis[]);
void SetSize(int, int, int, int);

void main(int argc, char *args[]) {
  double x[100];
  double y[100];

  SetSize(0,0,200,200);
  for (int i=1; i<argc; i++) {
          y[i-1]=atof(args[i]);
          x[i-1]=i;
  }
  xyPlot(x,y, argc-1, "X", "Y");
}
http://localhost/Graphics/xyplot.exe?15+27+5+7+-8

Example Form Data - The following uses the xy.lib to take y-axis data from a form text box and plot.
 
Plotting Posted User Entered Data
test.cpp

#include <iostream.h>
#include <stdlib.h> 
#include <stdio.h> 

void xyPlot(double x[], double y[], int nValues, 
            char xaxis[], char yaxis[]);
void SetSize(int, int, int, int);

void main() {
  double x[256];
  double y[256];
  float a;
  int n=0, length;
  char input[4096], remainder[4096];

  sscanf( getenv("CONTENT_LENGTH"), "%d", &length); 
  for (int i=0; i<length; i++) cin >> input[i];
  input[length]='\0';
  sscanf(input, "userinput=%s", remainder);

  n=0;
  while(sscanf(remainder,"%f+%s",&a,remainder) == 2) {
     y[n]=a;
     x[n]=n;
     n++;
  }
  sscanf(remainder,"%f",&a);
  y[n]=a;
  x[n]=n;
  n++;

  SetSize(0,0,200,200);
  xyPlot(x, y, n, "X", "Y");
}
xyplot.htm

<form method=post action="http://localhost/Graphics/xyplot.exe">
<input type=text name=userinput>
</form>



Browser




http://localhost/Graphics/xyplot.exe

Exercise 2 - Graphing User Data

The two examples above graphs user data appended to the URL or entered in a form text box. The first four steps below are identical to Exercise 1.
  1. Download zip file with xy library, test.cpp, and project file for VC++
  2. Unzip to any virtual directory, perhaps Graphics.
  3. Then to test, in a browser enter URL: http://localhost/Graphics/Debug/xyPlot.exe
  4. In Visual C++, open xyPlot.dsw and edit the C++ test.cpp file.
  5. Copy and paste either of the example code above. For the Form Data example you'll also need to copy the HTML file.
  6. Test using different data in the browser.

gnuplot

For standard graphical displays such as plotting, bar graphs, etc. gnuplot is a good choice. It runs on most computer platforms, produces file formats understandable by browsers, and can be executed from Perl to produce on the fly graphics such as the following sine wave (the example runs under SUSE Linux directory locations as http://localhost/cgi-bin/sine.pl). gnuplot is freely available at http://www.gnuplot.info. The script runs gnuplot, piping the plotting commands in and sending graphical output back to browser. The HTML needed to run would request the output of executing the Perl CGI script named sine.pl:

    <img src="sine.pl">
 

sine.pl for Unix

#!/usr/bin/perl

$GNUPLOT = '/usr/bin/gnuplot';

$|=1;                     # no buffering
binmode STDOUT;   # binary output  

print "Content-type: image/png\n\n";

open(GRAPH,"| $GNUPLOT") || die;
print GRAPH <<END;
set terminal png
set size 0.5, 0.5
plot [-16:16] sin(x)
END

close (GRAPH);

Note that the sine.pl must be in the Web server's cgi-bin and executeable.

Microsoft

The above example should work on most Web servers, it does not on Microsoft IIS, the problem seems to be with how IIS and Perl handle standard input and output. The gnuplot version used should NOT be the standard one with the graphical interface but the one compiled for DOS, a recent version is gp400DJ2.

The following is a less satisfactory work-around in which:

  1. The Perl script runs gnuplot.
  2. gnuplot reads the graphing commands from a file (which would be written by the Perl script) and writes the graphics to another file.
  3. Perl copies the graphics file to standard output, that is, back to the browser.

The sine.gp file contains the gnuplot commands.

The HTML to execute the Perl would be the same:

    <img src="sine.pl">

sine.pl for Microsoft

$GNUPLOT = 'C:\\gp400DJ2\\gnuplot.exe'; 

$|=1;            # no buffering
                     # execute gnuplot, read sine.gp for commands  
open(GRAPH,"|$GNUPLOT sine.gp") || die "Can't run gnuplot: $!\n";
close (GRAPH);
                     # input graphics file 
open( GRAPHFILE, "< sine.png" ) || die( "Can't open sine.png: $!\n" );

print "Content-type: image/png\r\n\r\n";

binmode GRAPHFILE; # Required for Microsoft OS
binmode STDOUT;
                      # copy graphics file to STDOUT
while ( $cb = read( GRAPHFILE, $data, 4096 ) ) {
   print $data;
}

close GRAPHFILE;
unlink GRAPHFILE;       # Delete graphics file

 

sine.gp

set terminal png
set output "sine.png"
set size 0.5, 0.5
plot [-16:16] sin(x)

 

Scalable Vector Graphics

What is SVG?

SVG History & Advantages

SVG 1.1 became a W3C Recommendation in January 2003.

Sun Microsystems, Adobe, Apple, IBM, and Kodak are some of the well-known organizations that have been involved in defining SVG.

Advantages of using SVG over other image formats (like JPEG and GIF):

SVG Shapes

SVG has some predefined shape elements:

The following chapters will explain each element, starting with the rect element.

The <rect> Tag

The <rect> tag is used to create a rectangle and variations of a rectangle shape.

As an example, copy and save the file as "rect1.svg".

<?xml version="1.0" ?>

<svg width="30" height="30">
       <rect width="30" height="10" style="fill:rgb(0,0,255); stroke-width:1; stroke:rgb(0,0,0)"/>
</svg>

Code explanation:

Copy and save the file as "rect1.htm", which loads and displays "rect1.svg".

<html>
  <body>

     <embed src="rect1.svg" width="40" height="40" type="image/svg-xml" />

  </body>
</html>

 

Another example

<?xml version="1.0"?>

<svg width="30" height="30">
    <rect x="20" y="20" width="25" height="25" style="fill:blue;stroke:pink;stroke-width:5; fill-opacity:0.1;stroke-opacity:0.9"/>
</svg>
 

Code explanation:

Another example, create a rectangle with rounded corners:

<?xml version="1.0"?>
<svg width="300" height="300" >
  <rect x="20" y="20" rx="20" ry="20" width="250" height="100" style="fill:red;stroke:black; stroke-width:5;opacity:0.5"/>
</svg>

Code explanation:

SVG <circle>

<?xml version="1.0" ?>

<svg width="60" height="60">
     <circle cx="20" cy="20" r="15" stroke="black" stroke-width="2" fill="red"/>
</svg>

Some examples

 

Further Information - None presently for xy, check documentation on gd for making changes to font sizes, etc.