Imagick::queryFontMetrics()
(PECL imagick 2.0.0)
Returns an array representing the font metrics
说明
Imagick::queryFontMetrics(ImagickDraw$properties,string $text[,bool $multiline]): array
Returns a multi-dimensional array representing the font metrics.
参数
- $properties
ImagickDraw object containing font properties
- $text
The text
- $multiline
Multiline parameter. If left empty it is autodetected
返回值
Returns a multi-dimensional array representing the font metrics.
错误/异常
错误时抛出 ImagickException。
范例
Example #1 Using Imagick::queryFontMetrics():
Query the metrics for the text and dump the results on the screen.
<?php /* Create a new Imagick object */ $im = new Imagick(); /* Create an ImagickDraw object */ $draw = new ImagickDraw(); /* Set the font */ $draw->setFont('/path/to/font.ttf'); /* Dump the font metrics, autodetect multiline */ var_dump($im->queryFontMetrics($draw, "Hello World!")); ?>
Having spent quite a bit of time looking at these values for various fonts, this is my understanding of the values given by the fontMetrics function. I am using php 5.3 and ImageMagick 6.5.4-7 on Centos 6.5. characterWidth and characterHeight - These seem to be related to the size you have specified for the font and don't seem to differ from font to font (at the same size). As such, they are not especially useful (to me, at least). They are not a reliable indicator of how much space the font will use. ascender - The ascender is the part of the font that is above the baseline. It is not character related - the ascender value is the same for every character in the font. descender - The descender is the part of the font that is below the baseline. It is represented as a negative figure. Adding the absolute values of the ascender and the descender gives you the... textHeight - This is the total height available to the font. It is the same for every character in the font irrespective of its case or how much space the character seems to occupy. This can be used to determined the line height when outputting paragraphs, etc. textWidth - This value varies from character to character and is the width of the character. This is useful if the boundingBox does not provide usable values (see boundingBox below). When positioning characters one by one - don't use textWidth, use originX (see below). maxHorizontalAdvance - I'm afraid I haven't quite figured out the purpose of this. It is the same for every character in the font. For the font Arial Italic at size 67, the value is 89 which is much wider than the advance reported for the M or the W at the same size. boundingBox - This returns an associative array describing the four points (x1, y1, x2, y2) of a rectangle that contain the character. These values are relative to the origin (i.e. the coordinates of where you are drawing the character within an image). The returned rectangle is very accurate and encloses all parts of the printed character completely - but the boundingBox only works on single characters. It will not give accurate figures for multiple characters (in my experience anyway). When drawing a box you need to ADD "x" values to the origin and SUBTRACT "y" values from the origin. You cannot rely on the boundingBox for the SPACE character. It returns a boundingBox of (0,0,0,0). textWidth (see above) comes in handy here. originX and originY - these are inaccurately titled. The values returned in originX and originY are actually advanceX and advanceY. These values give you the position of the next character relative to the current one. I hope this is useful.
Example output from queryFontMetrics: Array ( [characterWidth] => 9 [characterHeight] => 9 [ascender] => 9 [descender] => -2 [textWidth] => 71 [textHeight] => 10 [maxHorizontalAdvance] => 12 [boundingBox] => Array ( [x1] => 0 [y1] => -2 [x2] => 6.890625 [y2] => 7 ) [originX] => 70 [originY] => 0 )
The following fields constitute my current PHP 5.2.1/Imagick 6.5.1 queryFontMetrics() return array (once setFontSize() and setFont() have been set): characterWidth: maximum character ("em") width characterHeight: maximum character height ascender: the height of character ascensions (i.e. the straight bit on a 'b') descender: the height of character descensions (i.e. the straight bit on a 'p') textWidth: width of drawn text in pixels textHeight: height of drawn text in pixels maxHorizontalAdvance: maximum pixels from start of one character to start of the next boundingBox: array of x1, y1, x2, y2 bounding borders originX, originY: ? originX seems to shadow the textWidth field, and originY has been zero thus far in my exploration. If you're looking to center text or locate it at an edge, though, use ImagickDraw::setGravity(int $gravity), where $gravity is one of the following constants: 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 Using setGravity() is far less finicky for the simpler tasks.
Up to and including imagick 3.0.1, queryfontmetrics would output size data based on an image resolution of 72x72. (see bug: http://pecl.php.net/bugs/bug.php?id=19907) Should you have set a resolution other than this and be using 3.0.1 or below, you need to scale measurements up by a factor of YOUR_RESOLUTION / 72 e.g. assuming you've set a resolution of 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); ?> In 3.0.2 and above, the solution is to set the resolution on the draw object to that of the image resolution <?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); ?>
The values do not match the array descriptors at all. If you have to know exactly how much space is being taken up by an annotation, use the following: <?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); //these are the values which accurately described the extent of the text and where it is to be drawn: $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 (); ?> The file test.png should now contain pretty much the complete text with no borders. This may not work for very unusual fonts, but will work OK for Times New Roman and Arial.
This script will print a watermark on the middle of an image. The width of the watermark will depend on the width of the image. <?php // Create a new Imagick object $objImage = new Imagick( 'path/to/image.jpg' ); // Get the width and height of the image $imgSize = $objImage->getImageGeometry(); $imgWidth = $imgSize['width']; $imgHeight = $imgSize['height']; // Create a new text object $objText = new ImagickDraw(); // Set te text color $objText->setFillColor( new ImagickPixel('grey') ); // Set the text transparency: 0 = transparent, 1 = opaque $objText->setFillAlpha( 0.2 ); // Top left will be point of reference $objText->setGravity( Imagick::GRAVITY_NORTHWEST ); // Create an array for the textwidth and textheight $textProperties = array( 'textWidth' => 0 ); // Set the desired width of the watermark to 90% of the image width $textDesiredWidth = intval( $imgWidth * 0.9 ); // Set an initial value for the fontsize, will be increased in the loop below $fontSize = 0; // We use the domain name of the server for the watermark text $text = $_SERVER['SERVER_NAME']; // Increase the fontsize until we have reached our desired width while ( $textProperties['textWidth'] <= $textDesiredWidth ) { $objText->setFontSize( $fontSize ); $textProperties = $objImage->queryFontMetrics( $objText, $text ); $fontSize++; } // Calculate the horizontal starting position $watermarkPosX = intval( ($imgWidth - $textProperties['textWidth']) / 2 ); // Calculate the vertical starting position $watermarkPosY = floor( ($imgHeight - $textProperties['textHeight']) / 2 ); // Composite the text on the image $objImage->annotateImage( $objText, $watermarkPosX, $watermarkPosY, 0, $text ); // The browser must know this is JPEG image or else it will display garbled text header( 'Content-Type: image/jpeg' ); // Display the image echo $objImage; ?>
You can also use $imagickDraw() >setTextAlignmnent(Imagick::ALIGN_CENTER) and $imagickDraw->annotation(..) instead.
You can use this to center a text within a box <?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 is now the starting location you need to use to feed to your annotateImage() function.