为什么我的最后一句话被切断了?

时间:2014-11-15 04:40:40

标签: php image text gd text2image

我使用imagettftextimageTTFBbox将字符串转换为字符串图像。

例如,

下面的这个字符串
  

这个星球已经 - 或者更确切地说 - 有一个问题,就是这样:生活在它上面的大多数人几乎一直都不开心。针对这个问题提出了许多解决方案,但其中大多数都主要关注小绿纸的移动,这很奇怪,因为总的来说不是那些不开心的小绿纸。

成为

img

然而,最后一行左右被切断了。

我的设置包括以下内容:一个用于包装文本的包装函数(工作完全正常),以及如下所示的主要img2Text函数:

function imagettfJustifytext($text, $font="../../fonts/Roboto-Light.ttf", $Justify=2, $W=0, $H=0, $X=0, $Y=0, $fsize=12, $color=array(0x0,0x0,0x0), $bgcolor=array(0xFF,0xFF,0xFF)){
    $angle = 0;
    $L_R_C = $Justify; 
    $_bx = imageTTFBbox($fsize,0,$font,$text);

    $W = ($W==0)?abs($_bx[2]-$_bx[0]):$W;
    $H = ($H==0)?abs($_bx[5]-$_bx[3]):$H;

    $im = @imagecreate($W, $H)
    or die("Cannot Initialize new GD image stream");

    $background_color = imagecolorallocate($im, $bgcolor[0], $bgcolor[1], $bgcolor[2]);
    $text_color = imagecolorallocate($im, $color[0], $color[1], $color[2]); 

    if($L_R_C == 0){ //Justify Left
        imagettftext($im, $fsize, $angle, $X, $fsize, $text_color, $font, $text);
    } elseif ($L_R_C == 1) { //Justify Right
        $s = split("[\n]+", $text);
        $__H=0;
        foreach($s as $key=>$val){
            $_b = imageTTFBbox($fsize,0,$font,$val);
            $_W = abs($_b[2]-$_b[0]); 
            $_X = $W-$_W;
            $_H = abs($_b[5]-$_b[3]);  
            $__H += $_H;              
            imagettftext($im, $fsize, $angle, $_X, $__H, $text_color, $font, $val);    
            $__H += 6;
        }
    } elseif ($L_R_C == 2) { //Justify Center
        $s = split("[\n]+", $text);
        $__H=0;
        foreach($s as $key=>$val){
            $_b = imageTTFBbox($fsize,0,$font,$val);
            $_W = abs($_b[2]-$_b[0]); 
            $_X = abs($W/2)-abs($_W/2);
            $_H = abs($_b[5]-$_b[3]);  
            $__H += $_H;              
            imagettftext($im, $fsize, $angle, $_X, $__H, $text_color, $font, $val);    
            $__H += 6;
        }
    }        
    return $im;
  }

我认为问题出在imageTTFBox内置函数或我用它来计算图像的高度。它似乎低估了较长的文本串的高度。相关的代码行是line 6,为方便起见,我在下面转载了这些代码:

$H = ($H==0)?abs($_bx[5]-$_bx[3]):$H;

供参考:

$_bx = imageTTFBbox($fsize,0,$font,$text);

和未经宣传的imageTTFBbox

array imagettfbbox ( float $size , float $angle , string $fontfile , string $text )

此函数计算并返回TrueType文本的边界框(以像素为单位)。

修改

timclutton的回答是有道理的,我已尝试删除$__H += 6;行,但确实有帮助。现在只有最后一点被切断了。 (见下图)

img2

1 个答案:

答案 0 :(得分:2)

图片是在函数开头根据imagettfbbox()返回的尺寸创建的,但是在foreach循环结束时添加了一个'行间距&#39 ;通过$__H += 6;获得+6。这会导致垂直文本大小增加到原始测量的维度之外。

您可以通过删除该行并查看文本现在适合图像来进行测试。

如果要包含额外的行间距,则应在函数的开头为它创建一个变量,然后根据imagettfbbox()返回的维度加上行间距值乘以行数。


我已将您的功能重写为以下内容:

function imagettftextalign($text, $align = 0, $fsize = 12, $color = array(0x0, 0x0, 0x0), $bgcolor = array(0xFF, 0xFF, 0xFF), $font = './font/Roboto-Light.ttf', $angle = 0)
{
    // measure input text.
    $box = imagettfbbox($fsize, $angle, $font, $text);
    $w = abs($box[2] - $box[0]);
    $h = abs($box[5] - $box[3]);

    // create resources.
    $im = imagecreatetruecolor($w, $h);
    $background_color = imagecolorallocate($im, $bgcolor[0], $bgcolor[1], $bgcolor[2]);
    $text_color = imagecolorallocate($im, $color[0], $color[1], $color[2]);

    // set background.
    imagefilledrectangle($im, 0, 0, $w, $h, $background_color);

    // split text by line and get line height.
    $lines = explode("\n", $text);
    $lh = floor($h / count($lines));

    // output lines.
    $y = ($lh * .8); // note: this is a guesstimate at the font baseline!
    foreach ($lines as $line) {
        if ($align > 0) {
            $box = imagettfbbox($fsize, $angle, $font, $line);
            $lw = abs($box[2] - $box[0]); // line width.
            switch ($align) {
                case 1: // centre.
                    $x = ($w / 2) - ($lw / 2);
                    break;
                case 2: // right.
                    $x = $w - $lw;
                    break;
            }
        } else {
            $x = 0;
        }

        imagettftext($im, $fsize, $angle, $x, $y, $text_color, $font, $line);
        $y += $lh; // increment line y position.
    }

    return $im;
}

$txt = "This planet has — or rather had — a problem, which
was this: most of the people living on it were unhappy
for pretty much all of the time. Many solutions were
suggested for this problem, but most of these were
largely concerned with the movement of small green
pieces of paper, which was odd because on the whole
it wasn't the small green pieces of paper that were
unhappy.";

$im = imagettftextalign($txt, 1);

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

这给了我以下输出,这似乎是你的目标:

example of function output