Графика в PHP
Всякому 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
Что еще можно рисовать?
Естественно, кроме линий с помощью 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="5170/10.gif" border=0></a> </td></tr>
<? } ?>
</table>
</body> </html>
рисунок 10
Результат работы этого скрипта можно увидеть на рисунке
10. Единственное, на что хочу обратить ваше внимание - способ вызова кода
для формирования изображения. Взгляните на следующую конструкцию:
<img src="5170/10.gif"
Здесь в качестве параметра 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), однако я надеюсь, что
заинтересовал вас, и вы продолжите изучение этой темы.
|