2008-10-13 12 views
10

Estoy usando la función PHP imagettftext() para convertir texto en una imagen GIF. El texto que estoy convirtiendo tiene caracteres Unicode, incluido el japonés. Todo funciona bien en mi máquina local (Ubuntu 7.10), pero en mi servidor de host web, los caracteres japoneses están destrozados. ¿Qué podría estar causando la diferencia? Todo debe estar codificado como UTF-8.Función PHP imagettftext() y unicode

Imagen quebrada en el servidor de hosting: http://www.ibeni.net/flashcards/imagetest.php

Copia de la imagen correcta de mi máquina local: http://www.ibeni.net/flashcards/imagetest.php.gif

Copia de phpinfo() de mi máquina local: http://www.ibeni.net/flashcards/phpinfo.php.html

Copia del phpinfo() desde mi servidor de host web: http://example5.nfshost.com/phpinfo

Código:

mb_language('uni'); 
mb_internal_encoding('UTF-8'); 

header('Content-type: image/gif'); 

$text = '日本語'; 
$font = './Cyberbit.ttf'; 

// Create the image 
$im = imagecreatetruecolor(160, 160); 
$white = imagecolorallocate($im, 255, 255, 255); 
$black = imagecolorallocate($im, 0, 0, 0); 

// Create some colors 
imagefilledrectangle($im, 0, 0, 159, 159, $white); 

// Add the text 
imagettftext($im, 12, 0, 20, 20, $black, $font, $text); 
imagegif($im); 
imagedestroy($im); 

Respuesta

13

Aquí está la solución que finalmente funcionó para mí:

$text = "你好"; 
// Convert UTF-8 string to HTML entities 
$text = mb_convert_encoding($text, 'HTML-ENTITIES',"UTF-8"); 
// Convert HTML entities into ISO-8859-1 
$text = html_entity_decode($text,ENT_NOQUOTES, "ISO-8859-1"); 
// Convert characters > 127 into their hexidecimal equivalents 
$out = ""; 
for($i = 0; $i < strlen($text); $i++) { 
    $letter = $text[$i]; 
    $num = ord($letter); 
    if($num>127) { 
     $out .= "&#$num;"; 
    } else { 
     $out .= $letter; 
    } 
} 

convertir la cadena a HTML entidades que funciona excepto que la función imagettftext() no acepta las entidades nombradas. Por ejemplo,

&#26085;&#26412;&#35486; 

está bien, pero

&ccedil; 

no lo es. Convirtiendo nuevamente a ISO-8859-1, convierte las entidades nombradas a caracteres, pero hay un segundo problema. imagettftext() no admite caracteres con un valor mayor que> 127. El for-loop final codifica estos caracteres en hexadecimal. Esta solución me funciona con el texto que estoy usando (incluye caracteres latinos en japonés, chino y acentuado en portugués), pero no estoy 100% seguro de que funcione en todos los casos.

Todos estos gimnasia son necesarios porque imagettftext() realmente no acepta cadenas UTF-8 en mi servidor.

+1

¿Por qué UTF-8> entidades HTML> conversión ISO-8859 en lugar de simplemente UTF-8> ISO-8859? – deceze

+0

+1 Tal como lo mencionó el engaño, probablemente usaría 'iconv ('UTF-8', 'ISO-8859-1', $ text)' en lugar del enfoque de entidad, pero aparte de eso, la conversión a ** hexadecimal representación ** es el camino a seguir! ¡Gracias por la propina! – Levit

+0

confirmado NO funciona con árabe – AbiusX

0

Mi principal sospechoso es la fuente que está utilizando para la representación.

De acuerdo con http://fr3.php.net/imagettftext, las diferentes versiones de la biblioteca de GD utilizadas por php pueden mostrar un comportamiento diferente.

  • GD versión en el equipo local: 2.0 o superior
  • GD versión de su servidor de alojamiento web: incluido (2.0.34 compatibles)

Editar: Otra idea: ¿Puede usted Verifique que $text = '日本語'; esté realmente guardado así en su servidor de producción. Tal vez haya un problema de codificación con tu script.

Siguiente edición: BKB ya propuso eso. Entonces, en caso de que esta sea la causa: fue el primero en responder ;-)

-1

¿Existe ese archivo de fuente en particular en su máquina de producción? Si usa FTP para cargar sus archivos, ¿está usando codificación binaria?

+1

Este es un comentario, no una respuesta a la pregunta, por lo tanto el downvote. – mirabilos

11

He tenido el mismo problema con un script que renderiza texto en una imagen y lo muestra. El problema era que debido a los diferentes navegadores (o la resistencia/paranoia del código, de la forma que quieras pensar), no tenía forma de saber qué codificación se estaba poniendo dentro de la matriz $_GET.

Así es como he resuelto el problema.

$item_text = $_GET['text']; 

# detect if the string was passed in as unicode 
$text_encoding = mb_detect_encoding($item_text, 'UTF-8, ISO-8859-1'); 
# make sure it's in unicode 
if ($text_encoding != 'UTF-8') { 
    $item_text = mb_convert_encoding($item_text, 'UTF-8', $text_encoding); 
} 

# html numerically-escape everything (&#[dec];) 
$item_text = mb_encode_numericentity($item_text, 
    array (0x0, 0xffff, 0, 0xffff), 'UTF-8'); 

Esto resuelve cualquier problema con imagettftext no ser capaz de manejar caracteres por encima de # 127, simplemente cambiando todos los caracteres de varios bytes (incluyendo caracteres Unicode) en su entidad de carácter numérico HTML — "& # 65;" para "A", "& # 66;" para "B", etc. — que admite el manual page.

+2

funcionó para mí también, gracias ... debe aceptar su respuesta – braindamage

+0

Trabajó para yo también. Estaba intentando hacer que el personaje TM se imprima. Sin embargo, solo funcionó en ciertas fuentes, aunque todas las fuentes que probé tenían el carácter en ellas. –

+1

Confirmado que todavía no funciona con árabe. – AbiusX

3

Tuve el mismo problema. Convertir la fuente de otf a ttf ayudó. Puede usar FontForge (disponible en el repositorio estándar) para convertir.

+0

Este comentario me ha ahorrado muchas horas de depuración. Un consejo si no quieres usar FontForge: [http://www.freefontconverter.com/](http://www.freefontconverter.com/) –

0

que enfrentan el mismo problema y me encontré con una solución fácil de la referencia php PHP ImageTttfText frunction:

que copie el archivo de fuentes requerida por ejemplo (arial.ttf) en el mismo directorio con el archivo php:

(c:\wamp\www\mysite\mypage.php) 
(c:\wamp\www\mysite\arial.ttf) 

donde mysite: es el directorio de sitio web

pero trate de cambiar la variable $ fuente a ser

$font = 'arial.ttf';