521 lines
20 KiB
PHP
521 lines
20 KiB
PHP
<?php
|
|
/** \file include/plot_temp.php
|
|
* \brief DI webinterface plot temperature script.
|
|
* \author Rob Schalken, Core|Vision
|
|
* \version $Revision: 26247 $
|
|
* \date $Date: 2016-02-29 10:40:22 +0100 (Mon, 29 Feb 2016) $
|
|
*
|
|
* This file contains the temperature plot script
|
|
*/
|
|
|
|
/*
|
|
************************************************************************
|
|
**
|
|
** Display battery levels in a graph.
|
|
**
|
|
** Mandatory parameters, via "GET", all of which are retrieved from
|
|
** the database
|
|
** zkl - database ID of the ZKL to query
|
|
** logfile - sdcard,rpgmcount,startup of the logfile to plot
|
|
** and/or
|
|
** tmin,tmax - date/time of the time frame (the current time will
|
|
** be used if tmax is ommitted)
|
|
** Optional output options:
|
|
** w - width of the output image
|
|
** h - height of the output image
|
|
** hide_title - do not device id-code and date
|
|
** hide_info - do not show additional info
|
|
**
|
|
** Notes:
|
|
** - If both 'logfile' and a 'tmin'/'tmax' are specified, then the data
|
|
** from the logfile will be scaled to the specified time frame.
|
|
** - If _no_ 'logfile' is specified, all logfiles with data in the time
|
|
** frame will be shown.
|
|
** - Logfiles with an invalid date (i.e. 1970-1-1) are _never_ plotted.
|
|
**
|
|
************************************************************************
|
|
*/
|
|
|
|
require_once("graphics.php");
|
|
|
|
// Create temp plot and write to file
|
|
function plot_temp_graph($zkl, $start, $end, $log_files, $log_rt, $file, $transparent=1, $width=800, $height=600) {
|
|
GLOBAL $_PAGE_INFO;
|
|
|
|
// Download header
|
|
download_document_header("image/png", $file, "write_file", "plot_temp");
|
|
|
|
// temperature range
|
|
$T_max = 70;
|
|
$T_min = -25;
|
|
$T_range = $T_max - $T_min;
|
|
|
|
// create the image
|
|
$im = imagecreatetruecolor($width+5,$height);
|
|
if( function_exists("imageantialias") )
|
|
imageantialias($im, true);
|
|
$black = imagecolorallocate($im, 0, 0, 0);
|
|
$white = imagecolorallocate($im, 255, 255, 255);
|
|
$grey = imagecolorallocate($im, 192, 192, 192);
|
|
$lgrey = imagecolorallocate($im, 240, 240, 240);
|
|
$dgrey = imagecolorallocate($im, 128, 128, 128);
|
|
$green = imagecolorallocate($im, 0, 192, 0);
|
|
$lgreen = imagecolorallocate($im, 192, 255, 192);
|
|
$llgreen = imagecolorallocate($im, 248, 255, 248);
|
|
$dgreen = imagecolorallocate($im, 0, 160, 0);
|
|
$red = imagecolorallocate($im, 255, 0, 0);
|
|
$lred = imagecolorallocate($im, 255, 192, 192);
|
|
$dred = imagecolorallocate($im, 160, 0, 0);
|
|
$blue = imagecolorallocate($im, 0, 0, 224);
|
|
$dblue = imagecolorallocate($im, 0, 0, 160);
|
|
$purple = imagecolorallocate($im, 224, 0, 224);
|
|
$dpurple = imagecolorallocate($im, 160, 0, 160);
|
|
$font = 2; // 6x13
|
|
$bfont = 3; // 7x13 medium bold
|
|
$tfont = 1; // 5x8
|
|
|
|
//
|
|
// Colors and font to use
|
|
//
|
|
$bgcolor = imagecolorallocatealpha($im, 255, 255, 255, $transparent ? 127 : 0);
|
|
$bgcolor_transp = imagecolorallocatealpha($im, 255, 255, 255, 96);
|
|
$gridcolor = $black; // main grid and markers
|
|
$sgridcolor = $lgrey; // guides in the grid
|
|
$nextdaycolor = $grey; // next day line
|
|
$linecolor = array( 'on-board' => $blue, 'ntc' => $purple );
|
|
$zero_color = $lred; // 0 degrees line
|
|
$info_color = $red; // additional info
|
|
|
|
//
|
|
// Font selection (dependent on image size)
|
|
//
|
|
// labels and legenda
|
|
if( $width <= 320 || $height <= 240 ) {
|
|
$labelfont = 1;
|
|
$infofont = 1;
|
|
}
|
|
else if( $width >= 2048 || $height >= 1536 ) {
|
|
$labelfont = 5;
|
|
$infofont = 3;
|
|
}
|
|
else if( $width >= 1280 || $height >= 1024 ) {
|
|
$labelfont = 3;
|
|
$infofont = 2;
|
|
}
|
|
else {
|
|
$labelfont = 2;
|
|
$infofont = 1;
|
|
}
|
|
|
|
// Minimum time defined?
|
|
if (!strlen($start)) {
|
|
$tmin = $log_files[0]['tmin'];
|
|
}
|
|
else {
|
|
$tmin = strtotime($start);
|
|
}
|
|
|
|
// Maximum time defined?
|
|
if (!strlen($end)) {
|
|
$tmax = time();
|
|
}
|
|
else {
|
|
$tmax = strtotime($end);
|
|
}
|
|
|
|
// Get zkl info
|
|
$zkl_info = db_fetch_lance($zkl, "", 1);
|
|
|
|
// Determine for which sensors to plot the data (in logical order)
|
|
$supported_sensors = array();
|
|
if(
|
|
db_check_system_device_capabilities($zkl_info['device'],"temperatuursensor on-board")
|
|
) $supported_sensors['on-board'] = db_fetch_system_device_status($zkl_info['device'], $_SESSION[$_PAGE_INFO['id']]['i18n'], '', 'on-board');
|
|
if(
|
|
db_check_system_device_capabilities($zkl_info['device'], "temperatuursensor extern")
|
|
) $supported_sensors['ntc'] = db_fetch_system_device_status($zkl_info['device'], $_SESSION[$_PAGE_INFO['id']]['i18n'], '', 'extern');
|
|
// External sensor #2 are stored in the fields for the on-board sensor (MTinfo supports a maximum of two sensors in total)
|
|
if(
|
|
!db_check_system_device_capabilities($zkl_info['device'],"temperatuursensor on-board") &&
|
|
db_check_system_device_capabilities($zkl_info['device'], "temperatuursensor extern") &&
|
|
db_system_device_nr_tempsensors($zkl_info['device']) > 1
|
|
) $supported_sensors['on-board'] = db_fetch_system_device_status($zkl_info['device'], $_SESSION[$_PAGE_INFO['id']]['i18n'], '', 'on-board');
|
|
|
|
$tz_offset = $tmin - intval(gmstrftime("%s", $tmin));
|
|
$tz_info = localtime($tmin, true);
|
|
if( $tz_info['tm_isdst'] ) $tz_offset += 3600;
|
|
$duration = $tmax - $tmin;
|
|
|
|
//
|
|
// Draw the grid
|
|
//
|
|
|
|
// draw background
|
|
imagefill($im, 0, 0, $bgcolor);
|
|
|
|
// offsets with the drawing grid
|
|
// largest value label: 3 characters ("-10")
|
|
// x: left to right
|
|
// y: bottom to top
|
|
global $x_off, $x_ext, $y_off, $y_ext;
|
|
$x_off = 3 * imagefontwidth($labelfont) // value labels +
|
|
+ imagefontheight($labelfont) // legend +
|
|
+ (imagefontheight($labelfont) >> 1); // extra spacing
|
|
$x_ext = $width - $x_off - (imagefontheight($labelfont) >> 1); // + extent of the last date label
|
|
$y_off = ($height - 10 * imagefontwidth($labelfont)) - 1; // date/time
|
|
$y_ext = $y_off;
|
|
$y_ext -= imagefontheight($labelfont) >> 1; // extent of the top value label
|
|
|
|
// The grid is drawn _under_ the lines and ornaments like the title etc
|
|
// Y tick marks every 5.0 C
|
|
for( $T = $T_min; $T <= $T_max; $T += 5 ) {
|
|
$y = ($y_ext * ($T - $T_min) / $T_range);
|
|
imageline($im, $x_off, $y_off - $y, $x_off + $x_ext, $y_off - $y, $T == 0 ? $zero_color : $lgrey);
|
|
imageline($im, $x_off - 2, $y_off - $y, $x_off, $y_off - $y, $black);
|
|
imagestringalign($im,
|
|
$labelfont,
|
|
$x_off - 2, $y_off - $y,
|
|
sprintf("%d", $T),
|
|
$gridcolor,
|
|
ALV_MIDDLE | ALH_RIGHT
|
|
);
|
|
}
|
|
// X tick marks
|
|
// find a correct stepping for the date labels first
|
|
$x_tick_sec = array(5,15,1*60,5*60,15*60,30*60,60*60,2*60*60,4*60*60,6*60*60,8*60*60,12*60*60,24*60*60,7*24*60*60);
|
|
for(
|
|
$step = 0, $x_tick_step = 0;
|
|
$x_tick_step < (imagefontheight($labelfont) << 1) && $step < count($x_tick_sec);
|
|
$step++
|
|
) {
|
|
$x_tick_off = $x_tick_sec[$step];
|
|
$x_tick_step = ($x_ext * $x_tick_off) / $duration;
|
|
$x_tick_val = $x_tick_off - (($tmin + $tz_offset) % $x_tick_off);
|
|
if( $x_tick_val == $x_tick_off ) $x_tick_val = 0;
|
|
}
|
|
|
|
unset($x_save);
|
|
|
|
for( $x = ($x_ext * $x_tick_val) / $duration; $x <= $x_ext; $x += $x_tick_step ) {
|
|
$x_time = $tmin + $x_tick_val;
|
|
if( $x_tick_off >= (24*60*60) ) {
|
|
if ((!isset($x_save) || (($x_off + $x) >= ($x_save + (imagefontheight($labelfont) << 1))))) {
|
|
if( strftime("%d", $x_time) == "01" ) {
|
|
imageline($im, $x_off + $x, $y_off , $x_off + $x, $y_off - $y_ext - 1, $nextdaycolor);
|
|
imageline($im, $x_off + $x, $y_off + 2, $x_off + $x, $y_off, $gridcolor);
|
|
imagestringupalign($im, $labelfont, $x_off + $x, $y_off - 2, strftime("%F", $x_time), $nextdaycolor, ALV_BOTTOM | ALH_LEFT);
|
|
}
|
|
else {
|
|
imageline($im, $x_off + $x, $y_off , $x_off + $x, $y_off - $y_ext - 1, $sgridcolor);
|
|
imageline($im, $x_off + $x, $y_off + 2, $x_off + $x, $y_off, $gridcolor);
|
|
}
|
|
imagestringupalign($im, $labelfont, $x_off + $x, $y_off, strftime("%F", $x_time), $gridcolor, ALV_TOP | ALH_CENTER);
|
|
$x_save = $x_off + $x;
|
|
}
|
|
}
|
|
else {
|
|
if( strftime("%H%M%S", $x_time) == "000000" ) {
|
|
imageline($im, $x_off + $x, $y_off , $x_off + $x, $y_off - $y_ext - 1, $nextdaycolor);
|
|
imageline($im, $x_off + $x, $y_off + 2, $x_off + $x, $y_off, $gridcolor);
|
|
imagestringupalign($im, $labelfont, $x_off + $x , $y_off - 2, strftime("%F", $x_time), $nextdaycolor, ALV_BOTTOM | ALH_LEFT);
|
|
}
|
|
else {
|
|
imageline($im, $x_off + $x, $y_off , $x_off + $x, $y_off - $y_ext - 1, $sgridcolor);
|
|
imageline($im, $x_off + $x, $y_off + 2, $x_off + $x, $y_off, $gridcolor);
|
|
}
|
|
imagestringupalign($im, $labelfont, $x_off + $x, $y_off + 2, strftime("%X", $x_time), $gridcolor, ALV_TOP | ALH_CENTER);
|
|
}
|
|
$x_tick_val += $x_tick_off;
|
|
}
|
|
if( $x_tick_off != (24*60*60) )
|
|
imagestringupalign($im, $labelfont, $x_off, $y_off - 2, strftime("%F", $tmin), $grey, ALV_BOTTOM | ALH_LEFT);
|
|
|
|
//
|
|
// Draw the legend
|
|
//
|
|
$y_legend_off = $y_off;
|
|
// determine size of the legend; the lines are 3 characters long separated by a space;
|
|
// the labels are separated by four spaces
|
|
$y_legend_ext = 4; // (°C)
|
|
foreach( $supported_sensors as $sensor => $sensor_info ) {
|
|
$str = $sensor_info['display'];
|
|
$y_legend_ext += strlen($str) + 4 + 4;
|
|
}
|
|
$y_legend_ext *= imagefontwidth($labelfont);
|
|
if( $y_legend_ext < $y_ext ) $y_legend_off -= ($y_ext - $y_legend_ext) >> 1;
|
|
foreach( $supported_sensors as $sensor => $sensor_info ) {
|
|
$str = $sensor_info['display'];
|
|
|
|
$y_legend_off -= strlen($str) * imagefontwidth($labelfont);
|
|
imagestringupalign($im, $labelfont, 0, $y_legend_off, $str, $gridcolor, ALV_TOP | ALH_LEFT);
|
|
|
|
$y_legend_off -= imagefontwidth($labelfont);
|
|
imageline($im,
|
|
imagefontheight($labelfont) >> 1, $y_legend_off , /* space */
|
|
imagefontheight($labelfont) >> 1, $y_legend_off - 3 * imagefontwidth($labelfont), /* line length */
|
|
$linecolor[$sensor]
|
|
);
|
|
|
|
$y_legend_off -= (7 * imagefontwidth($labelfont));
|
|
}
|
|
imagestringupalign($im, $labelfont, 0, $y_legend_off - 4 * imagefontwidth($labelfont), "(\xB0C)", $gridcolor, ALV_TOP | ALH_LEFT);
|
|
|
|
//
|
|
// Draw the border to the left and bottom of the canvas
|
|
//
|
|
imageline($im, $x_off, $y_off, $x_off, $y_off - $y_ext + 1, $gridcolor);
|
|
imageline($im, $x_off, $y_off, $x_off + $x_ext, $y_off, $gridcolor);
|
|
|
|
//
|
|
// Plot the data
|
|
//
|
|
|
|
// Initial values
|
|
$skip_first = FALSE;
|
|
$log_count = 0;
|
|
|
|
// Valid data?
|
|
if ((is_array($log_files)) && (is_array($log_rt))) {
|
|
if ($log_files[0]['tmin'] > $log_rt[0]['t']) {
|
|
// End of log_realtime is start of "first" log file
|
|
$rt['end'] = $log_files[0]['tmin'];
|
|
|
|
// Add dummy log_file entry to log_files array => and skip log files check
|
|
$log_files = array_merge(array("Dummy"), $log_files);
|
|
|
|
// Set skip flag
|
|
$skip_first = TRUE;
|
|
}
|
|
}
|
|
|
|
do {
|
|
// Initial values
|
|
$valid_entry = FALSE;
|
|
|
|
//
|
|
// LOG_ZKL
|
|
//
|
|
if (is_array($log_files)) {
|
|
if (!$skip_first) {
|
|
// get tmin,tmax for this logfile
|
|
$log_tmin = $log_files[$log_count]['tmin'];
|
|
$log_tmax = $log_files[$log_count]['tmax'];
|
|
if ($log_tmin < $tmin && $log_tmax < $tmin) continue;
|
|
if( $log_tmin < $tmin ) $log_tmin = $tmin;
|
|
if( $log_tmax > $tmax ) $log_tmax = $tmax;
|
|
|
|
// define logfile info
|
|
$sdcard = $log_files[$log_count]['sdcard'];
|
|
$rpgmcount = $log_files[$log_count]['rpgmcount'];
|
|
$startup = $log_files[$log_count]['startup'];
|
|
|
|
// get the data
|
|
$query = "SELECT log_zkl.id,log_zkl.t,log_temp.sensor,log_temp.temp ";
|
|
$query .= "FROM log_zkl,log_temp ";
|
|
$query .= "WHERE ";
|
|
$query .= " log_zkl.id=log_temp.id AND ";
|
|
$query .= " log_zkl.zkl=" . $zkl . " AND ";
|
|
$query .= " log_zkl.sdcard=" . $sdcard . " AND ";
|
|
$query .= " log_zkl.rpgmcount=" . $rpgmcount . " AND ";
|
|
$query .= " log_zkl.startup=" . $startup . " ";
|
|
|
|
// select sensor
|
|
foreach( $supported_sensors as $sensor => $sensor_info ) {
|
|
$query .= " AND log_temp.sensor='" . $sensor . "' ";
|
|
}
|
|
$query .= "ORDER BY log_zkl.id";
|
|
$result = db_fetch_data($query, "log", null, 0);
|
|
|
|
foreach($supported_sensors as $sensor => $sensor_info) {
|
|
unset($t_begin[$sensor]);
|
|
unset($stored_value[$sensor]);
|
|
}
|
|
$counter = 0;
|
|
|
|
while($row = mysql_fetch_assoc($result['result'])) {
|
|
// Get sensor info
|
|
$sensor = $row['sensor'];
|
|
|
|
// Increment counter
|
|
$counter++;
|
|
|
|
// Valid sensor
|
|
if ($supported_sensors[$sensor]) {
|
|
// First sensor data
|
|
if(!isset($t_begin[$sensor])) {
|
|
// Valid log data
|
|
if ($row['t'] > $log_tmin) {
|
|
$t_begin[$sensor] = $row['t'];
|
|
}
|
|
|
|
// Store last value
|
|
$stored_value[$sensor] = $row;
|
|
}
|
|
else {
|
|
// Changed or last log value
|
|
if (($row['temp'] != $stored_value[$sensor]['temp']) || ($result['nr_rows'] == $counter)) {
|
|
// Get start and end time
|
|
$t_start = $t_begin[$sensor];
|
|
$t_end = $row['t'];
|
|
|
|
if ($t_end >= $log_tmin && $t_start <= $log_tmax) {
|
|
// Check boundaries
|
|
if($t_start < $log_tmin) {
|
|
$t_start = $log_tmin;
|
|
}
|
|
else if($t_end > $log_tmax) {
|
|
$t_end = $log_tmax;
|
|
}
|
|
|
|
// Invalid timestamp => next sample
|
|
if ($t_end < $t_start) continue;
|
|
|
|
// Data too old (1 hour limit)? => Restart
|
|
if (($t_begin[$sensor] < $t_end) && (($t_end - $t_begin[$sensor]) > 3600)) {
|
|
$t_begin[$sensor] = $t_end;
|
|
}
|
|
|
|
// Average
|
|
$row['temp'] = (($stored_value[$sensor]['temp'] + $row['temp'])/2);
|
|
|
|
// Set flag
|
|
$valid_entry = TRUE;
|
|
|
|
// Draw line
|
|
imageline($im,
|
|
$x_off + ((($t_start - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * ($stored_value[$sensor]['temp'] - $T_min) / $T_range),
|
|
$x_off + ((($t_end - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * ($row['temp'] - $T_min) / $T_range),
|
|
$linecolor[$sensor]);
|
|
|
|
// Update variables
|
|
$t_begin[$sensor] = $t_end;
|
|
$stored_value[$sensor] = $row;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Last log entry
|
|
foreach($supported_sensors as $sensor => $sensor_info) {
|
|
if ((isset($t_begin[$sensor])) && (isset($stored_value[$sensor]))) {
|
|
if ($log_tmax > $t_begin[$sensor]) {
|
|
// Define start/end
|
|
$t_start = $t_begin[$sensor];
|
|
$t_end = $log_tmax;
|
|
|
|
// Set flag
|
|
$valid_entry = TRUE;
|
|
|
|
// Draw line
|
|
imageline($im,
|
|
$x_off + ((($t_start - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * ($stored_value[$sensor]['temp'] - $T_min) / $T_range),
|
|
$x_off + ((($t_end - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * ($stored_value[$sensor]['temp'] - $T_min) / $T_range),
|
|
$linecolor[$sensor]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Reset flag
|
|
$skip_first = FALSE;
|
|
|
|
if (is_array($log_files)) {
|
|
// Valid entries found? Or searching for the end?
|
|
if ($valid_entry) {
|
|
// End of this log file is begin of log realtime
|
|
$rt['begin'] = $tmax;
|
|
}
|
|
else {
|
|
// No valid entries found => Retry with the log realtime, could be a "bug"
|
|
$rt['begin'] = $tmin;
|
|
}
|
|
|
|
// Last log file => end of period, else begin of next log file
|
|
$rt['end'] = (($log_count + 1) == sizeof($log_files)) ? $tmax : $log_files[$log_count + 1]['tmin'];
|
|
|
|
// Check if end is not before begin
|
|
if ((strlen($rt['begin'])) && (strlen($rt['end']))) {
|
|
$rt['end'] = ($rt['end'] > $rt['begin']) ? $rt['end'] : $rt['begin'];
|
|
}
|
|
}
|
|
else {
|
|
$rt['begin'] = $tmin;
|
|
$rt['end'] = $tmax;
|
|
}
|
|
|
|
//
|
|
// LOG_REALTIME
|
|
//
|
|
if (is_array($log_rt)) {
|
|
// Initial values
|
|
$counter = 0;
|
|
|
|
for ($i = 0; (($i < sizeof($log_rt)) && !((strlen($rt['end'])) && ($log_rt[$i]['t'] > $rt['end']))); $i++) {
|
|
// Valid timeframe?
|
|
if ((($log_rt[$i]['t'] >= $rt['begin']) || (!$rt['begin'])) && (($log_rt[$i]['t'] <= $rt['end']) || (!$rt['end']))) {
|
|
// Increment counter
|
|
$counter++;
|
|
|
|
// Handle all temperature sensors
|
|
foreach( $supported_sensors as $sensor => $sensor_info ) {
|
|
// Valid data?
|
|
if (!is_null($log_rt[$i]["temp_" . str_replace("-", "", $sensor)])) {
|
|
// First sensor data
|
|
if (!isset($t_begin[$sensor])) {
|
|
// Valid log data
|
|
$t_begin[$sensor] = $log_rt[$i]['t'];
|
|
|
|
// Store last value
|
|
$stored_value[$sensor] = $log_rt[$i]["temp_" . str_replace("-", "", $sensor)];
|
|
}
|
|
else {
|
|
if ($i) {
|
|
//// Data too old (1 hour limit)? => Restart
|
|
//if (($log_rt[$i - 1]['t'] < $log_rt[$i]['t']) && (($log_rt[$i]['t'] - $log_rt[$i - 1]['t']) > 3600)) {
|
|
// $t_begin[$sensor] = $log_rt[$i]['t'];
|
|
//
|
|
// // Store last value
|
|
// $stored_value[$sensor] = $log_rt[$i]["temp_" . str_replace("-", "", $sensor)];
|
|
//}
|
|
}
|
|
|
|
// Changed or last log value
|
|
if ((($log_rt[$i]["temp_" . str_replace("-", "", $sensor)] != $stored_value[$sensor]) || (sizeof($log_rt) == $counter))) {
|
|
|
|
// Get start and end time
|
|
$t_start = $t_begin[$sensor];
|
|
$t_end = $log_rt[$i]['t'];
|
|
|
|
// Average
|
|
$temp = (($stored_value[$sensor] + $log_rt[$i]["temp_" . str_replace("-", "", $sensor)])/2);
|
|
|
|
// Draw line
|
|
imageline($im,
|
|
$x_off + ((($t_start - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * ($stored_value[$sensor] - $T_min) / $T_range),
|
|
$x_off + ((($t_end - $tmin) / $duration) * $x_ext), $y_off - ($y_ext * ($temp - $T_min) / $T_range),
|
|
$linecolor[$sensor]);
|
|
|
|
// Update variables
|
|
$t_begin[$sensor] = $t_end;
|
|
$stored_value[$sensor] = $temp;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} while ((is_array($log_files)) && (++$log_count < sizeof($log_files)));
|
|
|
|
//
|
|
// Catch & destroy the final image
|
|
//
|
|
ob_start();
|
|
imagepng($im);
|
|
download_document_data(ob_get_contents(), "write_file", "plot_temp");
|
|
ob_end_clean();
|
|
imagedestroy($im);
|
|
}
|
|
?>
|