Фотомонтаж в PHP
08.10.2009 18:44Возвращаясь к теме работы с изображениями в PHP, рассмотрим механизм «смешивания» изображения из нескольких картинок, и способы практического применения такого трюка.
Постановка задачи
Итак, предположим, что для навигации по галерее вы решили прибегнуть к списку thumbnails*, однако дизайн вашего сайта требует, чтобы картинки имели скругленные края, а также вы хотите, чтобы на каждой картинке стоял логотип вашего сайта.
thumbnails* — так принято называть уменьшенные копии изображений, которые применяются для предварительного просмотра в графических программах, файловых менеджерах а также на сайтах галерей. В переводе с английского дословно значит «ноготь большого пальца руки».
Если вы знакомы с основами работы в Photoshop (а скорее всего, так и есть), то делали бы вы это примерно так (см. схему):
- создали бы скруглённые углы (с цветом фона по краям и прозрачной областью в середине)
- наложили бы полученную «маску» на исходное изображение
- если у вас непостоянный цвет фона на страницах, то вы также скорей всего указали бы цвет маски в индексе прозрачности

С другой стороны все эти операции может проделать за вас скрипт. То есть уменьшение, и все вышеперечисленные работы скрипт проделает за вас, прямо во время обращения пользователя за этой картинкой на сайте. Кроме того, «генерация на лету» даст возможность просто сменить обрамление всех картинок (например, оставить скругленными только два угла, или просто срезать уголок у картинки) а также поменять «наклееный» логотип, не перерисовывая при этом всех картинок. То есть, в конечном итоге, от вас будет только требоваться создать саму исходную картинку.
Инструментарий
Теперь давайте выясним, что же есть в PHP для реализации нашего замысла.
Для наложения одного изображения на другое существует функция imagecopy():
imagecopy (
resource dst_im,
resource src_im,
int dst_x, int dst_y,
int src_x, int src_y,
int src_w, int src_h
);
Здесь, dst_im и src_im — идентификаторы изображений (соответственно, исходного и накладываемого), dstX и dstY — x,y-координаты на исходном изображении, куда будет вставлено накладываемое; srcX и srcY — x,y-координаты, от которых будет отсчитыватся вырезаемая область изображения-источника (размеры этой области задаются параметрами src_w и src_h).
Как мы видим, эта функция просто переносит изображение (или его часть) на другое изображение. Однако, у нас есть также довольно полезная функция, которая делает это с изменением размеров изображения-источника — imagecopyresized(). Вот её общий вид:
imagecopyresized (
resource dst_im,
resource src_im,
int dstX, int dstY,
int srcX, int srcY,
int dstW, int dstH,
int srcW, int srcH
);
Все параметры тут аналогичны предыдущей функции, плюс добавилась ещё одна пара чисел — dstW и dstH, которые задают размеры накладываемой области на изображении dst_im.
Также нам понадобится функция работы с прозрачностью изображения — imagecolortransparent (img, color). Она устанавливает указанный цвет, как прозрачный. Здесь всего два параметра: первый — это, как обычно, идентификатор изображения, второй — номер цвета в таблице цветов (как его достать — ниже).
Для большей совместимости мы будем работать с форматом PNG, т. к. формат GIF поддерживается не всеми версиями GD-библиотеки.
Применение
Что ж, время переходить к примерам. Рассмотрим небольшой PHP-скрипт:
<?php
header("Content-type: image/png");
$res = imagecreate(120,120);
$img = imagecreatefromjpeg("photo.jpg");
$mask = imagecreatefrompng("border.png");
$logo = imagecreatefrompng("logo.png");
$green = imagecolorallocate($res,136,203,44);
imagecopyresized ($res,$img,
0,0,
0,0,
120,120,
imagesx($img),imagesy($img));
imagecopy ($res,$logo,60,110,0,0,60,12);
imagecopy ($res,$mask,0,0,0,0,120,120);
$trans = imagecolorat($res,0,0);
imagecolortransparent($res,$trans);
imagepng($res);
?>
Вот исходные данные и результат работы скрипта:
| Исходные данные | Результат |
![]() ![]() |
![]() |
А теперь взглянем поближе. Как видим, вначале создаются 4 изображения:
$res = imagecreate(120,120);
$img = imagecreatefromjpeg("photo.jpg");
$mask = imagecreatefrompng("border.png");
$logo = imagecreatefrompng("logo.png");
$res - соответственно, изображение для вывода (пока чистое), $img - сама исходная картинка, $mask - рамка, а также логотип (для наглядности тоже в отдельном файле) $logo.
Следующей строчкой мы резервируем в таблице цветов местечко для цвета нашего логотипа (я взял его RGB-значения из графического редактора):
$green = imagecolorallocate($res,136,203,44);
Далее идет самая главная по сути часть программы — наложение изображений:
imagecopyresized ($res,$img,
0,0,
0,0,
120,120,
imagesx($img),imagesy($img));
imagecopy ($res,$logo,60,110,0,0,60,12);
imagecopy ($res,$mask,0,0,0,0,120,120);
Первый оператор накладывает исходное изображение на наш чистый лист (одновременно, при необходимости, масштабируя его до нужного размера, в даном случае — 120?120 пикселей), второй — накладывает логотип в нижний правый угол, а третий кладет поверх всего этого нашу маску (при этом учитывается её прозрачность).
Далее идет выделение цвета, который станет прозрачным, и, собственно, этот цвет делается прозрачным :)
$trans = imagecolorat($res,0,0); imagecolortransparent($res,$trans);
Цвет прозрачности берется по самому верхнему левому пикселю (0;0). Кстати, цвет маски (и соответственно цвет прозрачности) выбирается таким образом, чтобы его точно не оказалось на самом изображении (в данном случае — чистый кислотный розовый, RGB[255,0,255]).
Ну, и последней строчкой собранное изображение отдается на выход:
imagepng($res);
Возможные усовершенствования
Во-первых, конечно же стоит вывести имя файла за пределы скрипта, чтобы подобные действия можно было проводить над любым изображением. Например, такой конструкцией:
$imgfile = implode("",$argv);
...
$img = imagecreatefromjpeg($imgfile.".jpg");
Таким образом, все, что будет указано после знака вопроса в обращении к скрипту, будет приниматся как имя файла (без расширения). Типичный вызов теперь может выглядеть так:
<img src="/getimg.php?photo">
Кроме того, можно ещё более расширить функциональность скрипта, вынеся также и тип рамки, чтобы иметь возможноть оформлять разные типы картинок одним и тем же скриптом, либо скажем передавать текст подписи к иллюстрации, или много чего ещё...
2 Комментариев

Александр
2011-03-23 09:28:19
Валерий,
когда это надо сделать динамически да еще на сервере, фотошоп тут совершенно не причем.





Валерий
2010-07-01 16:53:29
Интересно, конечно, но наверное лучше в фотошопе все это нарисовать.