PHP GD imagettftext измерения

Я пытаюсь написать скрипт, который генерирует изображение PNG из текста, размера и шрифта, который он получает в аргументах $_GET, но я не могу понять, как сделать так, чтобы размер изображения точно соответствовал тексту. Я уже использую imagettfbox:

$widthPx = abs($ttfBox[2] - $ttfBox[0]);
$heightPx = abs($ttfBox[1] - $ttfBox[7]);

что, вероятно, дает мне правильные измерения, но когда я рисую свой текст, он немного выходит за границы. Например, если я попытаюсь нарисовать букву «а» с помощью arial.ttf, она выйдет за границы как минимум на 5 пикселей. Есть ли способ нарисовать текст любого шрифта, точно соответствующий изображению, без проверки?

$text = $_GET["text"];

$cmToPixel = 15.0;

$sizeCm = floatval($_GET["sizeCm"]);
$sizePx = $cmToPixel * $sizeCm;
$fontFile = "fonts/".pathinfo($_GET["font"])["filename"].".".pathinfo($_GET["font"])["extension"];

if(!file_exists($fontFile)){
    die;
}
$ttfBox = imagettfbbox($sizePx, 0, $fontFile, $text);

$widthPx = abs($ttfBox[2] - $ttfBox[0]);
$heightPx = abs($ttfBox[1] - $ttfBox[7]);

$image = ImageCreate($widthPx, $heightPx);

$x = $ttfBox[0] + (imagesx($image)-$ttfBox[4] )/ 2 - 0;
$y = $ttfBox[1] + (imagesy($image) / 2) - ($ttfBox[5] / 2) - 5;

ImageRectangle($image,0,0,imagesx($image),imagesy($image), ImageColorAllocate($image,255,255,255));
imagettftext($image, $sizePx,0,$x,$y, ImageColorAllocate($image, 0, 0, 0), $fontFile, $text);

header("Content-Type: image/png");
ImagePng($image);
ImageDestroy($image);

person user1563232    schedule 07.02.2015    source источник
comment
Вы видели примеры, прилагаемые к руководству? Они могут помочь: imagettfbbox — создайте ограничивающую рамку текста, используя шрифты TrueType.   -  person Ryan Vincent    schedule 08.02.2015
comment
Я уже посмотрел все примеры, кажется, мне нужно обрезать изображение, проверяя цвета пикселей, потому что вывод текста слишком неточен. Каждый текст имеет разное смещение, когда я его рисую, поэтому он всегда выходит за границы.   -  person user1563232    schedule 08.02.2015
comment
Можно ли опубликовать код, который вы используете, чтобы мы могли поэкспериментировать с ним?   -  person Ryan Vincent    schedule 08.02.2015
comment
Я добавил код, я пробовал разные вещи для координат x и y текста, не совсем имеет значение. Вероятно, лучше попробовать другой подход, например, обрезку изображения по цветам пикселей.   -  person user1563232    schedule 08.02.2015
comment
Проблема в том, что GD не использует «метрики шрифта», которые дают значения и смещения от «базовой линии» символов. Imagack использует эти значения, поэтому они более точны. По сути, в GD вы получаете некоторые факторы «выдумки», которые зависят от «семейства шрифтов». Заставить «imagick» работать с «windows» «менее чем весело», и мне это еще не удалось.   -  person Ryan Vincent    schedule 08.02.2015


Ответы (1)


Ваши расчеты из ограничительной рамки отключены. Это работает:

<?php
/*-
 * $MirOS: www/mk/ttf2png,v 1.8 2016/11/02 16:16:26 tg Exp $
 *-
 * Copyright (c) 2009, 2016
 *  mirabilos <[email protected]>
 *
 * Provided that these terms and disclaimer and all copyright notices
 * are retained or reproduced in an accompanying document, permission
 * is granted to deal in this work without restriction, including un-
 * limited rights to use, publicly perform, distribute, sell, modify,
 * merge, give away, or sublicence.
 *
 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
 * the utmost extent permitted by applicable law, neither express nor
 * implied; without malicious intent or gross negligence. In no event
 * may a licensor, author or contributor be held liable for indirect,
 * direct, other damage, loss, or other issues arising in any way out
 * of dealing in the work, even if advised of the possibility of such
 * damage or existence of a defect, except proven that it results out
 * of said person's immediate fault when using the work as intended.
 *-
 * Syntax:
 *  php ttf2png [text [size [/path/to/font.ttf]]] >out.png
 */

if (!function_exists('gd_info'))
    die("Install php5-gd first.");
$gd = gd_info();
if ($gd["FreeType Support"] == false)
    die("Compile php5-gd with FreeType 2 support.");


$font = "/usr/src/www/files/FNT/GenI102.ttf";
$fontsize = 30;
$text = "EINVAL";

if (isset($argv[1]))
    $text = $argv[1];
if (isset($argv[2]))
    $fontsize = $argv[2];
if (isset($argv[3]))
    $font = $argv[3];


// Get bounding box
$bbox = imageftbbox($fontsize, 0, $font, $text);
// Transform coordinates into width+height and position
$ascender = abs($bbox[7]);
$descender = abs($bbox[1]);
$size_w = abs($bbox[0]) + abs($bbox[2]);
$size_h = $ascender + $descender;
$x = -$bbox[0];
$y = $ascender;

// Create image
$im = imagecreatetruecolor($size_w, $size_h);
// Allocate colours
$bgcol = imagecolorallocate($im, 0x24, 0x24, 0x24);
$fgcol = imagecolorallocate($im, 0xFF, 0xFF, 0xFF);

// Fill image with background colour
imagefilledrectangle($im, 0, 0, $size_w - 1, $size_h - 1, $bgcol);
// Render text into image
imagefttext($im, $fontsize, 0, $x, $y, $fgcol, $font, $text);

// Convert true colour image (needed for above) to palette image
imagetruecolortopalette($im, FALSE, 256);

// Output created image
imagepng($im, NULL, 9);

exit(0);

Если вы пишете несколько строк в одной строке и вам нужно вычислить общую высоту и смещение строки, это максимум всех выносных элементов плюс максимум всех выносных элементов, и $y для всех imagefttext вызывает для этого линия также является максимальной из всех восходящих элементов.

person mirabilos    schedule 02.11.2016
comment
@MarcielFonseca, это PNG, сохраните его в файл или передайте через xloadimage stdin или другое подходящее средство просмотра изображений. Для инструментов Unix характерно выводить результат на стандартный вывод, чтобы его можно было использовать в качестве фильтра через конвейеры. - person mirabilos; 25.03.2017