Статьи

Изменение размера изображения стало проще с PHP

Вы когда-нибудь хотели универсальный, простой в использовании метод изменения размера ваших изображений в PHP? Ну, для этого и нужны классы PHP — многократно используемые функциональные возможности, которые мы призываем сделать за кулисами грязную работу. Мы собираемся узнать, как создать наш собственный класс, который будет хорошо сконструирован и расширяем. Изменение размера должно быть легким. Как легко? Как насчет трех шагов!

Прежде чем мы перейдем к пошаговому процессу, давайте рассмотрим несколько премиум-вариантов от CodeCanyon. Есть десятки сценариев изменения размера изображения и плагинов на выбор — вот краткий обзор некоторых из них.

Это простой PHP-класс, который изменяет размер изображения на лету. Если вы используете любой веб-сервер с поддержкой PHP, и у вас есть какой-либо вид просмотра изображений, этот скрипт идеально подходит для вас. Он всегда сохраняет соотношение сторон, поэтому измененное изображение сохраняет свою форму.

Изменение размера изображения и создание эскизов
Изменение размера изображения и создание эскизов

anySize — это легкий, полностью автоматизированный скрипт для кэширования, «сделай себе кофе и подай в постели», который позволяет запрашивать и генерировать изображения (jpg, gif или png) любого размера.

anySize - изменение размера кэшируемого изображения
anySize — изменение размера кэшируемого изображения

Этот плагин Magento позволяет вам установить максимальную ширину и высоту изображения, которые могут быть загружены для изображения каталога. Это также уменьшает размер файла изображения каталога. Это поможет вам уменьшить использование дискового пространства, так как изображения будут изменены и сжаты.

Magento Image Resize
Magento Image Resize

Этот класс PHP поможет вам изменить размеры любых фотографий и сделать свой личный водяной знак.

Image Resizer And Watermark Maker
Image Resizer And Watermark Maker

RezImage — это простой и гибкий инструмент для изменения размера изображений, идеально подходящий для веб-дизайнеров или владельцев интернет-магазинов. Этот инструмент позволяет изменить размер всей папки, полной изображений, независимо от того, сколько их — просто загрузите папку с изображениями, установите ширину и высоту и ничего более. Включает в себя некоторые предустановки разрешения, такие как VGA, HD, QXGA, QSXGA и т. Д., Но вы также можете установить свои собственные.

RezImage - Простое изменение размера изображения
RezImage — Простое изменение размера изображения

Чтобы дать вам быстрый взгляд на то, что мы пытаемся достичь с помощью нашего класса, класс должен быть:

  • Легко использовать
  • Формат независимый. IE, открывайте, изменяйте размер и сохраняйте различные форматы изображений.
  • Интеллектуальный размер — без искажений изображения!

Примечание. Это не учебник о том, как создавать классы и объекты, и, хотя это умение поможет, оно не обязательно для того, чтобы следовать этому учебнику.

Там есть много чего, давайте начнем.


Мы начнем легко. В вашем рабочем каталоге создайте два файла: один называется index.php, другой resize-class.php


Чтобы дать вам представление о том, чего мы пытаемся достичь, начнем с кодирования вызовов, которые мы будем использовать для изменения размера изображений. Откройте файл index.php и добавьте следующий код.

Как видите, в том, что мы делаем, есть хорошая логика. Мы открываем файл изображения, мы устанавливаем размеры, к которым мы хотим изменить размер изображения, и тип изменения размера.
Затем мы сохраняем изображение, выбирая нужный формат изображения и качество изображения. Сохраните и закройте файл index.php.

01
02
03
04
05
06
07
08
09
10
11
// *** Include the class
       include(«resize-class.php»);
 
       // *** 1) Initialize / load image
       $resizeObj = new resize(‘sample.jpg’);
 
       // *** 2) Resize image (options: exact, portrait, landscape, auto, crop)
       $resizeObj -> resizeImage(150, 100, ‘crop’);
 
       // *** 3) Save image
       $resizeObj -> saveImage(‘sample-resized.gif’, 100);

Из приведенного выше кода видно, что мы открываем файл jpg, но сохраняем gif. Помните, это все о гибкости.


Именно объектно-ориентированное программирование (ООП) делает это чувство легкости возможным. Думайте о классе как о шаблоне; Вы можете инкапсулировать данные — еще один жаргонный термин, который на самом деле означает просто скрывать данные. Затем мы можем многократно использовать этот класс без необходимости переписывать любой код изменения размера — вам нужно только вызывать соответствующие методы, как мы это делали на втором шаге. Как только наш шаблон был создан, мы создаем экземпляры этого шаблона, называемые объектами.

«Функция конструкции, известная как конструктор, — это специальный метод класса, который вызывается классом при создании нового объекта».

Давайте начнем создавать наш класс изменения размера. Откройте файл resize-class.php. Ниже приведена действительно базовая структура скелета класса, которую я назвал «resize». Обратите внимание на строку комментария переменной класса; это где мы начнем добавлять наши важные переменные класса позже.

Функция конструкции, известная как конструктор, представляет собой специальный метод класса (однако термин «метод» — это то же самое, что и функция, однако, когда речь идет о классах и объектах, часто используется термин «метод»), который вызывается классом при создании новый объект. Это позволяет нам выполнить некоторую инициализацию — что мы и сделаем на следующем шаге.

1
2
3
4
5
6
7
8
9
Class resize
       {
           // *** Class variables
 
           public function __construct()
           {
 
           }
       }

Обратите внимание, что это двойное подчеркивание для метода конструкции.


Мы собираемся изменить метод конструктора выше. Во-первых, мы передадим имя файла (и путь) нашего изображения, которое будет изменено. Мы назовем эту переменную $ fileName.

Нам нужно открыть файл, переданный с помощью PHP (точнее, библиотеки PHP GD), чтобы PHP мог читать изображение. Мы делаем это с помощью пользовательского метода openImage. Я доберусь до того, как этот метод
работает через мгновение, но сейчас нам нужно сохранить результат как переменную класса. Переменная класса — это просто переменная, но она специфична для этого класса. Помните комментарий к переменной класса, о котором я упоминал ранее? Добавьте ‘image’ в качестве приватной переменной, набрав ‘private $ image;’. Установив переменную как «Private», вы устанавливаете область действия этой переменной, чтобы класс мог получить к ней доступ. Отныне мы можем сделать вызов нашему открытому изображению, известному как ресурс, который мы будем делать позже, когда будем изменять размер.

Пока мы на этом, давайте сохраним высоту и ширину изображения. У меня есть ощущение, что это будет полезно позже.

Теперь у вас должно быть следующее.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
Class resize
       {
           // *** Class variables
           private $image;
           private $width;
           private $height;
 
           function __construct($fileName)
           {
               // *** Open up the file
               $this->image = $this->openImage($fileName);
 
               // *** Get width and height
               $this->width = imagesx($this->image);
               $this->height = imagesy($this->image);
           }
       }

Методы imagesx и imagesy встроены в функции, которые являются частью библиотеки GD. Они получают ширину и высоту вашего изображения соответственно.


На предыдущем шаге мы вызываем пользовательский метод openImage. На этом этапе мы собираемся создать этот метод. Мы хотим, чтобы скрипт заставил нас задуматься, поэтому в зависимости от типа передаваемого файла скрипт должен определить, какую функцию библиотеки GD он вызывает для открытия изображения. Это легко сделать, сравнив расширение файла с оператором switch.

Мы передаем в наш файл, мы хотим изменить размер и вернуть этот файл ресурсов.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private function openImage($file)
       {
           // *** Get extension
           $extension = strtolower(strrchr($file, ‘.’));
 
           switch($extension)
           {
               case ‘.jpg’:
               case ‘.jpeg’:
                   $img = @imagecreatefromjpeg($file);
                   break;
               case ‘.gif’:
                   $img = @imagecreatefromgif($file);
                   break;
               case ‘.png’:
                   $img = @imagecreatefrompng($file);
                   break;
               default:
                   $img = false;
                   break;
           }
           return $img;
       }

Это где любовь происходит. Этот шаг на самом деле просто объяснение того, что мы собираемся сделать, поэтому здесь нет домашней работы. На следующем шаге мы собираемся создать публичный метод, который мы будем вызывать для выполнения нашего изменения размера; поэтому имеет смысл передать ширину и высоту, а также информацию о том, как мы хотим изменить размер изображения. Давайте поговорим об этом на минуту. Там будут сценарии, где вы хотели бы изменить размер изображения до точного размера. Отлично, давайте включим это. Но также будут случаи, когда вам придется изменять размеры сотен изображений, и у каждого изображения будет свое соотношение сторон — подумайте портретные изображения. Изменение размера до точного размера приведет к серьезным искажениям. Если мы посмотрим на наши варианты, чтобы предотвратить искажения, мы можем:

  1. Измените размер изображения как можно ближе к нашим новым размерам изображения, сохраняя при этом пропорции.
  2. Измените размер изображения как можно ближе к нашим новым размерам изображения и обрежьте остаток.

Оба варианта являются жизнеспособными, в зависимости от ваших потребностей.

Ага. мы собираемся попытаться справиться со всем вышеперечисленным. Напомним, что мы собираемся предоставить варианты для:

  1. Изменить размер на точную ширину / высоту. (Точный)
  2. Изменить размер по ширине — будет задана точная ширина, высота будет изменена в соответствии с соотношением сторон. (пейзаж)
  3. Изменение размера по высоте — как Изменение размера по ширине, но высота будет установлена, а ширина будет изменяться динамически. (портрет)
  4. Автоматическое определение параметров 2 и 3. Если вы просматриваете папку с фотографиями разных размеров, позвольте сценарию определить, как с этим справиться. (авто)
  5. Измените размер, затем обрежьте. Это мой любимый Точный размер, без искажений. (Растениеводство)

Метод изменения размера состоит из двух частей. Во-первых, мы получаем оптимальные ширину и высоту для нашего нового изображения, создавая некоторые пользовательские методы и, конечно же, передавая нашу опцию изменения размера, как описано выше. Ширина и высота возвращаются как массив и устанавливаются в соответствующие им переменные. Не стесняйтесь «передавать в качестве ссылки» — но я не большой поклонник этого.

Вторая часть — это то, что выполняет реальное изменение размера. Чтобы уменьшить размер этого урока, я позволю вам ознакомиться со следующими функциями GD:

Мы также сохраняем выходные данные метода imagecreatetruecolor (новое изображение с истинным цветом) как переменную класса. Добавьте ‘private $ imageResized;’ с вашими другими переменными класса.

Изменение размера выполняется модулем PHP, известным как библиотека GD. Многие из методов, которые мы используем, предоставляются этой библиотекой.

1
2
// *** Add to class variables
       private $imageResized;
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
public function resizeImage($newWidth, $newHeight, $option=»auto»)
       {
 
           // *** Get optimal width and height — based on $option
           $optionArray = $this->getDimensions($newWidth, $newHeight, strtolower($option));
 
           $optimalWidth = $optionArray[‘optimalWidth’];
           $optimalHeight = $optionArray[‘optimalHeight’];
 
           // *** Resample — create image canvas of x, y size
           $this->imageResized = imagecreatetruecolor($optimalWidth, $optimalHeight);
           imagecopyresampled($this->imageResized, $this->image, 0, 0, 0, 0, $optimalWidth, $optimalHeight, $this->width, $this->height);
 
           // *** if option is ‘crop’, then crop too
           if ($option == ‘crop’) {
               $this->crop($optimalWidth, $optimalHeight, $newWidth, $newHeight);
           }
       }

Чем больше работы вы делаете сейчас, тем меньше вы должны делать, когда вы изменяете размер. Этот метод выбирает маршрут, который нужно выбрать, с целью получения оптимальной ширины и высоты изменения размера в зависимости от вашего варианта изменения размера. Он вызовет соответствующий метод, который мы создадим на следующем шаге.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
private function getDimensions($newWidth, $newHeight, $option)
       {
 
          switch ($option)
           {
               case ‘exact’:
                   $optimalWidth = $newWidth;
                   $optimalHeight= $newHeight;
                   break;
               case ‘portrait’:
                   $optimalWidth = $this->getSizeByFixedHeight($newHeight);
                   $optimalHeight= $newHeight;
                   break;
               case ‘landscape’:
                   $optimalWidth = $newWidth;
                   $optimalHeight= $this->getSizeByFixedWidth($newWidth);
                   break;
               case ‘auto’:
                   $optionArray = $this->getSizeByAuto($newWidth, $newHeight);
                   $optimalWidth = $optionArray[‘optimalWidth’];
                   $optimalHeight = $optionArray[‘optimalHeight’];
                   break;
               case ‘crop’:
                   $optionArray = $this->getOptimalCrop($newWidth, $newHeight);
                   $optimalWidth = $optionArray[‘optimalWidth’];
                   $optimalHeight = $optionArray[‘optimalHeight’];
                   break;
           }
           return array(‘optimalWidth’ => $optimalWidth, ‘optimalHeight’ => $optimalHeight);
       }

Мы уже обсуждали, что делают эти четыре метода. На самом деле это просто базовая математика, которая рассчитывает нашу лучшую подгонку.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
private function getSizeByFixedHeight($newHeight)
       {
           $ratio = $this->width / $this->height;
           $newWidth = $newHeight * $ratio;
           return $newWidth;
       }
 
       private function getSizeByFixedWidth($newWidth)
       {
           $ratio = $this->height / $this->width;
           $newHeight = $newWidth * $ratio;
           return $newHeight;
       }
 
       private function getSizeByAuto($newWidth, $newHeight)
       {
           if ($this->height < $this->width)
           // *** Image to be resized is wider (landscape)
           {
               $optimalWidth = $newWidth;
               $optimalHeight= $this->getSizeByFixedWidth($newWidth);
           }
           elseif ($this->height > $this->width)
           // *** Image to be resized is taller (portrait)
           {
               $optimalWidth = $this->getSizeByFixedHeight($newHeight);
               $optimalHeight= $newHeight;
           }
           else
           // *** Image to be resizerd is a square
           {
               if ($newHeight < $newWidth) {
                   $optimalWidth = $newWidth;
                   $optimalHeight= $this->getSizeByFixedWidth($newWidth);
               } else if ($newHeight > $newWidth) {
                   $optimalWidth = $this->getSizeByFixedHeight($newHeight);
                   $optimalHeight= $newHeight;
               } else {
                   // *** Sqaure being resized to a square
                   $optimalWidth = $newWidth;
                   $optimalHeight= $newHeight;
               }
           }
 
           return array(‘optimalWidth’ => $optimalWidth, ‘optimalHeight’ => $optimalHeight);
       }
 
       private function getOptimalCrop($newWidth, $newHeight)
       {
 
           $heightRatio = $this->height / $newHeight;
           $widthRatio = $this->width / $newWidth;
 
           if ($heightRatio < $widthRatio) {
               $optimalRatio = $heightRatio;
           } else {
               $optimalRatio = $widthRatio;
           }
 
           $optimalHeight = $this->height / $optimalRatio;
           $optimalWidth = $this->width / $optimalRatio;
 
           return array(‘optimalWidth’ => $optimalWidth, ‘optimalHeight’ => $optimalHeight);
       }

Если вы выбрали обрезку — то есть вы использовали опцию обрезки, то у вас есть еще один маленький шаг. Мы собираемся обрезать изображение с
центр. Кадрирование очень похоже на процесс изменения размера, но с передачей еще нескольких параметров.

01
02
03
04
05
06
07
08
09
10
11
12
13
private function crop($optimalWidth, $optimalHeight, $newWidth, $newHeight)
       {
           // *** Find center — this will be used for the crop
           $cropStartX = ( $optimalWidth / 2) — ( $newWidth /2 );
           $cropStartY = ( $optimalHeight/ 2) — ( $newHeight/2 );
 
           $crop = $this->imageResized;
           //imagedestroy($this->imageResized);
 
           // *** Now crop from center to exact requested size
           $this->imageResized = imagecreatetruecolor($newWidth , $newHeight);
           imagecopyresampled($this->imageResized, $crop , 0, 0, $cropStartX, $cropStartY, $newWidth, $newHeight , $newWidth, $newHeight);
       }

Мы добираемся туда; почти сделано. Пришло время сохранить изображение. Мы проходим путь и получаем желаемое качество изображения в диапазоне от 0 до 100, 100 — лучшее, и вызываем соответствующий метод. Несколько моментов, касающихся качества изображения: JPG использует шкалу от 0 до 100, где 100 — лучшее. GIF изображения не имеют настройки качества изображения. PNG делают, но они используют шкалу 0-9, 0 является лучшим. Это нехорошо, поскольку мы не можем ожидать, что мы будем помнить это каждый раз, когда мы хотим сохранить изображение. Мы делаем немного магии, чтобы стандартизировать все.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public function saveImage($savePath, $imageQuality=»100″)
       {
           // *** Get extension
           $extension = strrchr($savePath, ‘.’);
           $extension = strtolower($extension);
 
           switch($extension)
           {
               case ‘.jpg’:
               case ‘.jpeg’:
                   if (imagetypes() & IMG_JPG) {
                       imagejpeg($this->imageResized, $savePath, $imageQuality);
                   }
                   break;
 
               case ‘.gif’:
                   if (imagetypes() & IMG_GIF) {
                       imagegif($this->imageResized, $savePath);
                   }
                   break;
 
               case ‘.png’:
                   // *** Scale quality from 0-100 to 0-9
                   $scaleQuality = round(($imageQuality/100) * 9);
 
                   // *** Invert quality setting as 0 is best, not 9
                   $invertScaleQuality = 9 — $scaleQuality;
 
                   if (imagetypes() & IMG_PNG) {
                       imagepng($this->imageResized, $savePath, $invertScaleQuality);
                   }
                   break;
 
               // … etc
 
               default:
                   // *** No extension — No save.
                   break;
           }
 
           imagedestroy($this->imageResized);
       }

Сейчас также самое время уничтожить наш ресурс изображений, чтобы освободить память. Если вы собираетесь использовать это в производственной среде, также может быть хорошей идеей захватить и вернуть результат сохраненного изображения.


Ну вот и все, ребята. Спасибо за то, что вы прочитали этот урок. Надеюсь, вы найдете его полезным Буду признателен за ваш отзыв, через комментарии ниже.