Blog. Just Blog

Растягивание фона изображения на PHP

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

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

Как я понял, работают эти программы по одному и тому же алгоритму: из всех граничных точек изображения вычисляется некий усредненный цвет и затем он используется в качестве фона подложки. Я считаю, что это неправильно. На примере логотипа Nikon: большая часть границы выполнена желтым цветом, но в некоторых местах он прерывается белыми полосками. Если посчитать усредненный цвет, то за счет этих белых вкраплений он будет заметно отличаться от основного желтого цвета. При наложении исходного изображения на такой фон результат будет выглядеть некрасиво. В случае же с котоламповой картинкой, за счет светлой нижней границы усредненный цвет получится вообще коричневым, тогда как в качестве фона правильно бы смотрелся черный цвет. То же самое относится к артефактам, появляющимся при JPEG-сжатии. Они могут хоть и незначительно, но все-таки отличаться от основного цвета, а при подсчете усредненного цвета вносить свою погрешность.

Примеры несоответствия фонового цвета
Примеры несоответствия фонового цвета

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

На мой взгляд, правильный алгоритм для вычисления цвета заливки фона должен быть другим. Программа или скрипт должны точно так же проходить по границам изображения, но при этом подсчитывать количество каждого встречающегося цвета граничных точек. В качестве заливки для подложки выбирается не усредненный, а самый часто встречающийся цвет. На PHP это выглядит примерно так:
  1. $file='image.png';
  2.  
  3. $im=ImageCreateFromPNG($file);
  4. $width=ImageSX($im);
  5. $height=ImageSY($im);
  6.  
  7. // Массив для подсчета частоты встречающихся цветов
  8. $clr=array();
  9.  
  10. // Подсчитать количество цветов на границах изображения
  11. for ($tmp_x=0$tmp_x<$width$tmp_x++) {
  12.     $rgb=ImageColorAt($im,$tmp_x,($height-1));
  13.     if (!isset($clr[$rgb])) { $clr[$rgb]=0; }
  14.     $clr[$rgb]++;
  15.  
  16.     $rgb=ImageColorAt($im,$tmp_x,0);
  17.     if (!isset($clr[$rgb])) { $clr[$rgb]=0; }
  18.     $clr[$rgb]++;
  19. }
  20.  
  21. for ($tmp_y=1$tmp_y<($height-1); $tmp_y++) {
  22.     $rgb=ImageColorAt($im,($width-1),$tmp_y);
  23.     if (!isset($clr[$rgb])) { $clr[$rgb]=0; }
  24.     $clr[$rgb]++;
  25.  
  26.     $rgb=ImageColorAt($im,0,$tmp_y);
  27.     if (!isset($clr[$rgb])) { $clr[$rgb]=0; }
  28.     $clr[$rgb]++;
  29. }
  30.  
  31. // Размеры нового изображения и отступ от краев
  32. $new_x=300;
  33. $new_y=225;
  34. $padding=10;
  35.  
  36. $dst_im=ImageCreateTrueColor($new_x$new_y);
  37.  
  38. // Определить самый популярный цвет границы
  39. arsort($clr);
  40. $keys=array_keys($clr);
  41. $rgb=$keys[0];
  42.  
  43. $avg_R=($rgb >> 16) & 0xFF;
  44. $avg_G=($rgb >> 8) & 0xFF;
  45. $avg_B=$rgb 0xFF;
  46.  
  47. // Выполнить заливку фона
  48. $color=ImageColorAllocate($dst_im$avg_R$avg_G$avg_B);
  49. ImageFilledRectangle($dst_im00$new_x$new_y$color);
  50.  
  51. // Вставить изображение в центр подложки
  52. if ($width>($new_x-$padding*2) || $height>($new_y-$padding*2)) {
  53.     $dst_w=$new_x-$padding*2;
  54.     $dst_h=$new_y-$padding*2;
  55.  
  56.     $coeff=min($dst_w/$width$dst_h/$height);
  57.  
  58.     $dst_w=$width*$coeff;
  59.     $dst_h=$height*$coeff;
  60.  
  61.     $dst_x=floor(($new_x-$dst_w)/2);
  62.     $dst_y=floor(($new_y-$dst_h)/2);
  63.  
  64.     ImageCopyResampled($dst_im$im$dst_x$dst_y00,\
  65.             $dst_w$dst_h$width$height);
  66. }
  67. else {
  68.     $dst_x=floor(($new_x-$width)/2);
  69.     $dst_y=floor(($new_y-$height)/2);
  70.  
  71.     ImageCopyResampled($dst_im$im$dst_x$dst_y00,\
  72.             $width$height$width$height);
  73. }
Тут не выполняется никаких проверок на корректность исходного файла и т.п., все размеры и значения "прибиты гвоздями", а для удобства понимания оставлен только основной код. В рабочих проектах, естественно, все это надо учитывать.

Результаты работы скрипта
Результаты работы скрипта

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

Поделиться ссылкой ВКонтакте Поделиться ссылкой на Facebook Поделиться ссылкой на LiveJournal Поделиться ссылкой в Мой Круг Добавить в Мой мир Добавить на ЛиРу (Liveinternet) Добавить в закладки Memori Добавить в закладки Google
Просмотров: 339 | Комментариев: 0

Метки: PHP, графика

Комментарии

Отзывы посетителей сайта о статье
Комментариeв нет

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

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

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