Сжимаем размер картинки на PHP. Обработчик картинок classSimpleImage.
Манипуляции с графикой на сайте часто доставляют разработчику немало проблем. Особенно актуальны вопросы загрузки пользовательских картинок на сервер. Например, у Вас сайт с тематикой ремонта, путешествий, народного творчества и т.п. там, где необходимо публиковать большое количество графики. Одно дело, когда картинки загружаются администратором для статьи или поста и её размеры, тип и вес заранее подогнаны для загрузки. Но, что делать, когда графика загружается в комментарии к статье, ведь подготавливать картинки перед загрузкой пользователь скорее всего не будет, а если попытаться мотивировать предупреждающими сообщениями о формате, размере и весе файла, то зачастую писать комментарий вовсе передумает. Если же разрешить загрузку на сайт пользовательской графики, то вебмастеру нужно позаботься о:
- Достаточном месте на сервере для размещения графики.
- Достаточной для обработки графики процессорной мощности.
- Реализации динамической оптимизации загружаемого графического контента.
В первых двух пунктах всё в принципе решается выбором хостинг провайдера и лимитов тарифа. Читайте: «Какой выбрать хостинг.»
К процедуре оптимизации загружаемой на сервер графики можно отнести функции:
- Проверки графических объектов на соответствие допустимых типов файлов, их планарного размера и объёма занимаемой памяти.
- Оперативной трансформирмации формата графического файла, размера и сжатия.
- Операции связанные с записью файлов на сервер. Каталогизация.
Ниже в демонстрационном фрейме смоделирована тестовая модель загрузки графики на хостинг, где сначала осуществляются проверки на источник отправки, тип, размер, габариты. На втором этапе, в зависимости от полученных данных и лимитных установок администратора, происходит изменение размера картинки. Если тип файла jpg, то ещё осуществляется сжатие файла в степени обратно пропорциональной от выбранного уровня качества трансформируемой графики.
Для теста я ограничил размер картинки до 250px по высоте и ширине. А максимальный вес файла в 600кб. Теперь:
- Если файл типа png или gif по габаритам меньше ограничений, то он запишется на сервер без трансформации. Если это jpg, то осуществиться компрессия файла, согласно качеству заданному в форме отправки.
- Если файл по габаритам больше лимитного ограничения, то он будет вписан в установленные максимальные размеры, в Demo это 250px.
- Если файл весит больше 600kb, то пользователь получит предупреждение о превышении лимита, а сам файл обрабатываться не будет.
- И, наконец, если файл не проходит проверки или пришёл пустой запрос, то появится соответствующее предупреждение об отсутствии файла.
Для реализации поставленных задач был использован, обнаруженный на просторах интернета и немного мной доработанный, PHP класс «classSimpleImage.php» Скачать.
В листинге ниже привожу комментированный код php принимающей стороны:
//Подключаем классclassSimpleImage include_once('./classSimpleImage.php'); //Определяем протокол $protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? "https://" : "http://"; //Вносим в массив разрешённые источники отправки $accepted_origins = array("http://localhost", "http://192.168.1.1", "https://my-skills.ru"); //Производим проверки if (isset($_SERVER['HTTP_ORIGIN'])) { // запросы с одинаковым источником не будут устанавливать источник. Если источник установлен, он должен быть действительным. if (in_array($_SERVER['HTTP_ORIGIN'], $accepted_origins)) { //Заголовки если принимать через ajax //header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']); return; $flag = true; } else { //header("HTTP/1.1 403 Origin Denied"); return; $flag = false; } } // Не пытайтесь обработать загрузку по запросу OPTIONS. if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { //header("Access-Control-Allow-Methods: POST, OPTIONS"); return; } if (is_uploaded_file($_FILES['userimg']['tmp_name']) and $flag === true) { //Получаем параметры качества $compession = trim(strip_tags($_POST['compression'])) * 1; //Путь к папке загрузки $imageFolder = "./img/"; reset ($_FILES); $temp = current($_FILES); // Sanitize input Очистить ввод if (preg_match("/([^wsd-_~,;:[]().])|([.]{2,})/", $temp['name'])) { header("HTTP/1.1 400 Invalid file name."); return; //В Demo я не провожу эту проверку на соответствие имени файла //$flag = false; } // Проверить расширение if (!in_array(strtolower(pathinfo($temp['name'], PATHINFO_EXTENSION)), array("gif", "jpg", "png"))) { //header("HTTP/1.1 400 Invalid extension."); return; $flag = false; } } if (is_uploaded_file($temp['tmp_name']) and $flag === true){ /* Если вашему сценарию необходимо получать файлы cookie, установите images_upload_credentials : true в конфигурацию и включите следующие два заголовка. */ // header('Access-Control-Allow-Credentials: true'); // header('P3P: CP="There is no P3P policy."'); $tempsize = $temp["size"].' Байт ';//Размер получаемого файла //Проверяем на превышение размера 600kb if($temp["size"] > 600000){ //Картинка предупреждение "MAX SIZE IMG" $imgurl = "img/max-size-img-250.png"; }else{ // Принять загрузку, если не было источника или если это принятый источник $ext = mb_strtolower(mb_substr(mb_strrchr($temp['name'], '.'), 1)); $filetowrite = $imageFolder . 'demo-45.'.$ext; $imgurl = 'img/demo-45.'.$ext; list($width, $height) = getimagesize($temp['tmp_name']); $nwh = 250; if (($width >= $nwh) || ($height >= $nwh)) { if($width > $height){ $rez = $nwh * 100 / $width; }else{ $rez = $nwh * 100 / $height;} // Класс для сжатия графики $image = new SimpleImage(); //Загружаем исходную картинку $image->load($temp['tmp_name']); //Трансформируем $image->scale($rez); //Запись в папку + компрессия $image->save($filetowrite, exif_imagetype($temp['tmp_name']), $compession); }else{ //Запись без трансформации $image->save($filetowrite, exif_imagetype($temp['tmp_name']), $compession); } } } else { //Картинка предупреждение "NO IMAGES" $imgurl = 'img/no-images-240.png'; }
Класс classSimpleImage.php
class SimpleImage { var $image; var $image_type; function load($filename) { $image_info = getimagesize($filename); $this->image_type = $image_info[2]; if( $this->image_type == IMAGETYPE_JPEG ) { $this->image = imagecreatefromjpeg($filename); } elseif( $this->image_type == IMAGETYPE_GIF ) { $this->image = imagecreatefromgif($filename); } elseif( $this->image_type == IMAGETYPE_PNG ) { $this->image = imagecreatefrompng($filename); } } function save($filename, $image_type=IMAGETYPE_JPEG, $compression=40, $permissions=null) { if( $image_type == IMAGETYPE_JPEG ) { imagejpeg($this->image,$filename,$compression); } elseif( $image_type == IMAGETYPE_GIF ) { imagegif($this->image,$filename); } elseif( $image_type == IMAGETYPE_PNG ) { imagepng($this->image,$filename); } if( $permissions != null) { chmod($filename,$permissions); } } function output($image_type=IMAGETYPE_JPEG) { if( $image_type == IMAGETYPE_JPEG ) { imagejpeg($this->image); } elseif( $image_type == IMAGETYPE_GIF ) { imagegif($this->image); } elseif( $image_type == IMAGETYPE_PNG ) { imagepng($this->image); } } function getWidth() { return imagesx($this->image); } function getHeight() { return imagesy($this->image); } function resizeToHeight($height) { $ratio = $height / $this->getHeight(); $width = $this->getWidth() * $ratio; $this->resize($width,$height); } function resizeToWidth($width) { $ratio = $width / $this->getWidth(); $height = $this->getheight() * $ratio; $this->resize($width,$height); } function scale($scale) { $width = $this->getWidth() * $scale/100; $height = $this->getheight() * $scale/100; $this->resize($width,$height); } function resize($width,$height) { $new_image = imagecreatetruecolor($width, $height); //Отключаем режим сопряжения цветов imagealphablending($new_image, false); //Включаем сохранение альфа канала imagesavealpha($new_image, true); imagecopyresampled($new_image, $this->image, 0, 0, 0, 0, $width, $height, $this->getWidth(), $this->getHeight()); $this->image = $new_image; } }
Дата публикации: