| Textpattern | PHP Cross Reference | Content Management Systems |
Description: class wet_thumb
1 <?php 2 /** 3 * class wet_thumb 4 * @author C. Erdmann 5 * @see <a href="http://www.cerdmann.de/thumb">http://www.cerdmann.de/thumb</a> 6 * @author Robert Wetzlmayr 7 * 8 * refactored from function.thumb.php by C. Erdmann, which contained the following credit & licensing terms: 9 * === 10 * Smarty plugin "Thumb" 11 * Purpose: creates cached thumbnails 12 * Home: http://www.cerdmann.com/thumb/ 13 * Copyright (C) 2005 Christoph Erdmann 14 * 15 * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. 16 * 17 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA 20 * ------------------------------------------------------------- 21 * Author: Christoph Erdmann (CE) <smarty@cerdmann.com> 22 * Internet: http://www.cerdmann.com 23 * 24 * Author: Benjamin Fleckenstein (BF) 25 * Internet: http://www.benjaminfleckenstein.de 26 * 27 * Author: Marcus Gueldenmeister (MG) 28 * Internet: http://www.gueldenmeister.de/marcus/ 29 * 30 * Author: Andreas Bösch (AB) 31 * 32 */ 33 34 /* 35 $HeadURL: https://textpattern.googlecode.com/svn/releases/4.5.4/source/textpattern/lib/class.thumb.php $ 36 $LastChangedRevision: 3733 $ 37 */ 38 39 $verbose = false; 40 41 42 class wet_thumb { 43 var $width; // The width of your thumbnail. The height (if not set) will be automatically calculated. 44 var $height; // The height of your thumbnail. The width (if not set) will be automatically calculated. 45 var $longside; // Set the longest side of the image if width, height and shortside is not set. 46 var $shortside; // Set the shortest side of the image if width, height and longside is not set. 47 var $extrapolate; // Set to 'false' if your source image is smaller than the calculated thumb and you do not want the image to get extrapolated. 48 var $crop; // If set to 'true', image will be cropped in the center to destination width and height params, while keeping aspect ratio. Otherwise the image will get resized. 49 var $sharpen; // Set to 'false' if you don't want to use the Unsharp-Mask. Thumbnail creation will be faster, but quality is reduced. 50 var $hint; // If set to 'false' the image will not have a lens-icon. 51 var $addgreytohint; // Set to 'false' to get no lightgrey bottombar. 52 var $quality; // JPEG image quality (0...100, defaults to 80). 53 // link related params 54 var $linkurl; // Set to your target URL (a href="linkurl") 55 var $html; // Will be inserted in the image-tag 56 57 var $types = array('','.gif','.jpg','.png'); 58 var $_SRC; 59 var $_DST; 60 61 /** 62 * constructor 63 */ 64 function wet_thumb( ) { 65 $this->extrapolate = false; 66 $this->crop = true; 67 $this->sharpen = true; 68 $this->hint = true; 69 $this->addgreytohint = true; 70 $this->quality = 80; 71 $this->html = " alt=\"\" title=\"\" "; 72 $this->link = true; 73 } 74 75 /** 76 * write thumbnail file 77 * @param infile image file name 78 * @param outfile array of thumb file names (1...n) 79 * @return boolean, true indicates success 80 */ 81 function write( $infile, $outfile ) { 82 global $verbose; 83 84 if( $verbose )echo "writing thumb nail..."; 85 86 ### fetch source (SRC) info 87 $temp = getimagesize($infile); 88 89 $this->_SRC['file'] = $infile; 90 $this->_SRC['width'] = $temp[0]; 91 $this->_SRC['height'] = $temp[1]; 92 $this->_SRC['type'] = $temp[2]; // 1=GIF, 2=JPG, 3=PNG, SWF=4 93 $this->_SRC['string'] = $temp[3]; 94 $this->_SRC['filename'] = basename($infile); 95 //$this->_SRC['modified'] = filemtime($infile); 96 97 //check image orientation 98 if ($this->_SRC['width'] >= $this->_SRC['height']) { 99 $this->_SRC['format'] = 'landscape'; 100 } else { 101 $this->_SRC['format'] = 'portrait'; 102 } 103 104 ### fetch destination (DST) info 105 if (is_numeric($this->width) AND empty($this->height)) { 106 $this->_DST['width'] = $this->width; 107 $this->_DST['height'] = round($this->width/($this->_SRC['width']/$this->_SRC['height'])); 108 } 109 elseif (is_numeric($this->height) AND empty($this->width)) { 110 $this->_DST['height'] = $this->height; 111 $this->_DST['width'] = round($this->height/($this->_SRC['height']/$this->_SRC['width'])); 112 } 113 elseif (is_numeric($this->width) AND is_numeric($this->height)) { 114 $this->_DST['width'] = $this->width; 115 $this->_DST['height'] = $this->height; 116 } 117 elseif (is_numeric($this->longside) AND empty($this->shortside)) { 118 // preserve aspect ratio based on provided height 119 if ($this->_SRC['format'] == 'portrait') { 120 $this->_DST['height'] = $this->longside; 121 $this->_DST['width'] = round($this->longside/($this->_SRC['height']/$this->_SRC['width'])); 122 } 123 else { 124 $this->_DST['width'] = $this->longside; 125 $this->_DST['height'] = round($this->longside/($this->_SRC['width']/$this->_SRC['height'])); 126 } 127 } 128 elseif (is_numeric($this->shortside)) { 129 // preserve aspect ratio based on provided width 130 if ($this->_SRC['format'] == 'portrait') { 131 $this->_DST['width'] = $this->shortside; 132 $this->_DST['height'] = round($this->shortside/($this->_SRC['width']/$this->_SRC['height'])); 133 } 134 else { 135 $this->_DST['height'] = $this->shortside; 136 $this->_DST['width'] = round($this->shortside/($this->_SRC['height']/$this->_SRC['width'])); 137 } 138 } 139 else { // default dimensions 140 $this->width = 100; 141 $this->_DST['width'] = $this->width; 142 $this->_DST['height'] = round($this->width/($this->_SRC['width']/$this->_SRC['height'])); 143 } 144 145 146 // don't make the new image larger than the original image 147 if ($this->extrapolate === false && $this->_DST['height'] > $this->_SRC['height'] && 148 $this->_DST['width'] > $this->_SRC['width']) { 149 $this->_DST['width'] = $this->_SRC['width']; 150 $this->_DST['height'] = $this->_SRC['height']; 151 } 152 153 $this->_DST['type'] = $this->_SRC['type']; 154 $this->_DST['file'] = $outfile; 155 156 // make sure we have enough memory if the image is large 157 if (max($this->_SRC['width'], $this->_SRC['height']) > 1024) { 158 $shorthand = array('/K/i','/M/i','/G/i'); 159 $tens = array('000','000000', '000000000'); // A good enough decimal approximation of K, M, and G 160 161 // Do not *decrease* memory_limit 162 // TODO: Try str_ireplace instead of preg_replace once we are on PHP5 163 list($ml, $extra) = preg_replace($shorthand, $tens, array(ini_get('memory_limit'), EXTRA_MEMORY)); 164 if ($ml < $extra) { 165 // this won't work on all servers but it's worth a try 166 ini_set('memory_limit', EXTRA_MEMORY); 167 } 168 } 169 170 // read SRC 171 if ($this->_SRC['type'] == 1) $this->_SRC['image'] = imagecreatefromgif($this->_SRC['file']); 172 elseif ($this->_SRC['type'] == 2) $this->_SRC['image'] = imagecreatefromjpeg($this->_SRC['file']); 173 elseif ($this->_SRC['type'] == 3) $this->_SRC['image'] = imagecreatefrompng($this->_SRC['file']); 174 175 // crop image? 176 $off_w = 0; 177 $off_h = 0; 178 if($this->crop != false) { 179 if($this->_SRC['height'] < $this->_SRC['width']) { 180 $ratio = (double)($this->_SRC['height'] / $this->_DST['height']); 181 $cpyWidth = round($this->_DST['width'] * $ratio); 182 if ($cpyWidth > $this->_SRC['width']) { 183 $ratio = (double)($this->_SRC['width'] / $this->_DST['width']); 184 $cpyWidth = $this->_SRC['width']; 185 $cpyHeight = round($this->_DST['height'] * $ratio); 186 $off_w = 0; 187 $off_h = round(($this->_SRC['height'] - $cpyHeight) / 2); 188 $this->_SRC['height'] = $cpyHeight; 189 } 190 else { 191 $cpyHeight = $this->_SRC['height']; 192 $off_w = round(($this->_SRC['width'] - $cpyWidth) / 2); 193 $off_h = 0; 194 $this->_SRC['width']= $cpyWidth; 195 } 196 } 197 else { 198 $ratio = (double)($this->_SRC['width'] / $this->_DST['width']); 199 $cpyHeight = round($this->_DST['height'] * $ratio); 200 if ($cpyHeight > $this->_SRC['height']) { 201 $ratio = (double)($this->_SRC['height'] / $this->_DST['height']); 202 $cpyHeight = $this->_SRC['height']; 203 $cpyWidth = round($this->_DST['width'] * $ratio); 204 $off_w = round(($this->_SRC['width'] - $cpyWidth) / 2); 205 $off_h = 0; 206 $this->_SRC['width']= $cpyWidth; 207 } 208 else { 209 $cpyWidth = $this->_SRC['width']; 210 $off_w = 0; 211 $off_h = round(($this->_SRC['height'] - $cpyHeight) / 2); 212 $this->_SRC['height'] = $cpyHeight; 213 } 214 } 215 } 216 217 // ensure non-zero height/width 218 if (!$this->_DST['height']) $this->_DST['height'] = 1; 219 if (!$this->_DST['width']) $this->_DST['width'] = 1; 220 221 // create DST 222 $this->_DST['image'] = imagecreatetruecolor($this->_DST['width'], $this->_DST['height']); 223 224 // GIF or PNG destination, set the transparency up. 225 if ($this->_DST['type'] == 1 || $this->_DST['type'] == 3) { 226 $trans_idx = imagecolortransparent($this->_SRC['image']); 227 228 // Is there a specific transparent colour? 229 if ($trans_idx >= 0) { 230 $trans_color = imagecolorsforindex($this->_SRC['image'], $trans_idx); 231 $trans_idx = imagecolorallocate($this->_DST['image'], $trans_color['red'], $trans_color['green'], $trans_color['blue']); 232 imagefill($this->_DST['image'], 0, 0, $trans_idx); 233 imagecolortransparent($this->_DST['image'], $trans_idx); 234 } else if ($this->_DST['type'] == 3) { 235 imagealphablending($this->_DST['image'], false); 236 $transparent = imagecolorallocatealpha($this->_DST['image'], 0, 0, 0, 127); 237 imagefill($this->_DST['image'], 0, 0, $transparent); 238 imagesavealpha($this->_DST['image'], true); 239 } 240 } 241 imagecopyresampled($this->_DST['image'], $this->_SRC['image'], 0, 0, $off_w, $off_h, $this->_DST['width'], $this->_DST['height'], $this->_SRC['width'], $this->_SRC['height']); 242 if ($this->sharpen === true) { 243 $this->_DST['image'] = UnsharpMask($this->_DST['image'],80,.5,3); 244 } 245 246 // finally: the real dimensions 247 $this->height = $this->_DST['height']; 248 $this->width = $this->_DST['width']; 249 250 // add magnifying glass? 251 if ( $this->hint === true) { 252 // should we really add white bars? 253 if ( $this->addgreytohint === true ) { 254 $trans = imagecolorallocatealpha($this->_DST['image'], 255, 255, 255, 25); 255 imagefilledrectangle($this->_DST['image'], 0, $this->_DST['height']-9, $this->_DST['width'], $this->_DST['height'], $trans); 256 } 257 258 $magnifier = imagecreatefromstring(gzuncompress(base64_decode("eJzrDPBz5+WS4mJgYOD19HAJAtLcIMzBBiRXrilXA1IsxU6eIRxAUMOR0gHkcxZ4RBYD1QiBMOOlu3V/gIISJa4RJc5FqYklmfl5CiGZuakMBoZ6hkZ6RgYGJs77ex2BalRBaoLz00rKE4tSGXwTk4vyc1NTMhMV3DKLUsvzi7KLFXwjFEAa2svWnGdgYPTydHEMqZhTOsE++1CAyNHzm2NZjgau+dAmXlAwoatQmOld3t/NPxlLMvY7sovPzXHf7re05BPzjpQTMkZTPjm1HlHkv6clYWK43Zt16rcDjdZ/3j2cd7qD4/HHH3GaprFrw0QZDHicORXl2JsPsveVTDz//L3N+WpxJ5Hff+10Tjdd2/Vi17vea79Om5w9zzyne9GLnWGrN8atby/ayXPOsu2w4quvVtxNCVVz5nAf3nDpZckBCedpqSc28WTOWnT7rZNXZSlPvFybie9EFc6y3bIMCn3JAoJ+kyyfn9qWq+LZ9Las26Jv482cDRE6Ci0B6gVbo2oj9KabzD8vyMK4ZMqMs2kSvW4chz88SXNzmeGjtj1QZK9M3HHL8L7HITX3t19//VVY8CYDg9Kvy2vDXu+6mGGxNOiltMPsjn/t9eJr0ja/FOdi5TyQ9Lz3fOqstOr99/dnro2vZ1jy76D/vYivPsBoYPB09XNZ55TQBAAJjs5s</body>"))); 259 imagealphablending($this->_DST['image'], true); 260 imagecopy($this->_DST['image'], $magnifier, $this->_DST['width']-15, $this->_DST['height']-14, 0, 0, 11, 11); 261 imagedestroy($magnifier); 262 } 263 264 if ($verbose ) echo "... saving image ..."; 265 266 if ($this->_DST['type'] == 1) { 267 imagetruecolortopalette($this->_DST['image'], false, 256); 268 if ( function_exists ('imagegif') ) { 269 imagegif($this->_DST['image'], $this->_DST['file']); 270 } else { 271 imagedestroy($this->_DST['image']); 272 imagedestroy($this->_SRC['image']); 273 return false; 274 } 275 } 276 elseif ($this->_DST['type'] == 2) { 277 imagejpeg($this->_DST['image'], $this->_DST['file'], $this->quality); 278 } 279 elseif ($this->_DST['type'] == 3) { 280 imagepng($this->_DST['image'], $this->_DST['file']); 281 } 282 283 if ($verbose ) echo "... image successfully saved ..."; 284 285 imagedestroy($this->_DST['image']); 286 imagedestroy($this->_SRC['image']); 287 return true; 288 } 289 290 /** 291 * return a reference to the the thumbnailimage as a HTML <a> or <img> tag 292 * @param aslink return an anchor tag to the source image 293 * @param aspopup open link in new window 294 * @return string with suitable HTML markup 295 */ 296 function asTag( $aslink = true, $aspopup = false ) 297 { 298 $imgtag = "<img src=\"" . $this->_DST['file']. "\" " . 299 $this->html . " " . 300 "width=\"".$this->width."\" " . 301 "height=\"".$this->height."\" " . 302 "/>"; 303 304 if ( $aslink === true ) { 305 return "<a href=\"" . ((empty($this->linkurl)) ? $this->_SRC['file'] : $this->linkurl) . "\" " . 306 (($aspopup === true) ? "target=\"_blank\"" : "") . ">" . 307 $imgtag . 308 "</a>"; 309 } 310 else { 311 return $imgtag; 312 } 313 } 314 } 315 /** 316 * class txp_thumb: wrapper for wet_thumb interfacing the TxP repository 317 */ 318 class txp_thumb extends wet_thumb { 319 320 var $m_ext; 321 var $m_id; 322 323 /*** 324 * constructor 325 * @param $id image id 326 */ 327 function txp_thumb ($id) { 328 $id = assert_int($id); 329 $rs = safe_row('*', 'txp_image', 'id = '.$id.' limit 1'); 330 if ($rs) { 331 extract($rs); 332 $this->m_ext = $ext; 333 $this->m_id = $id; 334 } 335 $this->wet_thumb(); // construct base class instance 336 } 337 338 /** 339 * create thumbnail image from source image 340 * @return boolean, true indicates success 341 */ 342 function write( ) { 343 if ( !isset($this->m_ext) ) return false; 344 345 if ( parent::write ( IMPATH.$this->m_id.$this->m_ext, IMPATH.$this->m_id.'t'.$this->m_ext ) ) { 346 safe_update('txp_image', "thumbnail = 1, thumb_w = $this->width, thumb_h = $this->height, date = now()", 'id = '.$this->m_id); 347 chmod(IMPATH.$this->m_id.'t'.$this->m_ext, 0644); 348 return true; 349 } 350 return false; 351 } 352 353 /** 354 * delete thumbnail 355 * @return boolean, true indicates success 356 */ 357 function delete( ) { 358 if (!isset($this->m_ext)) return false; 359 360 if (unlink(IMPATH.$this->m_id.'t'.$this->m_ext)) { 361 safe_update('txp_image', 'thumbnail = 0', 'id = '.$this->m_id); 362 return true; 363 } 364 return false; 365 } 366 367 } 368 369 /** 370 * Unsharp mask algorithm by Torstein Hønsi 2003 (thoensi_at_netcom_dot_no) 371 * Christoph Erdmann: changed it a little, cause i could not reproduce the 372 * darker blurred image, now it is up to 15% faster with same results 373 * @param img image as a ressource 374 * @param amount filter parameter 375 * @param radius filter parameter 376 * @param treshold filter parameter 377 * @return sharpened image as a ressource 378 * 379 * 380 * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. 381 */ 382 383 function UnsharpMask($img, $amount, $radius, $threshold) { 384 // Attempt to calibrate the parameters to Photoshop: 385 if ($amount > 500) $amount = 500; 386 $amount = $amount * 0.016; 387 if ($radius > 50) $radius = 50; 388 $radius = $radius * 2; 389 if ($threshold > 255) $threshold = 255; 390 391 $radius = abs(round($radius)); // Only integers make sense. 392 if ($radius == 0) { return $img; imagedestroy($img); break; } 393 $w = imagesx($img); $h = imagesy($img); 394 $imgCanvas = $img; 395 $imgCanvas2 = $img; 396 $imgBlur = imagecreatetruecolor($w, $h); 397 398 // Gaussian blur matrix: 399 // 1 2 1 400 // 2 4 2 401 // 1 2 1 402 403 // Move copies of the image around one pixel at the time and merge them with weight 404 // according to the matrix. The same matrix is simply repeated for higher radii. 405 for ($i = 0; $i < $radius; $i++) 406 { 407 imagecopy ($imgBlur, $imgCanvas, 0, 0, 1, 1, $w - 1, $h - 1); // up left 408 imagecopymerge ($imgBlur, $imgCanvas, 1, 1, 0, 0, $w, $h, 50); // down right 409 imagecopymerge ($imgBlur, $imgCanvas, 0, 1, 1, 0, $w - 1, $h, 33.33333); // down left 410 imagecopymerge ($imgBlur, $imgCanvas, 1, 0, 0, 1, $w, $h - 1, 25); // up right 411 imagecopymerge ($imgBlur, $imgCanvas, 0, 0, 1, 0, $w - 1, $h, 33.33333); // left 412 imagecopymerge ($imgBlur, $imgCanvas, 1, 0, 0, 0, $w, $h, 25); // right 413 imagecopymerge ($imgBlur, $imgCanvas, 0, 0, 0, 1, $w, $h - 1, 20 ); // up 414 imagecopymerge ($imgBlur, $imgCanvas, 0, 1, 0, 0, $w, $h, 16.666667); // down 415 imagecopymerge ($imgBlur, $imgCanvas, 0, 0, 0, 0, $w, $h, 50); // center 416 } 417 $imgCanvas = $imgBlur; 418 419 // Calculate the difference between the blurred pixels and the original 420 // and set the pixels 421 for ($x = 0; $x < $w; $x++) { // each row 422 for ($y = 0; $y < $h; $y++) { // each pixel 423 $rgbOrig = ImageColorAt($imgCanvas2, $x, $y); 424 $rOrig = (($rgbOrig >> 16) & 0xFF); 425 $gOrig = (($rgbOrig >> 8) & 0xFF); 426 $bOrig = ($rgbOrig & 0xFF); 427 $rgbBlur = ImageColorAt($imgCanvas, $x, $y); 428 $rBlur = (($rgbBlur >> 16) & 0xFF); 429 $gBlur = (($rgbBlur >> 8) & 0xFF); 430 $bBlur = ($rgbBlur & 0xFF); 431 432 // When the masked pixels differ less from the original 433 // than the threshold specifies, they are set to their original value. 434 $rNew = (abs($rOrig - $rBlur) >= $threshold) ? max(0, min(255, ($amount * ($rOrig - $rBlur)) + $rOrig)) : $rOrig; 435 $gNew = (abs($gOrig - $gBlur) >= $threshold) ? max(0, min(255, ($amount * ($gOrig - $gBlur)) + $gOrig)) : $gOrig; 436 $bNew = (abs($bOrig - $bBlur) >= $threshold) ? max(0, min(255, ($amount * ($bOrig - $bBlur)) + $bOrig)) : $bOrig; 437 438 if (($rOrig != $rNew) || ($gOrig != $gNew) || ($bOrig != $bNew)) { 439 $pixCol = ImageColorAllocate($img, $rNew, $gNew, $bNew); 440 ImageSetPixel($img, $x, $y, $pixCol); 441 } 442 } 443 } 444 return $img; 445 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
title