2014-11-15 3 views
1

Я использую imagettftext и imageTTFBbox для преобразования строк в образы строк.Почему мои последние слова отрезаны?

Например, эта строка ниже

Эта планета имеет - или, вернее, была - проблема, которая заключалась в следующем: большинство людей, живущих на ней были несчастна почти все время. Для этой проблемы было предложено много решений, но большинство из них в основном касалось движения небольших зеленых кусков бумаги, что было странно, потому что в целом это были не маленькие зеленые кусочки бумаги, которые были недовольны.

становится

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.

EDIT

timclutton «s ответ имеет смысл, и я попытался удалить $__H += 6; линию, и это действительно помогает. Теперь только последний бит обрезается. (См рисунок ниже)

img2

ответ

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); 

Это дает мне следующий вывод, который, кажется, что вы стремитесь:

example of function output

+0

@ Huey Любые отзывы об этом? – timclutton

+0

жаль насчет задержки. Я пробовал, и это помогает! (yay! см. мое редактирование) – Huey

+1

@Huey См. мое редактирование. – timclutton