Створення власного класу ресайза зображень. Частина 3

307

Від автора: продовжуємо створювати власний клас ресайза зображень. На даному етапі у нас готові методи, які розраховують розміри майбутніх мініатюр. Тому в даному заключному уроці серії ми завершимо метод resize(), який безпосередньо змінює розміри зображень, а також створимо метод save(), який необхідний для збереження створеної мініатюри в окремий файл.

Створення власного класу ресайза зображень. Частина 3Створення власного класу ресайза зображень. Частина 3

Допрацьовуємо метод resize()

Після того, як розраховані розміри по ширині і висоті майбутньої мініатюри, необхідно створити нове, пусте зображення (його можна назвати підкладкою), на яке буде скопійована мініатюра при створенні:

$this->imgRes = imagecreatetruecolor(round($arr[‘width’]),round($arr[‘height’]));

Для цього використовується функція imagecreatetruecolor(), яка створює нове повнокольорове зображення і повертає його дескриптор, який записується у властивість класу $imgRes. При виклику даної функції необхідно передати розміри майбутнього зображення. Далі виконуємо ресайз і створення мініатюри:

Для цього викликаємо функцію imagecopyresampled(), яка виконує копіювання і зміна розміру зображення з ресемплированием. Параметри, які необхідно передати даної функції:

$this->imgRes — дискриптор зображення, на яке виконується копіювання (приймач);

$this->img — дискриптор копіюється зображення (джерело);

Х-координата на зображенні приймачі, куди буде скопійоване зображення джерело;

У-координата на зображенні приймачі, куди буде скопійоване зображення джерело;

Х-координата точки на копійованому зображенні, з якої буде виконано копіювання;

У-координата точки на копійованому зображенні, з якої буде виконано копіювання;

round($arr[‘width’]) — ширина блоку на зображенні приймачі, який буде вміщено копируемое зображення;

round($arr[‘height’]) — висота блоку на зображенні приймачі, який буде вміщено копируемое зображення;

$this->width — ширина частини копіюється зображення, яку потрібно скопіювати;

$this->height — висота частини копіюється зображення, яку потрібно скопіювати.

Метод збереження мініатюри save()

Тепер, коли у властивості $imgRes, міститься дескриптор створеної мініатюри – необхідно створити метод, який збереже її в окремому файлі:

public function save($path = FALSE,$quality = 100) {
if(!$path) {
$str = md5(microtime());
$name = substr($str,0,10);
$ext = self::IMAGEEXT;
$path = $name . $ext;
}
else {
$ext = strtolower(strrchr($path,’.’));
}
switch($ext) {
case ‘.jpg’:
imagejpeg($this->imgRes,self::DIRSAVE.’/’.$path,$quality);
break;
case ‘.png’:
///70 100
///x 9
$quality = round(($quality*9)/100);
$quality = 9 – $quality;
//echo $quality;
imagepng($this->imgRes,self::DIRSAVE.’/’.$path,$quality);
break;
case ‘.gif’:
imagegif($this->imgRes,self::DIRSAVE.’/’.$path);
break;
imagedestroy($this->imgRes);
imagedestroy($this->img);
}
}

Метод приймає в якості параметрів наступні значення:

$path – ім’я файлу, що зберігається, разом з розширенням. За замовчуванням цей параметр дорівнює FALSE, і якщо при виклику методу, його не передавати, ім’я майбутнього файлу буде згенеровано випадковим чином;

$quality – якість чи ступінь стиснення майбутнього зображення (актуально для зображень формату jgp і png).

Насамперед необхідно перевірити, чи був переданий перший параметр, який містить ім’я майбутнього файлу, якщо це так, необхідно визначити розширення файлу, що б дізнатися в якому форматі потрібно зберегти файл (jpg, gif, png і т. д). Так як для кожного формату у бібліотеки GD2 передбачена окрема функція.

Якщо ж ім’я майбутнього зображення не зазначено, значить необхідно згенерувати його випадковим чином і додати розширення, яке міститься в константі класу IMAGEEXT. Після цього в залежності від формату майбутнього зображення — виконуємо його збереження в окремий файл.

Хотів би звернути Вашу увагу на другий параметр, даного методу — $quality = 100. Який задає відсоток якості збереженого зображення і він вимірюється від 0 до 100. У випадку з зображенням формату jpg – все відмінно. Нагадаю, що для збереження зображення у форматі jpg – необхідно викликати функцію imagejpeg(). Але якщо необхідно зберегти файл у форматі png, то значення якості, яка вимірюється від 0 до 100, не підійде (100 – найкраща якість). Так як для зображень png, ступінь стиснення, вимірюється в діапазоні від 0 до 9, причому 0 — це найкраща якість, а 9 — найгірше. Тому для зображень формату png, необхідно відсоток якості перевести в діапазон від 0 до 9, а потім інвертувати отримане значення.

Після збереження зображень в окремий файл, не забуваємо видалити зображення зберігаються в пам’яті.

Остаточний ресайз для режиму crop

Нагадаю, що якщо використовується режим обробки зображень crop, значить необхідно виконати подвійний ресайз. При першому — виконується ресайз по одній із сторін вихідного зображення, при цьому вибирається сторона з найбільшим коефіцієнтом ресайза, а потім необхідно вирізати все зайве, для того що б отримати зображення заданого розміру. Для цього в метод resize(), додамо умова:

if($option == ‘crop’) {
$w = round($arr[‘width’]);
$h = round($arr[‘height’]);
$sx = ($w/2)-($newWidth/2);
$sy = ($h/2) – ($newHeight/2);
$img = imagecreatetruecolor($newWidth,$newHeight);
imagecopyresampled($img, $this->imgRes, 0, 0, $sx, $sy, $newWidth, $newHeight, $newWidth, $newHeight);
$this->imgRes = $img;
}

Для виконання остаточного ресайза, необхідно знайти центр вихідного зображення і мініатюри відповідно, так як відсікати ми будемо рівні частини праворуч і з ліва зображення або зверху і знизу, у залежності від того, як був виконаний попередній ресайз. При цьому центр – це відстань у пікселях від початку зображення і до точки центру. А отже, після визначення цих даних викликаємо функцію imagecopyresampled() і виконуємо, остаточний ресайз.

Повний код методу resize():

public function resize($newWidth = self::WIDTH, $newHeight = self::HEIGHT, $option = ‘width’) {
$arr = $this->getSizes($newWidth,$newHeight,$option);
$this->imgRes = imagecreatetruecolor(round($arr[‘width’]), round($arr[‘height’]));
imagecopyresampled($this->imgRes, $this->img, 0, 0, 0, 0, round($arr[‘width’]), round($arr[‘height’]), $this->width,$this->height);
if($option == ‘crop’) {
$w = round($arr[‘width’]);
$h = round($arr[‘height’]);
$sx = ($w/2)-($newWidth/2);
$sy = ($h/2) – ($newHeight/2);
$img = imagecreatetruecolor($newWidth, $newHeight);
imagecopyresampled($img, $this->imgRes, 0, 0, $sx, $sy, $newWidth, $newHeight, $newWidth, $newHeight);
$this->imgRes = $img;
}
}

На цьому клас imgRes завершений, для його тестування і використання пропишемо наступне:

try {
$obj = new resImg(‘1.jpg’);
$obj->resize(70,180,’crop’);
$obj->save(‘crop.jpg’);
}
catch(Exception $e) {
echo $e->getMessage();
}

Ось і все, що я хотів розповісти Вам у цьому уроці. На мій погляд, клас вийшов досить функціональним і в теж час дуже простим. Звичайно, Ви його можете доопрацювати, або розширити його функціонал під власні потрібні, або змінити роботу деяких методів – тут все обмежується тільки Вашою фантазією.

На цьому даний урок завершено. Всього Вам доброго і вдалого кодування!!!