Главная
›
Новости
Класс обработки изображений с помощью php
Опубликовано: 02.11.2017
Управление визуальным объемом и резкостью изображений. Обработка. Алексей Шадрин
27
Окт
2011
Здравствуйте. Сегодня хотел бы с вами поделиться своим классом обработки изображений с помощью php * . У меня как-то возникла потребность сделать объект, методы которого могут следующее:
изменять изображения по заданным размерам с сохранением пропорции учитывая большую сторону,
изменять изображение по заданным размерам, если размеры не являются пропорциональными, обрезать изображения по центру,
изменять размер изображения.
И так создаем класс:
class resizeImage {
const TYPE_GIF = 1;
const TYPE_JPG = 2;
const TYPE_PNG = 3;
protected $image = FALSE;
protected $imageNew = FALSE;
protected $imageResourse = FALSE;
protected $type = 0;
protected $width = 0;
protected $height = 0;
protected $quality = 100;
где, константы у нас это три типа изображений, которым мы присваиваем соответствующие номера. Так же у нас есть ряд переменных необходимых для работы, которым мы задали начальные значения. Далее мы пропишем конструктор класса, который будет вызывать метод загрузки изображений исчитывания необходимых данных:
public function __construct($fileName) {
if (is_file($fileName)) {
$this->loadImage($fileName);
} else {
throw new Exception('Image not found');
}
}
protected function loadImage($fileName) {
$info = @getimagesize($fileName);
if ($info) {
if ($info[2] > 3) {
throw new Exception('Unsupported image type!');
} else {
$this->width = (int) $info[0];
$this->height = (int) $info[1];
$this->type = $info[2];
switch ($this->type) {
case self::TYPE_PNG:
$function = 'imagecreatefrompng';
$type = IMAGETYPE_PNG;
break;
case self::TYPE_JPG:
$function = 'imagecreatefromjpeg';
$type = IMAGETYPE_JPEG;
break;
case self::TYPE_GIF:
$function = 'imagecreatefromgif';
$type = IMAGETYPE_GIF;
break;
}
$this->image = $function($fileName);
$this->name = basename($fileName, $typeName);
}
} else {
throw new Exception('This is not image');
}
return;
}
Далее мы напишем метод обрезки изображения по заданным длине и ширине:
protected function crop($width, $height) {
if (($width > $this->width) or ($height > $this->height)) {
$width = $this->width;
$height = $this->height;
}
$this->imageNew = imagecreatetruecolor($width, $height);
imagecopyresampled(
$this->imageNew,
$this->image,
0, 0, 0, 0,
$width, $height,
$this->width,
$this->height);
}
Если вы обратили внимание, то наш метод защищеный и мы не сможем его вызвать из вне, поэтому напишем следующий метод для изменения размера, а так же метод на проверку введенных данных:
protected function testNumder($var) {
if (is_numeric($var) and $var > 0) {
return TRUE;
} else {
throw new Exception('Bad size for new image');
}
}
public function resize($newWidth, $newHeight) {
$this->testNumder($newWidth);
$this->testNumder($newHeight);
$this->crop($newWidth, $newHeight);
}
С одной из задач мы справились, теперь можно менять размер изображение по заданным размерам. Следующее что нам необходимо, это возможность изменять изображения по заданным размерам с сохранением пропорции учитывая большую сторону, для этого создадим следующий метод:
public function resizeProportional($newWidth, $newHeight) {
$this->testNumder($newWidth);
$this->testNumder($newHeight);
if ($this->width > $this->height) {
$newWidth = $newHeight * $this->width / $this->height;
} else {
$newHeight = ($this->height * $newWidth) / $this->width;
}
$this->crop($newWidth, $newHeight);
}
Далее самая сложная часть, необходимо изменять изображение по заданным размерам, если размеры не являются пропорциональными, обрезать изображения по центру. Я потратил около двух часов на расчеты, но получил следующий метод:
public function resizeCropped($newWidth, $newHeight) {
$this->testNumder($newWidth);
$this->testNumder($newHeight);
if (($newWidth > $this->width) or ($newHeight > $this->height)) {
$newWidth = $this->width;
$newHeight = $this->height;
}
$ratioOld = $this->width / $this->height;
$ratioNew = $newWidth / $newHeight;
if ($ratioNew > $ratioOld) {
$new_height = $newWidth / $ratioOld;
$new_width = $newWidth;
$kx = $ratioOld / $ratioNew;
$ky = $ratioNew;
} else {
$new_width = $newHeight * $ratioOld;
$new_height = $newHeight;
$kx = $ratioNew;
$ky = $ratioOld / $ratioNew;
}
$x = ($new_width * $kx - ($newWidth * $kx)) / 2;
$y = ($new_height * $ky - ($newHeight * $ky)) / 2;
$process = imagecreatetruecolor(round($new_width), round($new_height));
$this->imageNew = imagecreatetruecolor($newWidth, $newHeight);
imagecopyresampled($process,
$this->image, 0, 0, 0, 0,
$new_width, $new_height,
$this->width, $this->height);
imagecopyresampled($this->imageNew,
$process, 0, 0,
$x,
$y,
$newWidth, $newHeight,
$newWidth, $newHeight);
}
Заключительная часть нашего класса. На данный момент он бесполезен без метода, отвечающего за сохранение или передачу полученного изображения в поток:
public function free() {
imagedestroy($this->imageNew);
imagedestroy($this->image);
}
public function save($path, $type = Image::TYPE_PNG, $quality = 100, $freeMem = TRUE) {
if ((is_dir($path)) and (is_writable($path))) {
switch ($type) {
case self::TYPE_PNG:
$function = 'imagepng';
$quality = 9 - round(9 / 100 * $quality);
break;
case self::TYPE_JPG:
$function = 'imagejpeg';
break;
case self::TYPE_GIF:
$function = 'imagegif';
break;
default:
throw new Exception('Unsupported image type');
}
$function($this->imageNew, $path, $quality);
if ($freeMemory) {
$this->free();
}
return TRUE;
} else {
throw new Exception('Directory not exists, or not writable');
}
}
} // закрываем наш класс
Конечно, если использовать фреймворки к примеру CI и другие, где есть соотвествующие классы обработки изображений, то мой класс совершенно бесполезен. Но ведь не все работают с фреймворками. Рад буду критике от гуру программирования.
Примечание:
* — Для работы необходима php-библиотека GD.
Как определить шероховатость поверхности Анализ требований рабочего чертежа детализагрузка...
Обзор комплекта Dedolight SPS3