Blog. Just Blog

Эффект рисунка масляными красками на PHP

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Web-мастеру и не только | Автор: ManHunter
Эффект рисунка масляными красками на PHP
Эффект рисунка масляными красками на PHP

Еще один красивый художественный эффект на PHP - преобразование фотографии в рисунок масляными красками. Такой эффект часто встречается в различных графических редакторах и приложениях, а сегодня разберем, как он достигается.

Сперва немного теории. Для получения цветного мазка надо определить толщину кисти, то есть радиус области, в которой цвет будет приводиться к единому значению. Чем больше толщина кисти, тем менее детальным будет получаться изображение. Но и слишком тонкой кисть делать не надо, оптимальное значение радиуса 5-6. Второй важный параметр для преобразования - это интенсивность цвета. Она задает погрешность, при которой два слегка отличающихся цвета приравниваются к одному. Чем больше это значение, тем более детальным будет результат. По результатам тестирования наилучший баланс достигается при значении интенсивности в диапазоне 25-50. Значения лучше подбирать индивидуально для каждого изображения.
  1. $file='image.jpg';
  2.  
  3. // Файл для обработки
  4. $im=ImageCreateFromJPEG($file);
  5.  
  6. // Размеры изображения
  7. $width=ImageSX($im);
  8. $height=ImageSY($im);
  9.  
  10. // Результат
  11. $im2=ImageCreateTruecolor($width,$height);
  12.  
  13. // Радиус обработки
  14. $radius=5;
  15. // Предельная интенсивность
  16. $int_level=25;
  17.  
  18. for ($x=$radius$x<($width-$radius); $x++) {
  19.     for ($y=$radius$y<($height-$radius); $y++) {
  20.         $sumR=array();
  21.         $sumG=array();
  22.         $sumB=array();
  23.         $intensity=array();
  24.  
  25.         Получить интенсивность для всех точек в заданном радиусе
  26.         for($nx=-$radius$nx<$radius$nx++) {
  27.             for($ny=-$radius$ny<$radius$ny++) {
  28.                 $rgb=ImageColorAt($im,$x+$nx,$y+$ny);
  29.                 $R=($rgb >> 16) & 0xFF;
  30.                 $G=($rgb >> 8) & 0xFF;
  31.                 $B=$rgb 0xFF;
  32.  
  33.                 $cur_int=round(((($R+$G+$B)/3)*$int_level)/255);
  34.                 if ($cur_int>255) { $cur_int=255; }
  35.                 if (!isset($intensity[$cur_int])) {
  36.                     $intensity[$cur_int]=0;
  37.                     $sumR[$cur_int]=0;
  38.                     $sumG[$cur_int]=0;
  39.                     $sumB[$cur_int]=0;
  40.                 }
  41.                 $intensity[$cur_int]++;
  42.                 $sumR[$cur_int]+=$R;
  43.                 $sumG[$cur_int]+=$G;
  44.                 $sumB[$cur_int]+=$B;
  45.             }
  46.         }
  47.  
  48.         Определить преобладающий цвет в области
  49.         $cur_max=0;
  50.         $max_index=0;
  51.         for($i=0$i<256$i++) {
  52.             if (isset($intensity[$i])) {
  53.                 if ($intensity[$i]>$cur_max) {
  54.                     $cur_max=$intensity[$i];
  55.                     $max_index=$i;
  56.                 }
  57.             }
  58.         }
  59.  
  60.         $_R=round($sumR[$max_index]/$cur_max);
  61.         $_G=round($sumG[$max_index]/$cur_max);
  62.         $_B=round($sumB[$max_index]/$cur_max);
  63.  
  64.         $new_color=ImageColorAllocate($im2$_R$_G$_B);
  65.         ImageSetPixel($im2,$x,$y,$new_color);
  66.     }
  67. }
  68.  
  69. // Добавить размытие
  70. ImageFilter($im2IMG_FILTER_GAUSSIAN_BLUR);
  71. ImageFilter($im2IMG_FILTER_GAUSSIAN_BLUR);
  72.  
  73. // Вывести результат в браузер
  74. header("Content-type: image/jpeg");
  75. ImageJPEG($im2,NULL,100);
  76.  
  77. // Прибраться за собой
  78. ImageDestroy($im);
  79. ImageDestroy($im2);
Для каждого пиксела в области, заданной радиусом, определяется средний цвет и он применяется к центральному пикселу. Таким образом точки, расположенные рядом и имеющие похожий оттенок цвета, сливаются в единый мазок.

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

Эффект рисунка масляными красками на PHP
Эффект рисунка масляными красками на PHP

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

Эффект рисунка масляными красками на PHP
Эффект рисунка масляными красками на PHP

Для сглаживания резких линий можно воспользоваться функцией ImageFilter с эффектом размытия IMG_FILTER_GAUSSIAN_BLUR, причем применить ее к изображению надо как минимум дважды.

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

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

Комментарии

Отзывы посетителей сайта о статье
Дмитрий (09.04.2022 в 18:21):
МОНА САКС. МАКС ПАЙН!!!

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

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

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