1<?php 2// +----------------------------------------------------------------------+ 3// | PEAR :: Cache | 4// +----------------------------------------------------------------------+ 5// | Copyright (c) 1997-2003 The PHP Group | 6// +----------------------------------------------------------------------+ 7// | This source file is subject to version 2.0 of the PHP license, | 8// | that is bundled with this package in the file LICENSE, and is | 9// | available at through the world-wide-web at | 10// | http://www.php.net/license/2_02.txt. | 11// | If you did not receive a copy of the PHP license and are unable to | 12// | obtain it through the world-wide-web, please send a note to | 13// | license@php.net so we can mail you a copy immediately. | 14// +----------------------------------------------------------------------+ 15// | Authors: Ulf Wendel <ulf.wendel@phpdoc.de> | 16// +----------------------------------------------------------------------+ 17// 18// $Id: Graphics.php 178289 2005-01-26 09:47:28Z dufuz $ 19 20require_once 'Cache.php'; 21 22/** 23* Graphics disk cache. 24* 25* The usual way to create images is to pass some arguments that describe the image 26* to a script that dynamically creates an image. For every image of a page 27* a new PHP interpreter gets started. This is a good way to kill your webserver. 28* 29* When dealing with dynamically generated images you should not call another script 30* to generate the images but generate the images by the script that produces the page 31* that contains the images. This is a major improvement but it's only half the way. 32* 33* There's no need to rerender an image on every request. A simple disk cache can reduce 34* the computation time dramatically. This is what the class graphics_cache is for. 35* 36* Usage: 37* 38* // create an instance of the graphics cache 39* $cache = new graphics_cache; 40* 41* $img = ImageCreate(...); 42* 43* // compute an ID for your image based on typical parameters 44* $id = m5d( $size, $colors, $label); 45* 46* // check if it's cached 47* if (!($link = $cache->getImageLink($id, 'gif'))) { 48* 49* // hmmm, it's not cached, create it 50* ... 51* // cacheImageLink() and cacheImage() make the ImageGIF() call! 52* // cacheImage() returns the value of ImageGIF() [etc.], cacheImageLink() returns a URL 53* $link = $cache->cacheImageLink($id, $img, 'gif'); 54* 55* } 56* 57* // Ok, let's build the ImageLink 58* $size = getImageSize($link[0]); 59* printf('<img src="%s" %s>', $link[1], $size[3]); 60* 61* // for cacheImage(): 62* // header('Content-type: image/gif'); print $cache->cacheImage($id, $img, 'gif'); 63* 64* 65* The class requires PHP 4.0.2+ [ImageType()]. Note that cacheImage() works with 66* the output buffer. Modify it if required! 67* 68* @author Ulf Wendel <ulf.wendel@phpdoc.de> 69* @version $Id: Graphics.php 178289 2005-01-26 09:47:28Z dufuz $ 70* @package Cache 71*/ 72class Cache_Graphics extends Cache 73{ 74 75 76 /** 77 * Cache URL prefix. 78 * 79 * Make sure that the cache URL prefix points to the $cache_dir, otherwise 80 * your links will be broken. Use setCacheURL to specify the cache_url and 81 * setCacheDir() for the cache_dir. 82 * 83 * @var string 84 * @see setCacheURL(), setCacheDir() 85 */ 86 var $cache_url = ''; 87 88 /** 89 * Directory where cached files get stored. 90 * s 91 * Make sure that the cache_dir is writable and offers enough space. Check 92 * also if your cache_url points to the directory. Use setCacheDir() to set 93 * the variable. 94 * 95 * @var string 96 * @see setCacheDir(), setCacheURL() 97 */ 98 var $cache_dir = ''; 99 100 /** 101 * Nameprefix of cached files. 102 * 103 * Per default the prefix "graphics_" gets used. You might use this 104 * for versioning or to ease (manual) clean ups. 105 * 106 * @var string 107 */ 108 var $cache_file_prefix = 'graphics_'; 109 110 111 /** 112 * Cache container group. 113 * 114 * @var string 115 */ 116 var $cache_group = 'graphics'; 117 118 119 /** 120 * Mapping from supported image type to a ImageType() constant. 121 * 122 * Referr to the PHP manual for more informations on ImageType() 123 * 124 * @var array 125 * @link http://www.php.net/ImageType 126 */ 127 var $imagetypes = array( 128 'gif' => IMG_GIF, 129 'jpg' => IMG_JPG, 130 'png' => IMG_PNG, 131 'wbmp' => IMG_WBMP 132 ); 133 134 135 /** 136 * Instantiates a cache file container. 137 * 138 */ 139 function Cache_Graphics() 140 { 141 $this->Cache('file', array('cache_dir' => $this->cache_dir, 'filename_prefix' => $this->cache_file_prefix)); 142 143 } // end constructor 144 145 146 /** 147 * Returns the content of a cached image file. 148 * 149 * This function can be used to send the image directly to the browser. 150 * Make sure that you send a correspondending header before sending the image itself. 151 * 152 * Always try to get the image from the cache before you compute it. See 153 * the class docs for an example. 154 * 155 * @param string Image-ID 156 * @param string Image type: gif, jpg, png, wbmp 157 * @return string Image file contents if a cached file exists otherwise an empty string 158 * @see cacheImage() 159 */ 160 function getImage($id, $format = 'png') 161 { 162 $id = $this->generateID($id, $format); 163 return $this->get($id, $this->cache_group); 164 } // end func getImage 165 166 167 /** 168 * Returns an array with a link to the cached image and the image file path. 169 * 170 * Always try to get the image from the cache before you compute it. See 171 * the class docs for an example. 172 * 173 * @param string Image-ID 174 * @param string Image type: gif, jpg, png, wbmp 175 * @return array [ full path to the image file, image url ] 176 * @throw Cache_Error 177 * @see cacheImageLink() 178 */ 179 function getImageLink($id, $format = 'png') 180 { 181 $id = $this->generateID($id, $format); 182 if (!$this->container->idExists($id, $this->cache_group)) { 183 return array(); 184 } 185 $file = $this->cache_url . $this->cache_file_prefix . $id; 186 187 return array($this->container->getFilename($id, $this->cache_group), $file); 188 } // end func getImageLink 189 190 191 /** 192 * Create an image from the given image handler, cache it and return the file content. 193 * 194 * Always try to retrive the image from the cache before you compute it. 195 * 196 * Warning: this function uses the output buffer. If you expect collisions 197 * modify the code. 198 * 199 * @param string Image-ID. Used as a part of the cache filename. 200 * Use md5() to generate a "unique" ID for your image 201 * based on characteristic values such as the color, size etc. 202 * @param string Image handler to create the image from. 203 * @param string Image type: gif, jpg, png, wbmp. Also used as filename suffix. 204 * If an unsupported type is requested the functions tries to 205 * fallback to a supported type before throwing an exeption. 206 * @return string Image content returned by ImageGIF/... 207 * @throws Cache_Error 208 * @access public 209 * @see getImage() 210 */ 211 function cacheImage($id, $img, $format = 'png') 212 { 213 if (!$id) { 214 return new Cache_Error('You must provide an ID for and image to be cached!', __FILE__, __LINE__); 215 } 216 $id = $this->generateID($id, $format); 217 $types = ImageTypes(); 218 219 // Check if the requested image type is supported by the GD lib. 220 // If not, try a callback to the first available image type. 221 if (!isset($this->imagetypes[$format]) || !($types & $this->imagetypes[$format])) { 222 foreach ($this->imagetypes as $supported => $bitmask) { 223 if ($types & $bitmask) { 224 new Cache_Error("The build in GD lib does not support the image type $format. Fallback to $supported.", __FILE__, __LINE__); 225 } else { 226 return new Cache_Error("Hmm, is your PHP build with GD support? Can't find any supported types.", __FILE__, __LINE__); 227 } 228 } 229 } 230 231 if ($image = $this->get($id, $this->cache_group)) { 232 return $image; 233 } 234 // save the image to the output buffer, write it to disk and 235 // return the image. 236 ob_end_clean(); 237 ob_start(); 238 239 if (strtoupper($format) == 'JPG') { 240 $genFormat = 'JPEG'; 241 } else { 242 $genFormat = strtoupper($format); 243 } 244 245 // generate the image 246 $func = 'Image' . $genFormat; 247 $func($img); 248 ImageDestroy($img); 249 250 ob_end(); 251 $image = ob_get_contents(); 252 ob_end_clean(); 253 254 // save the generated image to disk 255 $this->save($id, $image, 0, $this->cache_group); 256 257 return $image; 258 } // end func cacheImage 259 260 261 /** 262 * Create an image from the given image handler, cache it and return a url and the file path of the image. 263 * 264 * Always try to retrive the image from the cache before you compute it. 265 * 266 * @param string Image-ID. Used as a part of the cache filename. 267 * Use md5() to generate a "unique" ID for your image 268 * based on characteristic values such as the color, size etc. 269 * @param string Image handler to create the image from. 270 * @param string Image type: gif, jpg, png, wbmp. Also used as filename suffix. 271 * If an unsupported type is requested the functions tries to 272 * fallback to a supported type before throwing an exeption. 273 * @return array [ full path to the image file, image url ] 274 * @throws Cache_Error 275 * @access public 276 */ 277 function cacheImageLink($id, &$img, $format = 'png') 278 { 279 if (!$id) { 280 return new Cache_Error ('You must provide an ID for and image to be cached!', __FILE__, __LINE__); 281 } 282 $id = $this->generateID($id, $format); 283 $types = ImageTypes(); 284 285 // Check if the requested image type is supported by the GD lib. 286 // If not, try a callback to the first available image type. 287 if (!isset($this->imagetypes[$format]) || !($types & $this->imagetypes[$format])) { 288 foreach ($this->imagetypes as $supported => $bitmask) 289 if ($types & $bitmask) { 290 new Cache_Error("The build in GD lib does not support the image type $format. Fallback to $supported.", __FILE__, __LINE__); 291 } else { 292 return new Cache_Error("Hmm, is your PHP build with GD support? Can't find any supported types.", __FILE__, __LINE__); 293 } 294 } 295 296 $url = $this->cache_url . $this->cache_file_prefix . $id; 297 $ffile = $this->container->getFilename($id, $this->cache_group); 298 299 if ($this->isCached($id, $this->cache_group) && !isExpired($id, $this->cache_group)) { 300 return array($ffile, $url); 301 } 302 303 if (strtoupper($format) == 'JPG') { 304 $genFormat = 'JPEG'; 305 } else { 306 $genFormat = strtoupper($format); 307 } 308 309 $func = 'Image' . $genFormat; 310 $func($img, $ffile); 311 312 ImageDestroy($img); 313 314 return array($ffile, $url); 315 } // end func cacheImageLink 316 317 318 /** 319 * Sets the URL prefix used when rendering HTML Tags. 320 * 321 * Make sure that the URL matches the cache directory, 322 * otherwise you'll get broken links. 323 * 324 * @param string 325 * @access public 326 * @see setCacheDir() 327 */ 328 function setCacheURL($cache_url) 329 { 330 if ($cache_url && '/' != substr($cache_url, 1)) { 331 $cache_url .= '/'; 332 } 333 $this->cache_url = $cache_url; 334 335 } // end func setCacheURL 336 337 338 /** 339 * Sets the directory where to cache generated Images 340 * 341 * @param string 342 * @access public 343 * @see setCacheURL() 344 */ 345 function setCacheDir($cache_dir) 346 { 347 if ($cache_dir && '/' != substr($cache_dir, 1)) { 348 $cache_dir .= '/'; 349 } 350 $this->cache_dir = $cache_dir; 351 $this->container->cache_dir = $cache_dir; 352 } // end func setCacheDir 353 354 355 function generateID($variable, $format = 'png') 356 { 357 return md5(serialize($variable)) . '.' . $format; 358 } // end func generateID 359 360 361} // end class Cache_Graphics 362?> 363