PHP-функция imagettftext() и unicode

Я использую функцию PHP imagettftext() для преобразования текста в GIF-образ. Текст, который я конвертирую, имеет символы Юникода, включая японский. Все работает нормально на моей локальной машине (Ubuntu 7.10), но на моем сервере веб-хостинга японские персонажи искалечены. Что может быть причиной разницы? Все должно быть закодировано как UTF-8.

Сломанное изображение на сервере веб-хостинга: http://www.ibeni.net/flashcards/imagetest.php

Копия правильного изображения с моей локальной машины: http://www.ibeni.net/flashcards/imagetest.php.gif

Копия phpinfo() с моей локальной машины: http://www.ibeni.net/flashcards/phpinfo.php.html

Скопировать phpinfo() с моего веб-хостинга: http://example5.nfshost.com/phpinfo

код:

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

Ответ 1

Вот решение, которое, наконец, помогло мне:

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

Преобразование строки в объекты HTML выполняется, за исключением того, что функция imagettftext() не принимает именованные объекты. Например,

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

в порядке, но

&ccedil;

нет. Возвращаясь к ISO-8859-1, преобразует именованные объекты обратно в символы, но есть вторая проблема. imagettftext() не поддерживает символы со значением больше > 127. Финал for-loop кодирует эти символы в шестнадцатеричном формате. Это решение работает для меня с текстом, который я использую (включает в себя японские, китайские и акцентированные латинские символы для португальцев), но я не уверен на 100%, что он будет работать во всех случаях.

Вся эта гимнастика необходима, потому что imagettftext() на самом деле не принимает строки UTF-8 на моем сервере.

Ответ 2

У меня была такая же проблема с script, которая будет отображать текст в изображении и выводить его. Проблема заключалась в том, что из-за разных браузеров (или выносливости кода/паранойи, какой бы способ вы ни думали об этом) я не знал, что кодировка помещается внутри массива $_GET.

Вот как я решил проблему.

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

Это решает любую проблему, когда imagettftext не может обрабатывать символы выше # 127, просто изменяя ВСЕ символы (включая многобайтовые символы Юникода) в их числовой символ символа HTML — "& # 65;" для "A", "& # 66;" для "B" и т.д., на которую ссылается справочная страница.

Ответ 3

У меня была та же проблема. Преобразование шрифта из otf в ttf помогло. Вы можете использовать FontForge (доступный в стандартном репозитории) для преобразования.

Ответ 4

Мой главный подозреваемый - это шрифт, который вы используете для рендеринга.

В соответствии с http://fr3.php.net/imagettftext различные версии библиотеки GD, используемые php, могут показывать различное поведение.

  • Версия GD на вашем локальном компьютере: 2.0 или выше
  • Версия GD на сервере веб-хостинга: в комплекте (совместим с 2.0.34)

Изменить: Другая идея: можете ли вы проверить, что $text = '日本語'; действительно сохраняется на вашем рабочем сервере, как это происходит на вашем рабочем сервере? Возможно, есть проблема с кодировкой с вашим script.

Далее править: BKB уже предложил это. Итак, в случае, если это причина: он сначала ответил: -)

Ответ 5

У меня возникла та же проблема, и я нашел простое решение из справочника php PHP ImageTttfText frunch:

Чтобы скопировать необходимый файл шрифта, например (arial.ttf), в тот же каталог с вашим php файлом:

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

где mysite: это ваш каталог веб-сайта

но попробуйте изменить переменную $font как

$font = 'arial.ttf';

Ответ 6

Этот файл шрифта существует на вашей производственной машине? Если вы используете FTP для загрузки ваших файлов, вы используете двоичное кодирование?