Всякому
web-программисту приходится
работать с изображениями – чисто
текстовых сайтов в интернете
немного. Самый простой способ
поместить на страницу картинку –
сохранить ее в файле и поставить
в HTML-файле соответствующий
тэг. Один из недостатков этого
способа очевиден: картинки,
которые лежат в файле никак не
меняются, чтобы пользователь
увидел другое изображение,
вебмастеру нужно открыть
графический редактор, внести
измения и сохранить их. В этой
статье я расскажу о создании
динамических изображений с
помощью языка
web-программирования PHP.
Для начала – несколько слов для
тех, кто не знаком с PHP. Это –
язык сценариев, выполняющихся на
стороне сервера для создания
динамических web-страниц.
Программа на PHP, подобно тексту
на JavaScript, VBScript или ASP,
вставляется в HTML-файл или
сохраняется в отдельном файле с
соответствующим расширением.
Начало и конец программы
отмечаются специальными тэгами
<? и ?>. Текст вне этих
скобок PHP не интерпретирует, он
передается web-браузеру «как
есть». Синтаксис PHP довольно
подробно описан в руководстве,
которое входит в комплект поставки
(его также можно взять на сайте
http://www.php.net).
Принцип работы с изображениями
такой: PHP-программа (а точнее
PHP-интерпретатор, работающий на
стороне сервера) создает картинку
«на лету» и передает ее браузеру в
нужном графическом формате.
Для того чтобы воспользоваться
возможностями PHP по работе с
изображениями, необходимо
установить в системе библиотеку
GD. Если вы работаете с Linux, то
эта библиотека уже должна быть
установлена. Если нет – ее можно
найти по адресу
http://www.boutell.com/gd. Если вы
работаете с Windows, то лучше
всего посетить
http://php.weblogs.com/easywindows.
Здесь можно скачать библиотеку
php_gd, которая позволит вам
насладиться всеми прелестями
работы с графикой на PHP. Если вы
планируете использовать в своих
изображениях шрифты TrueType, вам
понадобится библиотека FreeType
(http://www.freetype.org).
Несколько слов о поддерживаемых
библиотекой GD графических
форматах. Версии старше 1.6
поддерживают форматы GIF и JPEG.
Более новые версии позволяют
работать с JPEG и PNG. Начиная с
версии 1.6 формат GIF в GD не
поддерживается. Это связанно с
тем, что всеми правами на алгоритм
LZW-компрессии, использующийся в
этом формате, обладает компания
Unisys.
Первые шаги
Итак, система
настроена, все необходимые
библиотеки установлены. Для начала
создадим какое-нибудь простое
изображение:
<?
Header("Content-Type: image/gif");
$image = ImageCreate(500, 75);
$blue = ImagecolorAllocate($image,
0, 0, 255);
ImageFill($image, 1, 1, $blue);
ImageGIF($image);
ImageDestroy($image);
?>
Сохраните текст в
файле с расширением .php и
просмотрите его с помощью
браузера. Если вы все сделали
правильно, то вы увидите то, что
показано на рисунке 1.
рисунок 1
Рассмотрим код нашего скрипта
более подробно. В первой строчке
скрипт сообщает браузеру
информацию о типе передаваемых
данных с помощью HTTP-заголовка. В
нашем примере используется
предопределенный тип «image/gif»,
который означает, что далее
последует изображение в формате
GIF. Передавать браузеру
соответствующий заголовок
необходимо всегда. Для форматов
JPEG и PNG первая строчка
выглядела иначе:
Header(“Content-Type:
image/jpeg”);
Header(“Content-Type: image/png”);
Обратите
внимание, что заголовок
“Content-Type” передается для
каждой страницы только один раз,
поэтому PHP-код для генерации
изображения необходимо помещать в
отдельный файл. Кстати, размещение
динамической графики вместе с
HTML-кодом возможно только при
использовании механизма SSI
(Server Side Includes), о чем мы
поговорим чуть позже.
Создание графики в PHP состоит из
четыре этапов:
-
создание
дескриптора изображения;
-
регистрация
используемых цветов;
-
рисование с
использованием
предопределенных
функций;
-
и финальная
стадия – создание изображения
и передача его браузеру.
В нашем примере
первый этап выглядит так:
$image
= ImageCreate(500, 75);
Здесь функция
ImageCreate() создает дескриптор
изображения и присваивается его
переменной $image. Функция
вызывается с двумя параметрами –
высотой и шириной изображения. По
умолчанию изображение заливается
черным цветом. Следующий этап –
цвета:
$blue
= ImagecolorAllocate($image, 0, 0,
255);
Все используемые
в изображении цвета необходимо
регистрировать. Для этого
используется функция
ImageColorAllocate(); ее параметры
– дескриптор изображения и
RGB-кодировка цвета. Каждый цвет
ставится в соответствие
переменной, в дальнейшем эта
переменная передается функциям
рисования.
Вряд ли стоит перечислять все
функции рисования. Скажу лишь, что
их немало: вы можете «заливать»
изображения цветом, рисовать
различные фигуры, делать рисунок
прозрачным и т.д. Рассмотрим
некоторые из них на практике, а об
остальных вы сможете узнать из
документации.
В нашем первом примере мы
«заливаем» изображение синим
цветом с помощью функции
ImageFill:
ImageFill($image, 1, 1, $blue);
Второй и третий
параметр – координаты начала
заливки. Начало координат
располагается в левом верхнем углу
изображения. Таким образом,
координаты (500, 75) определяют
правый нижний угол изображения из
первого примера.
Теперь следует передать готовый
рисунок браузеру. Это делает
функция ImageGIF(), ее
единственный параметр – дескриптор
изображения. Для форматов JPEG и
PNG применяйте функции ImageJPEG()
и ImagePNG() соответственно. Для
освобождения памяти, выделенной
под рисунок, в конце скрипта надо
вызвать функцию ImageDestroy().
Использование
текста в рисунках
Рассмотрим еще
одну возможность: попробуем
что-нибудь написать на рисунке. Я
приведу небольшой пример, а потом
поясню механизм работы с текстом:
<?
// передаем заголовок
Header("Content-Type: image/gif");
// создаем дескриптор изображения
и регистрируем цвета
$image = ImageCreate(500, 75);
$black =
ImageColorAllocate($image, 0, 0,
0);
$yellow =
ImageColorAllocate($image, 255,
255, 0);
// выполняем "заливку" рисунка
ImageFill($image, 0, 0, $black);
// помещаем на изображение текст в
координаты (210, 30)
itring($image, 4, 210, 30, "Hello
World!", $yellow);
ImageGIF($image);
ImageDestroy($image);
?>
Результат
выполнения скрипта показан на
рисунке 2.
рисунок 2
Собственно
выводом текста занимается функция
itrings(). Ее параметры –
дескриптор изображения, номер
шрифта, координаты точки вывода
изображения, строка текста и цвет.
Можно использовать один из пяти
предопределенных шрифтов
фиксированного размера. Они
нумеруются от 1 (самый маленький)
до 5 (самый большой).
В следующем примере начинается
самое интересное: изображение
создается динамически на основе
вводимых пользователем данных.
Создадим простой HTML-файл с
формой (рисунок 3).
рисунок 3
Вот его
код:
<html>
<body>
<form action="example3.php"
method="get">
Введите Ваше имя:<input
type=text name=name><br>
<input type=submit>
</form>
</body>
</html>
А теперь создадим
такой файл example3.php:
<?
Header("Content-Type: image/gif");
if ($name)
{
$string = "Hello " . $name;
}
else
{
$string = "Hello All!";
}
$image = ImageCreate(500, 75);
$black =
ImageColorAllocate($image, 0, 0,
0);
$yellow =
ImageColorAllocate($image, 255,
255, 0);
ImageFill($image, 0, 0, $black);
itring($image, 4, 210, 30,
$string, $yellow);
ImageGIF($image);
ImageDestroy($image);
?>
Изображение будет
содержать введенный текст (рисунок
4).
рисунок 4
Скажу пару слов и о других
функциях из библиотеки GD,
предназначенных для работы с
текстом. itringUp() выводит текст
вертикально; ImageChar() и
ImageCharUp() выводят один символ;
ImageFontHeight() и
ImageFontWidth() возвращают высоту
и ширину шрифта. Последние две
функции используются в следующем
примере, в котором строка текста
подчеркивается линией (функция
ImageLine рисует линии по заданным
координатам):
<?
Header("Content-Type: image/gif");
if ($name)
{
$string = "Hello " . $name;
}
else
{
$string = "Hello All!";
}
$image = ImageCreate(500, 75);
$black =
ImageColorAllocate($image, 0, 0,
0);
$yellow =
ImageColorAllocate($image, 255,
255, 0);
ImageFill($image, 0, 0, $black);
itring($image, 4, 210, 30,
$string, $yellow);
// определяем ширину шрифта
$font_width = ImageFontWidth(4);
// вычисляем ширину строки
введенного текста
$string_width = $font_width *
(strlen($string));
// рисуем линию с началом в точке
с координатами (210,50)
ImageLine($image, 210, 50,
(210+$string_width), 50, $yellow);
ImageGIF($image);
ImageDestroy($image);
?>
Результат работы
скрипта показан на рисунке 5.
рисунок 5
Что еще можно
рисовать?
Естественно,
кроме линий с помощью GD можно
рисовать и другие фигуры. В
следующем примере мы воспользуемся
функцией ImageFilledRectangle()
для того, чтобы вывести в окне
браузера французский флаг. Функция
предназначена для рисования
заполненных определенным цветом
прямоугольников. Для начала
«зальем» весь рисунок белым
цветом, а затем нарисуем красный и
синий прямоугольники:
<?
// заголовок
Header("Content-Type: image/gif");
$image = ImageCreate(300, 300);
// регистрируем цвета
$red = ImageColorAllocate($image,
255, 0, 0);
$white =
ImageColorAllocate($image, 255,
255, 255);
$blue = ImageColorAllocate($image,
0, 0, 255);
// выполняем "заливку" рисунка
ImageFill($image, 0, 0, $white);
// рисуем прямоугольники
ImageFilledRectangle($image, 0, 0,
100, 300, $blue);
ImageFilledRectangle($image, 200,
0, 300, 300, $red);
// передаем броузеру на клиентском
компьютере
ImageGIF($image);
ImageDestroy($image);
?>
На рисунке 6
можно видеть результат наших
трудов.
рисунок 6
PHP позволяет
рисовать и другие типы
многоугольников. Для этого имеется
функция ImagePolygon(). Следующий
пример выводит на экран
пятиугольник. В качестве
параметров (кроме дескриптора
изображения и цвета линии) этой
функции передается следующая
информация: количество вершин (в
нашем случае – пять) и массив
координат точек, являющихся
вершинами. Результат работы
скрипта представлен на рисунке 7.
<?
Header("Content-Type: image/gif");
$image = ImageCreate(300, 300);
$green =
ImageColorAllocate($image, 0, 255,
0);
$white =
ImageColorAllocate($image, 255,
255, 255);
$blue = ImageColorAllocate($image,
0, 0, 255);
// массив вершин многоугольника
$vertices = Array(150, 10, 250,
100, 250, 200, 50, 200, 50, 100);
ImageFill($image, 0, 0, $white);
// рисуем многоугольник
ImagePolygon($image, $vertices, 5,
$blue);
// выполняем заливку
многоугольника зеленым цветом (до
синей границы)
ImageFillToBorder($image, 150,
150, $blue, $green);
ImageGIF($image);
ImageDestroy($image);
?>
рисунок 7
В этом же скрипте
используется еще одна функция, не
упоминавшаяся ранее –
ImageFillToBorder(). Она
используется для заливки области,
ограниченной определенным цветом
(в нашем случае это синяя линия
многоугольника).
Функция ImageArc() умеет рисовать
дуги и окружности. Приведу
небольшой пример (см. рисунок 8):
<?
Header("Content-Type: image/gif");
$image = ImageCreate(300, 300);
$white =
ImageColorAllocate($image, 255,
255, 255);
$black =
ImageColorAllocate($image, 0, 0,
0);
// переменные для окружности:
// центр окружности
$center_x = 150;
$center_y = 150;
// высота и ширина
$width = 150;
$height = 150;
// начальный и конечный углы
$start = 0;
$end = 360;
ImageFill($image, 0, 0, $white);
// рисуем окружность
ImageArc($image, $center_x,
$center_y, $width, $height,
$start, $end, $black);
ImageGIF($image);
ImageDestroy($image);
?>
рисунок 8
Меняя значения
переменных $width и $height, можно
рисовать овалы, а меняя углы –
добиться отображения различного
рода дуг.
Использование
готовых изображений
Библиотека GD
позволяет не только рисовать
картинки, но и пользоваться уже
готовыми. Рассмотрим вполне
реальную ситуацию: штатный
дизайнер вашей фирмы разработал
внешний вид кнопок для некоторого
сайта, а вам надо поместить на
странице несколько одинаковых по
дизайну кнопок и подписи к ним.
В состав библиотеки GD входят
такие функции, как
ImageCreateFromGIF(),
ImageCreateFromJPEG() и
ImageCreateFromPNG(). Они помогут
в тех случаях, когда надо создать
новое изображение на основе уже
существующего. Пусть у нас имеется
файл button.gif (рисунок 9),
который содержит гениальный дизайн
кнопки для сайта. Ниже приводится
PHP-код, который делает готовые
кнопки на основе этого файла.
Обратите внимание на то, как
размеры кнопки, шрифта, и строк
текста используются для вычисления
координат размещения заголовков.
Здесь в качестве подписи к кнопке
берется значение переменной
$caption, которая передается в
скрипт извне:
<?
// файл button.php – помещение
текста на рисунок.
// входные параметры:
// $caption - текст, размещаемый
посередине рисунка
Header("Content-Type: image/gif");
// создаем изображение на основе
существующего файла
$image =
ImageCreateFromGIF("button.gif");
//регистрируем цвет
$white =
ImageColorAllocate($image, 255,
255, 255);
// определяем размеры шрифта
$font_height = ImageFontHeight(3);
$font_width = ImageFontWidth(3);
// определяем размер рисунка
$image_height = iY($image);
$image_width = iX($image);
// получаем длину строки
$length = $font_width *
strlen($caption);
// вычисляем начальные координаты
для заголовка
$image_center_x =
($image_width/2)-($length/2);
$image_center_y =
($image_height/2)-($font_height/2);
// пишем текст
itring($image, 3, $image_center_x,
$image_center_y, $caption,
$white);
ImageGIF($image);
ImageDestroy($image);
?>
рисунок 9
Функции iX() и
iY() возвращают, соответственно,
ширину и высоту изображения. Также
существует функция Getiize(), с
помощью которой можно определить
размеры и тип изображения.
Сам по себе приведенный выше
скрипт большой практической
ценности не имеет, но его можно
использовать в любой HTML-странице
посредством SSI или так, как
описано в следующем коде:
<?
// данные для элементов меню:
// обычно такая информация
получается из базы данных
// в данном примере массивы
используются исключительно для
простоты
$menu_items = Array();
$menu_items[0] = "News";
$menu_items[1] = "Documentation";
$menu_items[2] = "FAQ";
$menu_items[3] = "GuestBook";
$menu_items[4] = "Forum";
$menu_items[5] = "Send message";
?>
<html>
<body>
<center><h2>Make your
choice!</h2></center>
<table border=0>
<?
// в цикле обрабатываем все
элементы массива
foreach($menu_items as $caption)
{
// для каждого элемента выводим
кнопку в отдельной строке таблицы
?>
<tr><td>
<a href="#"><img
src="button.php?caption=<? echo
$caption; ?>"
border=0></a>
</td></tr>
<?
}
?>
</table>
</body>
</html>
рисунок 10
Результат работы
этого скрипта можно увидеть на
рисунке 10. Единственное, на что
хочу обратить ваше внимание –
способ вызова кода для
формирования изображения.
Взгляните на следующую
конструкцию:
<img
src="button.php?caption=<? echo
$caption; ?>"
Здесь в качестве
параметра src тега img
используется результат выполнения
скрипта button.php, вызванного на
выполнение с соответствующим
значением параметра $caption.
Работаем с
диаграммами
Теперь вы уже
достаточно много знаете о
возможностях библиотеки GD,
поэтому в завершение нашего
разговора я предлагаю создать
какое-нибудь реальное приложение.
Пример будет весьма жизненным –
рисование диаграммы. В подавляющем
большинстве случаев данные,
которые отображает диаграммы,
изменяются динамически (например,
результаты голосования), поэтому
PHP-скрипт здесь очень кстати. В
примере мы рассмотрим создание
разноцветной круговой диаграммы на
основе вводимых пользователем
данных.
Для начала создадим HTML-файл, с
формой, в которую пользователь
будет вводить информацию,
необходимую для формирования
диаграммы. В нашем случае нужно
просто ввести пять чисел. Вот
HTML-код:
<html>
<body>
<h3>Создаем круговую
диаграмму</h3>
<table>
<form action="pie.php"
method=get>
<tr>
<td>Число №1</td>
<td><input type=text
name=slice[1]
value=0></td>
</tr>
<tr>
<td>Число №2</td>
<td><input type=text
name=slice[2]
value=0></td>
</tr>
<tr>
<td>Число №3</td>
<td><input type=text
name=slice[3]
value=0></td>
</tr>
<tr>
<td>Число №4</td>
<td><input type=text
name=slice[4]
value=0></td>
</tr>
<tr>
<td>Число №5</td>
<td><input type=text
name=slice[5]
value=0></td>
</tr>
<tr>
<td colspan=2
align=center><input
type=submit value="Показать
диаграмму!"></td>
</tr>
</form>
</table>
После нажатия
кнопки «Показать диаграмму»
введенные данные передаются
скрипту pie.php.
В скрипте все пять чисел
суммируются. Затем считается,
сколько процентов составляет
каждое значение от всей суммы.
Далее вычисляются углы дуг для
каждой из «долек» и происходит,
собственно, рисование дуг. Потом
каждый сегмент заливается своим
цветом. Для этого нужны координаты
точки, находящейся внутри
сегмента. В завершение над
диаграммой помещается заголовок.
Вот текст скрипта:
<?
// начнем с инициализации
переменных
$sum = 0;
$degrees = Array();
$diameter = 200;
$radius = $diameter/2;
$center_x = 150;
$center_y = 150;
// в цикле вычисляем сумму
введенных чисел
for ($x=1; $x<=5; $x++)
{
$sum += $slice[$x];
}
// преобразуем каждое значение в
соответствующий процент от 360
градусов
for ($y=1; $y<=5; $y++)
{
$degrees[$y] = ($slice[$y]/$sum) *
360;
}
// создаем дескриптор изображения
и инициализируем цвета
Header("Content-Type: image/gif");
$image = ImageCreate(300, 300);
$red = ImageColorAllocate($image,
255, 0, 0);
$blue = ImageColorAllocate($image,
0, 0, 255);
$green =
ImageColorAllocate($image, 0, 255,
0);
$yellow =
ImageColorAllocate($image, 255,
255, 0);
$black =
ImageColorAllocate($image, 0, 0,
0);
$white =
ImageColorAllocate($image, 255,
255, 255);
// первоначально зальем рисунок
белым цветом
ImageFill($image, 0, 0, $white);
for ($z=1; $z<=5; $z++)
{
// в цикле вычисляем угол каждого
сегмента и рисуем "дольки"
ImageArc($image, 150, 150,
$diameter, $diameter,
$last_angle,($last_angle+$degrees[$z]),
$black);
$last_angle =
$last_angle+$degrees[$z];
// вычисляем конечную точку каждой
дуги
// следует помнить, что функции
cos() и sin() возвращают значения
// в радианах, которые должны быть
преобразованы обратно в градусы
$end_x = round(150 + ($radius *
cos($last_angle*pi()/180)));
$end_y = round(150 + ($radius *
sin($last_angle*pi()/180)));
// разделяем сегменты черной
линией
ImageLine($image, 150, 150,
$end_x, $end_y, $black);
}
// теперь определим точки внутри
сегментов для того,
// чтобы мы могли выполнить их
заливку
$prev_angle = 0;
$pointer = 0;
for ($z=1; $z<=5; $z++)
{
$pointer = $prev_angle +
$degrees[$z];
$this_angle = ($prev_angle +
$pointer) / 2;
$prev_angle = $pointer;
$end_x = round(150 + ($radius *
cos($this_angle*pi()/180)));
$end_y = round(150 + ($radius *
sin($this_angle*pi()/180)));
$mid_x = round((150+($end_x))/2);
$mid_y = round((150+($end_y))/2);
// в зависимости от порядкового
номера сектор
// выбираем тот или иной цвет
if ($z == 1)
{
ImageFillToBorder($image, $mid_x,
$mid_y, $black, $red);
}
else if ($z == 2)
{
ImageFillToBorder($image, $mid_x,
$mid_y, $black, $blue);
}
else if ($z == 3)
{
ImageFillToBorder($image, $mid_x,
$mid_y, $black, $green);
}
else if ($z == 4)
{
ImageFillToBorder($image, $mid_x,
$mid_y, $black, $yellow);
}
else if ($z == 5)
{
ImageFillToBorder($image, $mid_x,
$mid_y, $black, $black);
}
}
// выводим заголовок
itring($image, 5, 100, 10, "Pie
Chart", $black);
ImageGIF($image);
ImageDestroy($image);
?>
рисунок 11
рисунок 12
На рисунке 11
показан пример заполнения формы, а
на рисунке 12 – результат работы
скрипта, соответствующий введенным
данным.
Еще несколько
полезных функций
В заключение я
упомяну еще несколько функций,
которые могут быть полезны при
изучении принципов работы с
графикой в PHP.
-
ImageColorTransparent().
Принимает два аргумента –
идентификатор изображения и
цвет из палитры RGB
(переменная PHP). Изображение
заливается прозрачным цветом,
указанным в переменной (второй
аргумент). Функция применима
только к GIF-изображениям.
-
ImageTTFText().
Прорисовывает текст с помощью
TrueType шрифтов, которые
разработчик может
самостоятельно подключить.
Второй аргумент указывает
размер шрифта, третий – угол
наклона будущего текста
относительно горизонтали. 4-й
и 5-й аргументы предназначены
для указания координат начала
текста (точнее, левого нижнего
угла первой буквы текста)
Обратите внимане: в функции
itring все наоборот, там
указываются координаты
верхнего правого угла первой
буквы текста. Далее идут цвет
текста, шрифт (путь к файлу
шрифта) и собственно текст.
-
ImageColorAt().
Возвращает цвет определенного
пикселя в RGB-формате.
-
ImageColorExact().
Возвращает значение
определенного (в переменной)
цвета в RGB-формате.
-
ImageColorsTotal().
Возвращает общее количество
цветов в палитре.
-
ietPixel().
Подсвечивает точку с
указанными координатами
указанным цветом.
На этом я
закончу. Естественно, в рамках
одной статьи невозможно
рассмотреть все возможности работы
с изображениями, предоставляемые
языком PHP (точнее библиотекой
GD), однако я надеюсь, что
заинтересовал вас, и вы продолжите
изучение этой темы.
|