Monday, March 22, 2010

Image class

Ok, here I go. The very first violation of my own rule - not posting anything obvious.
This time however I needed to find a good class Image that works with GD and is designed nicely. After 10 min of search I decided to write my own. So, for the lack of better place, I will put it here. If you are not into the obvious - skip this post.

<?

 /**
  * Class Image
  * @author Alexander Podgorny
  * @license GPL
  */

 class Image {
  const RESIZE_FILL   = 2; // When resizing, constrain proportions, keep largest dimension
  const RESIZE_FIT  = 3; // When resizing, constrain proportions, keep smallest dimension
  const RESIZE_STRETCH  = 1; // When resizing, do not constrain proportions, keep both dimensions
  
  const TYPE_JPEG   = 10;
  const TYPE_GIF   = 11;
  const TYPE_PNG   = 12;
  
  private $_sFileName = '';
  private $_oImage  = null;
  private $_nW   = 0;
  private $_nH  = 0;
  
  public function __construct($sFileName=null) {
   if ($sFileName) {
    $this->open($sFileName);
   }
  }
  
  public function __destruct() {
   imagedestroy($this->_oImage);
  }
  
  public function open($sFileName) {
   if (!file_exists($sFileName)) {
    throw new Exception('File could not be found: '.$sFileName);
   }
   $this->_sFileName  = $sFileName;
   $sExtension   = strtolower(strrchr($sFileName, '.'));
   switch ($sExtension) {
          case '.jpg':
          case '.jpeg':
              $this->_oImage = imagecreatefromjpeg($sFileName);
              break;
          case '.gif':
              $this->_oImage = imagecreatefromgif($sFileName);
              break;
          case '.png':
              $this->_oImage = imagecreatefrompng($sFileName);
              break;
          default:
     throw new Exception('Unknown file type: '.$sFileName);
      }   
   $this->_nW   = imagesx($this->_oImage);
   $this->_nH  = imagesy($this->_oImage);
   return $this;
  }
  
  public function resize($nW, $nH, $nOption=self::RESIZE_FIT) {
   $nSrcRatio = $this->_nW / $this->_nH;
   $nDstRatio = $nW / $nH;
   
   switch ($nOption) {
    case self::RESIZE_STRETCH:
     // do nothing;
     break;
    case self::RESIZE_FILL:
     if ($nDstRatio > $nSrcRatio) {
      $nH = $nW / $nSrcRatio;
     } else {
      $nW = $nSrcRatio * $nH;
     }
     break;
    case self::RESIZE_FIT:
    default:
     if ($nDstRatio > $nSrcRatio) {
      $nW = $nSrcRatio * $nH;
     } else {
      $nH = $nW / $nSrcRatio;
     }
     break;
   }
   $nW = floor($nW);
   $nH = floor($nH);
   $oImageResized = imagecreatetruecolor($nW, $nH);
   imagecopyresampled(
    $oImageResized, 
    $this->_oImage, 
    0, 0, 0, 0, 
    $nW, 
    $nH, 
    $this->_nW, 
    $this->_nH
   );
   imagedestroy($this->_oImage);
   $this->_oImage = $oImageResized;
   $this->_nW = $nW;
   $this->_nH = $nH;
   return $this;
  }
  
  public function save($sFileName=null, $nQuality=null) {
   if (!$sFileName) { $sFileName = $this->_sFileName; }
   $sExtension   = strtolower(strrchr($sFileName, '.'));
   if (!$sFileName) {
    throw new Exception('Could not save file. File name is not supplied');
   }
   switch ($sExtension) {
          case '.jpg':
          case '.jpeg':
           if ($nQuality !== null) {  // otherwise use built in default
      if ($nQuality < 0)   { $nQuality = 0; }
            if ($nQuality > 100) { $nQuality = 100; }
           }
              imagejpeg($this->_oImage, $sFileName, $nQuality);
              break;
          case '.gif':
              imagegif($this->_oImage, $sFileName);
              break;
          case '.png':
           if ($nQuality !== null) {  // otherwise use built in default
      if ($nQuality > 9) { $nQuality = 9; }
      if ($nQuality < 0) { $nQuality = 0; }
           }
              imagepng($this->_oImage, $sFileName, $nQuality);
              break;
          default:
     throw new Exception('Unknown file type: '.$sFileName);
     break;
      }   
   return $this;
  }
  
  public function output($nType=self::TYPE_JPEG, $nQuality=null) {
   switch ($nType) {
          case self::TYPE_JPEG:
           if ($nQuality) {  // otherwise use built in default
      if ($nQuality < 0)   { $nQuality = 0; }
            if ($nQuality > 100) { $nQuality = 100; }
           }
           header('Content-type: image/jpeg');
              imagejpeg($this->_oImage, null, $nQuality);
              break;
          case self::TYPE_GIF:
           header('Content-type: image/gif');
              imagegif($this->_oImage, null);
              break;
          case self::TYPE_PNG:
           if ($nQuality) {  // otherwise use built in default
      if ($nQuality > 9) { $nQuality = 9; }
      if ($nQuality < 0) { $nQuality = 0; }
           }
           header('Content-type: image/png');
              imagepng($this->_oImage, null, $nQuality);
              break;
          default:
     throw new Exception('Unknown file type');
     break;
      }   
   return $this;
  }
  
 }

?>

No comments: