Imagick::queryFontMetrics

(PECL imagick 2, PECL imagick 3)

Imagick::queryFontMetrics返回表示字体度量的数组

描述

public Imagick::queryFontMetrics(ImagickDraw $properties, string $text, bool $multiline = ?): array

返回一个多维数组,表示字体度量。

参数

properties

包含字体属性的 ImagickDraw 对象

text

文本

multiline

多行参数。如果为空,则自动检测

返回值

返回一个多维数组,表示字体度量。

错误/异常

在错误时抛出 ImagickException。

示例

示例 #1 使用 Imagick::queryFontMetrics()

查询文本的度量并在屏幕上打印结果。

<?php
/* 创建一个新的 Imagick 对象 */
$im = new Imagick();

/* 创建一个 ImagickDraw 对象 */
$draw = new ImagickDraw();

/* 设置字体 */
$draw->setFont('/path/to/font.ttf');

/* 打印字体度量,自动检测多行 */
var_dump($im->queryFontMetrics($draw, "Hello World!"));
?>

添加说明

用户贡献说明 8 条说明

stevepburgess at gmail dot com
9 年前
在花了一些时间查看各种字体的这些值后,这是我对 fontMetrics 函数给出的值的理解。我使用的是 php 5.3 和 ImageMagick 6.5.4-7 在 Centos 6.5 上。

characterWidth 和 characterHeight
- 这些似乎与您为字体指定的尺寸有关,并且似乎不会因字体而异(在相同尺寸下)。因此,它们不是特别有用(至少对我而言)。它们不是字体将使用多少空间的可靠指标。

ascender
- 升部是字体中高于基线的部分。它与字符无关 - 升部值对于字体中的每个字符都是相同的。

descender
- 降部是字体中低于基线的部分。它表示为一个负数。将升部和降部的绝对值相加,您将得到...

textHeight
- 这是字体可用的总高度。对于字体中的每个字符,无论其大小写或字符看起来占用了多少空间,它都是相同的。这可用于确定输出段落等时的行高。

textWidth
- 此值因字符而异,是字符的宽度。如果 boundingBox 未提供可用值,这将很有用(请参阅下面的 boundingBox)。在逐个定位字符时 - 不要使用 textWidth,请使用 originX(请参阅下面)。

maxHorizontalAdvance
- 恐怕我还没有完全弄清楚它的用途。对于字体中的每个字符,它都是相同的。对于尺寸为 67 的 Arial Italic 字体,该值为 89,这比相同尺寸的 M 或 W 报告的提前量要宽得多。

boundingBox
- 这将返回一个关联数组,描述包含字符的矩形的四个点 (x1, y1, x2, y2)。这些值相对于原点(即您在图像中绘制字符的坐标)。返回的矩形非常准确,并完全包含所有打印的字符部分 - 但 boundingBox 仅适用于单个字符。它不会给出多个字符的准确数字(根据我的经验)。绘制框时,您需要将“x”值添加到原点,并将“y”值从原点中减去。您不能依赖 SPACE 字符的 boundingBox。它返回 (0,0,0,0) 的 boundingBox。textWidth(见上文)在这里很方便。

originX 和 originY
- 这些标题不准确。originX 和 originY 中返回的值实际上是 advanceX 和 advanceY。这些值会告诉您下一个字符相对于当前字符的位置。

希望这对你有所帮助。
jlong at carouselchecks dot com
11 年前
queryFontMetrics 的示例输出

数组
(
[characterWidth] => 9
[characterHeight] => 9
[ascender] => 9
[descender] => -2
[textWidth] => 71
[textHeight] => 10
[maxHorizontalAdvance] => 12
[boundingBox] => 数组
(
[x1] => 0
[y1] => -2
[x2] => 6.890625
[y2] => 7
)

[originX] => 70
[originY] => 0
)
thok nojunk at spammail thok dot ca
13 年前
以下字段构成了我当前的 PHP 5.2.1/Imagick 6.5.1 queryFontMetrics() 返回数组(在设置了 setFontSize() 和 setFont() 之后)

characterWidth: 最大字符(“em”)宽度
characterHeight: 最大字符高度
ascender: 字符升部的高度(即“b”的直线部分)
descender: 字符降部的高度(即“p”的直线部分)
textWidth: 以像素为单位的绘制文本宽度
textHeight: 以像素为单位的绘制文本高度
maxHorizontalAdvance: 从一个字符的开始到下一个字符的开始的最大像素
boundingBox: x1、y1、x2、y2 边界的数组
originX, originY: ?

originX 似乎与 textWidth 字段重叠,而 originY 到目前为止在我的探索中一直为零。

但是,如果您想居中对齐文本或将其定位在边缘,请使用 ImagickDraw::setGravity(int $gravity),其中 $gravity 是以下常量之一

Imagick::GRAVITY_NORTHWEST
Imagick::GRAVITY_NORTH
Imagick::GRAVITY_NORTHEAST
Imagick::GRAVITY_WEST
Imagick::GRAVITY_CENTER
Imagick::GRAVITY_EAST
Imagick::GRAVITY_SOUTHWEST
Imagick::GRAVITY_SOUTH
Imagick::GRAVITY_SOUTHEAST

对于更简单的任务,使用 setGravity() 要灵活得多。
george at sogetthis dot com
13 年前
在 imagick 3.0.1 及之前版本中,queryfontmetrics 将根据 72x72 的图像分辨率输出尺寸数据。(见错误:http://pecl.php.net/bugs/bug.php?id=19907)

如果您设置了除此之外的分辨率,并且正在使用 3.0.1 或更低版本,则需要将测量值按 YOUR_RESOLUTION / 72 的比例放大

例如,假设您设置了 300 的分辨率
<?php
$im
= new Imagick();
$im->setResolution(300,300);

$draw = new ImagickDraw();
$draw->setFont('/path/to/arial.ttf');
$draw->setFontSize(72 * (300 / 72));
$data = $im->queryfontmetrics($draw, 'hello world');
var_dump($data);
?>

在 3.0.2 及更高版本中,解决方案是在绘制对象上设置与图像分辨率相同的分辨率
<?php
$im
= new Imagick();
$im->setResolution(300,300);

$draw = new ImagickDraw();
$draw->setResolution(300,300);
$draw->setFont('/path/to/arial.ttf');
$draw->setFontSize(72);
$draw->setFillColor('#ff0000');
$data = $im->queryFontMetrics($draw, $string);

var_dump($data);
?>
SkepticaLee
10 年前
这些值与数组描述符完全不匹配。如果您需要确切地知道注释占用了多少空间,请使用以下方法

<?php
$text
= "Algbqdj";
$im = new Imagick ();
$draw = new ImagickDraw ();
$draw->setStrokeColor ("none");
$draw->setFont ("Arial");
$draw->setFontSize (96);
$draw->setTextAlignment (Imagick::ALIGN_LEFT);
$metrics = $im->queryFontMetrics ($draw, $text);
// 这些值准确地描述了文本的范围以及应该绘制文本的位置:
$baseline = $metrics['boundingBox']['y2'];
$textwidth = $metrics['textWidth'] + 2 * $metrics['boundingBox']['x1'];
$textheight = $metrics['textHeight'] + $metrics['descender'];
$draw->annotation (0, $baseline, $text);
$im->newImage ($textwidth, $textheight, "white");
$im->drawImage ($draw);
$draw->clear ();
$im->writeImage ("test.png");
$im->clear ();
?>

test.png 文件现在应该包含几乎完整的文本,没有任何边框。这可能不适用于非常不寻常的字体,但对于 Times New Roman 和 Arial 来说效果很好。
abcrdw at gmail dot com
12 年前
此脚本将在图像的中间打印水印。水印的宽度将取决于图像的宽度。

<?php
// 创建一个新的 Imagick 对象
$objImage = new Imagick( 'path/to/image.jpg' );

// 获取图像的宽度和高度
$imgSize = $objImage->getImageGeometry();
$imgWidth = $imgSize['width'];
$imgHeight = $imgSize['height'];

// 创建一个新的文本对象
$objText = new ImagickDraw();

// 设置文本颜色
$objText->setFillColor( new ImagickPixel('grey') );

// 设置文本透明度:0 = 透明,1 = 不透明
$objText->setFillAlpha( 0.2 );

// 左上角将作为参考点
$objText->setGravity( Imagick::GRAVITY_NORTHWEST );

// 为文本宽度和文本高度创建一个数组
$textProperties = array( 'textWidth' => 0 );

// 将水印的所需宽度设置为图像宽度的 90%
$textDesiredWidth = intval( $imgWidth * 0.9 );

// 为字体大小设置初始值,将在下面的循环中增加
$fontSize = 0;

// 我们使用服务器的域名作为水印文本
$text = $_SERVER['SERVER_NAME'];

// 增加字体大小,直到我们达到所需的宽度
while ( $textProperties['textWidth'] <= $textDesiredWidth ) {
$objText->setFontSize( $fontSize );
$textProperties = $objImage->queryFontMetrics( $objText, $text );
$fontSize++;
}

// 计算水平起始位置
$watermarkPosX = intval( ($imgWidth - $textProperties['textWidth']) / 2 );

// 计算垂直起始位置
$watermarkPosY = floor( ($imgHeight - $textProperties['textHeight']) / 2 );

// 将文本合成到图像上
$objImage->annotateImage( $objText, $watermarkPosX, $watermarkPosY, 0, $text );

// 浏览器必须知道这是 JPEG 图像,否则它将显示乱码文本
header( 'Content-Type: image/jpeg' );

// 显示图像
echo $objImage;
?>
Pete &#39;the Pete&#39; de Pijd
15 年前
您也可以使用 $imagickDraw()->setTextAlignmnent(Imagick::ALIGN_CENTER) 和 $imagickDraw->annotation(..) 代替。
waage
16 年前
您可以使用它将文本居中放置在框中

<?php

$data
= "Hello world";

$text = new ImagickDraw();
$text->setFontSize(12);
$text->setFont("Arial");

$boxWidth = 210;

$im = new Imagick();

$fm = $im->queryFontMetrics($text, $data, false);

$textXLoc = ($boxWidth / 2) - ($fm["textWidth"] / 2);

?>

$textXLoc 现在是您需要提供给 annotateImage() 函数的起始位置。
To Top