Blog. Just Blog

Нанесение текстовых водяных знаков на изображение

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Web-мастеру и не только | Автор: ManHunter
Для предотвращения воровства контента часто используются водяные знаки на изображениях. Это может быть логотип сайта, надпись об авторских правах или, например, ссылка на ваш сайт. Для нанесения водяных знаков создано множество различных программ, но при наполнении сайта гораздо удобнее использовать скрипт, который будет маркировать картинки сразу при загрузке на сервер. Я написал такую функцию, наносящую нужный текст в указанное место изображения. Ее особенностью является то, что перед нанесением надписи анализируется цвет картинки в месте, где будет расположен текст. Для темных картинок будет выбран белый цвет надписи с черной рамкой, а для светлых наоборот, будет выбран черный цвет надписи с белой рамкой.
  1. //-------------------------------------------------------------------
  2. // Функция нанесения текстового водяного знака на изображение
  3. // Copyright (C) ManHunter / PCL
  4. // http://www.manhunter.ru
  5. //-------------------------------------------------------------------
  6. // Параметры вызова:
  7. // $picture - путь к файлу картинки на сервере
  8. // $font - путь к файлу с TrueType-шрифтом на сервере
  9. // $font_size - размер шрифта
  10. // $marker - текст водяного знака
  11. // $watermark_position - положение водяного знака на картинке
  12. //-------------------------------------------------------------------
  13.  
  14. // Константы положения водяного знака на картинке
  15. define ("WATERMARK_LEFT_BOTTOM",0);
  16. define ("WATERMARK_LEFT_TOP",1);
  17. define ("WATERMARK_RIGHT_BOTTOM",2);
  18. define ("WATERMARK_RIGHT_TOP",3);
  19. define ("WATERMARK_CENTER",4);
  20.  
  21. function Watermark_Image($picture$font$font_size$marker,
  22.                          $watermark_position=WATERMARK_LEFT_BOTTOM) {
  23.   // Проверки на наличие файлов и допустимые параметры
  24.   if (!file_exists($picture)) { return false; }
  25.   if (!file_exists($font)) { return false; }
  26.   if ($font_size<10) { return false; }
  27.   if (($marker=trim($marker))=="") { return false; }
  28.  
  29.   // Получить размеры исходного изображения
  30.   list ($sx,$sy)=GetImageSize($picture);
  31.   if ($sx==|| $sy==0) { return false; }
  32.  
  33.   $dst_im=imageCreatetruecolor($sx,$sy);
  34.  
  35.   // Определить цвета для нанесения водяных знаков
  36.   $black=ImageColorAllocate($dst_im,0,0,0);
  37.   $white=ImageColorAllocate($dst_im,255,255,255);
  38.  
  39.   // Если расширения нет, то выход с ошибкой
  40.   $pocket=Array();
  41.   eregi("\.([a-z]*)$",$picture,$pocket);
  42.   if ($pocket[1]=="") { return false; }
  43.  
  44.   // На основании расширения создать картинку
  45.   switch (strtolower($pocket[1])) {
  46.     case "jpeg":
  47.     case "jpg": {
  48.       if (!$im=@ImageCreateFromJpeg($picture)) { return false; }
  49.       break;
  50.     }
  51.     case "gif": {
  52.       if (!$im=@ImageCreateFromGif($picture)) { return false; }
  53.       break;
  54.     }
  55.     case "png": {
  56.       if (!$im=@ImageCreateFromPng($picture)) { return false; }
  57.       break;
  58.     }
  59.     default: { return false; }
  60.   }
  61.  
  62.   ImageCopyResampled($dst_im$im0000$sx$sy$sx$sy);
  63.   imageDestroy($im);
  64.  
  65.   // Получить координаты блока под текст
  66.   list($lnx,$lny,$rnx,$rny,$rvx,$rvy,$lvx,$lvy) =
  67.      ImageTTFBBox($font_size,0,$font,$marker);
  68.  
  69.   // Вычислить размеры блока
  70.   $text_width=$rnx-$lnx;
  71.   $text_height=$rny-$rvy;
  72.  
  73.   // Получить координаты блока на картинке для нанесения надписи
  74.   switch ($watermark_position) {
  75.     case WATERMARK_LEFT_BOTTOM: {
  76.       $pos_x=10;
  77.       $pos_y=$sy-10;
  78.       break;
  79.     }
  80.     case WATERMARK_RIGHT_BOTTOM: {
  81.       $pos_x=$sx-$text_width-10;
  82.       $pos_y=$sy-10;
  83.       break;
  84.     }
  85.     case WATERMARK_LEFT_TOP: {
  86.       $pos_x=10;
  87.       $pos_y=$text_height+10;
  88.       break;
  89.     }
  90.     case WATERMARK_RIGHT_TOP: {
  91.       $pos_x=$sx-$text_width-10;
  92.       $pos_y=$text_height+10;
  93.       break;
  94.     }
  95.     case WATERMARK_CENTER: {
  96.       $pos_x=intval($sx/2-$text_width/2);
  97.       $pos_y=intval($sy/2+$text_height/2);
  98.       break;
  99.     }
  100.     default: { return false; }
  101.   }
  102.  
  103.   // Подсчитать количество светлых и темных пикселов в блоке
  104.   $dark=0;
  105.   $light=0;
  106.  
  107.   for ($x=0$x<$text_width$x++) {
  108.     for ($y=0$y<$text_height$y++) {
  109.       $color=imageColorAt($dst_im,($pos_x+$x),($pos_y+$y-$text_height));
  110.       list($r,$g,$b)=array_values(imageColorsForIndex($dst_im,$color));
  111.       if (($r+$g+$b)<(128*3)) { $dark++; } else { $light++; }
  112.     }
  113.   }
  114.  
  115.   // В зависимости от количества светлых и темных точек нанести
  116.   // светлую или темную надпись
  117.   if ($light>$dark) {
  118.     // Темный текст со светлой рамкой
  119.     ImageTTFText($dst_im,$font_size,0,$pos_x-1,$pos_y-1,$white,$font,$marker);
  120.     ImageTTFText($dst_im,$font_size,0,$pos_x,$pos_y-1,$white,$font,$marker);
  121.     ImageTTFText($dst_im,$font_size,0,$pos_x+1,$pos_y-1,$white,$font,$marker);
  122.  
  123.     ImageTTFText($dst_im,$font_size,0,$pos_x-1,$pos_y,$white,$font,$marker);
  124.     ImageTTFText($dst_im,$font_size,0,$pos_x+1,$pos_y,$white,$font,$marker);
  125.  
  126.     ImageTTFText($dst_im,$font_size,0,$pos_x-1,$pos_y+1,$white,$font,$marker);
  127.     ImageTTFText($dst_im,$font_size,0,$pos_x,$pos_y+1,$white,$font,$marker);
  128.     ImageTTFText($dst_im,$font_size,0,$pos_x+1,$pos_y+1,$white,$font,$marker);
  129.  
  130.     ImageTTFText($dst_im,$font_size,0,$pos_x,$pos_y,$black,$font,$marker);
  131.   }
  132.   else {
  133.     // Светлый текст с темной рамкой
  134.     ImageTTFText($dst_im,$font_size,0,$pos_x-1,$pos_y-1,$black,$font,$marker);
  135.     ImageTTFText($dst_im,$font_size,0,$pos_x,$pos_y-1,$black,$font,$marker);
  136.     ImageTTFText($dst_im,$font_size,0,$pos_x+1,$pos_y-1,$black,$font,$marker);
  137.  
  138.     ImageTTFText($dst_im,$font_size,0,$pos_x-1,$pos_y,$black,$font,$marker);
  139.     ImageTTFText($dst_im,$font_size,0,$pos_x+1,$pos_y,$black,$font,$marker);
  140.  
  141.     ImageTTFText($dst_im,$font_size,0,$pos_x-1,$pos_y+1,$black,$font,$marker);
  142.     ImageTTFText($dst_im,$font_size,0,$pos_x,$pos_y+1,$black,$font,$marker);
  143.     ImageTTFText($dst_im,$font_size,0,$pos_x+1,$pos_y+1,$black,$font,$marker);
  144.  
  145.     ImageTTFText($dst_im,$font_size,0,$pos_x,$pos_y,$white,$font,$marker);
  146.   }
  147.  
  148.   // Записать измененный файл на место
  149.   switch (strtolower($pocket[1])) {
  150.     case "jpeg":
  151.     case "jpg": {
  152.       ImageJPEG($dst_im,$picture,90);
  153.       break;
  154.     }
  155.     case "gif": {
  156.       ImageGIF($dst_im,$picture);
  157.       break;
  158.     }
  159.     case "png": {
  160.       ImagePNG($dst_im,$picture);
  161.       break;
  162.     }
  163.   }
  164.   imageDestroy($dst_im);
  165.   return true;
  166. }
Параметры вызова функции: $picture - полный путь к файлу на сервере, поддерживаются форматы JPG, GIF, PNG. Файл должен быть доступен для записи, так как после нанесения водяного знака он будет перезаписан с тем же именем. $font - путь к файлу с TrueType-шрифтом, который должен быть размещен на сервере. $font_size - размер шрифта надписи, рекомендуется 12. $marker - текстовая строка водяного знака, если используется кириллица, то она должна быть в Юникоде. $watermark_position - положение надписи на картинке, необязательный параметр. Доступные значения определены константами, прочие значения игнорируются: 0 - левый нижний угол (значение по умолчанию), 1 - левый верхний угол, 2 - правый нижний угол, 3 - правый верхний угол, 4 - центр изображения.

Пример работы скрипта
Пример работы скрипта

Это пример работы скрипта с нанесением водяных знаков на все доступные области. Как видите, на темных участках картинки получились светлые надписи, а на светлых - темные. Используется шрифт Lucida Sans Unicode, размер шрифта 12. Как наносить графические водяные знаки на изображение написано в следующей статье.

Техническая поддержка и ответы на вопросы - за деньги. Для тех, кто на бронепоезде, повторяю еще раз: техническая поддержка и ответы на вопросы - за деньги.

Поделиться ссылкой ВКонтакте
Просмотров: 12541 | Комментариев: 10

Метки: PHP, графика
Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
Сергей (20.04.2014 в 00:34):
Здравствуйте.
А как, используя эту функцию, сразу отобразить изображение в браузере не сохраняя его на диск?
Вера (09.11.2012 в 15:34):
ManHunter, жаль :(
ManHunter (09.11.2012 в 13:40):
Никак.
Вера (09.11.2012 в 13:40):
Как с Вами связаться?
За деньги (12.10.2011 в 20:37):
СПАСИБО ЗА ДЕНЬГИ
Василий (18.07.2009 в 08:09):
Согласен. Если для портала какого нибудь для обязательного присвоения прав на фото материалы то да. Функция необходимая и полезная.
ManHunter (16.07.2009 в 15:21):
Ничего не мешает. Но это когда загружаешь 2-3 фотографии. А когда загружаешь 150, то фотошоп быстро надоест. Или, например, если картинки на твой сайт загружают сторонние пользователи, ты их всех тоже будешь заставлять в фотошопе надписи наносить?
Василий (16.07.2009 в 15:18):
Прошу прощения, а что мешает подобный текст просто в фотошопе сразу добавить? Легко и просто.
ManHunter (11.05.2009 в 15:40):
А что именно непонятно? Вот описание из официального мануала:
http://ru2.php.net/manual/ru/f...ettftext.php
Там же полно всяких примеров использования.
Андрей (11.05.2009 в 15:19):
Я недавно начал изучать php... Вот уже 2 дня не могу разобраться как работает функция ImageTTFText(). Буду очень рад если Вы создадите папку с изображением и php файлами для полного примера работы Вашей ОБАЛДЕННОЙ! функции! Просто ОЧЕНЬ прошу!

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.0054 сек.) / Память: 4.5 Mb
Наверх