データをGIFファイルに

"temp_chart.pl"




     1  #!/usr/local/bin/perl
     2  
     3  # "temp_chart.pl"
     4  
     5  # The following is a Perl version of the charting function. 
     6  # The Perl OR operator | can be used to combine 
     7  # any or all of these. 
     8  
     9  $chartBar = 1;
    10  $chartCross = 2;
    11  $chartLine = 4;
    12  
    13  # A function to draw a chart on the specified gd image. The
    14  # chart will occupy the entire image. The image should
    15  # be created first with gdImageCreate(). The "units"
    16  # string must be no longer than 100 characters! 
    17  #
    18  # chartDraw should be invoked with a GD.pm image object,
    19  # the chart type (see above), an array of X axis labels
    20  # (which can be empty), the unit of measurement
    21  # for the Y axis, and an array of numeric data values. 
    22  
    23  use GD;
    24  
    25  sub chartDraw
    26  {
    27          local($im, $t, *labels, $units, *data, *glabels, *gdata) = @_;
    28  
    29          $points = @data; 
    30          $gpoints = @gdata;
    31  
    32          # First, allocate colors. 
    33          $backgroundColor = $im->colorAllocate(192, 192, 192);
    34  
    35          # Set this as the transparent color for the GIF. 
    36          $im->transparent($backgroundColor);
    37  
    38          $borderColor = $im->colorAllocate(0, 0, 0);
    39  
    40          $textColor = $im->colorAllocate(0, 0, 0);
    41  
    42          $tickColor = $im->colorAllocate(64, 64, 64);
    43  
    44          if (! $points) {
    45                  # Nothing to draw! 
    46                  return;
    47          }
    48  
    49          $barColor = $im->colorAllocate(130,130 , 255);
    50          $bar2Color = $im->colorAllocate(180,180,255);
    51          $lineColor = $im->colorAllocate(255, 64, 64);
    52          $crossColor = $im->colorAllocate(0, 120, 0);
    53  
    54  
    55          # Second, find the range of the data. 
    56          $dataMin = 15;
    57          $dataMax = 35;
    58          $dataRange = $dataMax - $dataMin;
    59          $labelsMin = 0;
    60          $labelsMax = 24;
    60          $labelsMax = 24;
    61          $labelsRange = $labelsMax - $labelsMin;
    62  
    63  
    64          # Decide how much space is available. Start with all of it... 
    65  
    66          @imSize = $im->getBounds();
    67          $spaceX = $imSize[0];
    68  
    69          # The left edge is occupied by the Y axis labels and numbers,
    70          # plus a bit of space for aesthetic purposes... 
    71          $baseX = 0;
    72          if ($units ne "") {
    73                  $baseX += gdLargeFont->height;
    74          }
    75  
    76          $baseX += gdLargeFont->height + 2 +3;
    77  
    78          # Subtract that space from the space available for the graph... 
    79          $spaceX -= $baseX + 10;
    80  
    81          # Now compute the space available on the Y axis. 
    82          $spaceY = $imSize[1];
    83  
    84          $spaceY -= (gdLargeFont->height + 2 + 18);
    85  
    86          $baseY = 0;
    87  
    88          # Make sure we don't divide by zero. 
    89          if (!$dataRange) {
    90                  $dataRange = 1.0;
    91          }
    92  
    93          if (!$dataRange) {
    94                  $dataRange = 1.0;
    95          }
    96  
    97          # Discover how many Y-axis "ticks" are appropriate.
    98          # There should be at least two and no more than twenty, and
    99          # the step between ticks should be a power of ten. 
   100          $tick = 5.0 ** int(log($dataRange / 2.0) / log(10.0)); 
   101          $tickAccum = $tick * (int($dataMin / $tick) + 1);
   102  
   103          # Decide the divisor for labels. 
   104          # Powers of 1000 are familiar
   105          # to the user. 
   106          $divisor = 1.0;
   107          if (abs($dataMax) > abs($dataMin)) {
   108                  while (abs($dataMax) / $divisor >= 1000.0) {
   109                          $divisor *= 1000.0;
   110                  }
   111          } else {
   112                  while (abs($dataMin) / $divisor >= 1000.0) {
   113                          $divisor *= 1000.0;
   114                  }
   115          }
   116          # Draw the tick lines now, so they will appear
   117          # "behind" the graph. Also label the ticks
   118          # as often as is possible without crowding. 
   119  
   120  for ($i = 1; $i < 24; $i++){
   121  $im->line($baseX + $i*$spaceX/24.0, $baseY, $baseX + $i*$spaceX/24.0, $baseY + $spaceY, $bar2Color);
   122  }
   123  
   124  for ($i = 1; $i < 20; $i++){
   125  $im->line($baseX, $i*$spaceY/20.0, $baseX + $spaceX, $i*$spaceY/20.0, $bar2Color);
   126  }
   127  
   128          $first = 1;
   129          while ($tickAccum <= $dataMax) {
   130                  $y = $spaceY - ($spaceY * ($tickAccum - $dataMin) / $dataRange)
   131                           + $baseY; 
   132                  # Format the tick label, and see if there is enough
   133                  # space after the previous one to make room for
   134                  # a text label. 
   135                  $s = sprintf("%3.0f", $tickAccum / $divisor);
   136                  $w = gdLargeFont->width * length($s);
   137                  $textY = $y + $w / 2;
   138                  if ($first || ($textY < $lastLabel)) {
   139                          # Don't actually draw it unless it fits 
   140                          # in the image 
   141                          if (($textY - $w > $baseY) && 
   142                                  ($textY < ($spaceY + $baseY))) {
   143                                  $im->stringUp(gdLargeFont,
   144                                          $baseX - gdLargeFont->height,
   145                                          $textY, $s, $textColor);
   146                          }
   147                          # The extra two pixels are for aesthetic purposes 
   148                          $lastLabel = $y - $w / 2 - 2;
   149                          $first = 0;
   150                  }
   151  
   152                  $im->line($baseX, $y, $baseX + $spaceX, $y, $barColor);
   153                  $tickAccum += $tick;
   154          }
   155  
   156          # Now draw the graph. 
   157          for ($i=0; ($i < $gpoints); $i++) {
   158                  local($gx, $gy, $gw) = (0, 0, 0);
   159                  $gx = $spaceX * ($glabels[$i] - $labelsMin) / $labelsRange  + $baseX;
   160                  $gy = $spaceY - ($spaceY * ($gdata[$i] - $dataMin) / $dataRange)
   161                          + $baseY;
   162  
   163                  $im->line($gx - 2, $gy - 2, $gx + 2, $gy + 2, $crossColor);
   164                  $im->line($gx + 2, $gy - 2, $gx - 2, $gy + 2, $crossColor);
   165                  $lastX = $gx;
   166                  $lastY = $gy;
   167          }
   168          for ($i=0; ($i < $points); $i++) {
   169                  local($x, $y, $w) = (0, 0, 0);
   170                  $x = $spaceX * ($labels[$i] - $labelsMin) / $labelsRange  + $baseX;
   171                  $y = $spaceY - ($spaceY * ($data[$i] - $dataMin) / $dataRange) 
   172                          + $baseY; 
   173  
   174  
   175  
   176                  if ($t & $chartLine) {
   177                          if ($i) {
   178                                  $im->line($lastX, $lastY, $x, $y, $lineColor);
   179                          }
   180                  }
   181                  $lastX = $x;
   182                  $lastY = $y;
   183          }
   184  
   185          # Draw the border lines at left and bottom... 
   186          $im->line($baseX, $baseY, $baseX, $baseY + $spaceY, $barColor);
   187          $im->line($baseX, $baseY + $spaceY, 
   188                  $baseX + $spaceX, $baseY + $spaceY, $barColor);
   189  
   190          # Draw the border line at right..
   191          $im->line($baseX + $spaceX -1, $baseY + $spaceY,$baseX + $spaceX -1, $baseY, $barColor);
   192          for ($i = 1; $i < 8; $i++){
   193                  $im->line($baseX + $i*$spaceX/8.0, $baseY, $baseX + $i*$spaceX/8.0, $baseY + $spaceY, $barC
   194          }
   195          for ($i = 0; $i < 9; $i++){
   196                  $im->string(gdLargeFont,$baseX + $i*$spaceX/8.0-6,$baseY +$spaceY + 2,$i*3, $textColor);
   197          }
   198          $im->string(gdLargeFont,$baseX + 150,$baseY +$spaceY + 20,"Time (hour)", $textColor);
   199  
   200          # Label the Y axis (units) 
   201          if ($units ne "") {
   202                  local($h, $label) = ( 0 , "" );
   203                  if ($divisor != 1.0) {
   204                          $label = sprintf("%s x %2.0f", $units, $divisor);
   205                  } else {
   206                          $label = $units;
   207                  }
   208                  # Rotated 90 degrees 
   209                  $h = gdLargeFont->width * length($label);
   210                  $im->stringUp(gdLargeFont,
   211                          0, $baseY + ($spaceY / 2) + ($h / 2),
   212                          $label, $textColor);
   213          } else {
   214                  local($h, $label) = ( 0 , "" );
   215                  if ($divisor != 1.0) {
   216                          $label = sprintf("x%2.0f", $divisor);
   217                  } else {
   218                          $label = "";
   219                  }
   220                  # Rotated 90 degrees 
   221                  $h = gdLargeFont->width * length(label);
   222                  $im->stringUp(gdLargeFont,
   223                          0, $baseY + ($spaceY / 2) + ($h / 2),
   224                          $label, $textColor);
   225          }
   226  }
                        



SST_Labo's Home Page