<?php



	class UniteImageViewRev{

		

		private $pathCache;

		private $pathImages;

		private $urlImages;

		

		private $filename = null;

		private $maxWidth = null;

		private $maxHeight = null;

		private $type = null;

		private $effect = null;

		private $effect_arg1 = null;

		private $effect_arg2 = null;

		

		const EFFECT_BW = "bw";

		const EFFECT_BRIGHTNESS = "bright";

		const EFFECT_CONTRAST = "contrast";

		const EFFECT_EDGE = "edge";

		const EFFECT_EMBOSS = "emboss";

		const EFFECT_BLUR = "blur";

		const EFFECT_BLUR3 = "blur3";

		const EFFECT_MEAN = "mean";

		const EFFECT_SMOOTH = "smooth";

		const EFFECT_DARK = "dark";

		

		const TYPE_EXACT = "exact";

		const TYPE_EXACT_TOP = "exacttop";

		

		private $jpg_quality = 81;

		

		public function __construct($pathCache,$pathImages,$urlImages){

			

			$this->pathCache = $pathCache;

			$this->pathImages = $pathImages;

			$this->urlImages = $urlImages;

		}

		

		/**

		 * 

		 * set jpg quality output

		 */

		public function setJPGQuality($quality){

			$this->jpg_quality = $quality;

		}

		

		/**

		 * 

		 * get thumb url

		 */

		public static function getUrlThumb($urlBase, $filename,$width=null,$height=null,$exact=false,$effect=null,$effect_param=null){			

			

			$filename = urlencode($filename);

			

			$url = $urlBase."&img=$filename";

			if(!empty($width))

				$url .= "&w=".$width;

			if(!empty($height))

				$url .= "&h=".$height;

				

			if($exact == true){

				$url .= "&t=".self::TYPE_EXACT;

			}

			

			if(!empty($effect)){

				$url .= "&e=".$effect;

				if(!empty($effect_param))

					$url .= "&ea1=".$effect_param;

			}

			

			return($url);

		}

		

		/**

		 * 

		 * throw error

		 */

		private function throwError($message,$code=null){

			UniteFunctionsRev::throwError($message,$code);

		}

		

		/**

		 * 

		 * get filename for thumbnail save / retrieve

		 * TODO: do input validations - security measures

		 */

		private function getThumbFilename(){

			$info = pathInfo($this->filename);

			

			//add dirname as postfix (if exists)

			$postfix = "";

			

			$dirname = UniteFunctionsRev::getVal($info, "dirname");

			if(!empty($dirname)){

				$postfix = str_replace("/", "-", $dirname);

			}

			

			

			$ext = $info["extension"];

			$name = $info["filename"];

			$width = ceil($this->maxWidth);

			$height = ceil($this->maxHeight);

			$thumbFilename = $name."_".$width."x".$height;		

			

			if(!empty($this->type)) 

				$thumbFilename .= "_" . $this->type;

				

			if(!empty($this->effect)){

				$thumbFilename .= "_e" . $this->effect;

				if(!empty($this->effect_arg1)){

					$thumbFilename .= "x" . $this->effect_arg1;

				}

			}

			

			//add postfix

			if(!empty($postfix))

				$thumbFilename .= "_".$postfix;

			

			$thumbFilename .= ".".$ext;

			

			return($thumbFilename);

		}

		

		//------------------------------------------------------------------------------------------

		// get thumbnail fielpath by parameters.

		private function getThumbFilepath(){

			$filename = $this->getThumbFilename();

			$filepath = $this->pathCache .$filename;

			return($filepath);

		}

	

		//------------------------------------------------------------------------------------------

		// ouptput emtpy image code.

		private function outputEmptyImageCode(){	

			echo "empty image";

			exit();

		}

		

		//------------------------------------------------------------------------------------------

		// outputs image and exit.

		private function outputImage($filepath){

						

			$info = UniteFunctionsRev::getPathInfo($filepath);

			$ext = $info["extension"];				

			//$filetime = filemtime($filepath);

			

			$ext = strtolower($ext);

			if($ext == "jpg")

				$ext = "jpeg";

			

			$numExpires = 31536000;	//one year

			$strExpires = @date('D, d M Y H:i:s',time()+$numExpires);

			//$strModified = @date('D, d M Y H:i:s',$filetime);

			

			$contents = file_get_contents($filepath);

			$filesize = strlen($contents);

			/*header("Last-Modified: $strModified GMT");*/

			header("Expires: $strExpires GMT");

			header("Cache-Control: public");

			header("Content-Type: image/$ext");

			header("Content-Length: $filesize");

			

			echo $contents;

			exit();

		}

		

		

		//------------------------------------------------------------------------------------------

		// get src image from filepath according the image type

		private function getGdSrcImage($filepath,$type){

			// create the image

			$src_img = false;

			switch($type){

				case IMAGETYPE_JPEG:

					$src_img = @imagecreatefromjpeg($filepath);

				break;

				case IMAGETYPE_PNG:

					$src_img = @imagecreatefrompng($filepath);

				break;

				case IMAGETYPE_GIF:

					$src_img = @imagecreatefromgif($filepath);

				break;

				case IMAGETYPE_BMP:

					$src_img = @imagecreatefromwbmp($filepath);

				break;

				default:

					$this->throwError("wrong image format, can't resize");

				break;

			}

			

			if($src_img == false){

				$this->throwError("Can't resize image");

			}

			 

			return($src_img);

		}

		

		//------------------------------------------------------------------------------------------

		// save gd image to some filepath. return if success or not

		private function saveGdImage($dst_img,$filepath,$type){

			$successSaving = false;

			switch($type){

				case IMAGETYPE_JPEG:

					$successSaving = imagejpeg($dst_img,$filepath,$this->jpg_quality);

				break;

				case IMAGETYPE_PNG:

					$successSaving = imagepng($dst_img,$filepath);

				break;

				case IMAGETYPE_GIF:

					$successSaving = imagegif($dst_img,$filepath);

				break;

				case IMAGETYPE_BMP:

					$successSaving = imagewbmp($dst_img,$filepath);

				break;

			}

			

			return($successSaving);

		}

		

		//------------------------------------------------------------------------------------------

		// crop image to specifix height and width , and save it to new path

		private function cropImageSaveNew($filepath,$filepathNew){

			

			$imgInfo = getimagesize($filepath);

			$imgType = $imgInfo[2];

			

			$src_img = $this->getGdSrcImage($filepath,$imgType);

			

			$width = imageSX($src_img);

			$height = imageSY($src_img);

			

			//crop the image from the top

			$startx = 0;

			$starty = 0;

			

			//find precrop width and height:

			$percent = $this->maxWidth / $width;

			$newWidth = $this->maxWidth;

			$newHeight = ceil($percent * $height);

			

			if($this->type == "exact"){ 	//crop the image from the middle

				$startx = 0;

				$starty = ($newHeight-$this->maxHeight)/2 / $percent;

			}

			

			if($newHeight < $this->maxHeight){	//by width

				$percent = $this->maxHeight / $height;

				$newHeight = $this->maxHeight;

				$newWidth = ceil($percent * $width);

				

				if($this->type == "exact"){ 	//crop the image from the middle

					$startx = ($newWidth - $this->maxWidth) /2 / $percent;	//the startx is related to big image

					$starty = 0;

				}

			}

			

			//resize the picture:

			$tmp_img = ImageCreateTrueColor($newWidth,$newHeight);

			

			$this->handleTransparency($tmp_img,$imgType,$newWidth,$newHeight);

			

			imagecopyresampled($tmp_img,$src_img,0,0,$startx,$starty,$newWidth,$newHeight,$width,$height);

			

			$this->handleImageEffects($tmp_img);

			

			//crop the picture:

			$dst_img = ImageCreateTrueColor($this->maxWidth,$this->maxHeight);

			

			$this->handleTransparency($dst_img,$imgType,$this->maxWidth,$this->maxHeight);

			

			imagecopy($dst_img, $tmp_img, 0, 0, 0, 0, $newWidth, $newHeight);

			

			//save the picture

			$is_saved = $this->saveGdImage($dst_img,$filepathNew,$imgType);

			

			imagedestroy($dst_img);

			imagedestroy($src_img);

			imagedestroy($tmp_img);

			

			return($is_saved);		

		}

		

		//------------------------------------------------------------------------------------------

		// if the images are png or gif - handle image transparency

		private function handleTransparency(&$dst_img,$imgType,$newWidth,$newHeight){

			//handle transparency:

			if($imgType == IMAGETYPE_PNG || $imgType == IMAGETYPE_GIF){

			  imagealphablending($dst_img, false);

			  imagesavealpha($dst_img,true);

			  $transparent = imagecolorallocatealpha($dst_img, 255,  255, 255, 127);

			  imagefilledrectangle($dst_img, 0,  0, $newWidth, $newHeight,  $transparent);

			}

		}

		

		//------------------------------------------------------------------------------------------

		// handle image effects

		private function handleImageEffects(&$imgHandle){

			if(empty($this->effect))

				return(false);

			

			switch($this->effect){

				case self::EFFECT_BW:

					if(defined("IMG_FILTER_GRAYSCALE"))

						imagefilter($imgHandle,IMG_FILTER_GRAYSCALE);

				break;

				case self::EFFECT_BRIGHTNESS:

					if(defined("IMG_FILTER_BRIGHTNESS")){

						if(!is_numeric($this->effect_arg1))

							$this->effect_arg1 = 50;	//set default value

						UniteFunctionsRev::validateNumeric($this->effect_arg1,"'ea1' argument");

						imagefilter($imgHandle,IMG_FILTER_BRIGHTNESS,$this->effect_arg1);

					}

				break;

				case self::EFFECT_DARK:

					if(defined("IMG_FILTER_BRIGHTNESS")){

						if(!is_numeric($this->effect_arg1))

							$this->effect_arg1 = -50;	//set default value

						UniteFunctionsRev::validateNumeric($this->effect_arg1,"'ea1' argument");

						imagefilter($imgHandle,IMG_FILTER_BRIGHTNESS,$this->effect_arg1);

					}

				break;

				case self::EFFECT_CONTRAST:

					if(defined("IMG_FILTER_CONTRAST")){

						if(!is_numeric($this->effect_arg1))

							$this->effect_arg1 = -5;	//set default value	

						imagefilter($imgHandle,IMG_FILTER_CONTRAST,$this->effect_arg1);

					}

				break;

				case self::EFFECT_EDGE:

					if(defined("IMG_FILTER_EDGEDETECT"))

						imagefilter($imgHandle,IMG_FILTER_EDGEDETECT);

				break;

				case self::EFFECT_EMBOSS:

					if(defined("IMG_FILTER_EMBOSS"))

						imagefilter($imgHandle,IMG_FILTER_EMBOSS);

				break;

				case self::EFFECT_BLUR:

					$this->effect_Blur($imgHandle,5);

					/*

					if(defined("IMG_FILTER_GAUSSIAN_BLUR"))

						imagefilter($imgHandle,IMG_FILTER_GAUSSIAN_BLUR);

					*/

				break;

				case self::EFFECT_MEAN:

					if(defined("IMG_FILTER_MEAN_REMOVAL"))

						imagefilter($imgHandle,IMG_FILTER_MEAN_REMOVAL);

				break;

				case self::EFFECT_SMOOTH:

					if(defined("IMG_FILTER_SMOOTH")){

						if(!is_numeric($this->effect_arg1))

							$this->effect_arg1 = 15;	//set default value							

						imagefilter($imgHandle,IMG_FILTER_SMOOTH,$this->effect_arg1);

					}

				break;

				case self::EFFECT_BLUR3:

					$this->effect_Blur($imgHandle,5);

				break;

				default:

					$this->throwError("Effect not supported: <b>".$this->effect."</b>");

				break;

			}

			

		}



	private function effect_Blur(&$gdimg, $radius=0.5) {

		// Taken from Torstein Hרnsi's phpUnsharpMask (see phpthumb.unsharp.php)



		$radius = round(max(0, min($radius, 50)) * 2);

		if (!$radius) {

			return false;

		}



		$w = ImageSX($gdimg);

		$h = ImageSY($gdimg);

		if ($imgBlur = ImageCreateTrueColor($w, $h)) {

			// Gaussian blur matrix:

			//	1	2	1

			//	2	4	2

			//	1	2	1



			// Move copies of the image around one pixel at the time and merge them with weight

			// according to the matrix. The same matrix is simply repeated for higher radii.

			for ($i = 0; $i < $radius; $i++)	{

				ImageCopy     ($imgBlur, $gdimg, 0, 0, 1, 1, $w - 1, $h - 1);            // up left

				ImageCopyMerge($imgBlur, $gdimg, 1, 1, 0, 0, $w,     $h,     50.00000);  // down right

				ImageCopyMerge($imgBlur, $gdimg, 0, 1, 1, 0, $w - 1, $h,     33.33333);  // down left

				ImageCopyMerge($imgBlur, $gdimg, 1, 0, 0, 1, $w,     $h - 1, 25.00000);  // up right

				ImageCopyMerge($imgBlur, $gdimg, 0, 0, 1, 0, $w - 1, $h,     33.33333);  // left

				ImageCopyMerge($imgBlur, $gdimg, 1, 0, 0, 0, $w,     $h,     25.00000);  // right

				ImageCopyMerge($imgBlur, $gdimg, 0, 0, 0, 1, $w,     $h - 1, 20.00000);  // up

				ImageCopyMerge($imgBlur, $gdimg, 0, 1, 0, 0, $w,     $h,     16.666667); // down

				ImageCopyMerge($imgBlur, $gdimg, 0, 0, 0, 0, $w,     $h,     50.000000); // center

				ImageCopy     ($gdimg, $imgBlur, 0, 0, 0, 0, $w,     $h);

			}

			return true;

		}

		return false;

	}

		

		

		//------------------------------------------------------------------------------------------

		// resize image and save it to new path

		private function resizeImageSaveNew($filepath,$filepathNew){

			

			$imgInfo = getimagesize($filepath);

			$imgType = $imgInfo[2];

			

			$src_img = $this->getGdSrcImage($filepath,$imgType);

			 

			$width = imageSX($src_img);

			$height = imageSY($src_img);

			

			$newWidth = $width;

			$newHeight = $height;

			

			//find new width

			if($height > $this->maxHeight){

				$procent = $this->maxHeight / $height;

				$newWidth = ceil($width * $procent);

				$newHeight = $this->maxHeight;

			}

			

			//if the new width is grater than max width, find new height, and remain the width.

			if($newWidth > $this->maxWidth){

				$procent = $this->maxWidth / $newWidth;

				$newHeight = ceil($newHeight * $procent);

				$newWidth = $this->maxWidth;

			}

			

			//if the image don't need to be resized, just copy it from source to destanation.

			if($newWidth == $width && $newHeight == $height && empty($this->effect)){

				$success = copy($filepath,$filepathNew);				

				if($success == false) 

					$this->throwError("can't copy the image from one path to another");

			}

			else{		//else create the resized image, and save it to new path:				

				$dst_img = ImageCreateTrueColor($newWidth,$newHeight);			

				

				$this->handleTransparency($dst_img,$imgType,$newWidth,$newHeight);

				

				//copy the new resampled image:

				imagecopyresampled($dst_img,$src_img,0,0,0,0,$newWidth,$newHeight,$width,$height);

				

				$this->handleImageEffects($dst_img);

				

				$is_saved = $this->saveGdImage($dst_img,$filepathNew,$imgType);

				imagedestroy($dst_img);

			}

			

			imagedestroy($src_img);

			

			return(true);

		}

		

		/**

		 * 

		 * set image effect

		 */

		public function setEffect($effect,$arg1 = ""){

			$this->effect = $effect;

			$this->effect_arg1 = $arg1;

		}

		

		

		private function showImageByID($fileID, $maxWidth=-1, $maxHeight=-1, $type=""){

			$fileID = intval($fileID);

			

			if($fileID == 0) $this->throwError("image not found");

			

			$img = wp_get_attachment_image_src( $fileID, 'thumb' );

			

			if(empty($img)) $this->throwError("image not found");

			

			

			$this->outputImage($img[0]);

			

			

			exit();

		}

		

		//------------------------------------------------------------------------------------------

		//return image

		private function showImage($filename,$maxWidth=-1,$maxHeight=-1,$type=""){

			

			if(empty($filename))

				$this->throwError("image filename not found");

			

			//validate input

			if($type == self::TYPE_EXACT || $type == self::TYPE_EXACT_TOP){

				if($maxHeight == -1)

					$this->throwError("image with exact type must have height!");

				if($maxWidth == -1)

					$this->throwError("image with exact type must have width!");

			}

			

			$filepath = $this->pathImages.$filename;					

			

			

			if(!is_file($filepath)) $this->outputEmptyImageCode();

			

			//if gd library doesn't exists - output normal image without resizing.

			if(function_exists("gd_info") == false)

				$this->throwError("php must support GD Library");



			//check conditions for output original image

			if(empty($this->effect)){

				if((is_numeric($maxWidth) == false || is_numeric($maxHeight) == false)) outputImage($filepath);

				

				if($maxWidth == -1 && $maxHeight == -1) 

					$this->outputImage($filepath);

			}

			

			if($maxWidth == -1) $maxWidth = 1000000;

			if($maxHeight == -1) $maxHeight = 100000;

			

			//init variables

			$this->filename = $filename;

			$this->maxWidth = $maxWidth;

			$this->maxHeight = $maxHeight;

			$this->type = $type;

			

			$filepathNew = $this->getThumbFilepath();

			

			if(is_file($filepathNew)){

				$this->outputImage($filepathNew);

				exit();		

			}

			

			try{

				if($type == self::TYPE_EXACT || $type == self::TYPE_EXACT_TOP){

					$isSaved = $this->cropImageSaveNew($filepath,$filepathNew);

				}

				else 

					$isSaved = $this->resizeImageSaveNew($filepath,$filepathNew);

				

				if($isSaved == false){

					$this->outputImage($filepath);

					exit();

				}

					

			}catch(Exception $e){

				$this->outputImage($filepath);

			}

						

			if(is_file($filepathNew)) 

				$this->outputImage($filepathNew);

			else 

				$this->outputImage($filepath);

			

			exit();

		}

		

		/**

		 * 

		 * show image from get params

		 */

		public function showImageFromGet(){

			

			//$imageFilename = UniteFunctionsRev::getGetVar("img");

			$imageID = intval(UniteFunctionsRev::getGetVar("img"));

			$maxWidth = UniteFunctionsRev::getGetVar("w",-1);

			$maxHeight = UniteFunctionsRev::getGetVar("h",-1);

			$type = UniteFunctionsRev::getGetVar("t","");

			

			//set effect

			$effect = UniteFunctionsRev::getGetVar("e");

			$effectArgument1 = UniteFunctionsRev::getGetVar("ea1");

			

			if(!empty($effect))

				$this->setEffect($effect,$effectArgument1);

			

			$this->showImageByID($imageID);

			echo 'sechs<br>';

			//$this->showImage($imageFilename,$maxWidth,$maxHeight,$type);

		}

		

		

		//------------------------------------------------------------------------------------------

		// download image, change size and name if needed.

		public function downloadImage($filename){

			$filepath = $this->urlImages."/".$filename;

			if(!is_file($filepath)) {

				echo "file doesn't exists";

				exit();

			}

			

			$this->outputImageForDownload($filepath,$filename);

		}

		

		//------------------------------------------------------------------------------------------

		// output image for downloading

		private function outputImageForDownload($filepath,$filename,$mimeType=""){		

			$contents = file_get_contents($filepath);

			$filesize = strlen($contents);

			

			if($mimeType == ""){

				$info = UniteFunctionsRev::getPathInfo($filepath);

				$ext = $info["extension"];

				$mimeType = "image/$ext";

			}

			

			header("Content-Type: $mimeType");	

			header("Content-Disposition: attachment; filename=\"$filename\"");

			header("Content-Length: $filesize");		

			echo $contents;

			exit();

		}

		

		

		/**

		 * 

		 * validate type

		 * @param unknown_type $type

		 */

		public function validateType($type){

			switch($type){

				case self::TYPE_EXACT:

				case self::TYPE_EXACT_TOP:					

				break;

				default:

					$this->throwError("Wrong image type: ".$type);

				break;

			}

		}

		

	}



?>