Тестовый дизайн новой версии сайта IGD.BY         RU   |   EN
PHP. Наложение прозрачного ватермарка (watermark) на изображения с учетом масштабирования
Автор: Кристофер

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

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

1. Смешивание двух изображений "на лету" при генерации страницы.

2. Создание файлового кэша с изображениями, на которые уже наложены ватермарки.

Первый вариант не стоит считать приемлемым, поскольку он нагружает сервер. И учитывая, что многие современные фреймворки и CMS, и так "тяжелы" до невозможности, давать дополнительную вычислительную нагрузку — смысла не много.

Особенно, если мы говорим о больших каталогах со множеством картинок и так далее. Второй вариант является лучшим, на нем мы сегодня и остановимся. Есть еще и третий вариант защиты, который не относится к PHP, и делается на уровне CSS.

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

Пишем задание

Итак, что же мы сделаем в представленном ниже коде, и как он будет работать? Условимся так:

1. Файл с ватермарком лежит в корневой папке /images/ и называется water_logo.png.

2. Ватермарк должен раполагаться по центру изображений и его ширина должна составлять 40% от ширины основного изображения.

3. Файлы с ватермарками сохраняются в корневую папку /watermark/.

Примечания к структуре работы алгоритма:

1. Ключевая функция-триггер в качестве аргумента приминает путь к необработнному изображению. На его базе формирует уникальное имя, затем производит сверку: если файл с таким именем уже существует в папке watermark, то просто возращает это имя, если не существует, то запускает механизм создания изображения с ватермарком, после чего возвращает лпять же это имя.

2. Наложение png должно учитывать прозрачный слой.

Наш код

В принципе, тут все откомментировано, хотя после добавим несколько отдельных замечаний... Итак, watermak.php

<?
//функция проверки существования файла и триггер
function watermark_function($path)
    {
        //получаем имя файла с ватермарком
		$i_name=watermark_image_name($path);
		//формируем строку адреса файла с ватермарком
		$w_path='/watermark/'.$i_name;
		if(@fopen($_SERVER['DOCUMENT_ROOT'].$w_path, "r")) {
			return $w_path;
			} else {
			watermark_on_image($i_name, $path);
			return $w_path;
			}
    }

//функция создания имени файла с ватермарком
function watermark_image_name($path)
    {
        //формируем уникальное название
		$i_path=explode('/', trim($path, ' /'));
		$i_name=$i_path[1];
		$i=2;
		while($i_path[$i]!='')
			{
				$i_name=$i_name.'-'.$i_path[$i];
				$i++;
				}
        return $i_name;
    }

//функция добавления водяного знака
function watermark_on_image($i_name, $path)
    {
//полный путь к файлу-исходнику
		$path = $_SERVER['DOCUMENT_ROOT'].$path;
//загружаем картинку-исходник
		$image = imagecreatefromstring(file_get_contents($path));
//узнаем ширину и высоту
		$w = imagesx($image);
		$h = imagesy($image);
//находим 40% от ширины
		$w_40=round(0.4*$w);
// загружаем watermark
		$watermark = imagecreatefrompng($_SERVER['DOCUMENT_ROOT'].'/images/water_logo.png');
//узнаем ширину и высоту ватермарка
		$ww = imagesx($watermark);
		$wh = imagesy($watermark);
		//находим коэффициэнт
		$koeff=$w_40/$ww;
		//новая высота ватермарка
		$h_40=round($koeff*$wh);
// изменяем размер ватермарка
		$image_w = imagecreatetruecolor($w_40, $h_40) or die('Изображение не создается...'); 
		$transparent = imagecolorallocatealpha($image_w, 0, 0, 0, 127); 
		imagefill($image_w, 0, 0, $transparent); 
		imagesavealpha($image_w, true); // сохранение смешивания с прозрачным слоем (важно); 
		imagecopyresampled($image_w, $watermark, 0, 0, 0, 0, $w_40, $h_40, $ww, $wh);
// Помещаем ватермарк по центру картинки
		imagecopy($image, $image_w, (($w/2)-($w_40/2)), (($h/2)-($h_40/2)), 0, 0, $w_40, $h_40);
		imagealphablending($image, false);
		imagesavealpha($image, true);
//сохраняем файл с ватермарком
		imagejpeg($image, $_SERVER['DOCUMENT_ROOT'].'/watermark/'.$i_name);
    }
?>

Вызов функции и отображение картинки с ватермарком в данном случае будет производиться к примеру так:

<?
include($_SERVER['DOCUMENT_ROOT'].'/watermark.php');//если файл в корне сайта
//...
$image_src='/upload/iblock/6b1/pen.jpg';
$w_image=watermark_function($image_src);
?>
<img src="<?=$w_image;?>" alt=""/>

Отдельно прокомментируем несколько моментов из файла watermark.php. Функция watermark_image_name($path) дробит путь к картинке с учетом того, что она может располагаться глубоко внутри каталога. Параметр 40% (то, что ширина ватермарка должна быть равна 40% от основного изображения) задана не входным аргументом, а просто цифрой 0.4, что легко исправимо. Проверяем работу кода...

Все работает.