Сервис для нанесения водяного знака своими руками на PHP
На работе возникала необходимость нанесения водяного знака на техническое свидетельство. Водяной знак представлял собой обычно 4-5 строк текста.
В начале я данную задачу делал обычно при помощи графической программы Photoshop. Однако со временем надоело выполнять данную задачу в ручную и пришла идея написать готовый скрипт на PHP (тем более проблем с разворачиванием сервера не было, т.к. для разработки уже использовался локальный сервер). Задача написания скрипта оказалось простой и не сложной. Итак, приступим.
В начале необходимо создать вот такую структуру папок и файлов на вашем локальном сервере:
В папке fonts мы удобно поместили шрифт, используемый для написания текста водяного знака. Я использовал шрифт Moscow Sans Regular. Вы же можете воспользоваться любым своим шрифтом.
Папка output необходима для автоматического создания в ней изображений с наложенным водяным знаком на каждое из них.
Папка source необходима для наших исходных изображений, на которые будет накладываться водяной знак. Кстати, я для своей задачи использовал 17 изображений, представляющих отсканированные страницы формата А4. Естественно можно помесить в нее как одно изображение, так хоть сотню. Просто увеличется время выполнения скрипта. Однако, не рекомендую слишком большое количество файлов.
В файле index.php мы разместим нашу форму, на которой будет возможность менять текст водяного знака, а также управлять размером шрифта и углом наклона водяного знака.
Размер шрифта и угол наклона уже настроены оптимально. Еще после наложения знака значения строк сохраняются в сессию. Если хотите вернуть значения по умолчанию, то необходимо нажать на кнопку «Сбросить значения». По умолчанию значения строк заполнены некоторым текстом, который можно изменить в файле index.php.
В файле create.php разместим сам код для наложения водяного знака на наши исходные изображения. В случае успеха будет сделано перенаправление на index.php и вывод сообщения об успехе.
Для оформления я использовал css-фреймворк bootstrap и собственный файл css-стилей.
Файл style.css
body { background-color: #222; color: #fff; } input[type=text]{ border-radius: 0; width: 400px !important; } button.btn{ border-radius: 0; } div.alert-success { margin-top: 10px; border-radius: 0; width: 400px; } .width100p { width: 100% !important; } .noresize { resize: none; border-radius: 0; }
Файл index.php
<?php session_start(); $text = [ 'Техническое свидетельство и Техническая оценка', 'выданы: ООО "Организация"', 'объект: ООО "Название объекта"', 'по адресу: г. Название, ул. Название, д. 1' ]; ?> <!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Водяной знак для тех. свидетельства</title> <link rel="stylesheet" href="../css/bootstrap.min.css"/> <link rel="stylesheet" href="../css/style.css"/> </head> <body> <div class="container"> <div class="row"> <div class="col-sm-12"> <br> <a href="/" class="btn btn-default">Назад</a> </div> </div> <div class="row"> <div class="col-sm-12"> <h3>Данные для водяного знака</h3> <? if ($_GET['result'] == 'success'){?> <div class="alert alert-success" role="alert">Водяной знак успешно наложен.</div> <?}?> <? if (!isset($_GET['result']) && $_GET['result'] != 'success') { unset($_SESSION['text']); } ?> <form method="post" action="create.php"> <div class="form-group"> <label>Строка 1</label> <input type="text" name="text[]" class="form-control" value="<?= isset($_SESSION['text']) ? htmlspecialchars($_SESSION['text'][0]) : htmlspecialchars($text[0]) ?>"> </div> <div class="form-group"> <label>Строка 2</label> <input type="text" name="text[]" class="form-control" value="<?= isset($_SESSION['text']) ? htmlspecialchars($_SESSION['text'][1]) : htmlspecialchars($text[1]) ?>"> </div> <div class="form-group"> <label>Строка 3</label> <input type="text" name="text[]" class="form-control" value="<?= isset($_SESSION['text']) ? htmlspecialchars($_SESSION['text'][2]) : htmlspecialchars($text[2]) ?>"> </div> <div class="form-group"> <label>Строка 4</label> <input type="text" name="text[]" class="form-control" value="<?= isset($_SESSION['text']) ? htmlspecialchars($_SESSION['text'][3]) : htmlspecialchars($text[3]) ?>"> </div> <div class="form-group"> <label>Строка 5</label> <input type="text" name="text[]" class="form-control" value="<?= isset($_SESSION['text']) ? htmlspecialchars($_SESSION['text'][4]) : htmlspecialchars($text[4]) ?>"> </div> <div class="form-group"> <label>Размер шрифта</label> <input type="text" name="sizeFont" class="form-control" value="54" style="width: 60px !important;"> </div> <div class="form-group"> <label>Угол наклона вод. знака</label> <input type="text" name="angleText" class="form-control" value="30" style="width: 60px !important;"> </div> <button type="submit" class="btn btn-success">Наложить водяной знак</button> <? if (isset($_SESSION['text'])) {?> <a href="/watermark/" class="btn btn-warning">Сбросить значения</a> <?}?> </form> </div> </div> </div> </body> </html>
Особых комментариев по данному коду не стану делать. Все итак довольно просто и понятно. Переменная $text является массивом всех строк для водяного знака, т.е. каждая новая строка — это новый элемент массива $text.
А вот и сам более интересный файл create.php.
<?php session_start(); /** * Создание водяного знака */ if ($_POST){ $arrText = array_diff($_POST['text'], ['']); // Из массива отсеиваем пустые строки $sizeFont = (int)$_POST['sizeFont']; $angleText = (int)$_POST['angleText']; $fontPath = dirname(__FILE__) . '/fonts/MoscowSansRegular.ttf'; $sourcePath = dirname(__FILE__) . '/source/'; $outputPath = dirname(__FILE__) . '/output/'; /** * @param $img Идентификатор изображения, на которое добавляется водяной знак * @param $text Текст надписи * @param $font Имя файла шрифта .ttf * @param int $r Цвет надписи в формате RGB * @param int $g Цвет надписи в формате RGB * @param int $b Цвет надписи в формате RGB * @param int $alpha Уровень прозрачности от 0 до 128 * @return mixed */ function addWatermark($img, $text, $font, $r = 128, $g = 128, $b = 128, $alpha = 100) { if(!is_array($text)) return false; $width = imagesx($img); $height = imagesy($img); $angle = 30; $c = imagecolorallocatealpha($img, $r, $g, $b, $alpha); $size = 54; $offset = 100; // Смещение между строками для оси Y // Нанесение текста из массива со смещением по оси Y for($i=0;$i<count($text);$i++){ $box = imagettfbbox ($size, $angle, $font, $text[$i]); $x = $width/2 - abs($box[4] - $box[0])/2; $y = ($height/2 + abs($box[5] - $box[1])/2) + $offset*$i; imagettftext($img, $size, $angle, $x, $y, $c, $font, $text[$i]); } return $img; } $allFilenames = glob($sourcePath . '*.jpg'); $countFiles = count($allFilenames); for($i=0;$i<$countFiles;$i++){ $img = imagecreatefromjpeg($allFilenames[$i]); $image = addWatermark($img, $arrText, $fontPath, 72, 72, 72, 60); imageJPEG($image, $outputPath . basename($allFilenames[$i])); imagedestroy($image); } $_SESSION['text'] = $arrText; header('Location: /watermark/?result=success'); }
Код максимально снабжен комментариями, что сделает его понимание более простым.
Внимание. Для правильной работы необходимо добавить шрифт в папку fonts и изменить его имя в переменной $fontPath. В папку source необходимо добавить хотя бы одно исходное изображение (учитываются только файлы с расширением JPG).
Еще одна пометка — все файлы я располагал в отдельной папке watermark. Если будите менять папку, то следует учитывать пути в коде.
Таким образом, за короткий промежуток времени набросал небольшой полезный скрипт, который сэкономит время при создании водяного знака в несколько строк.
Конечно, вы можете изменить скрипт под свои нужды или доработать его так как вам необходимо.
Спасибо за внимание. Если возникли вопросы, пишите.