我需要用中文文本注释图像,并且现在正在使用Imagick库。

中文文本的一个例子是

这是中文

使用的中文字体文件是this

该文件最初名为华文黑体.ttf

也可以在Mac OSX的/Library/Font下找到它

我将其重命名为英语STHeiTi.ttf,可以更轻松地用php代码调用文件。

特别是the Imagick::annotateImage function

我也是using the answer from "How can I draw wrapped text using Imagick in PHP?"

我之所以使用它,是因为它对英语文本是成功的,并且应用程序需要同时注释英语和中文。

问题是,当我使用中文文本运行annotateImage时,得到的注释看起来像是

包含的代码here

最佳答案

问题是您要给imagemagick输入“line splitter”(wordWrapAnnotation)的输出,并用utf8_decode来输入文本。如果您要处理中文文本,这肯定是错误的。 utf8_decode 只能处理可以转换为ISO-8859-1(ASCII最常见的8位扩展名)的UTF-8文本。

现在,我希望您的文本是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)。

然后(至少)需要在代码中修复两件事:
  • 将文本“按原样”(不带utf8_decode)传递给wordWrapAnnotation
  • setTextEncoding的参数从"utf-8"更改为"UTF-8"按照specs

  • 我希望代码中的所有变量都在缺少的部分中初始化。有了上面的两个更改(第二个更改可能不是必需的,但是您永远都不知道...),并且缺少适当的部分,我看不出您的代码不起作用的任何理由,除非您的TTF文件已损坏或Imagick库已损坏(imagemagick所基于的Imagick是一个不错的库,因此我认为这种可能性不大)。

    编辑:

    根据您的要求,我用

    a)就像您在answer中所说的那样,设置mb_internal_encoding('utf-8')对解决方案非常重要,并且

    b)我提出了一个更好的行分隔符的建议,该分隔符对于西方语言和中文都可以接受,并且对于使用汉字(日语汉字和朝鲜汉字)的其他语言来说,这可能是一个很好的起点:
    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像素,除非分割规则无法做到(在这种情况下,最终的呈现可能会溢出)。为了在溢出情况下强制拆分而进行的修改并不困难。注意,例如,中文标点符号在Unicode中未归类为Han,因此,除“前导”标点符号外,该算法不能在其前面插入换行符。

    关于php - 如何将imagick annotateImage用于中文文本?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11101544/

    10-13 06:36