Сжимаем размер картинки на 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;
}
}Дата публикации:

