- Введение [http://www.php5.ru#intro]
- Сборка [http://www.php5.ru#build]
- Генерация изображения [http://www.php5.ru#paint]
- Вывод текста, а также диаграммы и коллекционеры марок [http://www.php5.ru#text]
- Изменение размера: thumbnails, или "превьюшки" [http://www.php5.ru#size]
Введение
PHP приобрел всемирную популярность не только как удобное средство
вывода HTML и обработки форм, но и, во многом, благодаря набору расширений,
позволяющим выполнять всевозможные стоящие перед веб-разработчиком задачи.
Одним из таких расширений является библиотека GD, предназначенная для работы
с растровыми изображениями.
В этой статье мы рассмотрим работу со второй версией библиотеки GD.
Сборка
Для успешного выполнения примеров из этой статьи необходимо, чтобы PHP
был собран с поддержкой второй версии библиотеки GD.
Для того, чтобы узнать наличие и используемую версию графической
библиотеки, воспользуемся всеми нами, без сомнения, любимой функцией
phpinfo() [http://www.php.net/phpinfo], и взглянем на раздел "GD":
gd
| GD Support | enabled |
| GD Version | bundled (2.0.15 compatible) |
| FreeType Support | enabled |
| FreeType Linkage | with freetype |
| GIF Read Support | enabled |
| JPG Support | enabled |
| PNG Support | enabled |
| WBMP Support | enabled |
| XBM Support | enabled |
| JIS-mapped Japanese Font Support | enabled |
Если ничего похожего вы не нашли - значит, PHP собран без поддержки графической
библиотеки, и придется его пересобирать (или попросить об этом админа).
В противном случае, сначала взглянем на строку "GD Version".
Если версия GD - первая (например, 1.6), то часть материала этой статьи
вам не подойдет (и, в любом случае, рекомендую обновиться до второй версии).
Вторая же версия тоже может быть разная. :) Обратите внимание на слово "bundled".
Его присуствие означает, что PHP собран с библиотекой GD, поставляемой вместе с PHP: именно
эту библиотеку рекомендуется использовать, так как разработчики PHP исправили множество ошибок
и недочетов, присущих оригинальной GD. Впрочем, если используется внешняя библиотека (слово
"bundled" в строке "GD Version" отсутствует) - ничего страшного, все
приведенные ниже примеры будут работать.
В нижеследующих строках мы видим, какие графические форматы поддерживаются данной конфигурацией библиотеки GD.
В частности, работа с форматом GIF поддерживается в режиме "только чтение"
из-за проблем с лицензированием используемого в GIF алгоритма компрессии.
Итак, если требуется пересборка PHP, следует это и сделать, загрузив при необходимости
последнюю версию PHP, и указать при сборке параметр:
--with-gd[=location]
Необязательный параметр location указывает путь к внешней библиотеке GD. Если
его опустить (в смысле, не указывать) - используется bundled-версия.
Для поддержки работы с шрифтами TrueType, обсуждаемой в главе "Вывод текста..." [http://www.php5.ru#text],
также понадобится наличие библиотеки FreeType [http://www.freetype.org]
и следующие параметры конфигурационной строки:
--enable-gd-native-ttf
--with-freetype-dir=/путь/к/библиотеке/FreeType
Примечание: Для сборки GD с поддержкой GIF Write под FreeBSD, необходимо предварительно установить переменную среды WITH_LZW:
export WITH_LZW=yes
Примечание 2:Выше подразумевалось, что используется Unix-подобная ОС.
Если же PHP установлен локально, да еще и под Windows - то надо просто раскомментить одну
строчку в php.ini - надеюсь, догадаетесь, какую. :)
Генерация изображения с помощью PHP
Ну что ж, со сборкой PHP мы разобрались, и теперь нам не терпится
нарисовать и вывести в броузер какую-нибудь картинку с помощью PHP.
Надеюсь, вы прекрасно осознаете, что нельзя вот так вот просто взять и
вывести картинку посреди HTML-кода в том же самом скрипте
(если не осознаете, прочтите внимательно эту статью [http://faq.phpclub.net/na_tanke]):
в HTML-документе мы разместим, как и обычно, тэг <img>, а в его атрибуте
src укажем не картинку, как обычно, а PHP-скрипт:
<img src="/i/articles/image/image.php">
Теперь приступим к написанию этого самого image.php.
Заголовок. Он же header.
Прежде всего, как броузер узнает, что image.php - это не HTML-документ и не что-то еще, а картинка?
Тип документа броузер определяет по заголовку Content-type.
На самом деле, этот заголовок - обязательный и всегда присуствует;
по умолчанию, PHP услужливо "отдает" заголовок Content-type: text/html.
Обычно это поведение PHP нам прекрасно подходит - но не в данном случае.
Придется нам вывести нужный заголовок самим:
<?php
header(′Content-type: image/png′); ?>
Приступим теперь непосредственно к генерации картинки.
Создание изображения
Для создания изображения, в нашем распоряжении две функции:
1. imagecreate() [http://www.php.net/imagecreate]. С помощью этой функции можно создать изображение
на основе палитры, содержащей фиксированный набор цветов. Каждый цвет палитры
необходимо описать с помощью функции imagecolorallocate() [http://www.php.net/imagecolorallocate]. Этот способ
создания изображения был единственным при работе с первой версией GD, и необходим
при работе с ориентированными на палитру форматами, такими как GIF. Однако
введенный во второй версии (и отныне рекомендуемый разработчиками) способ,
на мой взгляд, гораздо более удобен.
2. imagecreatetruecolor() [http://www.php.net/imagecreatetruecolor]. Эта функция создает TrueColor-изображение,
то есть цвет каждой точки определяется произвольным цветом, задаваемым в координатах
RGB. Помимо того, что это удобнее, чем работа с палитрой, такой подход позволяет
производить масштабирование изображения с гораздо меньшими потерями качества. Но об этом
позже. Сейчас просто создадим изображение:
<?php
$image = imagecreatetruecolor(80,60) or die(′Cannot create image′); imagedestroy($image); ?>
Функция imagecreatetruecolor (как, кстати, и функция imagecreate), принимает два обязательных
целочисленных параметра - ширину (в нашем примере - 80 пикселей) и высоту (60 пикселей)
картинки, и возвращает идентификатор ресурса (в данном случае - изображения), который мы присваиваем переменной
$image, которой в дальнейшем будем постоянно пользоваться.
Если по какой-либо страшной причине (недостатке памяти, например) создать
изображение не получается, функция возвращает false - в этом случае мы прерываем работу
скрипта.
Хотя мы с этим изображением, пока что, ничего не делаем, мы обязаны освободить выделенную
для него память с помощью функции imagedestroy() [http://www.php.net/imagedestroy]: к сожалению, автоматическое
освобождение памяти происходит не всегда, и игнорирование рекомендации всегда использовать
imagedestroy может привести к весьма серьезным утечкам памяти.
Немножко порисуем
Итак, с помощью функции imagecreatetruecolor() [http://www.php.net/imagecreatetruecolor] мы создали "труколорное" и,
если верить документации, черное изображение размером 80x60. Так что, те, в чьи планы
входит создание Web-галереи репродукций "квадрата Малевича", могут
смело переходить к следующей главе. :) Для остальных, продолжим. Нарисуем на картинке
что-нибудь содержательное.
<?php
$image = imagecreatetruecolor(80,60) or die(′Cannot create image′); imagefill($image, 0, 0, 0x000080);
imageellipse($image, 40, 30, 50, 50, 0xFFFF00);
imagefilledellipse($image, 30, 20, 10, 10, 0xFFFF00);
imagefilledellipse($image, 50, 20, 10, 10, 0xFFFF00);
imageline($image, 40, 28, 40, 38, 0xFFFF00);
imagearc($image, 40, 30, 40, 40, 45, 135, 0xFFFF00);
header(′Content-type: image/png′);
imagepng($image);
imagedestroy($image); ?>
Палка, палка, огуречик, вот и вышел человечек :)
Используемые для рисования функции весьма просты для понимания. Их описание (как и описание
всех GD-функций) вы найдете здесь [http://www.php.net/image]. В случае трудностей с английским,
просто "поиграйтесь", меняя значения параметров - как вы, несомненно, уже догадались, это
ни что иное, как координаты, и цвета в виде 0xRRGGBB.
Подробнее же мы разберем вот эту строку:
imagepng($image);
Выше мы создали в памяти изображение, и всячески над ним извращались. :)
Это мы делали без привязки к какому-либо выходному формату - просто работали
с набором байтов в памяти. А вот функции вида imageформат
(imagepng() [http://www.php.net/imagepng], imagejpeg() [http://www.php.net/imagejpeg], imagewbmp() [http://www.php.net/imagewbmp]...)
генерируют на основе этого самого набора байтов, на который ссылается
идентификатор $image, картинку в соответствующем формате,
и выводят ее в выходной поток - то бишь, проще говоря, в броузер.
Нелишне здесь вспомнить и о строке header(′Content-type: image/png′),
где мы указали тип документа - обратите внимание: здесь png, и там png. :)
Справедливости ради, надо заметить, что большинство броузеров воспринимают
только часть "image" этого заголовка, а формат самой картинки уже
определяют по ее заголовкам, характерным для каждого формата; однако, лучше
все же не надеяться на "интеллект" броузера и указывать правильный формат изображения.
Вывод текста, а также диаграммы и коллекционеры марок
Используя полученные в результате рисования смайликов знания, попробуем
порисовать диаграммы, а заодно и научимся выводить на картинках текст (не забудьте только
о библиотеке FreeType, о необходимости наличия которой сказано в главе "Сборка".
Предположим, вы располагаете следующей важной статистической информацией о коллекционерах почтовых марок:
<?php
$Title = ′Количество марок у моих друзей′;
$Data = array(
′Коля′ => 16,
′Петя′ => 14,
′Федя′ => 11,
′Маша′ => 17,
′Ипполит′ => 8
);
?>...и горите желанием представить эту информацию в виде "столбиков" - для
удобного сравнения. Столбики мы рисовать уже умеем - стоит только немножко вспомнить азы
арифметики:
<?php
define(′GRAPH_WIDTH′, 400); define(′GRAPH_HEIGHT′, 300); define(′GRAPH_OFFSET_TOP′, 40); define(′GRAPH_OFFSET_LEFT′, 40); define(′GRAPH_OFFSET_RIGHT′, 5); define(′GRAPH_OFFSET_BOTTOM′, 30); $colors = array(0xFF0000,0x00FF00,0x0000FF, 0xFFFF00,0x00FFFF,0xFF00FF);
require(′data.php′); $col_width = (GRAPH_WIDTH - GRAPH_OFFSET_LEFT - GRAPH_OFFSET_RIGHT) / count($Data);
$col_maxheight = (GRAPH_HEIGHT - GRAPH_OFFSET_TOP - GRAPH_OFFSET_BOTTOM);
$max_value = max($Data);
$image = imagecreatetruecolor(GRAPH_WIDTH,GRAPH_HEIGHT) or die(′Cannot create image′); imagefill($image, 0, 0, 0xFFFFFF); $x = GRAPH_OFFSET_LEFT;
$y = GRAPH_OFFSET_TOP + $col_maxheight;
$i = 0;
foreach($Data as $value) {
imagefilledrectangle( $image,
$x,
$y - round($value*$col_maxheight/$max_value),
$x + $col_width - 1,
$y,
$colors[$i++%count($colors)]
);
$x += $col_width;
}
imageline($image, GRAPH_OFFSET_LEFT - 5, GRAPH_OFFSET_TOP,
GRAPH_OFFSET_LEFT - 5, $y, 0xCCCCCC);
for($value=0; $value<=$max_value; $value++) {
imageline($image, GRAPH_OFFSET_LEFT - 7, $Y = $y - round($value*$col_maxheight/$max_value),
GRAPH_OFFSET_LEFT - 5, $Y, 0xCCCCCC);
imagestring($image, 1, GRAPH_OFFSET_LEFT / 2, $Y - 4, $value, 0x000000);
}
header(′Content-type: image/png′);
imagepng($image);
imagedestroy($image); ?>
Обратите внимание на строку
imagestring [http://www.php.net/imagestring]($image, 1, GRAPH_OFFSET_LEFT / 2, $Y - 4, $value, 0x000000);
с помощью которой мы выводим числа на координатной оси. Второй параметр - один
из встроенных в GD шрифтов (от 1 до 5, чем больше число - тем крупнее шрифт).
Так зачем же, скажете вы, нам какие-то там TrueType-шрифты и FreeType-библиотеки,
если мы и так прекрасно пишем на картинке? А вот затем, скажу я вам,
что писать-то мы хотим по-русски, а встроенные шрифты о существовании кириллицы
даже и не подозревают. А нам надо бы подписать столбики именно по-русски. Да и выбор
встроенных шрифтов невелик.
Итак, нам понадобится:
- Функция imagettftext() [http://www.php.net/imagettftext], которая рисует выбранным TrueType-шрифтом на картинке,
- Какой-нибудь кириллический TrueType-шрифт. Возьмем, например, arial.ttf из всеми
нами любимой Винды, да не просто возьмем, а положим его туда, где лежит наш скрипт,
- Поскольку функция imagettftext() [http://www.php.net/imagettftext] воспринимает кодировку Unicode,
но никак не Windows-1251, то нам пригодится вот такая функция для соответствующего преобразования:
<?php function win2uni($s)
{
$s = convert_cyr_string($s,′w′,′i′); for ($result=′′, $i=0; $i<strlen($s); $i++) {
$charcode = ord($s[$i]);
$result .= ($charcode>175)?"&#".(1040+($charcode-176)).";":$s[$i];
}
return $result;
}
?>- Функция imagettfbbox() [http://www.php.net/imagettfbbox], которая поможет нам вычислить высоту и ширину
выводимого шрифтом текста.
Сначала потренируемся:
<?php
require(′win2uni.php′);
define(′WIDTH′, 200);
define(′HEIGHT′, 60);
define(′FONT_NAME′, ′arial.ttf′);
define(′FONT_SIZE′, 20);
$image = imagecreatetruecolor(WIDTH,HEIGHT)
or die(′Cannot create image′);
$text = win2uni(′Всем привет! :)′);
$coord = imagettfbbox(
FONT_SIZE, 0, FONT_NAME, $text );
$width = $coord[2] - $coord[0];
$height = $coord[1] - $coord[7];
$X = (WIDTH - $width) / 2;
$Y = (HEIGHT + $height) / 2;
imagettftext(
$image, FONT_SIZE, 0, $X, $Y, 0xFFFFFF, FONT_NAME, $text
);
header(′Content-type: image/png′);
imagepng($image);
imagedestroy($image);
?>
Тренировка прошла успешно - всех поприветствовали. Можно теперь приступать к нашим диаграммам.
<?php
define(′GRAPH_WIDTH′, 400); define(′GRAPH_HEIGHT′, 300); define(′GRAPH_OFFSET_TOP′, 40); define(′GRAPH_OFFSET_LEFT′, 40); define(′GRAPH_OFFSET_RIGHT′, 5); define(′GRAPH_OFFSET_BOTTOM′, 30); define(′FONT_NAME′, ′arial.ttf′); define(′FONT_SIZE′, 12); $colors = array(0xFF0000,0x00FF00,0x0000FF, 0xFFFF00,0x00FFFF,0xFF00FF);
require(′data.php′);
require(′win2uni.php′);
$col_width = (GRAPH_WIDTH - GRAPH_OFFSET_LEFT - GRAPH_OFFSET_RIGHT) / count($Data);
$col_maxheight = (GRAPH_HEIGHT - GRAPH_OFFSET_TOP - GRAPH_OFFSET_BOTTOM);
$max_value = max($Data);
$image = imagecreatetruecolor(GRAPH_WIDTH,GRAPH_HEIGHT) or die(′Cannot create image′); imagefill($image, 0, 0, 0xFFFFFF); $x = GRAPH_OFFSET_LEFT;
$y = GRAPH_OFFSET_TOP + $col_maxheight;
$i = 0;
foreach($Data as $name => $value) {
imagefilledrectangle( $image,
$x,
$y - round($value*$col_maxheight/$max_value),
$x + $col_width - 1,
$y,
$colors[$i++%count($colors)]
);
$text = win2uni($name);
$coord = imagettfbbox(FONT_SIZE,0,FONT_NAME,$text);
$text_x = $x + ($col_width - $coord[2] - $coord[0]) / 2;
$text_y = GRAPH_HEIGHT - 5;
imagettftext($image,FONT_SIZE,0,$text_x,$text_y,0x000000,FONT_NAME,$text);
$x += $col_width;
}
$text = win2uni($Title);
$coord = imagettfbbox(FONT_SIZE,0,FONT_NAME,$text);
$text_x = $x + ($col_width - $coord[2] - $coord[0]) / 2;
$text_y = (GRAPH_OFFSET_TOP - $coord[1] - $coord[7]) / 2;
imagettftext($image,FONT_SIZE,0,$text_x,$text_y,0x000000,FONT_NAME,$text);
imageline($image, GRAPH_OFFSET_LEFT - 5, GRAPH_OFFSET_TOP,
GRAPH_OFFSET_LEFT - 5, $y, 0xCCCCCC);
for($value=0; $value<=$max_value; $value++) {
imageline($image, GRAPH_OFFSET_LEFT - 7, $Y = $y - round($value*$col_maxheight/$max_value),
GRAPH_OFFSET_LEFT - 5, $Y, 0xCCCCCC);
imagestring($image, 1, GRAPH_OFFSET_LEFT / 2, $Y - 4, $value, 0x000000);
}
header(′Content-type: image/png′);
imagepng($image);
imagedestroy($image);
?>Барабанная дробь... Запускаем...
Ура! Получилось! :)
Изменение размера: thumbnails, или "превьюшки"
Часто перед веб-разработчиком стоит задача генерации уменьшенных копий изображений для
предварительного просмотра; можно даже сказать, что это - одно из самых
распространенных применений библиотеки GD.
В GD1, поддерживающей только изображения на основе палитры, присуствовала
лишь функция imagecopyresized() [http://www.php.net/imagecopyresized]; качество уменьшенных изображений, генерируемых
этой ей, мягко говоря, оставляло желать лучшего: работая с фиксированной палитрой,
ограниченной 255 цветами, весьма затруднительно обеспечить качественный антиалиасинг.
Во второй версии библиотеки, с появлением поддержки TrueColor и imagecreatetruecolor() [http://www.php.net/imagecreatetruecolor],
введена новая функция - imagecopyresampled() [http://www.php.net/imagecopyresampled], обеспечивающая весьма достойное
качество "превьюшек".
Продемонстрируем работу с этой функцией. Предположим, у нас есть
файл original.jpg, допустим, 400x250 пикселей, и мы хотим создать ее уменьшенный
вариант small.jpg - 100x60. Можно поступить так:
<?php
define(′SOURCE′, ′original.jpg′)К началу статьи
| Добавил: PIXEL | Дата публикации: 2007-10-12 14:36:08 |
| Рейтинг статьи: | 3.00 [Голосов 5] | Кол-во просмотров: 5845 |
Комментарии читателейВсего комментариев: 1
| 2009-10-25 03:17:08 |
| 5RAY STUDIO |
Спасибо за статью, пригодилась.
|