DelphiFAQ Home Search:

Greating GIF, JPEG or PNG images with perl

 

comments6 comments. Current rating: 5 stars (2 votes). Leave comments and/ or rate it.

Question:

I need to create a chart with statistical numbers for my web site. How can I do this?

Answer:

If you have perl and module GD installed then you can create the graphic on the fly as the page gets requested or maybe once every 3 hours, just as you need it.

The example below should get you started with GD. It creates a PNG file. For statistics, PNG is more suitable than JPEG. The lossless compressed PNG file will be of better quality than the JPEG and even be smaller. JPEG is more suitable for photos.
use GD;

$HEIGHT = 480;
$WIDTH  = 800;

open(PNGFILE, ">/var/www/stats/usage.png") || die "Cannot open usage.png for write: $!\n";

binmode PNGFILE;

$MAXX = &ddiff($t_y,$t_m,$t_d,2003,1,0);
$MAXY   = 2000;
$XOFFSET= 30;
$YOFFSET= 60; # for agenda


$im = new GD::Image($WIDTH, $HEIGHT);
$black = $im->colorAllocate(0, 0, 0);
$red = $im->colorAllocate(255, 0, 0);
$silver = $im->colorAllocate(192, 192, 192);
$green = $im->colorAllocate(0, 255, 0);
$yellow = $im->colorAllocate(255, 255, 0);
$blue = $im->colorAllocate(0, 0, 255);
$white = $im->colorAllocate(255, 255, 255);
$im->setStyle($silver, $silver, gdTransparent, gdTransparent, gdTransparent);

# numbers to the left from 0 to MAXY

$y1=0;
while ($y1<=$MAXY) {
  $im->string(gdSmallFont, 5, ($HEIGHT-$YOFFSET)-$y1*($HEIGHT-$YOFFSET)/$MAXY, $y1, $silver);
  $y1 = $y1 + ($MAXY/5);
}
$x1=0;
$imonth=0;
$im->setStyle($black, $black, $black, $silver, $silver, $silver);
while ($x1<$MAXX) {
  $nn=$x1-$monthdays[$imonth]+1;
  $cx = $XOFFSET + $x1 * ($WIDTH-$XOFFSET)/$MAXX;
  if ($x1>=$monthdays[$imonth+1]) {
    $imonth=$imonth+1;
    $nn=$x1-$monthdays[$imonth]+1;
  }
  $mname = $monthnames[$imonth];
  if ($nn<10) { $nn = '0' . $nn; }
  $im->stringUp(gdSmallFont, $cx-10, $HEIGHT-5, "$nn.$mname", $silver);
  $im->line($cx,$HEIGHT-$YOFFSET,$cx,0,gdStyled);
  $x1 = $x1 + 5;
}
$im->line($XOFFSET,$HEIGHT-$YOFFSET,$WIDTH,$HEIGHT-$YOFFSET,$silver);
$im->line($XOFFSET,$HEIGHT-$YOFFSET,$XOFFSET,0,$silver);

open(FILE1, $FILENAME_USAGETXT);
$output = '';
$lasty1=$lasty2=$lasty3=$HEIGHT-$YOFFSET;
$lastx1=$XOFFSET;
$firstday = $lastday = '';
while ($line = <FILE1>) {
  $line =~ /(.*)\:(.*)\,(.*)\,(.*)/;
  $dat = $1;
  $n1 = $2;
  $n2 = $3;
  $n3 = $4;
  if (!$firstday) { $firstday = $dat; }

  # plot the graphic..

  $y1 = $HEIGHT - $YOFFSET - $n1 * ($HEIGHT-$YOFFSET)/$MAXY;
  $y2 = $HEIGHT - $YOFFSET - $n2 * ($HEIGHT-$YOFFSET)/$MAXY;
  $y3 = $HEIGHT - $YOFFSET - $n3 * ($HEIGHT-$YOFFSET)/$MAXY;

  $dat =~ /([\d]+)\-([\d]+)\-([\d]+)/;
  $a_y = $1; $a_m = $2; $a_d = $3;
  $x1 = ($a_y-2003) * 365 + ($a_m-1) * 30 + $a_d;

  $cx = $XOFFSET + $x1 * ($WIDTH-$XOFFSET)/$MAXX;

  if (!$lasty1) {
    $lasty1=$y1;
    $lasty2=$y2;
    $lasty3=$y3;
  }

  $im->setStyle($red, $red, $red, $white, $white, $white);
  $im->line($lastx1,$lasty1,$cx,$y1,gdStyled);
  $im->setStyle($blue, $blue, $blue, $white, $white, $white);
  $im->line($lastx1,$lasty2,$cx,$y2,gdStyled);
  $im->setStyle($yellow, $yellow, $yellow, $white, $white, $white);
  $im->line($lastx1,$lasty3,$cx,$y3,gdStyled);

  $lasty1=$y1;
  $lasty2=$y2;
  $lasty3=$y3;
  $lastx1=$cx;
} # while days..

$lastday = $dat;
$im->string(gdSmallFont, $XOFFSET+5, 20, "Zeitraum: $firstday - $lastday", $white);

print PNGFILE $im->jpeg || die "Error writing to PNG file: $!\n";
close (PNGFILE);
close(FILE1);
} # end of drawing the graphic



#==============================================================================
# difference between 2 dates:
# 2003-8-1   and    2003-7-29   -->
# ddiff(2003,8,1,2003,7,29) = 3
sub ddiff {
  local($ny,$nm,$nd,$oy,$om,$od) = @_;
  return ($ny-$oy) * 365 + $monthdays[$nm-1]-$monthdays[$om-1] + ($nd-$od);
}

Content-type: text/html

Comments:

2006-01-04, 13:30:04
anonymous from United States  
rating
good
2008-09-17, 16:40:06
anonymous from United States  
There's a typo in the code - you need to remove the line that contains 'end of drawing the graphic'. The right curly brace that begins the line is unmatched.

Also, the line that prints out the graphic to the output file is writing a JPG file, not a PNG. Do this to get a PNG file:

print PNGFILE $im->png || die 'Error writing to PNG file: $!\n';

Other than that, very nice code. Thank you!

2009-12-31, 03:55:56
anonymous from India  
HAPPY NEW YEAR
2010-01-02, 07:44:23
btpkhzhf from Germany  
rating
2015-02-01, 07:46:06
anonymous from Venezuela  
There's a terrific amount of knelowdge in this article!
2015-02-03, 19:20:50
anonymous from United States  
imho there's a slightly betetr way and more efficient..you actually build all your assets in flash and convert them to movieclips/sprites by clicking the F8 (each asset at a time), then when converting it -choose export to ActionScript , after doing that you need to check the export swc in the publish settings panel and then include this entire virtual library in your flex project (same as you did), you then only need to access those assets as first-class citizens, you even get code completion for nested sprites/movieclips. http://kiryurnb.com [url= http://utsykeirq.co..eirq[/url] [link= http://upvzyb.com]u..zyb[/link]

 

 

NEW: Optional: Register   Login
Email address (not necessary):

Rate as
Hide my email when showing my comment.
Please notify me once a day about new comments on this topic.
Please provide a valid email address if you select this option, or post under a registered account.
 

Show city and country
Show country only
Hide my location
You can mark text as 'quoted' by putting [quote] .. [/quote] around it.
Please type in the code:

Please do not post inappropriate pictures. Inappropriate pictures include pictures of minors and nudity.
The owner of this web site reserves the right to delete such material.

photo Add a picture: