Рисование центрированного текста

Задача
Необходимо нарисовать текст в центре изображения.

Решение
Определите размер изображения и прямоугольника, ограничивающего текст. По этим координатам вычислите соответствующую область для рисования текста.

Для встроенных в GD шрифтов применяется функция pc_ImageString-Center(), приведенная в примере 15.1.

Пример 15.1. pc_ImageStringCenter()
function pc_ImageStringCenter($image, $text, $font) {
// размеры шрифта
$width = array(1 => 5, 6, 7, 8, 9);
$height = array(1 => 6, 8, 13, 15, 15);
// определяем размер изображения
$xi = ImageSX($image);
$yi = ImageSY($image);
// определяем размер текста
$xr = $width[$font] * strlen($text);
$yr = $height[$font];
// вычисляем среднюю точку$x = intval(($xi - $xr) / 2);
$y = intval(($yi - $yr) / 2);
return array($x, $y);
}

Например:
list($x, $y) = pc_ImageStringCenter($image, $text, $font);
ImageString($image, $font, $x, $y, $text, $fore);

Для шрифтов PostScript следует применять функцию pc_ImagePSCenter(), показанную в примере 15.2.

Пример 15.2.


pc_ImagePSCenter()
function pc_ImagePSCenter($image, $text, $font, $size, $space = 0,
$tightness = 0, $angle = 0) {
// определяем размер изображения
$xi = ImageSX($image);
$yi = ImageSY($image);
// определяем размер текста
list($xl, $yl, $xr, $yr) = ImagePSBBox($text, $font, $size,
$space, $tightness, $angle);
// вычисляем среднюю точку
$x = intval(($xi - $xr) / 2);
$y = intval(($yi + $yr) / 2);
return array($x, $y);
}

Например:
list($x, $y) = pc_ImagePSCenter($image, $text, $font, $size);
ImagePSText($image, $text, $font, $size, $fore, $back, $x, $y);

В примере 15.3 показана функция pc_ImageTTFCenter(), предназначенная для шрифтов TrueType.

Пример 15.3. pc_ImageTTFCenter()
function pc_ImageTTFCenter($image, $text, $font, $size) {
// определяем размер изображения
$xi = ImageSX($image);
$yi = ImageSY($image);
// определяем размер текста
$box = ImageTTFBBox($size, $angle, $font, $text);
$xr = abs(max($box[2], $box[4]));
$yr = abs(max($box[5], $box[7]));
// вычисляем среднюю точку
$x = intval(($xi - $xr) / 2);
$y = intval(($yi + $yr) / 2);return array($x, $y);
}

Например:
list($x, $y) = pc_ImageTTFCenter($image, $text, $font, $size);
ImageTTFText($image, $size, $angle, $x, $y, $fore, $font, $text);

Обсуждение
Все три функции из раздела «Решение» возвращают координаты x и y рисунка.


Конечно, для вычисления этих координат применяются различные методы, в зависимости от типа шрифта, размера и настроек.

Для шрифтов PostScript Type 1 передайте функции pc_ImagePSCenter() изображение, размещенное функцией ImageCreate() (или одним из ее аналогов), и набор аргументов, определяющий способ отрисовки текста.

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

Для определения размера области изображения внутри функции применяются функции ImageSX() и ImageSY(), возвращающие ширину и высоту изображения. Затем надо вызвать функцию ImagePSBBox(). Она возвращает четыре целочисленных значения: координаты x и y крайнего левого нижнего положения текста и координаты x и y крайнего правого верхнего положения текста. Поскольку координаты отсчитываются относительно базовой линии текста, то обычно они не равны нулю. Например, буква «g» продолжается ниже границы остальных букв; поэтому в данном случае значение для нижнего левого положения отрицательное. Вооружившись этими шестью значениями, можно вычислить правильное местоположение средней точки.


Поскольку координаты верхнего левого угла области отображения равны (0,0), а функции Image-PSBText() требуется левый нижний угол, то формулы определения переменных $x и $y не совпадают друг с другом. Для $x мы берем разность между размером области отображения и текста. Это дает размер пространства, окружающего текст. Затем мы делим это число пополам, чтобы определить количество пикселов, которые мы должны оставить слева от текста. Для $y мы делаем то же самое, но прибавляем переменные $yi и $yr. Добавляя эти числа, мы можем определить координату
дальней стороны прямоугольника, которая необходима в данном случае из-за обратного порядка отсчета координаты y в библиотеке GD.

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

Чтобы отцентрировать текст, соберем все вместе:function pc_ImagePSCenter($image, $text, $font, $size, $space = 0,
$tightness = 0, $angle = 0) {
// определяем размер изображения
$xi = ImageSX($image);
$yi = ImageSY($image);
// определяем размер текста
list($xl, $yl, $xr, $yr) = ImagePSBBox($text, $font, $size,
$space, $tightness, $angle);
// вычисляем среднюю точку
$x = intval(($xi - $xr) / 2);
$y = intval(($yi + $yr) / 2);
return array($x, $y);
}
$image = ImageCreate(500,500);
$text = 'PHP Cookbook Rules!';
$font = ImagePSLoadFont('/path/to/font.pfb');
$size = 20;
$black = ImageColorAllocate($image, 0, 0, 0);
$white = ImageColorAllocate($image, 255, 255, 255);
list($x, $y) = pc_ImagePSCenter($image, $text, $font, $size);
ImagePSText($image, $text, $font, $size, $white, $black, $x, $y);
ImagePSFreeFont($font);
header('Content-type: image/png');
ImagePng($image);
ImageDestroy($image);

К сожалению, этот пример не работает для встроенных в GD шрифтов TrueType.


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

Встроенные шрифты имеют фиксированную ширину, поэтому можно
без труда определить размер символа и создать функцию, возвращаю-
щую размер текста на основании его длины.Внутри функции pc_ImageStringCenter() мы вычисляем длину строки как целое кратное от ее длины; высота – это просто высота одного символа. Обратите внимание, что функция ImageString() считает ее координату y наивысшей координатой части текста, поэтому при вычислении переменной $y надо изменить знак обратно на минус.

Приведем пример, задействующий все пять шрифтов, в котором выполняется горизонтальное центрирование текста:

$text = 'The quick brown fox jumps over the lazy dog.';
for ($font = 1, $y = 5; $font <= 5; $font++, $y += 20) {
list($x, $y) = pc_ImageStringCenter($image, $text, $font);
ImageString($image, $font, $x, $y, $text, $color);
}

Для шрифтов TrueType необходимо использовать функцию ImageTTFBBox() или более современную функцию ImageFtBBox( ) (функция, в имени которой есть буквы «TTF», предназначена для FreeType версии 1.x; функция с буквами «Ft» применяется для FreeType версии 2.x.).


Она возвращает восемь чисел: координаты (x,y) четырех углов текста, начиная с нижнего левого и далее по кругу, против часовой стрелки. Таким образом, вторые две координаты – для нижнего правого угла области и т. д.

Чтобы создать функцию pc_ImageTTFCenter(), начните с функции pc_ImagePSCenter() и замените строку:

// определяем размер текста
list($xl, $yl, $xr, $yr) = ImagePSBBox($text, $font, $size,
$space, $tightness, $angle);
на следующий фрагмент:
// определяем размер текста
$box = ImageTTFBBox($size, $angle, $font, $text);
$xr = abs(max($box[2], $box[4]));
$yr = abs(max($box[5], $box[7]));

Приведем пример применения функции pc_ImageTTFCenter():

list($x, $y) = pc_ImageTTFCenter($image, $text, $font, $size);ImageTTFText($image, $size, $angle, $x, $y, $white, $black,
'/path/to/font.ttf', $text);

Оцените статью: (0 голосов)
0 5 0

Статьи из раздела PHP на эту тему:
Безопасная работа с изображениями
Построение динамических изображений
Программа: создание гистограмм результатов голосования
Рисование дуг, эллипсов и окружностей
Рисование линий, прямоугольников и многоугольников

Вернуться в раздел: PHP / 15. Графика