2008-10-13 10 views
10

J'utilise la fonction PHP imagettftext() pour convertir le texte en une image GIF. Le texte que je convertis contient des caractères Unicode, y compris le japonais. Tout fonctionne correctement sur ma machine locale (Ubuntu 7.10), mais sur mon serveur webhost, les caractères japonais sont mutilés. Qu'est-ce qui pourrait causer la différence? Tout devrait être encodé en UTF-8.fonction PHP imagettftext() et unicode

Broken Image sur le serveur webhost: http://www.ibeni.net/flashcards/imagetest.php

Copie image correcte de ma machine locale: http://www.ibeni.net/flashcards/imagetest.php.gif

Copie phpinfo() de ma machine locale: http://www.ibeni.net/flashcards/phpinfo.php.html

Copie phpinfo() de mon serveur webhost: http://example5.nfshost.com/phpinfo

Code:

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

Répondre

13

est ici la solution qui a finalement fonctionné pour moi:

$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; 
    } 
} 

Conversion de la chaîne à des entités HTML fonctionne, sauf que le imagettftext() fonction n'accepte pas les entités nommées. Par exemple,

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

est OK, mais

&ccedil; 

est pas. La conversion à ISO-8859-1 convertit les entités nommées en caractères, mais il y a un deuxième problème. imagettftext() ne prend pas en charge les caractères dont la valeur est supérieure à 127. La dernière boucle for-code ces caractères en hexadécimal. Cette solution fonctionne pour moi avec le texte que j'utilise (inclut des caractères latins japonais, chinois et accentués pour le portugais), mais je ne suis pas sûr à 100% que cela fonctionnera dans tous les cas.

Toutes ces gymnastiques sont nécessaires car imagettftext() n'accepte pas vraiment les chaînes UTF-8 sur mon serveur.

+1

Pourquoi les entités UTF-8> HTML> conversion ISO-8859 au lieu de simplement UTF-8> ISO-8859? – deceze

+0

+1 Tout comme deceze mentionné, j'irais probablement avec 'iconv ('UTF-8', 'ISO-8859-1', $ text)' au lieu de l'approche d'entité, mais autre que la conversion à ** hex la représentation ** est la voie à suivre! Merci pour le conseil! – Levit

+0

confirmé ne fonctionne pas avec l'arabe – AbiusX

0

Mon principal suspect est la police que vous utilisez pour le rendu.

Selon http://fr3.php.net/imagettftext, les différentes versions de la bibliothèque GD utilisée par PHP peut montrer un comportement différent.

  • GD Version sur votre machine locale: 2.0 ou supérieur
  • GD version sur votre serveur hébergeur: fourni (compatible 2.0.34)

Edit: Une autre idée: pouvez-vous Vérifiez que $text = '日本語'; est vraiment enregistré comme ceci sur votre serveur de production? Peut-être qu'il y a un problème d'encodage avec votre script.

Prochaine modification: BKB l'a déjà proposé. Donc, au cas où c'est la cause: il était le premier avec la réponse ;-)

-1

Est-ce que ce fichier de police particulier existe sur votre machine de production? Si vous utilisez FTP pour télécharger vos fichiers, utilisez-vous l'encodage binaire?

+1

Ceci est un commentaire, pas une réponse à la question, d'où le downvote. – mirabilos

11

J'ai eu le même problème avec un script qui va rendre le texte dans une image et le sortir. Le problème était, qu'en raison de différents navigateurs (ou de la robustesse/paranoïa de code, de quelque manière que vous vouliez y penser), je n'avais aucun moyen de savoir quel encodage était mis dans le tableau $_GET.

Voici comment j'ai résolu le problème.

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

Cela résout un problème avec imagettftext ne pas être en mesure de traiter les caractères ci-dessus # 127 en changeant simplement tous les caractères (y compris les caractères Unicode) multi-octets dans leur entité de caractère numérique HTML — « & # 65; » pour "A", "& # 66;" pour "B", etc. — pour lequel les revendications manual page prennent en charge.

+2

travaillé pour moi aussi, merci .. il devrait accepter votre réponse – braindamage

+0

A travaillé pour moi aussi. J'essayais d'imprimer le personnage TM. Seulement travaillé dans certaines polices, cependant, même si toutes les polices que j'ai essayées avaient le caractère en eux. –

+1

Confirmé ne fonctionne toujours pas avec l'arabe. – AbiusX

3

J'ai eu le même problème. Conversion de police de otf à ttf aidé. Vous pouvez utiliser FontForge (disponible dans le référentiel standard) pour convertir.

+0

Ce commentaire m'a juste sauvé de nombreuses heures de débogage. Un conseil si vous ne voulez pas utiliser FontForge: [http://www.freefontconverter.com/](http://www.freefontconverter.com/) –

0

J'ai fait face au même problème et je l'ai trouvé une solution facile à partir de la référence php PHP ImageTttfText frunction:

que vous copiez le fichier de police requis par exemple (arial.ttf) dans le même répertoire avec votre fichier php:

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

monsite: est votre site web répertoire

mais essayez de changer la variable de police $ pour être

$font = 'arial.ttf';