От автора: в данном уроке мы с Вами рассмотрим один из способов нанесения водяного знака на изображение средствами языка PHP. Так как используя водяные знаки на своих изображениях, Вы защитите их от использования другими пользователями, к тому же, если изображение будет использоваться на других сайтах, или будет найдено поисковой системой — водяной знак, содержащий ссылку на Ваш ресурс может привлечь дополнительный трафик.
Постановка задачи
В данном уроке нам с Вами необходимо реализовать динамическое добавление водяного знака к выводимому на экран изображению. При этом исходное изображение не должно быть изменено. А также необходимо сделать так, что бы, к примеру, при загрузке изображений на сервер, через обычную форму, выполнялось добавление водяных знаков к загружаемым изображениям.
Для решения поставленной задачи, я подготовил два изображения: исходное, на которое мы будем добавлять водяной знак, и, собственно, сам водяной знак. В качестве исходного изображения, мы будем использовать следующее изображение:
В качестве водяного знака, будем использовать следующее изображение:
Это изображение формата PNG с 50% степенью прозрачности.
Подготовка к написанию скрипта
Первым делом необходимо убедиться, что в Вашем интерпретаторе языка PHP подключена библиотека GD. Данная библиотека используется для работы с изображениями средствами языка PHP. Поэтому если Вы не уверены, что данная библиотека подключена, откройте конфигурационный файл языка PHP и найдите строку: extension=php_gd2.dll
Напротив данной строки не должно быть символа “;”(точка с запятой). Если он есть, то удалите его и перезапустите веб-сервер Apache. Далее, для сегодняшнего урока я подготовил тестовую страницу, которая отображает на экране исходное изображение:
1 2 3 4 5 6 7 8 9 |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title></title> </head> <body> <img src="img/img1.jpg"> </body> </html> |
Но если мы хотим динамически наносить на изображение водяной знак и при этом не изменять исходное изображение, значит, изображение должно обрабатываться скриптом на языке PHP. Поэтому в теге img необходимо изменить значение атрибута src. То есть значение данного атрибута должно указывать не на изображение, а на файл, который обработает исходное изображение и нанесет на него водяной знак. И конечно же вернет новое изображение. Поэтому перепишем тег img:
1 |
<img src="image.php?image=img1.jpg"> |
Как Вы видите, теперь мы обращаемся к файлу image.php, который вернет нам новое изображение, и передаем ему через GET параметры путь к исходному изображению. Перед тем как приступить к созданию файла image.php, который должен вернуть нам новое изображение, давайте создадим файл конфигурации config.php, с вот таким содержимым:
1 2 3 4 |
<?php define("DIR_IMG","img/"); define("WM",DIR_IMG."watermark.png"); ?> |
Данный фал нам необходим для хранения некоторых настроек, а именно:
DIR_IMG – папка где содержатся все изображения;
WM – путь к изображения, которое используется как водяной знак.
Затем создадим еще один файл – functions.php, который будет содержать в себе необходимые функции для работы скрипта. Теперь создадим файл image.php и первым делом подключим только что созданные файлы к нему.
1 2 |
include "config.php"; include "functions.php"; |
Далее проверим наличие ячейки image в суперглобальном массиве $_GET, если данная ячейка есть, то создадим переменную и сохраним в нее значение данной ячейки:
1 2 3 |
if($_GET['image']) { $image_for_wm = DIR_IMG.$_GET['image']; } |
Далее вызовем функцию, которая и будет автоматический добавлять водяной знак к изображению (данную функцию мы с Вами еще напишем):
1 |
get_water($image_for_wm); |
Теперь переходим непосредственно к написанию функции get_water(), которая обработает исходное изображение и нанесет на него водяной знак.
Функция наложения водяного знака
Итак, переходим в файл functions.php и начнем создавать функцию get_water():
1 2 3 |
function get_water($main_img_path, $load = FALSE) { $main_img = getimagesize($main_img_path); } |
Смотрите, функция принимает всего два параметра (из которых один не обязательный):
$main_img_path – путь к исходному изображению, которое требуется обработать;
$load – данный необязательный параметр принимает имя файла, под которым должно быть сохранено новое обработанное изображение. Данный параметр относится к случаю, когда мы хотим не вывести изображение на экран, а создать новое изображение из исходного, с наложенным водяным знаком, и сохранить его в папке. Путь к которой задан в конфигурационном файле.
В данной функции первым делом необходимо получить параметры исходного изображения. Для этого мы используем функцию getimagesize(), которая вернет нам массив, содержащий различные параметры изображения (путь к которому передан ей параметром). Давайте распечатаем данный массив в браузере и посмотрим, что у нас получилось:
То есть в ячейках 0 и 1 содержится ширина и высота данного изображения. В ячейке 2 одна из констант типа изображения (в нашем случае значение 2 соответствует типу jpeg). Индекс 3 содержит строку со значениями ширины и высоты изображения width=»xxx» height=»yyy», которая может быть использована внутри img тэга. Ячейка mime – содержит в себе соответствующий MIME-тип изображения.
Далее весь код будем вести внутри функции get_water(). Теперь необходимо проверить, не вернула ли функция getimagesize() – FALSE. Если да, то выходим из скрипта:
1 2 3 |
if(!$main_img) { exit(); } |
Далее в соответствии с MIME-типом изображения создаем на основе исходного изображения — новое изображение в памяти. Для этого мы используем оператор switch() и функции создания нового изображения на основе заданного в соответствии с его типом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
switch($main_img['mime']) { case 'image/jpeg': case 'image/pjpeg': $img = imagecreatefromjpeg($main_img_path); break; case 'image/png': case 'image/x-png': $img = imagecreatefrompng($main_img_path); break; case 'image/gif': $img = imagecreatefromgif($main_img_path); break; } |
Обратите внимание, что для MIME-типа ‘image/jpeg’, как и для ‘image/png’, нужно учитывать и дополнительные типы (‘image/pjpeg’ и ‘image/x-png’), которые может нам вернуть браузер Internet Explorer. Далее создаем изображение в памяти из заготовленного изображения под водяной знак:
1 2 3 |
if(file_exists(WM)) { $water = imagecreatefrompng(WM); } |
Здесь условимся, что изображения для водяного знака должно быть только формата PNG, поэтому используем соответственно функцию imagecreatefrompng(). Затем нам необходимо создать пустое изображение, точно такого же размера, как и исходное. И перенести на него сначала исходное изображение, а затем водяной знак. Для начала создаем переменные для хранения ширины и высоты будущего пустого изображения:
1 2 |
$res_width = $main_img[0]; $res_height = $main_img[1]; |
Далее при помощи функций imagesx() и imagesy(), определяем ширину и высоту, соответственно, изображения водяного знака:
1 2 |
$water_width = imagesx($water); $water_height = imagesy($water); |
Затем создаем пустое полноцветное изображение, с размерами равными размерам исходного изображения:
1 |
$res_img = imagecreatetruecolor($res_width,$res_height); |
Теперь остается перенести исходное изображение на только что созданное:
1 2 |
imagecopyresampled($res_img,$img,0,0,0,0, $res_width,$res_height,$main_img[0],$main_img[1]); |
Для этого используем функцию imagecopyresampled(), которая копирует и изменяет, по необходимости, размеры изображения. Параметры передаваемые данной функции:
$res_img – дискриптор изображения на которое выполняется копирование (изображение приемник, то которое мы только что создали);
$img – копируемое изображение (источник);
0 — x-координата изображения на которое выполняется копирование (точка по оси x в которую будет помещено копируемое изображение);
0 — y-координата изображения на которое выполняется копирование (точка по оси y в которую будет помещено копируемое изображение);
0 — x-координата изображения источника (точка по оси x c которой будет выполнено копирование);
0 — y-координата изображения источника (точка по оси y c которой будет выполнено копирование);
$res_width – ширина участка изображения приемника, куда будет помещено копируемое изображение;
$res_height — высота участка изображения приемника, куда будет помещено копируемое изображение;
$main_img[0] – ширина участка копируемого изображения (в нашем случае указываем полную ширину, так как нам необходимо скопировать все изображения, а не его часть);
$main_img[1] — высота участка копируемого изображения (в нашем случае указываем полную высоту, так как нам необходимо скопировать все изображения, а не его часть);
Далее, нам необходимо перенести водяной знак:
1 2 |
imagecopy($res_img,$water,$res_width-$water_width,$res_height-$water_height, 0,0,$water_width,$water_height); |
Для этого используем функцию imagecopy. Параметры, передаваемые данной функции:
$res_img – дискриптор изображения, на которое выполняется копирование (изображение приемник, то которое мы только что создали);
$water – дискриптор копируемого изображения;
$res_width-$water_width – координата по оси х, на изображении приемнике, в которую будет помещено копируемое изображение;
$res_height-$water_height — – координата по оси у, на изображении приемнике, в которую будет помещено копируемое изображение;
0 — x-координата изображения источника (точка по оси x c которой будет выполнено копирование);
0 — y-координата изображения источника (точка по оси y c которой будет выполнено копирование);
$water_width — ширина участка копируемого изображения (в нашем случае указываем полную ширину, так как нам необходимо скопировать все изображения, а не его часть);
$water_height — высота участка копируемого изображения (в нашем случае указываем полную высоту, так как нам необходимо скопировать все изображения, а не его часть).
Далее необходимо в зависимости от того, что содержится в переменной $load, либо вывести изображение на экран, либо сохранить его в файл, что собственно мы и сделаем:
1 2 3 4 5 6 7 |
if(!$load) { header("Content-Type:image/jpeg"); imagejpeg($res_img,NULL,100); } else { imagejpeg($res_img,DIR_IMG.$load,100); } |
То есть, если мы не передадим при вызове функции параметр $load, значит, изображение будет выведено на экран. Если же передать через параметр $load имя файла, значит, новое изображение будет сохранено под этим именем. Теперь давайте откроем в браузере файл index.php и посмотрим, как отрабатывает наш скрипт:
Как Вы видите, все отлично работает. На всякий случай приведу полный код данной функции:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
function get_water($main_img_path, $load = FALSE) { $main_img = getimagesize($main_img_path); if(!$main_img) { exit(); } switch($main_img['mime']) { case 'image/jpeg': case 'image/pjpeg': $img = imagecreatefromjpeg($main_img_path); break; case 'image/png': case 'image/x-png': $img = imagecreatefrompng($main_img_path); break; case 'image/gif': $img = imagecreatefromgif($main_img_path); break; } if(file_exists(WM)) { $water = imagecreatefrompng(WM); } $res_width = $main_img[0]; $res_height = $main_img[1]; $water_width = imagesx($water); $water_height = imagesy($water); $res_img = imagecreatetruecolor($res_width,$res_height); imagecopyresampled($res_img,$img,0,0,0,0,$res_width,$res_height, $main_img[0],$main_img[1]); imagecopy($res_img,$water,$res_width-$water_width,$res_height-$water_height, 0,0,$water_width,$water_height); if(!$load) { header("Content-Type:image/jpeg"); imagejpeg($res_img,NULL,100); } else { imagejpeg($res_img,DIR_IMG.$load,100); } } |
Сохранение обработанного изображения в файле
Для того чтобы не выводить на экран изображение с водяным знаком, а сохранить его в папке. К примеру, это полезно, если выполняется загрузка изображений на сервер через текстовую форму. В этом случае удобно сразу же наносить водяной знак на все изображения (если конечно Вы не планируете в будущем изменять водяной знак). В этом случае можно создать простейшую страницу с формой загрузки файлов и следующим образом вызвать нашу созданную функцию (в моем случае это файл load.php):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<?php include "config.php"; include "functions.php"; if($_FILES['load']) { if(move_uploaded_file($_FILES['load']['tmp_name'],DIR_IMG.$_FILES['load']['name'])) { get_water(DIR_IMG.$_FILES['load']['name'],'wm_'.$_FILES['load']['name']); } } ?> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title></title> <meta name="" content=""> <meta name="vs_targetSchema" content="//schemas.microsoft.com/intellisense/ie5"> </head> <body> <form method="POST" enctype="multipart/form-data"> <input type="file" name="load"> <input type="submit"> </form> </body> </html> |
Если запустить данный файл в браузере, то при загрузке изображения на сервер, будет создаваться его копия с наложенным водяным знаком.
На этом данный урок можно завершать. Всего Вам доброго, удачного кодирования! И увидимся в следующих уроках!
Комментарии (14)