Растягивание фона изображения на PHP
Растягивание фона изображения на PHP
Чтобы не таскать с собой кучу пластиковых карточек, я пользуюсь программой на смартфоне, куда их все можно легко добавить. Для предустановленных брендов в программе есть свои логотипы, для отсутствующих можно загрузить какие-нибудь свои. Все хорошо и удобно, но речь сегодня не об этом. При загрузке логотипа программа пытается автоматически заполнить подложку фоновым цветом, который определяется из цвета загружаемого изображения. И вот это действие меня заинтересовало.
Как я понял, работают эти программы по одному и тому же алгоритму: из всех граничных точек изображения вычисляется некий усредненный цвет и затем он используется в качестве фона подложки. Я считаю, что это неправильно. На примере логотипа Nikon: большая часть границы выполнена желтым цветом, но в некоторых местах он прерывается белыми полосками. Если посчитать усредненный цвет, то за счет этих белых вкраплений он будет заметно отличаться от основного желтого цвета. При наложении исходного изображения на такой фон результат будет выглядеть некрасиво. В случае же с котоламповой картинкой, за счет светлой нижней границы усредненный цвет получится вообще коричневым, тогда как в качестве фона правильно бы смотрелся черный цвет. То же самое относится к артефактам, появляющимся при JPEG-сжатии. Они могут хоть и незначительно, но все-таки отличаться от основного цвета, а при подсчете усредненного цвета вносить свою погрешность.
Примеры несоответствия фонового цвета
На примере фрагмент реального скриншота из программы. Логотип аптеки выбивается из фонового цвета из-за артефактов исходного изображения, а сложный фон накопительной карточки Алкомаркета при усреднении вообще превратился в грязно-серый.
На мой взгляд, правильный алгоритм для вычисления цвета заливки фона должен быть другим. Программа или скрипт должны точно так же проходить по границам изображения, но при этом подсчитывать количество каждого встречающегося цвета граничных точек. В качестве заливки для подложки выбирается не усредненный, а самый часто встречающийся цвет. На PHP это выглядит примерно так:
Code (PHP) : Убрать нумерацию
- $file='image.png';
- $im=ImageCreateFromPNG($file);
- $width=ImageSX($im);
- $height=ImageSY($im);
- // Массив для подсчета частоты встречающихся цветов
- $clr=array();
- // Подсчитать количество цветов на границах изображения
- for ($tmp_x=0; $tmp_x<$width; $tmp_x++) {
- $rgb=ImageColorAt($im,$tmp_x,($height-1));
- if (!isset($clr[$rgb])) { $clr[$rgb]=0; }
- $clr[$rgb]++;
- $rgb=ImageColorAt($im,$tmp_x,0);
- if (!isset($clr[$rgb])) { $clr[$rgb]=0; }
- $clr[$rgb]++;
- }
- for ($tmp_y=1; $tmp_y<($height-1); $tmp_y++) {
- $rgb=ImageColorAt($im,($width-1),$tmp_y);
- if (!isset($clr[$rgb])) { $clr[$rgb]=0; }
- $clr[$rgb]++;
- $rgb=ImageColorAt($im,0,$tmp_y);
- if (!isset($clr[$rgb])) { $clr[$rgb]=0; }
- $clr[$rgb]++;
- }
- // Размеры нового изображения и отступ от краев
- $new_x=300;
- $new_y=225;
- $padding=10;
- $dst_im=ImageCreateTrueColor($new_x, $new_y);
- // Определить самый популярный цвет границы
- arsort($clr);
- $keys=array_keys($clr);
- $rgb=$keys[0];
- $avg_R=($rgb >> 16) & 0xFF;
- $avg_G=($rgb >> 8) & 0xFF;
- $avg_B=$rgb & 0xFF;
- // Выполнить заливку фона
- $color=ImageColorAllocate($dst_im, $avg_R, $avg_G, $avg_B);
- ImageFilledRectangle($dst_im, 0, 0, $new_x, $new_y, $color);
- // Вставить изображение в центр подложки
- if ($width>($new_x-$padding*2) || $height>($new_y-$padding*2)) {
- $dst_w=$new_x-$padding*2;
- $dst_h=$new_y-$padding*2;
- $coeff=min($dst_w/$width, $dst_h/$height);
- $dst_w=$width*$coeff;
- $dst_h=$height*$coeff;
- $dst_x=floor(($new_x-$dst_w)/2);
- $dst_y=floor(($new_y-$dst_h)/2);
- ImageCopyResampled($dst_im, $im, $dst_x, $dst_y, 0, 0,\
- $dst_w, $dst_h, $width, $height);
- }
- else {
- $dst_x=floor(($new_x-$width)/2);
- $dst_y=floor(($new_y-$height)/2);
- ImageCopyResampled($dst_im, $im, $dst_x, $dst_y, 0, 0,\
- $width, $height, $width, $height);
- }
Результаты работы скрипта
Вот результаты работы скрипта с приведенными выше примерами. Как вы видите, зеленый цвет подложки подобран точно. Для разноцветного рисунка, наверное, черный цвет фона будет не самым лучшим вариантом, но он хотя бы гармонично сливается с черными элементами изображения.
Просмотров: 1806 | Комментариев: 0
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
Комментариeв нет
Добавить комментарий
Заполните форму для добавления комментария