【问题标题】:Why are my last words being cut off?为什么我的遗言被打断了?
【发布时间】:2014-11-15 04:40:39
【问题描述】:

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

比如下面这个字符串

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

变成

但是,最后一行左右被截断了。

我的设置包括以下内容:用于包装文本的包装器函数(工作正常),以及如下所示的主要 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; 行,它确实有帮助。现在只有最后一点被切断了。 (见下图)

【问题讨论】:

    标签: php image text gd text2image


    【解决方案1】:

    图像是在函数开始时根据imagettfbbox() 返回的尺寸创建的,但在foreach 循环结束时,您通过$__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);
    

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

    【讨论】:

    • @Huey 对此有何反馈?
    • 抱歉耽搁了。我已经尝试过了,它有帮助! (耶!看我的编辑)
    猜你喜欢
    • 2011-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-09
    • 2021-04-18
    • 1970-01-01
    • 2020-05-21
    • 1970-01-01
    相关资源
    最近更新 更多