PHP Conference Japan 2024

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
- ascender是字体高于基线的部分。它与字符无关——ascender值对于字体中的每个字符都是相同的。

descender
- descender是字体低于基线的部分。它表示为负数。ascender和descender的绝对值之和得到……

textHeight
- 这是字体可用的总高度。对于字体中的每个字符,无论其大小写或字符似乎占据的空间大小如何,它都是相同的。这可以用于确定输出段落等时的行高。

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

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

boundingBox
- 这将返回一个关联数组,描述包含字符的矩形的四个点(x1,y1,x2,y2)。这些值相对于原点(即您在图像中绘制字符的坐标)。返回的矩形非常准确,并且完全包含打印字符的所有部分——但boundingBox仅适用于单个字符。它不会为多个字符提供准确的数字(至少在我的经验中是这样)。绘制方框时,需要将“x”值添加到原点,并从原点减去“y”值。您不能依赖于空格字符的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
14 年前
在imagick 3.0.1及以下版本中,queryfontmetrics将基于72x72的图像分辨率输出大小数据。(参见bug: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
13 年前
此脚本将在图像中间打印水印。水印的宽度将取决于图像的宽度。

<?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