Масштабирование изображений

В UMI.CMS есть удобный макрос для автоматического масштабирования изображений. Основной его недостаток - жестко можно  задать только один размер, второй же будет промасштабирован пропорционально. Если же указать оба размера, изображение будет искажено.

Исправим это. Изменим метод makeThumbnail так, чтобы при указании ширины и высоты изображение оказалось вписано в заданную область без искажения пропорций.

В общем, все понятно из кода. Обозначу общую лишь идею: уменьшаем одну из сторон до заданного размера, смотрим какой получилась вторая, при необходимости уменьшаем ее и пересчитываем первую.

Параметр fixHeight указывает, что нужно создать полотно заданных размеров и уменьшенное изображение размесить по его центру.

Вызываем %custom makeThumbnail....%

public function makeThumbnail($path, $width, $height, $template = "default", $returnArrayOnly  = false, $fixHeight = false) {
	if(!$template) $template = "default";

	$thumbs_path = "./images/cms/thumbs/";

	$image = new umiImageFile($path);
	$file_name = $image->getFileName();
	$file_ext = $image->getExt();
	$thumbPath = sha1($image->getDirName());

	if (!is_dir($thumbs_path.$thumbPath)) {
		mkdir($thumbs_path.$thumbPath, 0755);
	}

	$file_ext = strtolower($file_ext);
	$allowedExts = Array('gif', 'jpeg', 'jpg', 'png', 'bmp');
	if(!in_array($file_ext, $allowedExts)) return "";

	$file_name = substr($file_name, 0, (strlen($file_name) - (strlen($file_ext) +  1)) );
	$file_name_new = $file_name . "_" . $width . "_" . $height . "." . $file_ext;
	$path_new = $thumbs_path .$thumbPath."/". $file_name_new;

	if(!file_exists($path_new) || filemtime($path_new) < filemtime($path)) {
		if(file_exists($path_new)) {
			unlink($path_new);
		}
		$width_src = $image->getWidth();
		$height_src = $image->getHeight();

		if($width_src <= $width && $height_src <= $height) {
			copy($path, $path_new);
			$real_width = $width;
			$real_height = $height;
		} else {

			if ($width == "auto" && $height == "auto"){
				$real_height = $height_src;
				$real_width = $width_src;
			} elseif ($width == "auto" || $height == "auto"){
				if ($height == "auto"){
					$real_width = (int) $width;
					$real_height = (int) round($height_src * ($width / $width_src));
				} elseif ($width == "auto"){
					$real_height = (int) $height;
					$real_width = (int) round($width_src * ($height / $height_src));
				}
			} else {
				//для фона
				if($fixHeight){
					$real_width = $width;// для макс заданного контура
					$real_height = $height;// для макс заданного контура
				}

				//определяем размеры картинки
				if($width_src > $height_src) {//горизонт
					$real_width = $width;
					$real_height = (int) round($height_src * ($width / $width_src));
					
					if($real_height > (int) $height){
						$real_height = (int) $height;
						$real_width = (int) round($width_src * ($real_height / $height_src));
					}
				} else{
					$real_height = (int) $height;
					$real_width = (int) round($width_src * ($height / $height_src));
	
					if($real_width > $width){
						$real_width = (int) $width;
						$real_height = (int) round($height_src * ($real_width / $width_src));
					}
				}
			}

			if($fixHeight){
				$thumb = imagecreatetruecolor($width, $height);//width для макс заданного  контура
			} else $thumb = imagecreatetruecolor($real_width, $real_height);

			if($image->getExt() == "gif") {
				$source = imagecreatefromgif($path);

				$thumb_white_color = imagecolorallocate($thumb, 255, 255, 255);
				imagefill($thumb, 0, 0, $thumb_white_color);
				imagecolortransparent($thumb, $thumb_white_color);

				imagealphablending($source, TRUE);
				imagealphablending($thumb, TRUE);
			} else if ($image->getExt() == "png") {
				$source = imagecreatefrompng($path);

				$thumb_white_color = imagecolorallocate($thumb, 255, 255, 255);
				imagefill($thumb, 0, 0, $thumb_white_color);
				imagecolortransparent($thumb, $thumb_white_color);

				imagealphablending($source, TRUE);
				imagealphablending($thumb, TRUE);
			} else {
				$source = imagecreatefromjpeg($path);
				$thumb_white_color = imagecolorallocate($thumb, 255, 255, 255);
				imagefill($thumb, 0, 0, $thumb_white_color);
				imagecolortransparent($thumb, $thumb_white_color);

				imagealphablending($source, TRUE);
				imagealphablending($thumb, TRUE);
			}

			//определяем координаты по середине полотна


			$dstY = 0;
			$dstX = 0;
			
			if($fixHeight){
				$dstX = round(($width - $real_width)/2);//для макс контура
				$dstY = round(($height - $real_height)/2);
			}

			imagecopyresampled($thumb, $source, $dstX, $dstY, 0, 0, $real_width,  $real_height, $width_src, $height_src);

			if($image->getExt() == "png") {
				imagepng($thumb, $path_new);
			} else if($image->getExt() == "gif") {
				imagegif($thumb, $path_new);
			} else {
				imagejpeg($thumb, $path_new, 100);
			}
		}
	}

	//Parsing
	$value = new umiImageFile($path_new);

	$arr = Array();
	$arr['size'] = $value->getSize();
	$arr['filename'] = $value->getFileName();
	$arr['filepath'] = $value->getFilePath();
	$arr['src'] = $value->getFilePath(true);
	$arr['ext'] = $value->getExt();

	$arr['width'] = $value->getWidth();
	$arr['height'] = $value->getHeight();

	$arr['template'] = $template;

	if(cmsController::getInstance()->getCurrentMode() == "admin") {
		$arr['src'] = str_replace("&", "&amp;", $arr['src']);
	}
	// с
	if($returnArrayOnly) {
		return $arr;
	} else {
		list($tpl) = def_module::loadTemplates("tpls/thumbs/{$template}.tpl", "image");
		return def_module::parseTemplate($tpl, $arr);
	}
}