Нередко возникает необходимость защитить фотографии на сайте от воровства. Особенно популярно в различных каталогах и т.д. Самый простой и надежный способ — наложение так называемых ватермарков.
Создается картинка, размерами MxN с прозрачным фоном и полупрозрачной надписью с именем домена. Сохраняется в формате PNG-24. Вся штука кроется в библиотеке GD при наложении друг на друга картинок. Первая картинка, собственно, сама фотография; на нее накладывается другая — полупрозрачная ватермарка.
Вот самый распространенный код для этих целей. Он вполне хорош в плане потребления оперативной памяти и сравнительно быстро работает. Но имеет значительный недостаток, о котором поговорим чуть ниже:
//Загружаем фотографию из нужного формата. Здесь JPG. $image = imagecreatefromjpeg($filename); //Можно создать небольшую функцию определения формата и загрузки изображения. //Или воспользоваться imagecreatefromstring //Загружаем нашу ватермарку $water=imagecreatefrompng($file); //Определяем ее ширину $water_width=imagesx($water); //Определяем ее высоту $water_height=imagesy($water); $img_width=imagesx($image); $img_height=imagesy($image); //Вычисляем координаты, чтобы ватермарка оказалась посередине фотографии $dest_x = ($img_width-$water_width)/2; $dest_y = ($img_height-$water_height)/2; imagealphablending($this->image, 1); imagealphablending($this->water, 1); imagesavealpha($this->image, 1); imagesavealpha($this->water, 1); imagecopyresampled($image, $water, $dest_x, $dest_y,0, 0, $water_width, $water_height,$water_width, $water_height); //Сохраняем. Вторым параметром идет имя файла, третьим - качество. Чем выше, тем лучше. imagejpeg($image, $filename, 95); |
Данный код прекрасно работает, если фотография или картинка загружается из формата JPG. Если у нас формат PNG или GIF то после наложения получим несколько не тот результат, который бы хотелось. То фон становится непрозрачным а то и вовсе получаем белое (серое, зеленое) пятно на месте предполагаемой ватермарки. Причем совершенно непрозрачное и размером во весь холст. Так что значительная часть фото становится замазана а-ля цензура.
Как оказалось, этот баг давно известен разработчикам библиотеки GD, но очевидно они не спешат его исправлять. С проблемой впервые столкнулись примерно в 2010 году. Сейчас на дворе 2015, я использую версию библиотеки 2.0.35 и все ок, баг на месте. Хорошо поддерживается формат PNG-8, но беда в том, что у него нет прозрачности.
Теперь о том, как с этой ситуацией бороться. К сожалению чуточку костыльный способ, требует чуть больше ресурсов, зато без проблем работает на всех типах исходных картинок:
//Первая часть точно такая же. Никакой разницы. //$dest_y = ($img_height-$water_height)/2; //А вот здесь начинаются изменения... //Подготавливаем пустой холст размером с нашу ватермарку $cut = imagecreatetruecolor($water_width, $water_height); //Копируем туда кусок исходной картинки из середины. //Ровно то место, куда будет наложена ватермарка imagecopy($cut, $image, 0, 0, $dest_x, $dest_y, $water_width, $water_height); //Теперь копируем туда же саму ватермарку. imagecopy($cut, $water, 0, 0, 0, 0, $water_width, $water_height); //Соединяем наш подготовленный холст с целевой картинкой imagecopymerge($image, $cut, $dest_x, $dest_y, 0, 0, $water_width, $water_height, 100); //Сохраняем imagejpeg($image, $filename, 95); |
Вот собственно и все. Теперь можем ставить watermarks на изображения любых (поддерживаемых библиотекой GD) форматов.
За подробными разъяснениями по параметрам функций, обращайтесь к официальной документации.