![]() |
perkiset
Here is the image class that I use as a base for generating images on the fly. Note that it requires both GD and FreeType to be on the
machine before this will work. In the next post I will show usage:<? phpclass image { private $myHandle; private $myOutputMode; private $fontHandles; private $colorHandles; public $fadeHandles; private $currentColorHandle; private $currentFontSize; private $currentFontHandle; private $currentFontColor; public $handle; function __construct($width=-1, $height=-1, $backgroundColor='ffffff') { $this->fontHandles = array(); $this->colorHandles = array(); $this->fadeHandles = array(); $this->outputMode = 0; $this->myHandle = null; if (is_string($width) && ($height == -1)) { $fileName = $width; if (!file_exists($fileName)) { "Filename passed to image->construct does not exist or is inaccessible"; } $ptr = strrpos($fileName, '.'); $suffix = strtolower(substr($fileName, $ptr + 1, 4)); switch ($suffix) { case 'gif': $this->myHandle = imagecreatefromgif($fileName); break; case 'jpeg': case 'jpg': $this->myHandle = imagecreatefromjpeg($fileName); break; case 'png': $this->myHandle = imagecreatefrompng($fileName); break; default: die("Image class cannot be created from file with suffix '$suffix'"); } } else { if (($width==-1) || ($height==-1)) { die('You must pass both a height width to create an image object.'); } $this->myHandle = imagecreate($width, $height); } $red = hexdec(substr($backgroundColor, 0, 2)); $green = hexdec(substr($backgroundColor, 2, 2)); $blue = hexdec(substr($backgroundColor, 4, 2)); imagecolorallocate($this->myHandle, $red, $green, $blue); $this->handle = $this->myHandle; } function __destruct() { if (!$this->myHandle) { imagedestroy($this->myHandle); } } private function buildImage($fileName='') { switch ($this->myOutputMode) { case 0: if (strlen($fileName) > 0) { imagegif($this->myHandle, $filename); } else { imagegif($this->myHandle); } break; case 1: if (strlen($fileName) > 0) { imagejpeg($this->myHandle, $filename); } else { imagejpeg($this->myHandle); } break; case 2: if (strlen($fileName) > 0) { imagepng($this->myHandle, $filename); } else { imagepng($this->myHandle); } break; default: die('Unknown output mode "' . $this->myOutputMode . '"'); } } public function colorHandle($theHandle) { return $this->colorHandles[$theHandle]; } public function fadeValue($fadeName, $ptr) { return $this->fadeHandles[$fadeName][$ptr]; } public function generateFade($fadeName='NONAME', $fadeStart='######', $fadeEnd='######', $fadeSteps=0) { // Pass colors as "ae126f' - you do not need the # if ($fadeName == 'NONAME') { die('You must pass a fade name to image->generateFade as parameter 1'); } if ($fadeStart == '#######') { die('You must pass a fade start color value (hex) to image->generateFade as parameter 2'); } if ($fadeEnd == '#######') { die('You must pass a fade end color value (hex) to image->generateFade as parameter 3'); } if ($fadeSteps <= 0) { die('You must pass a non-zero positive value to image->generateFade as parameter 4'); } unset($this->fadeHandles[$fadeName]); $startRed = hexdec(substr($fadeStart, 0, 2)); $startGreen = hexdec(substr($fadeStart, 2, 2)); $startBlue = hexdec(substr($fadeStart, 4, 2)); $endRed = hexdec(substr($fadeEnd, 0, 2)); $endGreen = hexdec(substr($fadeEnd, 2, 2)); $endBlue = hexdec(substr($fadeEnd, 4, 2)); $deltaRed = $endRed - $startRed; $deltaGreen = $endGreen - $startGreen; $deltaBlue = $endBlue - $startBlue; $sineRed = ($deltaRed >= 0); $sineGreen = ($deltaGreen >= 0); $sineBlue = ($deltaBlue >= 0); $deltaRed = abs($deltaRed); $deltaGreen = abs($deltaGreen); $deltaBlue = abs($deltaBlue); $stepsRed = $deltaRed / $fadeSteps; $stepsGreen = $deltaGreen / $fadeSteps; $stepsBlue = $deltaBlue / $fadeSteps; $this->fadeHandles[$fadeName][0] = imagecolorallocate($this->myHandle, $startRed, $startGreen, $startBlue); $lastRed = $startRed; $lastGreen = $startGreen; $lastBlue = $startBlue; for ($i=1; $i<$fadeSteps; $i++) { $newRed = ($sineRed) ? ($lastRed + $stepsRed) : ($lastRed - $stepsRed); $newGreen = ($sineGreen) ? ($lastGreen + $stepsGreen) : ($lastGreen - $stepsGreen); $newBlue = ($sineBlue) ? ($lastBlue + $stepsBlue) : ($lastBlue - $stepsBlue); $thisRed = floor($newRed); $thisGreen = floor($newGreen); $thisBlue = floor($newBlue); if ( ($thisRed == floor($lastRed)) && ($thisGreen == floor($lastGreen)) && ($thisBlue == floor($lastBlue)) ) { $this->fadeHandles[$fadeName][$i] = $this->fadeHandles[$fadeName][$i - 1]; } else { $this->fadeHandles[$fadeName][$i] = imagecolorallocate($this->myHandle, $thisRed, $thisGreen, $thisBlue); } $lastRed = $newRed; $lastGreen = $newGreen; $lastBlue = $newBlue; } } public function getHeight() { return imagesy($this->myHandle); } public function getWidth() { return imagesx($this->myHandle); } public function importImage($theImage, $x=0, $y=0) { if (!is_a($theImage, 'image')) { die("image->importImage must be passed a reference to an image object"); } imagecopy($this->myHandle, $theImage->handle, $x, $y, 0, 0, imagesx($theImage->handle), imagesy($theImage->handle)); } public function outputMode($mode=-1) { if ($mode == -1) { die("You must pass a mode (0/1/2) to image->outputMode"); } switch ($mode) { case 0: case 1: case 2: $this->myOutputMode = $mode; break; default: die("You must pass a mode that is either 0, 1 or 2 to image->outputMode"); break; } } public function output() { list($usec, $sec) = explode(' ', microtime()); $theRand = rand(1000000000); $fileName = ((float)$usec + (float)$sec) . $theRand; $this->buildOutput("/tmp/$fileName"); $buffer = file_get_contents($fileName); unlink($fileName); return $buffer; } public function outputDirect() { switch($this->myOutputMode) { case 0: header('Content-type: image/gif'); break; case 1: header('Content-type: image/jpeg'); break; case 2: header('Content-type: image/png'); break; } $this->buildImage(); exit; } public function outputFile($fileName='') { if ($fileName == '') { die('You must pass a filename to image->fileOutput'); } $this->buildImage($fileName); } function rectangle($x0, $y0, $x1, $y1, $cHandle=-1) { if ($cHandle == -1) { $cHandle = $this->currentColorHandle; } imagerectangle($this->myHandle, $x0, $y0, $x1, $y1, $this->colorHandles[$cHandle]); } function rectangleFade($startColor, $endColor, $direction, $width, $height, $destX, $destY) { $tempImage = new image($width, $height); if ($direction) { // Horitzontal Fade $tempImage->generateFade('temp', $startColor, $endColor, $width); $fadeArr = &$tempImage->fadeHandles['temp']; for ($i=0; $i<$width; $i++) { imageline($tempImage->handle, $i, 0, $i, $height, $fadeArr[$i]); } imagecopy($this->myHandle, $tempImage->handle, $destX, $destY, 0, 0, $width, $height); } else { // Vertical Fade $tempImage->generateFade('temp', $startColor, $endColor, $height); $fadeArr = &$tempImage->fadeHandles['temp']; for ($i=0; $i<$height; $i++) { imageline($tempImage->handle, 0, $i, $width, $i, $fadeArr[$i]); } imagecopy($this->myHandle, $tempImage->handle, $destX, $destY, 0, 0, $width, $height); } } function registerColor($colorStr) { $red = hexdec(substr($colorStr, 0, 2)); $green = hexdec(substr($colorStr, 2, 2)); $blue = hexdec(substr($colorStr, 4, 2)); $this->colorHandles[] = imagecolorallocate($this->myHandle, $red, $green, $blue); $retVal = count($this->colorHandles) - 1; $this->currentColorHandle = $retVal; return $retVal; } function registerFont($fontPath) { if (!file_exists($fontPath)) { die("Font file '$fontPath' does not exist, or cannot be accessed (image->registerFont)"); } $this->fontHandles[] = $fontPath; return count($this->fontHandles) - 1; } public function setCurrentColor($theHandle = -1) { if (($theHandle < 0) || ($theHandle >= count($this->colorHandles))) { die('You must pass a valid handle to image->setColorHandle'); } $this->currentColorHandle = $theHandle; } public function setCurrentFont($theHandle) { if (($theHandle < 0) || ($theHandle >= count($this->fontHandles))) { die('You must pass a valid handle to image->setCurrentFont'); } $this->currentFontHandle = $theHandle; } public function setFontHandle($theHandle=-1) { if (($theHandle < 0) || ($theHandle >= count($this->fontHandles))) { die('You must pass a valid handle to image->setFontHandle'); } $this->currentFontHandle = $theHandle; } public function setFontSize($theSize=-1) { if ($theSize == -1) { die('You must pass a point size to image->setFontSize'); } $this->currentFontSize = $theSize; } public function simpleText($x, $y, $message, $cHandle=-1) { if ($cHandle == -1) { $cHandle = $this->currentColorHandle; } imagettftext($this->myHandle, $this->currentFontSize, 0, $x, $y, $this->colorHandles[$cHandle], $this->fontHandles[$this->currentFontHandle], $message); } public function vLine($hPos, $cHandle=-1, $vStart=-1, $vEnd = -1) { if ($vStart == -1) { $vStart = 0; } if ($vEnd == -1) { $vEnd = imagesy($this->myHandle); } if ($cHandle == -1) { $cHandle = $this->currentColorHandle; } imageline($this->myHandle, $hPos, $vStart, $hPos, $vEnd, $this->colorHandles[$cHandle]); } public function hLine($vPos, $cHandle=-1, $hStart=-1, $hEnd = -1) { if ($hStart == -1) { $hStart = 0; } if ($hEnd == -1) { $hEnd = imagesx($this->myHandle); } if ($cHandle == -1) { $cHandle = $this->currentColorHandle; } imageline($this->myHandle, $hStart, $vPos, $hEnd, $vPos, $this->colorHandles[$cHandle]); } } ?> perkiset
Here is a fragment of an image I created using the class above and the code below. This simulates an area chart with an interesting looking grid, left hand legend and imported images. I use similar stuff to this (although considerably less garrish) for my telemetry pages:
perkiset
This is the code that I used to create the image above. Note that it simply randomizes data points, imports a couple graphics that are on my
machine and also expects a font, " ENMARK.TTF" to be available. Again, the class above requires GD installed as well as FreeType, although you can get by without FreeType if you don't use the text functions.Not also an interesting trick - I show the digits in the left handle legend in white at x-1 & y-1, x+1 & y-1, x-1 & y+1, x+1 & y+1 and then in dark black at x,y - this gives the effect of a white "stroke" around the letters so that it stands out over the blues. <? phperror_reporting(E_ALL); require_once('/www/sites/lib/classes/class.image. php');$sun = new image('/www/sites/graphics/telem_sun.gif'); $moon = new image('/www/sites/graphics/telem_moon.gif'); $main = new image(960, 300); $main->outputMode(2); $ht = $main->getHeight(); $wd = $main->getWidth(); $white = $main->registerColor('ffffff'); $black = $main->registerColor('000000'); $yellow = $main->registerColor('ffff00'); $gray = $main->registerColor('6a6a6a'); $denmark = $main->registerFont('/www/sites/lib/fonts/DENMARK.TTF'); $main->rectangleFade('09293c', '167cb8', true, 240, 300, 0, 0); $main->rectangleFade('167cb8', '09293c', true, 240, 300, 240, 0); $main->rectangleFade('09293c', '167cb8', true, 240, 300, 480, 0); $main->rectangleFade('167cb8', '09293c', true, 240, 300, 720, 0); // Draw the gray verticals... $i = -1; while (($i++ * 20) <= $wd) {$main->vLine($i * 20); } // Randomize my "data points" $traffic = array(); for ($i=0; $i<48; $i++) { $traffic[] = rand(75,300) - 50; } // Create my white polygon $chart = array(0, 0); for ($i=0; $i<48; $i++) { $chart[] = $i * 20; $chart[] = $traffic[$i]; } $chart[] = 960; $chart[] = 0; imagefilledpolygon($main->handle, $chart, 50, $main->colorHandle($white)); // Now the horizontal lines & legend... $i = -1; while (($i++ * 20) <= $ht) { $main->hLine($i * 20); } // Sun & moon... $main->importImage($moon, -40, 200); $main->importImage($sun, 200, 200); $main->importImage($moon, 440, 200); $main->importImage($sun, 680, 200); $main->importImage($moon, 920, 200); // Now the horizontal lines & legend... $i = -1; $main->setCurrentFont($denmark); $main->setFontSize(9); while (($i++ * 20) <= $ht) { $msg = (30 - $i) * 10; if ($msg > '160') { $main->simpleText(9, ($i * 20) - 2, $msg, $white); $main->simpleText(11, ($i * 20) - 2, $msg, $white); $main->simpleText(10, ($i * 20) - 1, $msg, $white); $main->simpleText(10, ($i * 20) - 3, $msg, $white); $main->simpleText(10, ($i * 20) - 2, $msg, $black); } } $main->outputDirect(); ?> thedarkness
Very cool Perk, I have a project which requires the generation of gantt style charts (actually a visual disply of employee's shifts0 this could be very handy.
Thanks, td perkiset
Dig it!
A favor - if you make a cool one, please post an example and some script... that'd be ginormously cool. /p thedarkness
Done, my "cool" may not be veryone elses "cool" though ;-)
I've got a class that reads mp3 headers and a few other bits and pieces that I wat to post, got to find them though :-P Cheers, td |
Thread Categories
| Best of The Cache Home | ||
| Search The Cache |
- Ajax
- Apache & mod_rewrite
- BlackHat SEO & Web Stuff
- C/++/#, Pascal etc.
- Database Stuff
- General & Non-Technical Discussion
- General programming, learning to code
- Javascript Discussions & Code
- Linux Related
- Mac, iPhone & OS-X Stuff
- Miscellaneous
- MS Windows Related
- PERL & Python Related
- PHP: Questions & Discussion
- PHP: Techniques, Classes & Examples
- Regular Expressions
- Uncategorized Threads



ENMARK.TTF" to be available. Again, the class above requires GD installed as well as FreeType, although you can get by without FreeType if you don't use the text functions.