| Всякому 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), однако я надеюсь, что заинтересовал вас, и вы продолжите изучение этой темы. |