如何用GD库包装写在图像上的文本

时间:2017-05-14 15:14:46

标签: php text gd

如何使用PHP图像生成功能在图像上放置长文本,选择区域,水平对齐,垂直对齐,以及在所选区域中正确包装长文本?

这可以复制并在其他语言中变得有用吗?

1 个答案:

答案 0 :(得分:1)

PHP函数imagettftext(...)可以写文本但不支持包装长文本,因此必须将文本分成单词,并为每个单词调用imagettfbbox(...)来计算单词边界并测试如果这个词应该换行了。

为了能够垂直对齐文本,当您知道文本的总高度时,必须将渲染推迟到最后。

这是代码。

DEMO USAGE

<?php


// Image params

    $imgWidth = 240;
    $imgHeight = 900;


// Text params

    $text='Tanto va la gatta al lardo che ci lascia lo zampino!';
    $drawFrame=array(10,340,$imgWidth-10,$imgHeight-140);
    $fontType = 'ArialBlack.ttf';
    $fontSize = 30;
    $lineHeight=32;
    $wordSpacing=' ';
    $hAlign=0; // -1:left  0:center 1:right
    $vAlign=0; // -1:top  0:middle 1:bottom


// allocate

    $img = imagecreatetruecolor($imgWidth,$imgHeight);
    $background = imagecolorallocate($img, 78,129,154);
    $textColor = imagecolorallocate($img, 255,255,255);

// debug show text area

    $area_color = imagecolorallocate($img, 255,0,0);
    imagerectangle ($img, $drawFrame[0], $drawFrame[1], $drawFrame[2], $drawFrame[3], $area_color);

// write text

    wrapimagettftext($img, $fontSize, $drawFrame, $textColor,$fontType, $text, '100%',' ',$hAlign,$vAlign);

// output image

    header("Content-type: image/png");
    imagepng($img);
    imagecolordeallocate($img, $textColor );
    imagecolordeallocate($img, $background );

?>

主要功能

<?php


function wrapimagettftext($img, $fontSize, $drawFrame, $textColor,$fontType, $text, $lineHeight='',$wordSpacing='',$hAlign=0,$vAlign=0) {

    if($wordSpacing===' ' || $wordSpacing==='') {
        $size = imagettfbbox($fontSize, 0, $fontType, ' ');
        $wordSpacing=abs($size[4]-$size[0]);
    }
    $size = imagettfbbox($fontSize, 0, $fontType, 'Zltfgyjp');
    $baseHeight=abs($size[5]-$size[1]);
    $size = imagettfbbox($fontSize, 0, $fontType, 'Zltf');
    $topHeight=abs($size[5]-$size[1]);

    if($lineHeight==='' || $lineHeight==='') {
        $lineHeight=$baseHeight*110/100;
    } else if(is_string($lineHeight) && $lineHeight{strlen($lineHeight)-1}==='%') {
        $lineHeight=floatVal(substr($lineHeight,0,-1));
        $lineHeight=$baseHeight*$lineHeight/100;
    } else {

    }

    $usableWidth=$drawFrame[2]-$drawFrame[0];
    $usableHeight=$drawFrame[3]-$drawFrame[1];

    $leftX=$drawFrame[0];
    $centerX=$drawFrame[0]+$usableWidth/2;
    $rightX=$drawFrame[0]+$usableWidth;

    $topY=$drawFrame[1];
    $centerY=$drawFrame[1]+$usableHeight/2;
    $bottomY=$drawFrame[1]+$usableHeight;

    $text = explode(" ", $text);

    $line_w=-$wordSpacing;
    $line_h=0;
    $total_w=0;
    $total_h=0;
    $total_lines=0;

    $toWrite=array();
    $pendingLastLine=array();

    for($i=0;$i<count($text);$i++) {
        $size = imagettfbbox($fontSize, 0, $fontType, $text[$i]);

        $width = abs($size[4] - $size[0]);
        $height = abs($size[5] - $size[1]);

        $x = -$size[0]-$width/2;
        $y = $size[1]+$height/2;

        if($line_w+$wordSpacing+$width>$usableWidth) {
            $lastLineW=$line_w;
            $lastLineH=$line_h;

            if($total_w<$lastLineW) $total_w=$lastLineW;
            $total_h+=$lineHeight;

            foreach($pendingLastLine as $aPendingWord) {

                if($hAlign<0) $tx=$leftX+$aPendingWord['tx'];
                else if($hAlign>0) $tx=$rightX-$lastLineW+$aPendingWord['tx'];
                else if($hAlign==0) $tx=$centerX-$lastLineW/2+$aPendingWord['tx'];

                $toWrite[]=array('line'=>$total_lines,'x'=>$tx,'y'=>$total_h,'txt'=>$aPendingWord['txt']);
            }
            $pendingLastLine=array();

            $total_lines++;
            $line_w=$width;
            $line_h=$height;

            $pendingLastLine[]=array('tx'=>0,'w'=>$width,'h'=>$height,'x'=>$x,'y'=>$y,'txt'=>$text[$i]);
        } else {

            $line_w+=$wordSpacing;
            $pendingLastLine[]=array('tx'=>$line_w,'h'=>$width,'w'=>$height,'x'=>$x,'y'=>$y,'txt'=>$text[$i]);
            $line_w+=$width;
            if($line_h<$height) $line_h=$height;
        }
    }

    $lastLineW=$line_w;
    $lastLineH=$line_h;

    if($total_w<$lastLineW) $total_w=$lastLineW;
    $total_h+=$lineHeight;

    foreach($pendingLastLine as $aPendingWord) {

        if($hAlign<0) $tx=$leftX+$aPendingWord['tx'];
        else if($hAlign>0) $tx=$rightX-$lastLineW+$aPendingWord['tx'];
        else if($hAlign==0) $tx=$centerX-$lastLineW/2+$aPendingWord['tx'];

        $toWrite[]=array('line'=>$total_lines,'x'=>$tx,'y'=>$total_h,'txt'=>$aPendingWord['txt']);
    }
    $pendingLastLine=array();
    $total_lines++;

    $total_h+=$lineHeight-$topHeight;

    foreach($toWrite as $aWord) {

        $posx = $aWord['x'];

        if($vAlign<0) $posy=$topY+$aWord['y'];
        else if($vAlign>0) $posy=$bottomY-$total_h+$aWord['y'];
        else if($vAlign==0) $posy=$centerY-$total_h/2+$aWord['y'];

        imagettftext($img, $fontSize, 0, $posx, $posy , $textColor, $fontType, $aWord['txt']);

    }
}
?>