PHP 函数 imagettftext() 和 unicode

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/198007/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 21:54:53  来源:igfitidea点击:

PHP function imagettftext() and unicode

phpunicodegd

提问by gerdemb

I'm using the PHP function imagettftext() to convert text into a GIF image. The text I am converting has Unicode characters including Japanese. Everything works fine on my local machine (Ubuntu 7.10), but on my webhost server, the Japanese characters are mangled. What could be causing the difference? Everything should be encoded as UTF-8.

我正在使用 PHP 函数 imagettftext() 将文本转换为 GIF 图像。我正在转换的文本包含 Unicode 字符,包括日语。在我的本地机器(Ubuntu 7.10)上一切正常,但在我的网络主机服务器上,日语字符被破坏了。什么可能导致差异?一切都应编码为 UTF-8。

Broken Image on webhost server: http://www.ibeni.net/flashcards/imagetest.php

虚拟主机服务器上的损坏图像:http: //www.ibeni.net/flashcards/imagetest.php

Copy of correct image from my local machine: http://www.ibeni.net/flashcards/imagetest.php.gif

从我的本地机器复制正确的图像:http: //www.ibeni.net/flashcards/imagetest.php.gif

Copy of phpinfo() from my local machine: http://www.ibeni.net/flashcards/phpinfo.php.html

从我的本地机器复制 phpinfo():http: //www.ibeni.net/flashcards/phpinfo.php.html

Copy of phpinfo() from my webhost server: http://example5.nfshost.com/phpinfo

从我的虚拟主机服务器复制 phpinfo():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); 

回答by gerdemb

Here's the solution that finally worked for me:

这是最终对我有用的解决方案:

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

Converting the string to HTML entities works except that the function imagettftext() doesn't accept named entities. For example,

将字符串转换为 HTML 实体是可行的,只是函数 imagettftext() 不接受命名实体。例如,

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

is OK, but

可以,但是

&ccedil;

is not. Converting back to ISO-8859-1, converts the named entities back to characters, but there is a second problem. imagettftext() doesn't support characters with a value greater than >127. The final for-loop encodes these characters in hexadecimal. This solution is working for me with the text that I am using (includes Japanese, Chinese and accented latin characters for Portuguese), but I'm not 100% sure it will work in all cases.

不是。转换回 ISO-8859-1,将命名实体转换回字符,但还有第二个问题。imagettftext() 不支持值大于 >127 的字符。最后的 for 循环以十六进制对这些字符进行编码。此解决方案适用于我正在使用的文本(包括日语、中文和葡萄牙语的重音拉丁字符),但我不能 100% 确定它适用于所有情况。

All of these gymnastics are needed because imagettftext() doesn't really accept UTF-8 strings on my server.

所有这些体操都是必需的,因为 imagettftext() 在我的服务器上并不真正接受 UTF-8 字符串。

回答by amphetamachine

I have been having the same problem with a script that will render text in an image and output it. Problem was, that due to different browsers (or code hardiness/paranoia, whichever way you want to think of it), I had no way of knowing what encoding was being put inside the $_GETarray.

我在使用将在图像中呈现文本并输出它的脚本时遇到了同样的问题。问题是,由于不同的浏览器(或代码顽固性/偏执狂,无论您想怎么想),我无法知道$_GET数组中放入了什么编码。

Here is how I solved the problem.

这是我解决问题的方法。

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

This solves any problem with imagettftextnot being able to handle characters above #127 by simply changing ALL the characters (including multibyte Unicode characters) into their HTML numeric character entity—"&#65;" for "A", "&#66;" for "B", etc.—which the manual pageclaims support for.

这解决了imagettftext无法通过简单地将所有字符(包括多字节 Unicode 字符)更改为其 HTML 数字字符实体“A”来处理 #127 以上字符的任何问题 对于 "A", "B" 对于“B”等——手册页声称支持。

回答by obi

I had the same problem. Converting font from otf to ttf helped. You can use FontForge (available in standard repository) to convert.

我有同样的问题。将字体从 otf 转换为 ttf 有帮助。您可以使用 FontForge(在标准存储库中可用)进行转换。

回答by Treb

My prime suspect is the font you are using for rendering.

我的主要怀疑是您用于渲染的字体。

According to http://fr3.php.net/imagettftext, different versions of the GD library used by php can show different behaviour.

根据http://fr3.php.net/imagettftext,php 使用的 GD 库的不同版本可以显示不同的行为。

  • GD Version on your local machine: 2.0 or higher
  • GD Version on your webhost server: bundled (2.0.34 compatible)
  • 本地机器上的GD版本:2.0或更高
  • 您的虚拟主机服务器上的 GD 版本:捆绑(2.0.34 兼容)

Edit:Another idea: can you verify that $text = '日本語';is really saved like this on your production server? Maybe there is an encoding problem with your script.

编辑:另一个想法:你能验证它$text = '日本語';真的像这样保存在你的生产服务器上吗?也许您的脚本存在编码问题。

Next edit:BKB already proposed that. So in case this is the cause: he was first with the answer ;-)

下一次编辑:BKB 已经提出了这一点。因此,万一这是原因:他是第一个给出答案的人;-)

回答by Jordan S. Jones

Does that particular font file exist on your production machine? If using FTP to upload your files, are you using binary encoding?

您的生产机器上是否存在该特定字体文件?如果使用 FTP 上传文件,您是否使用二进制编码?