Генерация картинок из текста на php (text2image)

Опубликовано автор 0 comment

text2image: чего не хватает в стандартной imageTtfText?

Всё выросло из банальной задачи: показ на сайте большого количества надписей, набранных нестандартными шрифтами. Для решения этой задачи существуют множества различных подходов, например, популярны CSS и Flash решения. После некоторого перебора, мной был выбран подход text2image. На php в библиотеке GD уже есть отличное решение: imagefttext. Но у него есть один критичный для меня недостаток: нельзя задать выравнивание для многострочного текста. Поэтому функция imagefttext была расширена. И стало возможным получать такие картинки:

Пример картинки полученной при помощи text2image

Реализация своего text2image

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// 8 первых параметров совпадают с параметрами функции imagettftext
function myimagettftext(&$image, $size, $angle, $left, $top, $color, $font, $text, $align, $width, $height) {
    // Текст разбивается на строки
    $text_lines = explode("\n", $text);
    // С левым выравниванием и однострочными текстами отлично справляется imagettftext
    if ($align == ALIGN_LEFT || count($text_lines) <= 1) {
        imagettftext($image, $size, $angle, $left, $top, $color, $font, $text);
    } else {
        $lines = array();
        $line_widths = array();
        $line_heights = array();
        $line_ys = array();
        $sum_height = 0;
        // Для каждой строки считаем её размеры
        foreach ($text_lines as $index => $block) {
            $dimensions = imagettfbbox($size, $angle, $font, $block);
            // Ширина строки
            $line_width = abs($dimensions[0]) + abs($dimensions[2]);
            // Высота строки
            $line_height = abs($dimensions[5]) + abs($dimensions[1]);
            // отступ по вертикали
            $line_y = abs($dimensions[5]);
            $lines[$index] = $block;
            $line_widths[$index] = $line_width;
            $line_heights[$index] = $line_height;
            $line_ys[$index] = $line_y;
            $sum_height += $line_height;
        }
        // Рассчитываем максимальную ширину строки
        $max_width = max($line_widths);
        $max_width = $max_width + floor(($width - $max_width) / 2);
        // Рассчитываем расстояние между строками
        $delta_h = floor(($height - $sum_height) / (count($lines) - 1));
        $top_offset = 0;
        $left_offset = 0;
        foreach ($lines as $index => $line) {
            // В зависимости от выравнивания рассчитываем левый отступ
            if ($align == ALIGN_CENTER) {
                $left_offset = ($max_width - $line_widths[$index]) / 2;
            } elseif ($align == ALIGN_RIGHT) {
                $left_offset = ($max_width - $line_widths[$index]);
            }
            // Рисуем каждую строку отдельно
            imagettftext($image, $size, $angle, $left_offset - $left, $line_ys[$index] + $top_offset, $color, $font, $line);
            // Запоминаем отступ сверху для новой строки.
            $top_offset += (isset($line_heights[$index]) ? $line_heights[$index] : 0) + $delta_h;
        }
    }
}

Осталось используя эту функцию генерировать картинки на php. Скрипт на вход будет получать текст, шрифт, размер, выравнивание, а на выходе будет отдавать картинку (В общем text2image).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Вычисляем размер картинки
$bbox = imagettfbbox($inFontSize, 0, $inFontFile, $inText);
$width = abs($bbox[0]) + abs($bbox[2]);
$height = abs($bbox[5]) + abs($bbox[1]);
$x = abs($bbox[0]);
$y = abs($bbox[5]);
// Создаем изображение
header('Content-type: image/png');
$img = imagecreatetruecolor($width, $height);
// Создаем цвет для текста
$text_colour = imagecolorallocate($img, $redColor, $greenColor, $blueColor);
$background = ImageColorAllocateAlpha($img, ($redColor == 255 ? 254 : $redColor + 1), ($greenColor == 255 ? 254 : $greenColor + 1), ($blueColor == 255 ? 254 : $blueColor + 1), 127);
// задаем текст и прозрачный фон для картинки
imagefill($img, 0, 0, $background);
imagecolortransparent($img, $background);
// Используя нашу функцию генерим картинку
myimagettftext($img, $inFontSize, 0, $x, $y, $text_colour, $inFontFile, $inText, $inAlign, $width, $height);
imageAlphaBlending($img, false);
imageSaveAlpha($img, true);
imagepng($img);
// освобождаем ресурсы
imagecolordeallocate($img, $text_colour);
imagecolordeallocate($img, $background);
imagedestroy($img);

З.Ы.

Исходники примера лежат на ГитХабе. Очень жду комментариев. Для примера использовал шрифт BillMoney от Джефа Шрайбера.

VKLiveJournalПоделиться!
Разделы: Велосипеды | Tags: ,