Обрезка и изменение размера изображений

Если на вашем сайте есть возможность пользователям загружать изображения на сервер. Обрезка и изменение размера изображения как в Photoshop вам очень пригодится. Вы можете позволить пользователям загружать фотографии с любого устройства (например с планшета или телефона) и не переживать за конечный размер файла. Кроме того вы можете создавать разные версии одного и того же изображения и позволить пользователям обрезать определенные части загружаемой картинки.

В этой статье показано как создать инструмент обрезки изображения с помощью расширения PHP ImageMagick. Если у вас не установлено это расширение, тогда обязательно прочтите руководство по установке и настройке ImageMagick.

Знакомство с ImageMagick

В ImageMagick есть своя библиотека которая обрабатывает изображение. ImageMagick предоставляет множество методов API, с помощью которых вы можете манипулировать изображениями, например сделать водяной знак.

Библиотека ImageMagick предлагает простой, объектно-ориентированный интерфейс для использования API, вам просто необходимо создать экземпляр класса Imagick, а затем вызвать соответствующие методы для начала манипулирования изображениями.

Демо

Поскольку мы собираемся создать обрезку картинок (crop), мы в основном будем использовать два метода: cropImage() и thumbnailimage().

к меню ↑

cropImage

Метод cropImage() принимает четыре аргумента. Первые два аргумента указывают высоту и ширину обрезаемой области, а последние два указывают координаты X и Y верхнего левого угла обрезаемой области.

Например:
<?php
$inFile = "test.jpg";
$outFile = "test-cropped.jpg";
$image = new Imagick($inFile);
$image->cropImage(400,400, 30,10);
$image->writeImage($outFile);

Сначала мы создали объект Imagick, передавая конструктору Imagick имя нашего изображения. Затем мы вызываем cropImage() с соответствующими аргументами. В этом случае код обрезает изображение, начиная с сверху 30px и 10px слева, исходного изображения, кадрируя его размером 400×400px. И в конце writeImage() сохраняет результат.

к меню ↑

thumbnailImage

Метод thumbnailImage() принимает высоту и ширину масштабированного изображения и может быть использован следующим образом:

<?php
$inFile = "test.jpg";
$outFile = "test-thumbnail.jpg";
$image = new Imagick($inFile);
$image->thumbnailImage(200, 200);
$image->writeImage($outFile);

Этот код делает миниатюру изображения с размером 200×200px. В том случае если аргумент thumbnailImage() ширина или высота установлены в значение 0, соотношение сторон сохраняется.

Есть еще один аргумент известен как bestfit; если его значение true, значит новые размеры изображения будут изменены таким образом, чтобы соблюдать указанные размеры высоты и ширины. Например, вызов thumbnailImage(400, 400, true) для изображения 1200×768px будет создавать версии изображения с размером 400×200px. Новые размеры меньше и равны указанному размеру.

к меню ↑

Обрезать изображение

Конечно, нам нужно создать форму HTML с помощью которого пользователи смогут загружать картинки:

<form action="upload.php" enctype="multipart/form-data" method="post">
 <label for="file">Изображение:</label>
 <input id="file" type="file" name="file" />
 <input type="submit" name="submit" value="Загрузить и обрезать" />
</form>

Как только пользователь нажимает кнопку Сохранить, запросу method="post" будет отправлен в скрипт, который будет обрабатывать процесс загрузки файла на сервер, а потом покажет загруженное изображение пользователю для обрезки. Помните, для загрузки файлов вам необходимо установить атрибут формы enctype "multipart/form-data".

Скрипт обрабатывает загрузку изображений и изменит размер изображения, если нужно.

<?php
if (isset($_FILES["file"])) {
    $tmpFile = $_FILES["file"]["tmp_name"];
    $fileName = …
    // определить безопасное имя для закачиваемого файла
    list($width, $height) = getimagesize($tmpFile);
   // проверить, файл действительно изображение
if ($width == null && $height == null) {
    header("Location: index.php"); return; }
   // если необходимо изменить размер
if ($width —>= 400 && $height >= 400) {
    $image = new Imagick($tmpFile);
    $image->thumbnailImage(400, 400);
    $image->writeImage($fileName);
  }
  else {
    move_uploaded_file($tmpFile, $fileName);
  }
}

Нужно быть очень осторожным при загрузке файлов от пользователей, кто-то может загрузить вредоносный файл на ваш сервер.

к меню ↑

Безопасная загрузка файлов

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

Один из них, проверяет тип загружаемого файла.

$_FILES["myFile"]["type"]

но имя расширения файла не является безопасным потому что его можно легко подделать. Лучше всего использовать функцию exif_imagetype() она анализирует содержимое файла и определит, действительно это файл GIF, JPEG, или другие форматы изображений. Если exif_imagetype() не доступен (функция требует расширения Exif), тогда используйте getimagesize(). В массиве getimagesize() возврат будет содержать тип изображения.

<?php
 // проверить файл в формате GIF, JPEG или PNG
$fileType = exif_imagetype($_FILES["myFile"]["tmp_name"]);
$allowed = array(IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG);
if (!in_array($fileType, $allowed)) {
  // этот тип файла не поддерживается
  … 

Функция getimagesize() возвращает null, если файл не является изображением, поэтому, если код определяет что файл не является изображением, он просто отправит пользователя на… другое место.

Так как сценарий уже знает ширину и высоту загруженного изображения в этот пункт может определить, нужно ли изменить изображение. Если размер больше чем 400×400px, значит изменит, и создать миниатюру 400×400px, вызвав thumbnailImage(). Поскольку Я объяснил ранее, метод берет два параметра: ширина и высота. Если Вы хотите сохранить соотношение сторон изображения, ставим параметр 0.

Наконец, измененное изображение сохраняется путем вызова writeImage(), или перемещает с move_uploaded_file() если это был подходящий размер.

Сохраненное изображение выводится в браузер, так что пользователь получает возможность обрезать его. Чтобы предоставить пользователям возможность выбрать определенные участки изображения, я использую плагин ImageAreaSelect. Для использования плагина, должна быть подключена библиотека jQuery.

к меню ↑

Файлы JavaScript и CSS

<script type="text/javascript" src="scripts/jquery.min.js"></script>
<script type="text/javascript" src="scripts/jquery.imgareaselect.pack.js"></script>
<link href="css/imgareaselect-default.css" rel="stylesheet" type="text/css" />

Для инициализации плагина используйте следующий код:

selection = $('#photo').imgAreaSelect({
  handles: true,
  instance: true
});

#photo — id изображения, которое показывается пользователю. Устанавливая true свойства handles на изображении будут показаны маркеры для изменения размеров выбранной области, и instance true получит экземпляр и сохранить его в переменной selection. Именно через переменную selection извлекается выделенная область когда пользователь подтвердит обрезку изображения.

getSelection() предоставит вам все, что вам нужно. Например, getSelection().width дает вам ширину области selection. Кроме того, вы можете использовать getSelection().x1 и getSelection().y1 чтобы найти координаты верхнего левого угла выбранной области.

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

$("#crop").click(function(){
  var s = selection.getSelection();
  var width = s.width;
  var height = s.height;
  var x = s.x1;
  var y = s.y1;
  …
});

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

var request = $.ajax({
  url: "crop.php",
  type: "GET",
  data: {
    x: x,
    y: y,
    height: height,
    width: width,
    image: $("#photo").attr("src")
  }
});

Когда запрос сделан, новое, уже обрезанное изображение будет показано на месте оригинального изображения.

request.done(function(msg) {
  $("#photo").attr("src", msg);
  selection.cancelSelection();
});

При обрезке, делается запрос, возвращает имя вставляемого изображения и новая картинка загружается при изменении атрибут src.

к меню ↑

Завершение обрезки

<?php $file = basename($_GET["image"]);
  $cropped = "cropped_" . $file;
  $image = new Imagick($file);
  $image->cropImage($_GET["width"],
  $_GET["height"], $_GET["x"], $_GET["y"]);
  $image->writeImage($cropped);
echo $cropped;

Этот скрипт сначала извлекает имя изображения, которое должно быть обрезано; название изображения будет в виде полного URL адреса например: http://example.com/path/image.jpg. Далее, в строке cropped ставим название, которое после обрезки будет выглядеть по другому чем оригинал, например cropped_image.jpg. Это и есть изменённое изображение, таким способом оригинал изображения не изменяется.

Метод cropImage() используется для обрезки исходного изображения, используя четыре параметра относящиеся к выбранной области, которые были отправлены в скрипт, а затем обрезанное изображение сохраняется как новый файл. Имя кадрированного изображение затем echo вернёт к запросу Ajax для отображения в браузере.

к меню ↑

Заключение

В этой статье создан простой инструмент обрезки, чтобы показать как можно использовать расширение ImageMagick для своих проектов. Вы можете узнать больше об этом, и сделать что-то более полезное с использованием его API. Пример кода этой статьи доступен на PHPMaster GitHub. Если вам нужно готовое решение обрезки изображения смотрите HTML5 загрузка и изменение размера изображений.

htmlhook.ru | Скрипты для веб-приложений