[ Index ]

PHP Cross Reference of Textpattern 4.0.8

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: https://textpattern.googlecode.com/svn/releases/4.0.8/source/textpattern/lib/class.thumb.php $
  36  $LastChangedRevision: 3041 $
  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          // this won't work on all servers but it's worth a try
 159          ini_set('memory_limit', EXTRA_MEMORY);
 160  
 161      // read SRC
 162      if ($this->_SRC['type'] == 1)    $this->_SRC['image'] = imagecreatefromgif($this->_SRC['file']);
 163      elseif ($this->_SRC['type'] == 2)    $this->_SRC['image'] = imagecreatefromjpeg($this->_SRC['file']);
 164      elseif ($this->_SRC['type'] == 3)    $this->_SRC['image'] = imagecreatefrompng($this->_SRC['file']);
 165  
 166      // crop image?
 167      $off_w = 0;
 168      $off_h = 0;
 169      if($this->crop != false) {
 170          if($this->_SRC['height'] < $this->_SRC['width']) {
 171          $ratio = (double)($this->_SRC['height'] / $this->_DST['height']);
 172          $cpyWidth = round($this->_DST['width'] * $ratio);
 173          if ($cpyWidth > $this->_SRC['width']) {
 174              $ratio = (double)($this->_SRC['width'] / $this->_DST['width']);
 175              $cpyWidth = $this->_SRC['width'];
 176              $cpyHeight = round($this->_DST['height'] * $ratio);
 177              $off_w = 0;
 178              $off_h = round(($this->_SRC['height'] - $cpyHeight) / 2);
 179              $this->_SRC['height'] = $cpyHeight;
 180          }
 181          else {
 182              $cpyHeight = $this->_SRC['height'];
 183              $off_w = round(($this->_SRC['width'] - $cpyWidth) / 2);
 184              $off_h = 0;
 185              $this->_SRC['width']= $cpyWidth;
 186          }
 187          }
 188          else {
 189          $ratio = (double)($this->_SRC['width'] / $this->_DST['width']);
 190          $cpyHeight = round($this->_DST['height'] * $ratio);
 191          if ($cpyHeight > $this->_SRC['height']) {
 192              $ratio = (double)($this->_SRC['height'] / $this->_DST['height']);
 193              $cpyHeight = $this->_SRC['height'];
 194              $cpyWidth = round($this->_DST['width'] * $ratio);
 195              $off_w = round(($this->_SRC['width'] - $cpyWidth) / 2);
 196              $off_h = 0;
 197              $this->_SRC['width']= $cpyWidth;
 198          }
 199          else {
 200              $cpyWidth = $this->_SRC['width'];
 201              $off_w = 0;
 202              $off_h = round(($this->_SRC['height'] - $cpyHeight) / 2);
 203              $this->_SRC['height'] = $cpyHeight;
 204          }
 205          }
 206      }
 207  
 208      // ensure non-zero height/width
 209      if (!$this->_DST['height']) $this->_DST['height'] = 1;
 210      if (!$this->_DST['width'])  $this->_DST['width']  = 1;
 211  
 212      // create DST
 213      $this->_DST['image'] = imagecreatetruecolor($this->_DST['width'], $this->_DST['height']);
 214      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']);
 215      if ($this->sharpen === true) {
 216          $this->_DST['image'] = UnsharpMask($this->_DST['image'],80,.5,3);
 217      }
 218  
 219          // finally: the real dimensions
 220          $this->height =  $this->_DST['height'];
 221          $this->width =  $this->_DST['width'];
 222  
 223      // add magnifying glass?
 224      if ( $this->hint === true) {
 225          // should we really add white bars?
 226          if ( $this->addgreytohint === true ) {
 227          $trans = imagecolorallocatealpha($this->_DST['image'], 255, 255, 255, 25);
 228          imagefilledrectangle($this->_DST['image'], 0, $this->_DST['height']-9, $this->_DST['width'], $this->_DST['height'], $trans);
 229          }
 230  
 231          $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>")));
 232          imagealphablending($this->_DST['image'], true);
 233          imagecopy($this->_DST['image'], $magnifier, $this->_DST['width']-15, $this->_DST['height']-14, 0, 0, 11, 11);
 234          imagedestroy($magnifier);
 235      }
 236  
 237          if ($verbose ) echo "... saving image ...";
 238  
 239          if ($this->_DST['type'] == 1)    {
 240          imagetruecolortopalette($this->_DST['image'], false, 256);
 241          if ( function_exists ('imagegif') ) {
 242              imagegif($this->_DST['image'], $this->_DST['file']);
 243          } else {
 244              imagedestroy($this->_DST['image']);
 245              imagedestroy($this->_SRC['image']);
 246              return false;
 247          }
 248      }
 249      elseif ($this->_DST['type'] == 2) {
 250          imagejpeg($this->_DST['image'], $this->_DST['file'], $this->quality);
 251      }
 252      elseif ($this->_DST['type'] == 3) {
 253          imagepng($this->_DST['image'], $this->_DST['file']);
 254      }
 255  
 256          if ($verbose ) echo "... image successfully saved ...";
 257  
 258      imagedestroy($this->_DST['image']);
 259      imagedestroy($this->_SRC['image']);
 260      return true;
 261      }
 262  
 263      /**
 264       * return a reference to the the thumbnailimage as a HTML <a> or <img> tag
 265       * @param    aslink    return an anchor tag to the source image
 266       * @param    aspopup    open link in new window
 267       * @return    string with suitable HTML markup
 268       */
 269      function asTag( $aslink = true, $aspopup = false  )
 270      {
 271          $imgtag = "<img src=\"" . $this->_DST['file']. "\" " .
 272                      $this->html . " " .
 273                      "width=\"".$this->width."\" " .
 274                      "height=\"".$this->height."\" " .
 275                      "/>";
 276  
 277          if ( $aslink === true ) {
 278              return "<a href=\"" . ((empty($this->linkurl)) ? $this->_SRC['file'] : $this->linkurl) . "\" " .
 279                      (($aspopup === true) ? "target=\"_blank\"" : "") . ">" .
 280                      $imgtag .
 281                      "</a>";
 282          }
 283          else {
 284              return $imgtag;
 285          }
 286      }
 287  }
 288  /**
 289   * class txp_thumb: wrapper for wet_thumb interfacing the TxP repository
 290   */
 291  class txp_thumb extends wet_thumb {
 292  
 293      var $m_ext;
 294      var $m_id;
 295  
 296      /***
 297       * constructor
 298       * @param    $id    image id
 299       */
 300      function txp_thumb ($id) {
 301          $id = assert_int($id);
 302          $rs = safe_row('*', 'txp_image', 'id = '.$id.' limit 1');
 303          if ($rs) {
 304              extract($rs);
 305              $this->m_ext = $ext;
 306              $this->m_id = $id;
 307          }
 308          $this->wet_thumb(); // construct base class instance
 309      }
 310  
 311      /**
 312       * create thumbnail image from source image
 313       * @return    boolean, true indicates success
 314       */
 315      function write( ) {
 316          if ( !isset($this->m_ext) ) return false;
 317  
 318          if ( parent::write ( IMPATH.$this->m_id.$this->m_ext, IMPATH.$this->m_id.'t'.$this->m_ext ) ) {
 319              safe_update('txp_image', 'thumbnail = 1', 'id = '.$this->m_id);
 320              chmod(IMPATH.$this->m_id.'t'.$this->m_ext, 0644);
 321              return true;
 322          }
 323          return false;
 324      }
 325  
 326       /**
 327       * delete thumbnail
 328       * @return    boolean, true indicates success
 329       */
 330      function delete( ) {
 331          if (!isset($this->m_ext)) return false;
 332  
 333          if (unlink(IMPATH.$this->m_id.'t'.$this->m_ext)) {
 334              safe_update('txp_image', 'thumbnail = 0', 'id = '.$this->m_id);
 335              return true;
 336          }
 337      return false;
 338      }
 339  
 340  }
 341  
 342  /**
 343   * Unsharp mask algorithm by Torstein Hønsi 2003 (thoensi_at_netcom_dot_no)
 344   * Christoph Erdmann: changed it a little, cause i could not reproduce the
 345   * darker blurred image, now it is up to 15% faster with same results
 346   * @param   img     image as a ressource
 347   * @param   amount  filter parameter
 348   * @param   radius  filter parameter
 349   * @param   treshold    filter parameter
 350   * @return  sharpened image as a ressource
 351   *
 352   *
 353   * 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.
 354  */
 355  
 356  function UnsharpMask($img, $amount, $radius, $threshold)    {
 357      // Attempt to calibrate the parameters to Photoshop:
 358      if ($amount > 500) $amount = 500;
 359      $amount = $amount * 0.016;
 360      if ($radius > 50) $radius = 50;
 361      $radius = $radius * 2;
 362      if ($threshold > 255) $threshold = 255;
 363  
 364      $radius = abs(round($radius));     // Only integers make sense.
 365      if ($radius == 0) {    return $img; imagedestroy($img); break;    }
 366      $w = imagesx($img); $h = imagesy($img);
 367      $imgCanvas = $img;
 368      $imgCanvas2 = $img;
 369      $imgBlur = imagecreatetruecolor($w, $h);
 370  
 371      // Gaussian blur matrix:
 372      //    1    2    1
 373      //    2    4    2
 374      //    1    2    1
 375  
 376      // Move copies of the image around one pixel at the time and merge them with weight
 377      // according to the matrix. The same matrix is simply repeated for higher radii.
 378      for ($i = 0; $i < $radius; $i++)
 379              {
 380              imagecopy      ($imgBlur, $imgCanvas, 0, 0, 1, 1, $w - 1, $h - 1); // up left
 381              imagecopymerge ($imgBlur, $imgCanvas, 1, 1, 0, 0, $w, $h, 50); // down right
 382              imagecopymerge ($imgBlur, $imgCanvas, 0, 1, 1, 0, $w - 1, $h, 33.33333); // down left
 383              imagecopymerge ($imgBlur, $imgCanvas, 1, 0, 0, 1, $w, $h - 1, 25); // up right
 384              imagecopymerge ($imgBlur, $imgCanvas, 0, 0, 1, 0, $w - 1, $h, 33.33333); // left
 385              imagecopymerge ($imgBlur, $imgCanvas, 1, 0, 0, 0, $w, $h, 25); // right
 386              imagecopymerge ($imgBlur, $imgCanvas, 0, 0, 0, 1, $w, $h - 1, 20 ); // up
 387              imagecopymerge ($imgBlur, $imgCanvas, 0, 1, 0, 0, $w, $h, 16.666667); // down
 388              imagecopymerge ($imgBlur, $imgCanvas, 0, 0, 0, 0, $w, $h, 50); // center
 389              }
 390      $imgCanvas = $imgBlur;
 391  
 392      // Calculate the difference between the blurred pixels and the original
 393      // and set the pixels
 394      for ($x = 0; $x < $w; $x++) { // each row
 395          for ($y = 0; $y < $h; $y++) { // each pixel
 396              $rgbOrig = ImageColorAt($imgCanvas2, $x, $y);
 397              $rOrig = (($rgbOrig >> 16) & 0xFF);
 398              $gOrig = (($rgbOrig >> 8) & 0xFF);
 399              $bOrig = ($rgbOrig & 0xFF);
 400              $rgbBlur = ImageColorAt($imgCanvas, $x, $y);
 401              $rBlur = (($rgbBlur >> 16) & 0xFF);
 402              $gBlur = (($rgbBlur >> 8) & 0xFF);
 403              $bBlur = ($rgbBlur & 0xFF);
 404  
 405              // When the masked pixels differ less from the original
 406              // than the threshold specifies, they are set to their original value.
 407              $rNew = (abs($rOrig - $rBlur) >= $threshold) ? max(0, min(255, ($amount * ($rOrig - $rBlur)) + $rOrig)) : $rOrig;
 408              $gNew = (abs($gOrig - $gBlur) >= $threshold) ? max(0, min(255, ($amount * ($gOrig - $gBlur)) + $gOrig)) : $gOrig;
 409              $bNew = (abs($bOrig - $bBlur) >= $threshold) ? max(0, min(255, ($amount * ($bOrig - $bBlur)) + $bOrig)) : $bOrig;
 410  
 411              if (($rOrig != $rNew) || ($gOrig != $gNew) || ($bOrig != $bNew)) {
 412                  $pixCol = ImageColorAllocate($img, $rNew, $gNew, $bNew);
 413                  ImageSetPixel($img, $x, $y, $pixCol);
 414              }
 415          }
 416      }
 417      return $img;
 418  }


Generated: Thu May 21 23:03:01 2009 Cross-referenced by PHPXref 0.7