Файл: core/autoload/acResizeImage.class.php
Строк: 208
<?
/**
* acResizeImage
*
* Класс для изменения размеров изображений. Реализованы различные методы ресайза, кроп, а также создание миниатюр.
*
* @author Загорцев Андрей Михайлович <freeron@yandex.ru>
* @version 1.0
*/
class acResizeImage
{
private $image;
private $width;
private $height;
private $type;
/**
* Инициализация объекта
* @param $file string Путь к временному файлу
*/
function __construct($file)
{
if (@!file_exists($file)) exit("File does not exist");
if(!$this->setType($file)) exit("File is not an image");
$this->openImage($file);
$this->setSize();
}
/**
* Изменение размеров изображения
*
* Оба принимаемых параметра необязательны.
* Если переданы и ширина и высота, изображение ужмётся в рамки.
* Если передана лишь ширина - изображение сжимается по ней (аналогично и с высотой)
*
* @param $width integer Новая ширина изображения
* @param $height integer Новая высота изображения
* @return object Текущий объект класса
*/
function resize($width = false, $height = false)
{
/**
* В зависимости от типа ресайза, запишем в $newSize новые размеры изображения.
*/
if(is_numeric($width) && is_numeric($height) && $width > 0 && $height > 0)
{
$newSize = $this->getSizeByFramework($width, $height);
}
else if(is_numeric($width) && $width > 0)
{
$newSize = $this->getSizeByWidth($width);
}
else if(is_numeric($height) && $height > 0)
{
$newSize = $this->getSizeByHeight($height);
}
else $newSize = array($this->width, $this->height);
$newImage = imagecreatetruecolor($newSize[0], $newSize[1]);
//завернуть в отдельную функцию, сжимающую изображение поэтапно
imagecopyresampled($newImage, $this->image, 0, 0, 0, 0, $newSize[0], $newSize[1], $this->width, $this->height);
$this->image = $newImage;
$this->setSize();
return $this;
}
/**
* Функция для обрезки изображения.
* Функция cropSave сохраняет обрезанное изображение и возвращает текущий объект класса acResizeImage.
*
* @param $x0 integer Координата x точки начала обрезки
* @param $y0 integer Координата y точки начала обрезки
* @param $w integer Ширина вырезаемой области
* @param $h integer Высота вырезаемой области
* @return object Текущий объект класса
*/
function crop($x0 = 0, $y0 = 0, $w = false, $h = false)
{
if(!is_numeric($x0) || $x0 < 0 || $x0 >= $this->width) $x0 = 0;
if(!is_numeric($y0) || $y0 < 0 || $y0 >= $this->height) $y0 = 0;
if(!is_numeric($w) || $w <= 0 || $w > $this->width - $x0) $w = $this->width - $x0;
if(!is_numeric($h) || $h <= 0 || $h > $this->height - $y0) $h = $this->height - $y0;
return $this->cropSave($x0, $y0, $w, $h);
}
/**
* Функция, вырезающая квадратную область из исходного изображения
* Функция cropSave сохраняет обрезанное изображение и возвращает текущий объект класса acResizeImage.
* Все параметры необязательны.
* Если не было ничего передано, будет вырезана центральная максимальная квадратная область.
*
* @param $x0 integer Координата x точки начала обрезки (по умолчанию - false)
* @param $y0 integer Координата y точки начала обрезки (по умолчанию - false)
* @param $size integer Сторона вырезаемой квадратной области
* @return object Текущий объект класса
*/
function cropSquare($x0 = false, $y0 = false, $size = false)
{
if(!is_numeric($size) || $size <= 0) $size = false;
if(!is_numeric($x0) && !is_numeric($y0))
{
if($this->width < $this->height)
{
$x0 = 0;
if(!$size || $size > $this->width)
{
$size = $this->width;
$y0 = round(($this->height - $size) / 2);
}
else $y0 = 0;
}
else
{
$y0 = 0;
if(!$size || $size > $this->height)
{
$size = $this->height;
$x0 = round(($this->width - $size) / 2);
}
else $x0 = 0;
}
}
else
{
if(!is_numeric($x0) || $x0 <= 0 || $x0 >= $this->width) $x0 = 0;
if(!is_numeric($y0) || $y0 <= 0 || $y0 >= $this->height) $y0 = 0;
if(!$size || $this->width < $size + $x0) $size = $this->width - $x0;
if(!$size || $this->height < $size + $y0) $size = $this->height - $y0;
}
return $this->cropSave($x0, $y0, $size, $size);
}
/**
* Приватная функция, сохраняющая обрезанное изображение.
*
* @return object Текущий объект класса
*/
private function cropSave($x0, $y0, $w, $h)
{
$newImage = imagecreatetruecolor($w, $h);
imagecopyresampled($newImage, $this->image, 0, 0, $x0, $y0, $w, $h, $w, $h);
$this->image = $newImage;
$this->setSize();
return $this;
}
/**
* Функция для создания миниатюр изображений.
* Функция getSizeByThumbnail возвращает новые размеры изображения.
*
* @param $width integer Ширина миниатюры
* @param $height integer Высота миниатюры
* @param $c integer Коэффициент превышения...
* @return object Текущий объект класса
*/
function thumbnail($width, $height, $c = 2)
{
if(!is_numeric($width) || $width <= 0) $width = $this->width;
if(!is_numeric($height) || $height <= 0) $height = $this->height;
if(!is_numeric($c) || $c <= 1) $c = 2;
$newSize = $this->getSizeByThumbnail($width, $height, $c);
$newImage = imagecreatetruecolor($newSize[0], $newSize[1]);
imagecopyresampled($newImage, $this->image, 0, 0, 0, 0, $newSize[0], $newSize[1], $this->width, $this->height);
$this->image = $newImage;
$this->setSize();
return $this;
}
/**
* Функция, сохраняющая изображение в файл
*
* @param $path string Путь, по которому следует сохранить файл
* @param $fileName string Имя нового файла
* @param $type string Тип файла (по умолчанию (false) - тот же, что и у исходного изображения)
* @param $rewrite boolean Флаг, определяющий, можно ли перезаписывать файлы с одинаковыми именами
* @param $quality integer Качество изображения для JPG-файлов
* @return string Адрес нового файла
*/
function save($path = '', $fileName, $type = false, $rewrite = false, $quality = 100)
{
if(trim($fileName) == '' || $this->image === false) return false;
$type = strtolower($type);
switch($type)
{
case false:
$savePath = $path.trim($fileName).".".$this->type;
switch($this->type)
{
case 'jpg':
if(!$rewrite && @file_exists($savePath)) return false;
if(!is_numeric($quality) || $quality < 0 || $quality > 100) $quality = 100;
imagejpeg($this->image, $savePath, $quality);
return $savePath;
case 'png':
if(!$rewrite && @file_exists($savePath)) return false;
imagepng($this->image, $savePath);
return $savePath;
case 'gif':
if(!$rewrite && @file_exists($savePath)) return false;
imagegif($this->image, $savePath);
return $savePath;
default:
return false;
}
break;
case 'jpg':
$savePath = $path.trim($fileName).".".$type;
if(!$rewrite && @file_exists($savePath)) return false;
if(!is_numeric($quality) || $quality < 0 || $quality > 100) $quality = 100;
imagejpeg($this->image, $savePath, $quality);
return $savePath;
case 'png':
$savePath = $path.trim($fileName).".".$type;
if(!$rewrite && @file_exists($savePath)) return false;
imagepng($this->image, $savePath);
return $savePath;
case 'gif':
$savePath = $path.trim($fileName).".".$type;
if(!$rewrite && @file_exists($savePath)) return false;
imagegif($this->image, $savePath);
return $savePath;
default:
return false;
}
}
/**
* Приватная функция, "открывающая" файл в зависимости от типа изображения.
*
* @param $file string Путь исходного файла
*/
private function openImage($file)
{
switch($this->type)
{
case 'jpg':
$this->image = @imagecreatefromjpeg($file);
break;
case 'png':
$this->image = @imagecreatefrompng($file);
break;
case 'gif':
$this->image = @imagecreatefromgif($file);
break;
default:
exit("File is not an image");
}
}
/**
* Приватная функция, записывающая в поле type тип исходного изображения
*
* @param $file string Путь исходного файла
* @return boolean TRUE, если файл является изображением. FALSE - в противном случае.
*/
private function setType($file)
{
$mime = mime_content_type($file);
switch($mime)
{
case 'image/jpeg':
$this->type = "jpg";
return true;
case 'image/png':
$this->type = "png";
return true;
case 'image/gif':
$this->type = "gif";
return true;
default:
return false;
}
}
/**
* Приватная функция, записывающая размеры исходного изображения
*/
private function setSize()
{
$this->width = imagesx($this->image);
$this->height = imagesy($this->image);
}
/**
* Приватная функция, определяющая размеры нового изображения при вписывании его в рамки.
* Сжатие происходит пропорционально.
*
* @param $width integer Максимальная ширина нового изображения
* @param $height integer Максимальная высота нового изображения
* @return array Массив, содержащий размеры нового изображения
*/
private function getSizeByFramework($width, $height)
{
if($this->width <= $width && $this->height <= height)
return array($this->width, $this->height);
if($this->width / $width > $this->height / $height)
{
$newSize[0] = $width;
$newSize[1] = round($this->height * $width / $this->width);
}
else
{
$newSize[1] = $height;
$newSize[0] = round($this->width * $height / $this->height);
}
return $newSize;
}
/**
* Приватная функция, определяющая размеры нового изображения при сжатии по ширине.
* Сжатие происходит пропорционально.
*
* @param $width integer Максимальная ширина нового изображения
* @return array Массив, содержащий размеры нового изображения
*/
private function getSizeByWidth($width)
{
if($width >= $this->width) return array($this->width, $this->height);
$newSize[0] = $width;
$newSize[1] = round($this->height * $width / $this->width);
return $newSize;
}
/**
* Приватная функция, определяющая размеры нового изображения при сжатии по высоте.
* Сжатие происходит пропорционально.
*
* @param $height integer Максимальная высота нового изображения
* @return array Массив, содержащий размеры нового изображения
*/
private function getSizeByHeight($height)
{
if($height >= $this->height) return array($this->width, $this->height);
$newSize[1] = $height;
$newSize[0] = round($this->width * $height / $this->height);
return $newSize;
}
/**
* Приватная функция, определяющая размеры нового изображения при создании миниатюры.
* Функция вписывает изображение в указанную область, стараясь максимально заполнить её.
* Если после ужатия по одной из сторон, вторая сторона привышает размеры области более чем в $c раз,
* то ужатие происходит по второй стороне.
* Если же вторая сторона превышает размер области в 2 * $c раз, то стороны уменьшаются в 2 раза.
* Если одна из сторон заведомо меньше соответствующей стороны области,
* проверяется, не превышает ли другая сторона соответствующую сторону области в $c раз и 2 * $c.
* Если ресайз производится не по ширине, а по высоте, переменные, содержащие размеры исходного изображения
* и размеры миниатюры, меняются местами.
* Также местами меняются мирина и высота в возвращаемом массиве.
*
* @param $width integer Максимальная ширина нового изображения
* @param $height integer Максимальная высота нового изображения
* @param $с integer Коэффициент превышения...
* @return array Массив, содержащий размеры нового изображения
*/
private function getSizeByThumbnail($width, $height, $c)
{
if($this->width <= $width && $this->height <= height)
return array($this->width, $this->height);
$realW = $this->width;
$realH = $this->height;
$rotate = false;
if($width / $realW <= $height / $realH)
{
$t = $realH;
$realH = $realW;
$realW = $t;
$t = $width;
$width = $height;
$height = $t;
$rotate = true;
}
$limX = $c * $width;
$limY = $c * $height;
$possH = $realH * $width / $realW;
if($realW > $width)
{
if($possH <= $limY)
{
$newSize[0] = $width;
$newSize[1] = round($possH);
}
else
{
if($possH <= 2 * $limY)
{
$newSize[1] = $limY;
$newSize[0] = $realW * $newSize[1] / $realH;
}
else
{
$newSize[0] = $width / 2;
$newSize[1] = $realH * $newSize[0] / $realW;
}
}
}
else
{
if($realH <= $limY)
{
$newSize[0] = $realW;
$newSize[1] = $realH;
}
else
{
if($realH <= 2 * $limY)
{
if($realW * $limY / $realH >= $width / 2)
{
$newSize[1] = $limY;
$newSize[0] = $realW * $limY / $realH;
}
else
{
$newSize[0] = $width / 2;
$newSize[1] = $realH * $newSize[0] / $realW;
}
}
else
{
$newSize[0] = $width / 2;
$newSize[1] = $realH * $newSize[0] / $realW;
}
}
}
if($rotate)
{
$t = $newSize[0];
$newSize[0] = $newSize[1];
$newSize[1] = $t;
}
return $newSize;
}
}