如何解释与PHP和GD的字体 [英] How to account for font swash with PHP and GD

查看:178
本文介绍了如何解释与PHP和GD的字体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码在图像上打印文本。我还在文本周围添加了一个调试框。但是,我注意到左边的文本位于PHP给出的<!c $ c> imagettfbbox 框的外部。

< a href =https://i.stack.imgur.com/n2WNQ.png =nofollow noreferrer>



这看起来像一个字体的问题。无论如何说明这一点?我可以计算一下这个斜杠的开始和实际位置之间的距离吗?

I不要认为这是字体的问题,因为我试着用几个脚本样式字体,结果是类似的。

 <?php 

$ font ='scriptin.ttf';
$ text ='Ipsum';
$ size = 30;
$ image = imagecreatetruecolor(200,200);
$ fontColour = imagecolorallocate($ image,hexdec('11'),hexdec('11'),hexdec('11'));
$ bgColour = imagecolorallocate($ image,hexdec('CC'),hexdec('CC'),hexdec('CC'));

imagefilledrectangle($ image,0,0,200,200,$ bgColour);

$ dimensions = imagettfbbox($ size,0,$ font,$ text);
imagefilledrectangle(
$ image,
$ dimensions [0] + 40,
$ dimensions [7] + 50,
$ dimensions [2] + 40,
$ dimensions [3] + 50,
imagecolorallocate($ image,mt_rand(1,180),mt_rand(1,180),mt_rand(1,180))
);

imagettftext(
$ image,
$ size,
0,
40,
50,
$ fontColour,
$ font,
$ text
);

header('Content-Type:image / png');
imagepng($ image);

代码和字体可以在这里找到:



我用一些其他的字体和大小运行它,它似乎准确的在1个像素以内。 / p>

I have the following code to print text on an image. I am also adding a debug box around the text. However, I noticed the text on the left lies outside of the box that PHP gives me with imagettfbbox.

This looks like an issue with the font swash. Is there anyway to account for this? Can I figure out the distance between the start of the swash and the actual position imagettfbbox gives to me?

I don't think this is an issue with the font, as I tried it with a few script style fonts and the results were similar.

<?php

$font       = 'scriptin.ttf';
$text       = 'Ipsum';
$size       = 30;
$image      = imagecreatetruecolor(200, 200);
$fontColour = imagecolorallocate($image, hexdec('11'), hexdec('11'), hexdec('11'));
$bgColour   = imagecolorallocate($image, hexdec('CC'), hexdec('CC'), hexdec('CC'));

imagefilledrectangle($image, 0, 0, 200, 200, $bgColour);

$dimensions = imagettfbbox($size, 0, $font, $text);
imagefilledrectangle(
    $image,
    $dimensions[0] + 40,
    $dimensions[7] + 50,
    $dimensions[2] + 40,
    $dimensions[3] + 50,
    imagecolorallocate($image, mt_rand(1, 180), mt_rand(1, 180), mt_rand(1, 180))
);

imagettftext(
    $image,
    $size,
    0,
    40,
    50,
    $fontColour,
    $font,
    $text
);

header('Content-Type: image/png');
imagepng($image);

The code and font is available here: https://github.com/AydinHassan/image-swash-example

If you point a VHOST at the repository, you can just hit swash.php

解决方案

Edit: This appears to be fixed in PHP 7.0.12 (bug #53504) so the code below shouldn't be required.


Based on a comment in the PHP manual I've written the following function to calculate and return the difference between where GD thinks the left side of the bounding box is and where the leftmost pixel is found:

function xadjust($size, $angle, $fontfile, $text)
{
    $bbox = imagettfbbox($size, $angle, $fontfile, $text);

    $width = $bbox[4] - $bbox[6]; // upper right x - upper left x;
    $height = $bbox[1] - $bbox[7]; // lower left y - upper left y;

    // create an image with height and width doubled to fit any 'swash'.
    $im = imagecreatetruecolor($width * 2, $height * 2);

    // set background color to opaque black.
    imagefill($im, 0, 0, 0x00000000);

    // draw the text in opaque white.
    imagettftext(
        $im,
        $size,
        0,
        $width / 2,
        $height,
        0x00ffffff,
        $fontfile,
        $text
    );

    // set the min-width to its possible maximum.
    $min_x = $width * 2;

    for ($x = 0; $x < $width * 2; $x++) {
        // each x-pixel (horizontal)
        for ($y = 0; $y < $height * 2; $y++) {
            // each y-pixel (vertical)
            if (imagecolorat($im, $x, $y) > 0) {
                // non-black pixel found!
                $min_x = min($x, $min_x);
            }
        }
    }

    imagedestroy($im);

    // return the difference between where GD thinks the bounding box is and
    // where we found the leftmost non-black pixel.
    return (($width / 2) - $min_x) - abs($bbox[0]);
}

This can be integrated to your script fairly easily:

$font       = 'scriptin.ttf';
$text       = 'Ipsum';
$size       = 30;
$image      = imagecreatetruecolor(200, 200);
$fontColour = imagecolorallocate($image, hexdec('11'), hexdec('11'), hexdec('11'));
$bgColour   = imagecolorallocate($image, hexdec('CC'), hexdec('CC'), hexdec('CC'));

imagefilledrectangle($image, 0, 0, 200, 200, $bgColour);

$xadjust = xadjust($size, 0, $font, $text); // 1. get the adjust value.

$dimensions = imagettfbbox($size, 0, $font, $text);
imagefilledrectangle(
    $image,
    $dimensions[0] + 40 - $xadjust, // 2. move the left-side of the box to the left.
    $dimensions[7] + 50,
    $dimensions[2] + 40 - $xadjust, // 3. move the right-side of the box to the left.
    $dimensions[3] + 50,
    imagecolorallocate($image, mt_rand(1, 180), mt_rand(1, 180), mt_rand(1, 180))
);

imagettftext(
    $image,
    $size,
    0,
    40,
    50,
    $fontColour,
    $font,
    $text
);

header('Content-Type: image/png');
imagepng($image);

This gives me the following output:

I've run it with a few other fonts and sizes and it seems to be accurate to within 1 pixel.

这篇关于如何解释与PHP和GD的字体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆