...и жалко и радостно, что не видят
исходных кодов пользователи...
...и плакать хочется, и радуешься,
что не узрят они твои велосипеды...
...и никто не узнает что же там на
самом деле...внутри...
...что не использовали мы стандартные
функции, а что живем мы правильно,
по-доброму...
...что все у нас хоть и криво, но родно...
Предисловие.
Несколько слов о GD
GD - библиотека, используемая для работы с двухмерной графикой. На
данный момент, в связи с проблемами авторского права начиная с GD
версии 1.6 - полностью удалена поддержка GIF, которую заменили
аналогичными функциями PNG (Однако же никто не мешает найти более
старую версию, которая несмотря не на что лежит на многих серверах).
PNG - новый формат-альтернатива формату GIF, специально разработанный
для передачи изображений через интернет, обеспечивающий большую
степень сжатия и лучшее качество. Данный формат поддерживается
ведущими браузерами - IE, Netscape и Opera.
Скачать модуль GD можно по адресу http://www.boutell.com/gd/
Чтобы проверить, что GD поддерживается в системе, попробуйте:
if(function_exists('imagetypes'))
echo 'GD is loaded';
else
echo 'GD is not loaded';
Я заметил, что множество народу ищут старые дистрибутивы GD, которые
еще поддерживают формат GIF. Хочу еще раз отметить, что это не всегда
обосновано, так как: (1) формат PNG поддерживается всеми новыми
браузерами и (2) одно и тоже изображение в GIF и PNG - в последнем
смотрится лучше, а места занимает меньше.
Где я могу использовать GD
Большое поле применения GD - интернет программирование. На самом деле
область применения GD в интернете намного выше, чем может показаться
на первый взгляд. Более подробно о возможности его применения смотрите
раздел примеры этой и последующих частей статьи.
Часть 1. Основные функции.
Черный квадрат...
Используя GD можно как создавать свои новые изображения, так и
загружать имеющиеся и модифицировать их (или нет - если, по какой-то
причине не хотите, чтобы пользователи видели что где у вас лежит :)).
Ниже описаны основные функции пакета GD:
* int ImageCreate(int x, int y)
Функция создает новое изображение размером x на y. Возвращает
идентификатор - номер картинки, который необходимо использовать как
ссылку при вызовах других функций.
* ImageDestroy(int image)
Уничтожает изображение тем самым, освободив связанные с ним ресурсы.
Этой функцией необходимо пользоваться после сохранения изображения или
отправки его в браузер.
Единственный параметр - ссылка.
* int ImageCreateFromGif(str filename)
Импортирует изображение из файла .gif и возвращает его идентификатор.
Единственный параметр - имя файла, импорт которого необходимо
совершить. В случае неудачи функция возвращает значение ФАЛСЕ.
* ImageGif(int image, string filename)
Позволяет сохранить объект-изображение в файле. Если параметр filename
опущен, то файл выводится непосредственно в поток данных.
Рассмотрим, как пример, маленький код, который открывает файл и
сохраняет его под новым именем:
<?php
$image = @ImageCreateFromGIF("images/picture01.gif");
if($image==" "){print "ERR"; exit();}
//Здесь возможно вставить код, изменяющий изображение
ImageGif($image,"p01.gif");
ImageDestroy($image);
?>
* ImageCopyResized
Функция позволяет делать копию изображения, или его прямоугольной
части, изменяя его размер. Синтаксис:
int ImageCopyResized(int new_image, int old_image, int newX, int newY,
int oldX, int oldY, int newW, int newH, int oldW, int oldH)
* ImageLine, ImageDashedLine (int image, int x1, int y1, int x2, int y2, int color)
Функции, вычерчивающие прямую линию между двумя точками. ImageLine -
прямую линию; ImageDashedLine - заштрихованную. Параметры функции -
точка начала линии, точка конца линии, цвет и идентификатор
изображения. Как всегда, левый верхний угол имеет значение x-y -
(0,0).
Я не буду очень подробно останавливаться на описании этой функции, так
как сомневаюсь в необходимости их постоянного использования обычным
программистом.
Данные функции рисуют прямоугольник (функции *Rectangle) или
непрямоугольные фигуры (функции Polygon). Синтаксис:
int Image(Filled)Rectangle(int im, int x1, int y1, int x2, int y2, int col);
int Image(Filled)Polygon(int im, array points, int num_points, int col);
* ImageFill, ImageFillToBorder
Функции делают заливку цветом color всей области вокруг указанной
точки имеющий такой же цвет, как и она сама. Вторая функция отличается
от первой наличием контура. Синтаксис функций:
int ImageFill(int image, int x, int y, int color);
int ImageFillToBorder(int image, int x, int y, int border_color, int color);
Некоторые основные функции работы с цветом
* int ImageColorAllocate(int image, int red, int green, int blue)
Одна из самых важных функций для работы с цветом. Используется для
назначения цветов изображениям. В функцию передаются три значения трех
цветов (красный, зеленый, синий) в диапазоне от нуля до 255.
Первые два вызова этой функции после ImageCreate задают цвет фона и
цвет вычерчивания.
* int ImageColorAt(int image, int x, int y)
Возвращает цвет точки (x,y) в изображении image.
* bool ImageColorSet(int image, int index, int red, int green, int blue)
Заменяет во всем изображении один цвет другим.
* int ImageColorTransparent(int image, int color)
Позволяет заменить во всем изображении какой-либо цвет прозрачностью.
Определяет цвет прозрачным.
* imagecolortransparent() устанавливает прозрачным цвет в изображении
image вместо цвета color. image - идентификатор изображения,
возвращаемый функцией imagecreate() и color - идентификатор цвета,
возвращаемый функцией imagecolorallocate().
Прозрачный цвет - свойство изображения! Это не свойство самого цвета.
Однажды выбрав, что цвет color будет заменен прозрачным цветом, - все
места изображения этого цвета будут прозрачными.
Функция возвращает идентификатор нового прозрачного цвета (или
текущего, если не указано).
После того (или до этого), как какой то цвет (color) определен как
прозрачный, при использовании этого цвета любой другой функции - цвет
будет прозрачным.
Пример:
Функция getimagesize() определяет размер любого изображения GIF, JPG, PNG, SWF,
SWC, PSD, TIFF, BMP или IFF.
Хорошая практика - использование результатов данной функции на динамических стр
аницах внутри IMG тэга.
Функция возвращает массив состоящий из четырех элементов. Индекс 0
содержит ширину изображения в пикселях. Индекс 1 - высоту. Индекс 2 -
индикатор типа изображения: 1 = GIF, 2 = JPG, 3 = PNG, 4 = SWF, 5 =
PSD, 6 = BMP, 7 = TIFF(intel byte order), 8 = TIFF(motorola byte
order), 9 = JPC, 10 = JP2, 11 = JPX, 12 = JB2, 13 = SWC, 14 = IFF.
Индекс 3 - корректная строка height="yyy" width="xxx" которая может
быть использована непосредственно в IMG тэге.
Функции ImageSX, ImageSY (аналогичные getimagesize) возвращают лишь
один размер - ширину или высоту соответственно.
Все три функции имеют лишь один параметр - ссылку на изображение.
?>
Пример (с URL):
<?php $size = getimagesize ("http://www.example.com/gifs/logo.gif");
?>
Для изображений JPG, или всех типов, начиная с PHP 4.3, возвращается
также два дополнительных элемента в массиве: канал(3=RGB,4=CMYK) и
битность(количество для каждого цвета).
В некоторых случаях (для некоторых форматов), когда функция
getimagesize() не может определить размеры изображения, возвращаются
два нуля вместо значений ширины и высоты.
Пример. Изменение размера изображения
Одна из наиболее часто встречающихся задач - изменение размера
картинки (например, при создании фотоальбома с предпросмотром).
Improved version of ResizeGif given by tjhunter with Height % Widht.
/* ResizeGif with (height % width) */
function RatioResizeImg( $image, $newWidth, $newHeight){
// открываем gif-файл
eregi(".(.*)$",$image,$regs);
switch($regs[1]){
case "gif": $srcImage = ImageCreateFromGIF( $image ); break;
case "jpg": $srcImage = ImageCreateFromJPEG( $image ); break;
case "png": $srcImage = ImageCreateFromPNG( $image ); break;
default: $srcImage = ImageCreateFromGIF( $image ); break;
}
// определяем изначальную высоту и ширину картинки
$srcWidth = ImageSX( $srcImage );
$srcHeight = ImageSY( $srcImage );
// следующий код проверяет если ширина больше высоты
// или высота больше ширины картинки так, чтобы
// при изменении сохранилась правильная пропорция
$ratioWidth = $srcWidth/$newWidth;
$ratioHeight = $srcHeight/$newHeight;
if( $ratioWidth < $ratioHeight){
$destWidth = $srcWidth/$ratioHeight;
$destHeight = $newHeight;
}else{
$destWidth = $newWidth;
$destHeight = $srcHeight/$ratioWidth;
}
// создаем новую картинку с конечными данными ширины и высоты
$destImage = imagecreate( $destWidth, $destHeight);
// копируем srcImage (исходная) в destImage (конечную)
ImageCopyResized( $destImage, $srcImage, 0, 0, 0, 0, $destWidth,
$destHeight, $srcWidth, $srcHeight );
//создаем gif
ImageGif( $destImage );
// освобаждаем память
ImageDestroy( $srcImage );
ImageDestroy( $destImage );
}
// сохраняем вывод в буфер
ob_start();
// изменяем размер; будет сохранено в буфере
ResizeGif( "/where/image/is/image.gif", "150", "150");
// копируем в переменную
$resizedImage = ob_get_contents();
// очищаем буфер
ob_end_clean();
// сохраняем $resizedImage в базу данных, файл, выводим ее в
браузер...
?>
Получение размера изображения GIF без использования GD
Зная формат GIF, возможно получить размеры изображения без
использования GD и не подгружая весь файл:
//Cache-Control сообщает браузеру (как и прокси-серверу) перезагрузить
// все картинки! В данном случае после 1 миллиона секунд.
Функция read_exif_data
Она же exif_read_data().
Читает информацию из заголовка TIFF или JPEG изображения.
Cинтаксис:
array exif_read_data ( string filename, string sections, bool arrays, bool thumbnail)
Так как read_exif_data() читает файл целиком, и если каждый файл по
размеру больше мегабайта, это слишком медленно, можно воспользоваться
нижеследующей функцией, которая читает лишь начало каждого файла:
$img - изображение, которое необходимо вращать.
$ang - угол поворота
$bg (опционально) - индекс цвета фона (по-умолчанию: белый)
$width и $height (опционально) - изображение будет приведено к этому
размеру. Обязательно использование обоих параметров вместе!
$bench (опционально)
"STRING" возвращает время, необходимое для выполнить функцию.
"IMAGE" поместит маленькую отметку с временем на изображение.
Примерное время выполнения функции при изображении размером 250x200px
при повороте <90° составляет примерно 1 секунду; при повороте на
угол >90° - ~2 секунды
!Эта функция работает только с изображениями JPEG!
Работа с текстом
Поместить текст на изображение можно используя одну из функций работы
с текстом.
* Функция imagestring().
Выводит строку текста.
Синтаксис:
int imagestring ( resource image, int font, int x, int y, string s, int col)
Функция выводит строку текста горизонтально в заданном изображении
image цветом col в координатах x, y (верхний левый угол соответствует
0, 0). Если значение шрифта указано 1, 2, 3, 4 или 5 - используются
встроенный шрифт (увеличение значения - больше по размеру шрифт).
* Функция imagestringup().
Выводит строку текста вертикально.
Синтаксис:
int imagestringup ( resource image, int font, int x, int y, string s, int col)
Аналогичная функции imagestring(). Выводит текст вертикально.
* Функция imagettftext().
Пишет текст на изображение используя шрифты TrueType.
Синтаксис:
array imagettftext ( resource image, int size, int angle, int x, int y,
int col, string fontfile, string text)
Функция пишет text на изображение image, начиная в координатах x, y
(верхний левый угол - 0, 0), под углом angle цеветом col, используя
шрифт TrueType fontfile. В зависимости от версии, если отсутствуют '/'
и '.ttf', то будет произведена попытка поиска шрифта в стандартной
папке шрифтов.
Координаты, заданные x и y, определяют базовую точку первого символа.
В отличии от функции imagestring(), где координаты определяют верхний
правый угол первой буквы, координаты указывают на левый верхний угол
первого символа.
Angle - угол в градусах. Значение 0 выведет текст справа налево;
повышение значения определяет отклонение против часовой стрелки. Таким
образом, значение 90, на выводе даст текст написанный снизу вверх.
Fontfile - путь к шрифту TrueType желаемый к использованию.
Text - текст; может включать в себя UTF-8 символы.
Функция imagettftext() возвращает массив из восьми эллементов. В нем
соответственно расположены следующие точки обрамляющие края текста:
нижний левый, нижний правый, верхний правый, верхний левый.
Точки находятся в соответствии с углом и относительно текста, т.е.
если текст расположен вертикально (снизу вверх), то <<правым верхним
углом>> на практике будет являться точка находящаяся слева вверху над
текстом.
Следующий пример создает черный GIF 400x30 пикселей, со словами
"Testing..." белым цветом и шрифтом Arial (этой функции необходима как
библиотека GD, так и FreeType библиотека).
// помещаем строку на него
ImageString($gif,3,70,90,"it works !",$tx);
// посылаем изображение
header("content-type: image/gif");
ImageGif($gif);
Пример:
Вставка строки Copyright в каждую фотографию в фотоальбоме посредствам PHP/GD
Еще один из наиболее частых случаев использования PHP/GD, как мне
кажется, - вставка авторской информации при выводе изображений.
Например, "Vasya (c) 2003". Такой скрипт в фотоальбоме - удобная вещь.
Каждый видит свои преимущества, а если поразмышлять еще, то находятся
и другие, о которых кто-то еще уже подумал :-).
Итак, алгоритм программы:
1. Загрузить готовую фотографию в объект.
2. Найти точки на рисунке где должна быть надпись. Надпись по длине,
по моим расчетам, примерно 130 и 12 пикселей по высоте.
3. Вставить надпись.
4. Передать фотографию на выход.
<?php
function ImageLoad($ImageToLoad){
$image = @ImageCreateFromGIF($ImageToLoad);
if($image==" ") {
#Случай неудачи открытия сообщения
#Используем заранее приготовленный файл с
#картинкой-изображением ошибки скрипта.
$err = ImageCreateFromGif("error.gif");
return $err;
} else {
return $image;
}
}
header("Content-Type: image/gif");
$str = "Vasya P. (C) 2003";
if(!isset($ImageToLoad)){
#Проверим, что переменная передана
print "No picture is selected";
exit();
}
$image=ImageLoad($ImageToLoad);
#Найдем X и Y где надо будет расположить надпись.
$X_var = ImageSX($image); $X_var = $X_var - 130; #shirina
$Y_var = ImageSY($image); $Y_var = $Y_var - 12; #visota
#Определим некоторые цвета
$black = ImageColorAllocate($image, 0, 0, 0);
$white = ImageColorAllocate($image, 255, 255, 255);
#Вывести изображение, затем уничтожив его
ImageGif($image);
ImageDestroy($image);
?>
Часть 2. Некоторые дополнительные функции GD/PHP.
* Функции imagechar() и imagecharup().
Выводят на изображение символ горизонтально и вертикально
соответственно.
Синтаксис:
int imagechar ( resource image, int font, int x, int y, string c, int col)
int imagecharup ( resource image, int font, int x, int y, string c, int col)
* Функция imagecolorclosest().
Возвращает индекс ближайшего цвета к указанному.
Синтаксис:
int imagecolorclosest ( resource image, int red, int green, int blue)
Возвращает индекс цвета ближайшего к указанному цвету формата RGB.
Эту функцию иногда необходимо использовать в работе с изображениями
JPEG в случае, если происходит эффект <<водных знаков>> на изображении
при использовании цвета.
* Функция imagecolorstotal().
Возвращает количество цветов, из палитры данного изображения.
Синтаксис:
int imagecolorstotal ( resource image)
Функция не всегда корректно работает с изображениями jpeg; также в
текущей версии функция не имеет возможность правильно определять
количество цветов в изображении где их более 256.
Функция imagecopyresized().
Копирует изображение, предварительно изменяя ее размер.
Синтаксис:
int imagecopyresized ( resource dst_im, resource src_im, int dstX, int
dstY, int srcX, int srcY, int dstW, int dstH, int srcW, int srcH)
Функция копирует прямоугольную область изображения на другое
изображение.
Dst_im - изображение назначени; src_im - источник.
Координаты соответствуют левому верхнему углу. Функция позволяет быть
использованной для копирования части изображения внутри себя (если
dst_im совпадает с src_im), но если изображения будут перекрываться -
результат может быть непредсказуемым.
* Функция imagecopymerge().
Копирует часть изображения и совмещает его с другим.
Синтаксис:
int imagecopymerge ( resource dst_im, resource src_im, int dst_x, int
dst_y, int src_x, int src_y, int src_w, int src_h, int pct)
Копируется часть src_im на dst_im начиная в координатах x,y - src_x,
src_y и dst_x, dst_y - соответственно исходного изображения и точек
второго изображения, на которое производится копирование. Размеры
прямоугольника, подлежащего копированию, определяются шириной и
высотой src_w и src_h.
Два изображение будут совмещены с интенсивностью определенной в pct,
которая имеет область от 0 до 100. При pct = 0, ничего не происходит;
При 100, данная функция действует идентично imagecopy().
* Функция imagecopymergegray().
Аналогичная предыдущей функция по синтаксису и работе. Исключение -
перед тем, как скопировать изображение, заменяет зону на которую будет
произведено копирование серым цветом.
* Функция iptcembed().
Позволяет работать с бинарной информацией IPTC в JPEG файлах.
При работе в системе необходимо понимать, что есть различие между
текстовыми и бинарными файлами. Так что если запускать нижележащий
пример на платформе Windows, изображение будет искажено. Добиться
правильной работы можно, поместив на открытие файла (функция fopen())
- 'wb', вместо 'w'.
Данный пример читает IPTC текст из изображение, изменяет его и
записывает в новый файл. Используемые функции - iptcparse() и
iptcembed().
<?
// имя исходного файла
$image_name_old = "test.jpg";
// имя нового файла
$image_name_new = "test2.jpg";
// Читаем IPTC-текст в массив '$iptc'
// Номер следующий за '#' - поле IPTC
// Например: $iptc["2#090"][0] - поле Город.
// $iptc["2#055"][0] - дата создания
$size = GetImageSize ("$image_name_old",&$info);
$iptc_old = iptcparse ($info["APP13"]);
// Добавление или замена текста IPTC.
// В этом примере заменяется оригинальная категория
// или создается, если не существует
$iptc_old["2#015"][0] = "Sport";
// .. и добавляем еще текст к заголовку (Caption)
$iptc_old["2#120"][0] .= " More caption text";
// Создаем новую строку IPTC
foreach (array_keys($iptc_old) as $s){
// Находим номера IPTC
$tag = str_replace("2#", "", $s);
// Создаем строку