Нижний колонтитул для картинки или фото с помощью ImageMagick
Сниппеты 20:09 / 05.07.2021 1 337
Недавно в одном из чатов обсуждалась задача на ImageMagick, которая мне показалось интересной, ввиду того, что её посчитали сложной и готовых похожих решений не нашлось.
Вкратце задача выглядела так: необходимо написать скрипт, который с помощью ImageMagick будет добавлять нижний колонтитул (футер) на фото или картинку. Причем этот колонтитул не должен накладываться на первоначальное изображение, а добавляться внизу по ширине обрабатываемого изображения. На колонтитуле (черном) должны быть логотип (статический) и две надписи (белые) с возможностью выбора произвольных шрифтов для этих надписей.
Ранее я никогда не имел опыта с ImageMagick для PHP, так как для моих задач мне вполне хватало возможностей библиотеки GD. Мне захотелось решить эту задачу, и с готовым решением я делюсь в этой публикации.
Внимание!
Это не готовый проект или библиотека, а просто пример кода - как вы можете использовать ImageMagick для добавления колонтитула с логотипом и надписью к картинке или фотографии.
Репозиторий с кодом на GitHub: https://github.com/Icemont/Simple-Imagick-Footer
Краткий план
Нам необходимо написать код, который затем можно будет использовать в библиотеке для обработки изображений в конечном проекте, и продемонстрировать работу этого кода. Главное тут сама идея как решить задачу, а не готовая библиотека для конечного проекта.
Для загрузки обрабатываемых изображений у нас будет простая статическая HTML страница, с помощью которой мы будем передавать наше изображение нашему скрипту обработчику. Скрипт обработчик будет проверять загруженное изображение на соответствие разрешенным к обработке типам изображений, обрабатывать изображение и выводить его непосредственно в браузер.
Идея
Немного ознакомившись с документацией ImageMagick для PHP на официальном сайте, у меня возникла идея, как решить эту задачу просто и быстро. Так как логотип нам нужен статический, а цвет фона тоже статичен - черный, то мы можем заранее нарисовать наш колонтитул с логотипом в графическом редакторе и сохранить его в размере, заведомо превышающем потенциальный размер выходного изображения. Для изображения колонтитула важно использовать формат использующий сжатие без потерь - я выбрал PNG. Назовем изображение "footer.png".
Вот такой колонтитул я по-быстрому нарисовал (это превью, оригинал в репозитории):
Решение
Данное решение не претендует на идеальность, а также не претендует быть истинной в последней инстанции, и всего лишь демонстрирует один из возможных вариантов решения этой задачи.
Создадим нашу статическую HTML страницу для передачи обрабатываемого фото или картинки скрипту-обработчику.
Для того, чтобы наша страница имела хоть какой-то визуально приятный вид, будем использовать CSS фреймворк Bootstrap 4.
Файл: imagemagick.html
<!doctype html>
<html lang="en">
<head>
<title>ImageMagick Test</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
</head>
<body>
<main role="main">
<div class="container">
<div class="jumbotron">
<h1 class="display-4 mb-4">ImageMagick Test!</h1>
<form method="post" action="imagemagick.php" enctype="multipart/form-data" id="loadform">
<div class="row">
<div class="col-auto col-lg-10">
<div class="form-group">
<label for="fileselect">Select an image file</label>
<input type="file" name="image" class="form-control" id="fileselect">
</div>
<div class="form-group">
<label for="text1">Label #1</label>
<input type="text" class="form-control" id="text1" name="text1" maxlength="35" aria-describedby="text1Help">
<small id="text1Help" class="form-text text-muted">Maximum 35 characters (will be trimmed)</small>
</div>
<div class="form-group">
<label for="text2">Label #2</label>
<input type="text" class="form-control" id="text2" name="text2" maxlength="65" aria-describedby="text2Help">
<small id="text2Help" class="form-text text-muted">Maximum 65 characters (will be trimmed)</small>
</div>
<button id="but_upload" type="submit" class="btn btn-primary">Upload & Test</button>
</div>
</div>
</form>
</div>
</div>
</main>
</body>
</html>
Вот так выглядит наша страница загрузки изображения в браузере:
Также нам понадобятся шрифты для надписей. Для примера я взял бесплатные шрифты Droid Sans и Droid Serif Italic. Они также присутствуют в репозитории проекта на GitHub. Для шрифтов создадим папку "fonts" и поместим шрифты в неё.
Код самого скрипта для обработки:
<?php
/**
* Simple Imagick Footer
*
* @author Ray Icemont <ray@icemont.dev>
* @license https://opensource.org/licenses/Apache-2.0
*/
setlocale(LC_ALL, 'ru_RU.utf-8');
mb_internal_encoding('utf-8');
define('MAIN_DIR', dirname(__FILE__));
$allowed_types = ['image/jpeg', 'image/png', 'image/gif'];
if (isset($_FILES['image']['tmp_name']) &&
in_array(mime_content_type($_FILES['image']['tmp_name']), $allowed_types)) {
if (!$string = filter_input(INPUT_POST, 'text1', FILTER_SANITIZE_SPECIAL_CHARS)) {
$string = "Header with the name of the picture";
}
if (!$string2 = filter_input(INPUT_POST, 'text2', FILTER_SANITIZE_SPECIAL_CHARS)) {
$string2 = "Signed by Lorem Ipsum";
}
$string = mb_substr($string, 0, 35);
$string2 = mb_substr($string2, 0, 65);
try {
$im = new Imagick();
$im->readImage($_FILES['image']['tmp_name']);
$im_res = $im->getImageGeometry();
$footer = new Imagick();
$footer->readImage(MAIN_DIR . '/footer.png');
$draw = new ImagickDraw();
$draw->setTextEncoding('UTF-8');
$draw->setFillColor(new ImagickPixel('white'));
$draw->setFont(MAIN_DIR . '/fonts/droid-sans.ttf');
$draw->setFontSize(120);
$footer->annotateImage($draw, 20, 150, 0, $string);
$draw->setFont(MAIN_DIR . '/fonts/droid-serif-italic.ttf');
$draw->setFontSize(62);
$footer->annotateImage($draw, 20, 250, 0, $string2);
$footer->resizeImage($im_res['width'], null, imagick::FILTER_LANCZOS, 0.9);
$im->addImage($footer);
$im->resetIterator();
$combined = $im->appendImages(true);
header("Content-Type: image/jpg");
echo $combined->getImageBlob();
} catch (ImagickException $e) {
exit('Imagick Error: ' . $e->getMessage());
} catch (ImagickDrawException $e) {
exit('Imagick Draw Error: ' . $e->getMessage());
}
} else {
exit('Error: Access denied! Select an image file!');
}
Для тестирования возьмем какое-нибудь изображение с любого источника бесплатных изображений и попробуем его загрузить для обработки. Я взял фото нашей планеты из космоса от NASA.
Результат обработки фото выглядит вот так:
Результат полностью соответствует поставленной задаче. Используя идею, реализованную в данном коде, мы можем легко создать библиотеку для удобной обработки изображений подобным образом в нашем проекте.