1

我正在使用imagettftextandimageTTFBbox将字符串转换为字符串的图像。

例如下面这个字符串

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

变成

图像

但是,最后一行左右正在被切断。

我的设置包括以下内容:用于包装文本的包装器函数(工作得很好),以及如下所示的主要 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

4

1 回答 1

2

图像是在函数开始时根据返回的尺寸创建的imagettfbbox(),但是在foreach循环结束时,您通过添加 +6 的“行距” $__H += 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);

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

函数输出示例

于 2014-11-16T09:43:13.303 回答