Динамическое создание изображений средствами PHP

Источник: php
Nykoh (Нико)

Динамическое создание изображений средствами PHP

В статье описывается работа с расширением PHP - GDLib, которое позволяет динамически формировать изображения на Web-страницах.

Для понимания этой статьи необходимо иметь представление об элементарных основах PHP, а также работе с изображениями.

Примечание переводчика

в примерах все названия идентификаторов даны на французском языке. Для того, чтобы облегчить читателю понимание кода, мы предлагаем их перевод:
blanc - белый
bleu - голубой
couleur - цвет
couleur_fond - цвет фона
fichier - файл
gris - серый
hauteur - высота
hauteurimage - высота изображения
largeur - ширина
largeurimage - ширина изображения
mois - месяц
noir - черный
police - гарнитура шрифта
rouge - красный
tableau - массив
vert - зеленый

Примечание переводчика

По умолчанию в PHP 5 все расширения отключены, в том числе и расширение для формирования динамических изображений - GD. Поэтому Вам необходимо включить расширение GD в файле конфигурации php.ini.

Цели: научить использовать различные функции библиотеки gd, предназначенные для динамического создания изображений.

Библиотека GD представляет собой набор функций для работы с изображениями. Благодаря ей можно не только динамически создавать собственные изображения, но и получать о них различную информацию, изменять размер и т.д.

Внимание: Прежде чем начать работу, нужно кое-что узнать. Дело в том, что существует несколько различных версий этого расширения PHP, а поставщики услуг хостинга могут отключить определенные функции, а то и всю библиотеку GD. С какой целью? Известно, что обработка изображений - это большая нагрузка на сервер.

Итак, вам необходимо узнать версию библиотеки GD установленную на используемом вами хостинге, а также получить информацию о разрешенных функциях. Первое, что следует сделать, - воспользоваться функцией phpinfo. Выполните следующий скрипт:

phpinfo.php

<?php
    phpinfo();
?>

Если у вас появится таблица похожая на эту - все нормально (особенно если версия библиотеки новее, чем 2.0)

GD

GD Support

enabled

GD Version

2.0 or higher

FreeType Support

enabled

FreeType Linkage

with freetype

JPG Support

enabled

PNG Support

enabled

WBMP Support

enabled

Как было упомянуто выше, некоторые возможности могут быть отключены. В таком случае следует просто попробовать использовать ту или иную функцию. Если это приведет к ошибке: Fatal error: Call to undefined function, - у вас не должно быть никаких сомнений, что данная функция отключена.

I) Создание холста

Для начала необходимо создать пустой холст. Сразу поясним, что в данной статье мы будем рассказывать исключительно об изображениях в формате PNG или JPG, формат GIF останется без нашего внимания. Дело в том, что этот формат перестал поддерживаться библиотекой GD, начиная с версии 1.3, правда ограниченная поддержка GIF появилась опять в версии 2. Вывод: формат PNG - выгодная альтернатива GIF

Важное замечание

Во всех учебных курсах сайта www.phpdebutant.org, скрипты имели целью динамическое создание html-страниц. На этот раз, используя библиотеку GD, мы создаем изображения, поэтому в данном случае вы должны забыть на время конструкции echo и print. По умолчанию PHP-скрипт генерирует html-страницу, что не требует уточнения в виде отправки особого http-заголовака. Но если мы создаем изображение, в самом начале скрипта необходимо указать его тип, отправкой соответствующего заголовка, например для PNG: header ("Content-type: image/png");

Дальнейшие действия чем-то напоминают работу с графическим редактором. Вы создаете новое изображение, указывая размеры, выбираете цвет фона и сохраняете его в нужном формате. Данную последовательность действий иллюстрирует следующий скрипт:

imagevide.php

<?php
    header ("Content-type: image/png");
    $im = ImageCreate (200, 100)
            or die ("Ошибка при создании изображения");         
    $couleur_fond = ImageColorAllocate ($im, 255, 0, 0);
    ImagePng ($im);
?>

Этот небольшой скрипт генерирует красный прямоугольник (очень скромное, но хорошее начало). Описание механизма:

  • Функция ImageCreate возвращает дескриптор $im. Дескриптор $im должен передаваться всем функциям прорисовки изображения. Параметры функции ImageCreate соответствуют длине и ширине создаваемого изображения (200х100).
  • Задача оператора or die - перехват возможных ошибок.
  • Создать цвет можно при помощи функции ImageColorAllocate. Она используется для
    • создания цвета и его сохранение в переменной с целью последующего использования
    • добавление цвета в палитру изображения $im

Ее параметры соответствуют красной, зеленой и синей компонентам цвета и представляют из себя целые числа от 0 до 255. В этом примере мы создали красный цвет.

Важное замечание

этот цвет соответствует цвету фона, поскольку он первым добавляется в палитру изображения

Вызов скрипта imagevide.php (пустое_изображение.php) создаст изображение в формате PNG. Для того, чтобы его использовать на web-сайте, нужно действовать так же, как и в случае с "классическими" изображениями.

<img src="imagevide.php">

Совсем несложно! Вы даже можете передавать параметры скрипту, который будет генерировать изображение (например цвет фона).

<img src="imagevide.php?couleur=bleu">

Итак, вы уже обладаете некоторыми базовыми знаниями для того, чтобы начать рисовать. Если вам хочется их углубить - вот несколько интересных функций

  • Вы можете заменить ImageCreate на ImageCreateTrueColor, чтобы создать 32 битное изображение (идеально для фотографий)
  • Вы можете заменить ImagePng функцией ImageJPEG чтобы создать изображение в формате JPEG (не забудьте поменять параметр функции header на header("Content-type: image/jpeg").
  • Ниже мы увидим, что сгенерированное изображение можно сохранить

II) Функции прорисовки изображения

Сначала вам необходимо знать, что любой рисунок связан с понятием координат, поэтому в этом небольшом абзаце статьи мы дадим некоторые представления об этом вопросе.
Верхний левый угол изображения имеет координаты (x=0, y=0), а нижний правый (x = ширина изображения, y=высота изображения).

Например, для изображения с разрешением 100 на 200 пикселей координаты будут такими:

1

Различные функции прорисовки изображения принимают в качестве параметров его координаты. Приучайтесь передавать их в требуемом порядке. Так, например, для того, чтобы нарисовать прямоугольник, необходимо передать координаты двух точек соответствующей функции (ImageRectangle). Координаты первой точки соответствуют верхнему левому углу изображения, координаты второй точки соответствуют нижнему правому углу. Не путайте аргументы, поскольку некоторые функции могут выдать ошибочные результаты.


Вот список функций, которые необходимы для прорисовки различных форм, а также для размещение текста на создаваемом изображении.
Для каждой функции вы найдете краткое описание синтаксиса и назначения.
Мы не ставим себе целью привести пример использования для каждой функции, здесь вы найдете только краткое описание. В таблице также указана версия библиотеки, начиная с которой поддерживается та или иная функция. Примеры употребления некоторых функций можно найти в разделе официального мануала, посвященного библиотеке расширения GD

Пример синтаксиса

Версия

Описание

$im = ImageCreate ($largeur, $hauteur)

Любая

Создает пустой холст (256 цветов) $im высотой $largeur и шириной $hauteur. (формат PNG предпочтителен)

$im = ImageCreateTrueColor ($largeur, $hauteur)

2.0.2

Эта функция похожа на ImageCreate но глубина цвета изображения не ограничена 256 цветами. (формат JPEG предпочтителен)

$col = ImageColorAllocate ($im, $rouge, $vert, $bleu)

Любая

Помещает в переменную $col цвет компонентами которого являются $rouge, $vert, $bleu (диапазон 0 .. 255).Подробности см. в первой части.

ImageEllipse ($im, $x, $y, $l, $h, $col)

2.0.2

Создает эллипс на изображении $im с центром в точке ($x,$y), шириной $l, высотой $h и цветом $col.

ImageFilledEllipse ($im, $x, $y, $l, $h, $col)

2.0.2

Идентична ImageEllipse, но эллипс заполняется цветом $col

ImageFill ($im, $x, $y, $col)

Любая

Создает на изображении $im прямоугольник цвета $col, расположенный между точкой с координатами ($x,$y) и нижним правым углом изображения цвета $col

ImageLine ($im, $x1, $y1, $x2, $y2, $col)

Любая

Рисует линию цвета $col, которая проходит между двумя точками с координатами ($x1,$y1) и ($x2,$y2)

ImagePolygon ($im, $points, $num_points, $col)

Любая

На изображении $im рисует многоугольник, координаты которого перечислены в массиве $points ($points[0]=$x0, $points[1]=$y0, $points[2]=$x1, $points[3]=$y1, и т. д.), $num_points - количество точек в массиве, $col - цвет.

ImageFilledPolygon ($im, $points, $num_points, $col)

Любая

Идентична ImagePolygo, но эллипс заполняется цветом $col

ImageRectangle ($im, $x1, $y1, $x2, $y2, $col)

Любая

На изображении $im рисует прямоугольник, верхний левый угол которого имеет координаты ($x0, $y0) , а правый нижний ($x1, $y1). $col - цвет прямоугольника

ImageFilledRectangle ($im, $x1, $y1, $x2, $y2, $col)

Любая

Идентична ImageRectangle, но эллипс заполняется цветом $col

ImageSetStyle ($im, $style) ImageSetBrush ($im, $brush)

2.0.2

Эти функции позволяют изменить стиль прочерчиваемых линий. Для более подробной информации посмотрите официальную документацию, особенно обратите внимание на пример использования функции ImageSetStyle , который также является показательным для функции ImageSetBrush

ImageSetPixel ($im, $x, $y, $col)

Любая

В изображении $im рисует точку с координатами ($x,$y) и цветом $col

ImageSetThickness ($im, $epaisseur)

Любая

Меняет толщину линий, созданных различными функциями.

ImageString ($im, $police, $x, $y, $chaine, $col)

Любая

В изображении $im создает строку $chaine с координатами (левый верхний угол) ($x,$y) цвета $col $police - размер (гарнитура) шрифта (от 0 до 5)

ImageStringUp ($im, $police, $x, $y, $chaine, $col)

Любая

Идентична ImageString , но строка выводится вертикально

III) Пример первый: статистика посещений сайта в виде графика

Чтобы применить полученные знания на практике - создадим простой скрипт-пример. Часто требуется представить статистику посещения сайта в форме гистограммы

Мы предполагаем, что вы уже разработали ту часть скрипта, которая отвечает за учет посетителей (возможно с использованием таблицы MySQL). Об ее реализации мы говорить здесь не будем, это не цель данной статьи. Допустим, что статистика посещений за каждый месяц помещена в массив $visites. В этой статье мы наполняем массив "вручную", но вы можете сделать это сами, используя данные вашей таблицы MySQL.

a) Статистика посещений: создание изображения и цвета

Начнем с создания массива, который содержит в себе статистику посещений сайта за 12 месяцев (12 элементов). Затем сгенерируем картинку разрешением 400х300 и создадим три цвета, один из которых (белый) будет цветом фона.

visites.php

<?php
    $visites = array(138, 254, 381, 652, 896, 720, 140, 556, 663, 331, 407, 768);

    header ("Content-type: image/png");  
    $largeurImage = 400;
    $hauteurImage = 300;
    $im = ImageCreate ($largeurImage, $hauteurImage)  
            or die ("Ошибка при создании изображения");          
    $blanc = ImageColorAllocate ($im, 255, 255, 255);  
    $noir = ImageColorAllocate ($im, 0, 0, 0);   
    $bleu = ImageColorAllocate ($im, 0, 0, 255);  
?>

b) Рисуем оси графика

Поместим горизонтальную ось времени (простая черная линия) в нижнюю часть изображения, оставив поле в 10 пикселов.

Внизу подписываем номер каждого из 12 месяцев, используя цикл for и функцию ImageString. Номера месяцев располагаются через каждые 30 пикселов, начиная с левой стороны изображения.

Наконец, проводим вертикальную линию, ось ординат статистики посещений.

<?php
// проводим горизонтальную линию, ось абсцисс (время)
ImageLine ($im, 10, $hauteurImage-10, $largeurImage-10, $hauteurImage-10, $noir);
// выводим порядковый номер каждого из 12 месяцев
for ($mois=1; $mois<=12; $mois++) {
ImageString ($im, 0, $mois*30, $hauteurImage-10, $mois, $noir);
}

// проводим вертикальную линию, чтобы ось ординат (число посещений)
ImageLine ($im, 10, 10, 10, $hauteurImage-10, $noir);
?>

c) Рисуем палочки

Теперь переходим к более сложной задаче - рисованию палочек.

Для начала нам необходимо узнать максимальное число посетителей, которое мы представим на графике. Здесь мы выбрали случайное значение - 1000, но на самом деле вам, наверное, придется его вычислять, осуществляя запрос на максимальное значение столбца вашей таблицы MySQL. Мы же сделаем проще…

Для каждого месяца необходимо вычислить высоту создаваемого прямоугольника. Для этого необходимо решить уравнение, зная что высота прямоугольника (палочки) для максимального количества посещений будет равна высоте всего изображения. Исходя из количества посещений за определенный месяц мы получаем искомую высоту

Нам остается только прорисовать каждый прямоугольник, начиная с координат его верхнего левого угла и кончая нижним правым.

Добавим количество посещений за месяц над каждым прямоугольником для улучшения гистограммы.

<?php
    // максимум посещений
    $visitesMax = 1000;
     
    // рисуем палочки
    for ($mois=1; $mois<=12; $mois++) {
        $hauteurImageRectangle = round(($visites[$mois-1]*$hauteurImage)/$visitesMax);
        ImageFilledRectangle ($im, $mois*30-7, $hauteurImage-$hauteurImageRectangle, $mois*30+7, $hauteurImage-10, $bleu);
        ImageString ($im, 0, $mois*30-7, $hauteurImage-$hauteurImageRectangle-10, $visites[$mois-1], $noir);
    }
     
    // вот и все
    ImagePng ($im);  
?>

d) А вот и результат!

Результат, конечно, не назовешь превосходным, но следует учитывать, что нам удалось сделать что-то более или менее презентабельное, написав всего 20 строчек простого кода, что само по себе уже неплохо.

2

Гистограмма посещаемости по 12 месяцам.


IV) Другие полезные функции

Вот еще один набор полезных функций, предназначенных для управления цветовой палитрой, а также для получения различной информации об изображениях.

Синтаксис с ссылкой на документацию

Версия

Описание

$tableau = GetImageSize ($fichier)

Любая

"Это функция использует в качестве параметра имя файла $fichier и возвращает массив, содержащий 4 элемента: (1) $tableau[0] ширина изображения (px), (2) $tableau[1] высота изображения (px), (3) $tableau[2] тип изображения (см. документацию), (4) $tableau[3] возвращает строку, которую можно вставить в тег IMG (width=""1024"" height=""768"")"

ImageColorTransparent ($im, $col)

Любая

Области изображения $im, прорисованные цветом $col становятся прозрачными. Чтобы сохранить прозрачность, используйте формат PNG

ImageCopy ($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_l, $src_h)

Любая

Копируем прямоугольную область изображения $src_im на изображение $dst_im. Область копирования ограничена координатами точки верхнего левого угла($src_x, $src_y), шириной $src_l и высотой $src_h. Скопированная область появляется в изображении-реципиенте в точке с координатами. ($dst_x, $dst_y)

ImageCopyMerge ($dst_im, $src_im, $dst_x, $dst_y, $src_x, $src_y, $src_l, $src_h, $intensite)

Любая

Идентична ImageCopy, в добавок к этому функция осуществляет постепенный переход тонов интенсивностью $intensite, которая принимает значения от 1 до 100.

ImageCopyResampled

2.0.2

Выполняет те же действие, что и ImageCopy, а также производит изменение размеров изображения. Смотрите следующий пример

ImageCopyResized

Любая

Идентична ImageCopyResampled, но результат масштабирования менее четок, зато функция работает быстрее.

$im = ImageCreateFromJpeg ($fichier)

Любая

Возвращает идентификатор ресурса, $im, указывающий на изображение, которое находится в файле формата jpeg $fichier.

$im = ImageCreateFromPng ($fichier)

Любая

Возвращает идентификатор ресурса, $im, указывающий на изображение, которое находится в файле формата png $fichier.

$largeur = ImageSX ($im)

Любая

Возвращает ширину изображения $im

$hauteur = ImageSY ($im)

Любая

Возвращает высоту изображения $im

V) Пример второй: генерация миниатюр (уменьшенных копий изображения)

Этот пример имеет целью создание уменьшенной копии существующего изображения. Возможно, вам придется реализовывать эту функцию при написании фотогалереи на РНР, в которой фотографии представлены в форме миниатюр, а посетитель может щелкнуть на них мышью, чтобы увеличить. В данном примере мы сгенерируем миниатюру, снабженную рамкой и некоторыми пояснениями (размер и имя изображения)

a) Начало

В отличие от первого примера, данный скрипт будет записывать изображение в файл, а не генерировать его на лету. Поэтому необходимость в отправке особого http-заголовка при помощи функции header() отпадает. Таким образом, скрипт становится "классическим" и может генерировать html.

Начнем с создания пустого холста размером 200х150, затем считаем существующее изображение (из файла) при помощи функции ImageCreateFromJpeg. Потом нам также могут понадобится размеры изображения-источника, для этого мы воспользуемся imagesx и imagesy.

miniature.php

<?php
    $fichierSource = "photo3.jpg";
     
    $largeurDestination = 200;
    $hauteurDestination = 150;
    $im = ImageCreateTrueColor ($largeurDestination, $hauteurDestination)  
            or die ("Ошибка при создании изображения");  

    $source = ImageCreateFromJpeg($fichierSource);
     
    $largeurSource = imagesx($source);
    $hauteurSource = imagesy($source);
?>

b) Рамка

Предварительно создав несколько цветов, рисуем рамку. Чтобы упростить задачу, мы будем использовать различные оттенки серого.

Существует простой способ создания подобной рамки, который заключается в прорисовке нескольких разноцветных прямоугольников, вложенных один в другой. Начинаем с самого большого прямоугольника темного цвета (его размер совпадает с размерами изображения). Затем на него накладываем другой меньший по размерам прямоугольник, цвет которого будет более светлым и т.д.

Толщина создаваемой нами рамки - 8 пикселов.

<?php
    $blanc = ImageColorAllocate ($im, 255, 255, 255);
    $gris[0] = ImageColorAllocate ($im, 90, 90, 90);  
    $gris[1] = ImageColorAllocate ($im, 110, 110, 110);         
    $gris[2] = ImageColorAllocate ($im, 130, 130, 130);  
    $gris[3] = ImageColorAllocate ($im, 150, 150, 150);  
    $gris[4] = ImageColorAllocate ($im, 170, 170, 170);  
    $gris[5] = ImageColorAllocate ($im, 190, 190, 190);  
    $gris[6] = ImageColorAllocate ($im, 210, 210, 210);  
    $gris[7] = ImageColorAllocate ($im, 230, 230, 230);  

    for ($i=0; $i<=7; $i++) {
        ImageFilledRectangle ($im, $i, $i, $largeurDestination-$i, $hauteurDestination-$i, $gris[$i]);     
    }
?>

c) Создание миниатюры

Для создания миниатюры используется функция ImageCopyResampled. Она копирует одно изображения на другое, при этом может изменять размер копируемой области. Данная функция принимает несколько параметров, значение которых очевидно. Перечислим их по порядку:

  • ($im) Изображение-реципиент
  • ($source) Изображение-источник
  • Координата х области изображения-реципиента, на которую накладывается изображение-копия.
  • Координата y
  • Координата х копируемой области изображения-источника (0 если мы хотим скопировать все изображение)
  • Координата (y)
  • Ширина копии , которая вставляется на изображение-источник ($largeurDestination-(2*8) ширина изображения-реципиента минус ширина рамки справа и слева).
  • Высота копии (проделываем те же операции, что и с шириной)
  • Ширина копируемой области изображения-источника
  • Высота копируемой области изображения-источника.

Создав миниатюру, добавим небольшой текст с информацией на нее.

Внимание

Функция ImageCopyResampled - создает большую нагрузку на сервер, не злоупотребляйте ей!

<?php
    ImageCopyResampled($im, $source, 8, 8, 0, 0, $largeurDestination-(2*8), $hauteurDestination-(2*8), $largeurSource, $hauteurSource);
    ImageString($im, 0, 12, $hauteurDestination-18, "$fichierSource - ($largeurSource x $hauteurSource)", $blanc);
?>

d) Сохранение результата.

Нам остается только сохранить полученный результат в файле, имя которого начинается с mini_. Это мы сделаем при помощи функции ImageJpeg.
Когда эта функция имеет только один параметр, изображение выводится в браузер пользователя. Однако если в качестве второго параметра передается имя файла, никакого вывода в браузер не произойдет, а картинка будет сохранена в указанном файле. То же правило действует для функции ImagePng

<?php
$miniature = "mini_$fichierSource";
    ImageJpeg ($im, $miniature);  
    echo "Миниатюра успешно создана: $miniature";
?>

Вот результат "mini_photo3.jpg":

3

mini_photo3.jpg


VI) FAQ и заключение

Библиотека GD предоставляет широкие возможности для работы с изображениями, но они порой слишком загружают сервер (это справедливо для большинства хостингов)

Вот небольшой набор вопросов и ответов по часто встречающимся проблемам

Мое изображение не выводится, браузер ведет себя так, как будто изображение не существует.
Скорее всего ошибку следует искать в вашем скрипте. Сделайте комментарий из строки header("Content-type: image/png") (или header("Content-type: image/jpeg" )), а также из строки ImagePng($im) (илиImageJpeg($im) ), чтобы получить сообщение об ошибке

Скрипт долго выполняется на моем хостинге, это нормально?
Если вы используйте "тяжеловесные" функции как ImageCopyResampled, это неудивительно. У интерпретатора PHP, установленного на хостинге, и без этого работы хватает…

Цвета моего изображения искажены (или оно выводится как черно-белое), почему?
Скорее всего вы использовали функцию ImageCreate, которая ограничивает цветовую палитру 256 цветами. Чтобы преодолеть это ограничение используйте функцию ImageCreateTrueColor вместо ImageCreate.

Заканчивая данную статью, покажем результат, который можно получить, скомбинировав два примера этой статьи. Тут к гистограмме мы добавили полутона, используя тот же метод, что и в примере 2.

4

Результат в виде гистограммы на фоне изображения.


Страница сайта http://test.interface.ru
Оригинал находится по адресу http://test.interface.ru/home.asp?artId=29346