[ Index ] [ Index ]     [ Classes ]     [ Functions ]     [ Variables ]     [ Constants ]

PHP Cross Reference of TXP stable 4.0.6

title

Body

[close]

/textpattern/lib/ -> class.thumb.php (source)

   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: http://svn.textpattern.com/releases/4.0.6/source/textpattern/lib/class.thumb.php $
  36  $LastChangedRevision: 2329 $
  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      ### Info über Source (SRC) holen
  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      //Prüfen ob das Orginalbild hoch oder querformatig ist
  98      if ($this->_SRC['width'] >= $this->_SRC['height']) {
  99          $this->_SRC['format'] = 'landscape';
 100      } else {
 101          $this->_SRC['format'] = 'portrait';
 102      }
 103  
 104      ### Info über Destination (DST) holen
 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          // Das Größenverhältnis soll erhalten bleiben egal ob das Bild hoch oder querformatig ist.
 119          // Hier wurde die lange Seite angegeben
 120          if ($this->_SRC['format'] == 'portrait') {
 121          $this->_DST['height']    = $this->longside;
 122          $this->_DST['width']    = round($this->longside/($this->_SRC['height']/$this->_SRC['width']));
 123          }
 124          else {
 125          $this->_DST['width']    = $this->longside;
 126          $this->_DST['height']    = round($this->longside/($this->_SRC['width']/$this->_SRC['height']));
 127          }
 128          }
 129      elseif (is_numeric($this->shortside)) {
 130          // Das Größenverhältnis soll erhalten bleiben egal ob das Bild hoch oder querformatig ist.
 131          // aber hier wurde die kurze Seite angeben.
 132          if ($this->_SRC['format'] == 'portrait') {
 133          $this->_DST['width']    = $this->shortside;
 134          $this->_DST['height']    = round($this->shortside/($this->_SRC['width']/$this->_SRC['height']));
 135          }
 136          else {
 137          $this->_DST['height']    = $this->shortside;
 138          $this->_DST['width']    = round($this->shortside/($this->_SRC['height']/$this->_SRC['width']));
 139          }
 140          }
 141          else { // default dimensions
 142              $this->width = 100;
 143              $this->_DST['width'] = $this->width;
 144              $this->_DST['height'] = round($this->width/($this->_SRC['width']/$this->_SRC['height']));
 145          }
 146  
 147  
 148      // Wenn das Ursprungsbild kleiner als das Ziel-Bild ist, soll nicht hochskaliert werden
 149      if ($this->extrapolate === false && $this->_DST['height'] > $this->_SRC['height'] &&
 150                          $this->_DST['width'] > $this->_SRC['width']) {
 151          $this->_DST['width'] = $this->_SRC['width'];
 152          $this->_DST['height'] = $this->_SRC['height'];
 153      }
 154  
 155      $this->_DST['type'] = $this->_SRC['type']; 
 156      $this->_DST['file'] = $outfile;
 157  
 158      // Make sure we have enough memory if the image is large
 159      if (max($this->_SRC['width'], $this->_SRC['height']) > 1024)
 160          // this won't work on all servers but it's worth a try
 161          ini_set('memory_limit', EXTRA_MEMORY);
 162  
 163      // SRC einlesen
 164      if ($this->_SRC['type'] == 1)    $this->_SRC['image'] = imagecreatefromgif($this->_SRC['file']);
 165      elseif ($this->_SRC['type'] == 2)    $this->_SRC['image'] = imagecreatefromjpeg($this->_SRC['file']);
 166      elseif ($this->_SRC['type'] == 3)    $this->_SRC['image'] = imagecreatefrompng($this->_SRC['file']);
 167  
 168      // Soll beschnitten werden?
 169      $off_w = 0;
 170      $off_h = 0;
 171      if($this->crop != false) {
 172          if($this->_SRC['height'] < $this->_SRC['width']) {
 173          $ratio = (double)($this->_SRC['height'] / $this->_DST['height']);
 174          $cpyWidth = round($this->_DST['width'] * $ratio);
 175          if ($cpyWidth > $this->_SRC['width']) {                   
 176              $ratio = (double)($this->_SRC['width'] / $this->_DST['width']);
 177              $cpyWidth = $this->_SRC['width'];
 178              $cpyHeight = round($this->_DST['height'] * $ratio);
 179              $off_w = 0;
 180              $off_h = round(($this->_SRC['height'] - $cpyHeight) / 2);                              
 181              $this->_SRC['height'] = $cpyHeight;
 182          }
 183          else {                   
 184              $cpyHeight = $this->_SRC['height'];
 185              $off_w = round(($this->_SRC['width'] - $cpyWidth) / 2);
 186              $off_h = 0;               
 187              $this->_SRC['width']= $cpyWidth;
 188          }
 189          }
 190          else {
 191          $ratio = (double)($this->_SRC['width'] / $this->_DST['width']);
 192          $cpyHeight = round($this->_DST['height'] * $ratio);
 193          if ($cpyHeight > $this->_SRC['height']) {
 194              $ratio = (double)($this->_SRC['height'] / $this->_DST['height']);
 195              $cpyHeight = $this->_SRC['height'];
 196              $cpyWidth = round($this->_DST['width'] * $ratio);
 197              $off_w = round(($this->_SRC['width'] - $cpyWidth) / 2);
 198              $off_h = 0;               
 199              $this->_SRC['width']= $cpyWidth;               
 200          }
 201          else {
 202              $cpyWidth = $this->_SRC['width'];
 203              $off_w = 0;
 204              $off_h = round(($this->_SRC['height'] - $cpyHeight) / 2);               
 205              $this->_SRC['height'] = $cpyHeight;               
 206          }
 207          }        
 208      }
 209  
 210      // DST erstellen
 211      $this->_DST['image'] = imagecreatetruecolor($this->_DST['width'], $this->_DST['height']);
 212      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']);
 213      if ($this->sharpen === true) {
 214          $this->_DST['image'] = UnsharpMask($this->_DST['image'],80,.5,3);
 215      }
 216  
 217          // finally: the real dimensions
 218          $this->height =  $this->_DST['height'];
 219          $this->width =  $this->_DST['width'];
 220  
 221      // Soll eine Lupe eingefügt werden?
 222      if ( $this->hint === true) {
 223          //Soll der weiße Balken wirklich hinzugefügt werden?
 224          if ( $this->addgreytohint === true ) {
 225          $trans = imagecolorallocatealpha($this->_DST['image'], 255, 255, 255, 25);
 226          imagefilledrectangle($this->_DST['image'], 0, $this->_DST['height']-9, $this->_DST['width'], $this->_DST['height'], $trans);
 227          }
 228  
 229          $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>")));
 230          imagealphablending($this->_DST['image'], true);
 231          imagecopy($this->_DST['image'], $magnifier, $this->_DST['width']-15, $this->_DST['height']-14, 0, 0, 11, 11);
 232          imagedestroy($magnifier);
 233      }
 234  
 235          if ($verbose ) echo "... saving image ...";        
 236      
 237          if ($this->_DST['type'] == 1)    {
 238          imagetruecolortopalette($this->_DST['image'], false, 256);
 239          if ( function_exists ('imagegif') ) {
 240              imagegif($this->_DST['image'], $this->_DST['file']);
 241          } else {
 242              imagedestroy($this->_DST['image']);
 243              imagedestroy($this->_SRC['image']);
 244              return false;
 245          }
 246      }
 247      elseif ($this->_DST['type'] == 2) {
 248          imagejpeg($this->_DST['image'], $this->_DST['file'], $this->quality);
 249      }
 250      elseif ($this->_DST['type'] == 3) {
 251          imagepng($this->_DST['image'], $this->_DST['file']);
 252      }
 253      
 254          if ($verbose ) echo "... image successfully saved ...";
 255          
 256      imagedestroy($this->_DST['image']);
 257      imagedestroy($this->_SRC['image']);
 258      return true;
 259      }
 260      
 261      /**
 262       * return a reference to the the thumbnailimage as a HTML <a> or <img> tag
 263       * @param    aslink    return an anchor tag to the source image
 264       * @param    aspopup    open link in new window
 265       * @return    string with suitable HTML markup
 266       */
 267      function asTag( $aslink = true, $aspopup = false  )
 268      {
 269          $imgtag = "<img src=\"" . $this->_DST['file']. "\" " .
 270                      $this->html . " " .
 271                      "width=\"".$this->width."\" " .
 272                      "height=\"".$this->height."\" " .
 273                      "/>";
 274                      
 275          if ( $aslink === true ) {
 276              return "<a href=\"" . ((empty($this->linkurl)) ? $this->_SRC['file'] : $this->linkurl) . "\" " .
 277                      (($aspopup === true) ? "target=\"_blank\"" : "") . ">" .
 278                      $imgtag .
 279                      "</a>";
 280          }
 281          else {
 282              return $imgtag;
 283          }    
 284      }
 285  }
 286  /**
 287   * class txp_thumb: wrapper for wet_thumb interfacing the TxP repository
 288   */ 
 289  class txp_thumb extends wet_thumb {
 290      
 291      var $m_ext;
 292      var $m_id;
 293      
 294      /***
 295       * constructor
 296       * @param    $id    image id
 297       */
 298      function txp_thumb ($id) {
 299          $id = assert_int($id);
 300          $rs = safe_row('*', 'txp_image', 'id = '.$id.' limit 1');
 301          if ($rs) {
 302              extract($rs);
 303              $this->m_ext = $ext;
 304              $this->m_id = $id;
 305          }
 306          $this->wet_thumb(); // construct base class instance
 307      }
 308      
 309      /**
 310       * create thumbnail image from source image
 311       * @return    boolean, true indicates success
 312       */
 313      function write( ) {
 314          if ( !isset($this->m_ext) ) return false;
 315          
 316          if ( parent::write ( IMPATH.$this->m_id.$this->m_ext, IMPATH.$this->m_id.'t'.$this->m_ext ) ) {
 317              safe_update('txp_image', 'thumbnail = 1', 'id = '.$this->m_id);
 318              return true;
 319          }
 320          return false;
 321      }
 322  
 323       /**
 324       * delete thumbnail
 325       * @return    boolean, true indicates success
 326       */
 327      function delete( ) {
 328          if (!isset($this->m_ext)) return false;
 329          
 330          if (unlink(IMPATH.$this->m_id.'t'.$this->m_ext)) {
 331              safe_update('txp_image', 'thumbnail = 0', 'id = '.$this->m_id);
 332              return true;
 333          }
 334      return false;
 335      }
 336    
 337  }
 338  
 339  /**
 340   * Unsharp mask algorithm by Torstein Hønsi 2003 (thoensi_at_netcom_dot_no)
 341   * Christoph Erdmann: changed it a little, cause i could not reproduce the
 342   * darker blurred image, now it is up to 15% faster with same results
 343   * @param   img     image as a ressource
 344   * @param   amount  filter parameter
 345   * @param   radius  filter parameter
 346   * @param   treshold    filter parameter
 347   * @return  sharpened image as a ressource
 348   *
 349   * 
 350   * 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.
 351  */
 352  
 353  function UnsharpMask($img, $amount, $radius, $threshold)    {
 354      // Attempt to calibrate the parameters to Photoshop:
 355      if ($amount > 500) $amount = 500;
 356      $amount = $amount * 0.016;
 357      if ($radius > 50) $radius = 50;
 358      $radius = $radius * 2;
 359      if ($threshold > 255) $threshold = 255;
 360      
 361      $radius = abs(round($radius));     // Only integers make sense.
 362      if ($radius == 0) {    return $img; imagedestroy($img); break;    }
 363      $w = imagesx($img); $h = imagesy($img);
 364      $imgCanvas = $img;
 365      $imgCanvas2 = $img;
 366      $imgBlur = imagecreatetruecolor($w, $h);
 367      
 368      // Gaussian blur matrix:
 369      //    1    2    1        
 370      //    2    4    2        
 371      //    1    2    1        
 372      
 373      // Move copies of the image around one pixel at the time and merge them with weight
 374      // according to the matrix. The same matrix is simply repeated for higher radii.
 375      for ($i = 0; $i < $radius; $i++)
 376              {
 377              imagecopy      ($imgBlur, $imgCanvas, 0, 0, 1, 1, $w - 1, $h - 1); // up left
 378              imagecopymerge ($imgBlur, $imgCanvas, 1, 1, 0, 0, $w, $h, 50); // down right
 379              imagecopymerge ($imgBlur, $imgCanvas, 0, 1, 1, 0, $w - 1, $h, 33.33333); // down left
 380              imagecopymerge ($imgBlur, $imgCanvas, 1, 0, 0, 1, $w, $h - 1, 25); // up right
 381              imagecopymerge ($imgBlur, $imgCanvas, 0, 0, 1, 0, $w - 1, $h, 33.33333); // left
 382              imagecopymerge ($imgBlur, $imgCanvas, 1, 0, 0, 0, $w, $h, 25); // right
 383              imagecopymerge ($imgBlur, $imgCanvas, 0, 0, 0, 1, $w, $h - 1, 20 ); // up
 384              imagecopymerge ($imgBlur, $imgCanvas, 0, 1, 0, 0, $w, $h, 16.666667); // down
 385              imagecopymerge ($imgBlur, $imgCanvas, 0, 0, 0, 0, $w, $h, 50); // center
 386              }
 387      $imgCanvas = $imgBlur;    
 388              
 389      // Calculate the difference between the blurred pixels and the original
 390      // and set the pixels
 391      for ($x = 0; $x < $w; $x++) { // each row
 392          for ($y = 0; $y < $h; $y++) { // each pixel
 393              $rgbOrig = ImageColorAt($imgCanvas2, $x, $y);
 394              $rOrig = (($rgbOrig >> 16) & 0xFF);
 395              $gOrig = (($rgbOrig >> 8) & 0xFF);
 396              $bOrig = ($rgbOrig & 0xFF);
 397              $rgbBlur = ImageColorAt($imgCanvas, $x, $y);
 398              $rBlur = (($rgbBlur >> 16) & 0xFF);
 399              $gBlur = (($rgbBlur >> 8) & 0xFF);
 400              $bBlur = ($rgbBlur & 0xFF);
 401      
 402              // When the masked pixels differ less from the original
 403              // than the threshold specifies, they are set to their original value.
 404              $rNew = (abs($rOrig - $rBlur) >= $threshold) ? max(0, min(255, ($amount * ($rOrig - $rBlur)) + $rOrig)) : $rOrig;
 405              $gNew = (abs($gOrig - $gBlur) >= $threshold) ? max(0, min(255, ($amount * ($gOrig - $gBlur)) + $gOrig)) : $gOrig;
 406              $bNew = (abs($bOrig - $bBlur) >= $threshold) ? max(0, min(255, ($amount * ($bOrig - $bBlur)) + $bOrig)) : $bOrig;
 407              
 408              if (($rOrig != $rNew) || ($gOrig != $gNew) || ($bOrig != $bNew)) {
 409                  $pixCol = ImageColorAllocate($img, $rNew, $gNew, $bNew);
 410                  ImageSetPixel($img, $x, $y, $pixCol);
 411              }
 412          }
 413      }
 414      return $img;
 415  }


Generated: Mon Feb 18 03:42:45 2008 Cross-referenced by PHPXref 0.7