как использовать imagik annotateImage для китайского текста?

Мне нужно аннотировать изображение с помощью китайского текста, и я использую библиотеку Imagick прямо сейчас.

Примером китайского текста является

这 是 中文

Используемый китайский файл шрифтов

Файл изначально называется 华文 黑体 .ttf

его также можно найти в Mac OSX в разделе / ​​Library / Font

Я переименовал его на английский STHeiTi.ttf, чтобы было проще вызвать файл в php-коде.

В частности, функция Imagick::annotateImage

Я также использую ответ из «Как я могу нарисовать завернутый текст с помощью Imagick в PHP?» ,

Причина, по которой я его использую, заключается в том, что для английского текста и приложения для успеха требуется аннотация как английского, так и китайского, хотя и не в одно и то же время.

Проблема в том, что когда я запускаю annotateImage с использованием китайского текста, я получаю аннотацию, которая выглядит как 罍

Включенный код

Solutions Collecting From Web of "как использовать imagik annotateImage для китайского текста?"

Проблема в том, что вы utf8_decode вывод «разделителя строк» ​​( wordWrapAnnotation ), к которому вы используете utf8_decode ввода текста. Это неверно, если вы имеете дело с китайским текстом. utf8_decode может utf8_decode только текст UTF-8, который может быть преобразован в ISO-8859-1 (наиболее распространенное 8-битное расширение ASCII).

Теперь я надеюсь, что вы кодируете текст UTF-8 . Если это не так, вы можете преобразовать его следующим образом:

 $text = mb_convert_encoding($text, 'UTF-8', 'BIG-5'); 

или как это

 $text = mb_convert_encoding($text, 'UTF-8', 'GB18030'); // only PHP >= 5.4.0 

(в вашем коде $text скорее $text1 и $text2 ).

Тогда в вашем коде есть (по крайней мере) две вещи:

  1. передать текст «как есть» (без utf8_decode ) в wordWrapAnnotation ,
  2. измените аргумент setTextEncoding с "utf-8" на "UTF-8" согласно спецификациям

Я надеюсь, что все переменные в вашем коде инициализируются в какой-то пропавшей части. С этими двумя изменениями выше (второй может быть не нужен, но вы никогда не знаете …), и с отсутствующими частями на месте, я не вижу причин, по которым ваш код не должен работать, если ваш файл TTF не сломан или Библиотека Imagick сломана ( imagemagick , на котором основан Imagick , – отличная библиотека, поэтому я считаю эту последнюю возможность весьма маловероятной).

РЕДАКТИРОВАТЬ:

Следуя вашему запросу, я обновляю свой ответ с помощью

а) тот факт, что установка mb_internal_encoding('utf-8') очень важна для решения, как вы говорите в своем ответе , и

б) мое предложение о лучшем разветвителе линии, которое подходит для западных языков и для китайцев, и это, вероятно, хорошая отправная точка для других языков с использованием логограмм Хан (японский иероглиф и корейский ханджа):

 function wordWrapAnnotation(&$image, &$draw, $text, $maxWidth) { $regex = '/( |(?=\p{Han})(?<!\p{Pi})(?<!\p{Ps})|(?=\p{Pi})|(?=\p{Ps}))/u'; $cleanText = trim(preg_replace('/[\s\v]+/', ' ', $text)); $strArr = preg_split($regex, $cleanText, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); $linesArr = array(); $lineHeight = 0; $goodLine = ''; $spacePending = false; foreach ($strArr as $str) { if ($str == ' ') { $spacePending = true; } else { if ($spacePending) { $spacePending = false; $line = $goodLine.' '.$str; } else { $line = $goodLine.$str; } $metrics = $image->queryFontMetrics($draw, $line); if ($metrics['textWidth'] > $maxWidth) { if ($goodLine != '') { $linesArr[] = $goodLine; } $goodLine = $str; } else { $goodLine = $line; } if ($metrics['textHeight'] > $lineHeight) { $lineHeight = $metrics['textHeight']; } } } if ($goodLine != '') { $linesArr[] = $goodLine; } return array($linesArr, $lineHeight); } 

В словах: вход сначала очищается, заменяя все пробелы пробелами, включая строки новой строки, одним пробелом, за исключением ведущего и конечного пробелов, который удаляется. Затем он разбивается либо в пространствах, либо непосредственно перед символами Хана, которым не предшествуют «ведущие» символы (например, открывающие круглые скобки или открывающие кавычки) или прямо перед «ведущими» символами. Строки собраны для того, чтобы они не отображались более чем в $maxWidth пикселей по горизонтали, за исключением случаев, когда это невозможно по правилам разделения (в этом случае окончательный рендеринг, вероятно, будет переполняться). Модификация для принудительного расщепления в случаях переполнения не составляет труда. Обратите внимание, что, например, китайская пунктуация не классифицируется как Хан в Юникоде, так что, за исключением «ведущей» пунктуации, до нее не может быть вставлен алгоритм.

Боюсь, вам придется выбирать TTF, который может поддерживать китайские кодовые точки. Для этого есть много источников, вот два:

http://www.wazu.jp/gallery/Fonts_ChineseTraditional.html

http://wildboar.net/multilingual/asian/chinese/language/fonts/unicode/non-microsoft/non-microsoft.html

Полное решение здесь:

https://gist.github.com/2971092/232adc3ebfc4b45f0e6e8bb5934308d9051450a4

Ключевые идеи:

Должен задавать кодировку html и внутреннюю кодировку в форме и на странице обработки

 header('Content-Type: text/html; charset=utf-8'); mb_internal_encoding('utf-8'); 

Эти строки должны быть в верхних строках php-файлов.

Используйте эту функцию, чтобы определить, является ли текст китайским и использовать правильный файл шрифта

 function isThisChineseText($text) { return preg_match("/\p{Han}+/u", $text); } 

Для получения дополнительной информации посетите https://stackoverflow.com/a/11219301/80353

Правильно установите TextEncoding в объекте ImagickDraw

 $draw = new ImagickDraw(); // set utf 8 format $draw->setTextEncoding('UTF-8'); 

Обратите внимание на обобщенную UTF. Это было полезно мне упомянуто Уолтером Троссом в его ответе здесь: https://stackoverflow.com/a/11207521/80353

Используйте preg_match_all, чтобы взорвать английские слова, китайские слова и пробелы

 // separate the text by chinese characters or words or spaces preg_match_all('/([\w]+)|(.)/u', $text, $matches); $words = $matches[0]; 

Вдохновленный этим ответом https://stackoverflow.com/a/4113903/80353

Работает так же хорошо для английского текста