我需要与中国文字注释的图像,我使用Imagick库现在。
中国的文字的一个例子是
这是中文
用中国的字体文件是这个
The file originally is named 华文黑体.ttf
它也可以在Mac OSX下/库/字体中找到
我已经给它改名为英语STHeiTi.ttf使其更容易调用PHP代码的文件。
特别是在Imagick::annotateImage
功能
我也是利用了答案:“我怎么能画在PHP中使用Imagick行文本?” 。
为什么我使用它是因为它是成功的英文文本和应用程序的原因需要注释英语和中国,虽然不是在同一时间。
问题是,当我使用中国文字运行annotateImage,我得到的注释,看起来像罍
代码中包含了这里
问题是你喂养ImageMagick的“线分离器”的输出( 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"
作为每规格
我希望在你的代码中的所有变量它的某些缺失的部分进行初始化。 通过上面的两个变化(第二个可能不是必要的,但你永远不知道...),并与地方缺少的部分,我不明白为什么你的代码不应该工作,除非你的TTF文件损坏或Imagick
库坏了( imagemagick
,其上Imagick
的基础,是一个伟大的图书馆,所以我认为这是最后的可能性相当不可能的)。
编辑:
按照你的要求,我更新我的答案
A)的事实,设置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,因此,除了“龙头”标点符号,没有断行可以收到由算法插入。
恐怕你将不得不选择能够支持中国的代码点的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。 这是有益向我指出的由沃尔特Tross在他的答案在这里: 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
作品也同样适用于英文文本