2016-04-29 36 views
15

Problem polega na tym, że podczas obliczania wymiarów tekstu za pomocą imagettfbbox zwracany jest zbyt mały prostokąt, gdy tekst wejściowy zaczyna się od cyfr. To jest mój kod:imagettfbbox oblicza niepoprawny prostokąt, gdy tekst zaczyna się od numeru

$fontSize = 150; 
$font = "font/courier_new.ttf"; 
$text = $_GET["text"]; 

//Determine font dimensions 
$bbox = imagettfbbox($fontSize, 0, $font, $text); 
$bbox["width"]= abs($bbox[4]-$bbox[0]); 
$bbox["height"]= abs($bbox[5]-$bbox[1]); 

$im = imagecreatetruecolor($bbox["width"], $bbox["height"]); 

echo "<b>Image size:</b>\n"; 
print_r($bbox); 

// This part makes transparent background 
imagesavealpha($im, true); 
$bg = imagecolorallocatealpha($im, 254, 254, 254,127); 
$text_color= imagecolorallocate($im, 0, 0, 0); 
imagealphablending($im, false); 
imagefilledrectangle($im, 0, 0, imagesx($im), imagesy($im), $bg); 
imagealphablending($im, true); 


header("X-Img-Size: ".$bbox["width"]."x".$bbox["height"].""); 

imagettftext($im, $fontSize, 0, 0, $bbox["height"], $text_color, $font, $text); 

// This is output  
header("Content-Type: text/html"); 
ob_start(); 
imagepng($im); 
$image_data = ob_get_contents(); 
ob_end_clean(); 
imagedestroy($im); 

echo "<img src=\"data:image/png;base64,".base64_encode($image_data)."\" />"; 

Online test here

Są to wyniki otrzymam za innego tekstu wejściowego:

image description

image description

image description

Jak mogę to naprawić?

+2

wydaje się, że jest to znany problem; patrz http://php.net/manual/en/function.imagettfbbox.php, esp. 'odpowiedź peterjwest3' z proponowaną poprawką. Pisarz funkcji musiał podjąć pewne skróty ... Wydaje się używać ['FT_BBox'] (http://www.freetype.org/freetype2/docs/reference/ft2-basic_types.html#FT_BBox), z wyjątkiem tego to * oznaczałoby * "nadanie znaku glifowi" poprawnie. – usr2564301

+1

@ TomášZato - czy poszedłeś do http://php.net/manual/en/function.imagettfbbox.php i przeczytałeś sugerowane obejścia, zwł. ten z "mike at mikeleigh dot com" sprzed 8 lat? Jeśli tak, to jest jakiś powód, dla którego jego sugerowane obejście/naprawa nie spowoduje obejścia/naprawienia problemu, który masz? –

+0

@BobJarvis Nie mogę przeklinać, użyłem tam każdego rozwiązania, ale ten kod już stosuje niektóre sugerowane kody - te równania dla szerokości i wysokości pochodzą z tej strony. Wypróbuję dokładnie to obejście, o którym wspomniałeś. –

Odpowiedz

6

Problem został spowodowany przez nieporozumienie. Wartości imagettfbbox również definiują gdzie trzeba zacząć rysować - i często te współrzędne są nawet ujemne. Zawsze zakładałem, że możesz zacząć od współrzędnych [0, 0]. To nie jest prawda, współrzędne rysunku mogą być ujemne.

Ta funkcja, również wspomniana w komentarzach i pochodząca ze składek użytkowników PHP.net, oblicza współrzędne początkowe, a także szerokość i wysokość (które były poprawne w danym kodzie).

// Source: http://php.net/manual/en/function.imagettfbbox.php#75407 
function imagettfbboxextended($size, $angle, $fontfile, $text) { 
    /*this function extends imagettfbbox and includes within the returned array 
    the actual text width and height as well as the x and y coordinates the 
    text should be drawn from to render correctly. This currently only works 
    for an angle of zero and corrects the issue of hanging letters e.g. jpqg*/ 
    $bbox = imagettfbbox($size, $angle, $fontfile, $text); 

    //calculate x baseline 
    if($bbox[0] >= -1) { 
     $bbox['x'] = abs($bbox[0] + 1) * -1; 
    } else { 
     //$bbox['x'] = 0; 
     $bbox['x'] = abs($bbox[0] + 2); 
    } 

    //calculate actual text width 
    $bbox['width'] = abs($bbox[2] - $bbox[0]); 
    if($bbox[0] < -1) { 
     $bbox['width'] = abs($bbox[2]) + abs($bbox[0]) - 1; 
    } 

    //calculate y baseline 
    $bbox['y'] = abs($bbox[5] + 1); 

    //calculate actual text height 
    $bbox['height'] = abs($bbox[7]) - abs($bbox[1]); 
    if($bbox[3] > 0) { 
     $bbox['height'] = abs($bbox[7] - $bbox[1]) - 1; 
    } 

    return $bbox; 
} 

Ale konieczne jest, aby użyć X i Y podane przez tę funkcję podczas rysowania:

imagettftext($im, $fontSize, 0, $bbox["x"], $bbox["y"], $text_color, $font, $text); 
+0

Świetnie, jeśli chodzi o samodzielną odpowiedź, która wydaje się być ekspertem na poziomie problemu. Dzięki! –

+0

@StijndeWitt Nie odkryłbym tego bez komentarzy na moje pytanie. –