解决imagettftext()因为–enable-gd-jis-conv导致乱码的另一种方法

虽然 imagettftext() 文档标明只接受UTF-8编码,但如果PHP编译时启用–enable-gd-jis-conv选项的话,那么非ASCII字符(例如汉字、拼音、希腊文和箭头) 会被当成EUC-JP编码 (phpinfo中美其名曰“支持JIS编码的字体”), 从而导致乱码(由于西文字体没有假名或汉字,一般表现为全部是方框)。

Although imagettftext() documentation indicates it only accepts UTF-8 encoding, but if –enable-gd-jis-conv is specified when compiling PHP, then non-ASCII characters (like Chinese, accented characters, Greek and arrows) will be (mis-)treated as EUC-JP encoding (referred to as “JIS-mapped Japanese Font Support” in phpinfo) leading to mojibake (this usually shows up as hollow rectangles, as most fonts for western text lacks glyphs for kanji or kana).

网上大部分对此的解决方法是重新编译PHP,但是这只有自己架设服务器的时候才有用。对于付费空间 (特别是每个月不到1美元的付费空间) 就没辙了。不过imagettftext()也接受另外一种字符表示方法,类似HTML的字符参考。说“类似”是因为GD只接受数字参考,所以内部函数 (如 mb_convert_encoding) 转出来的没用。 以下的函数可以将UTF-8转换成字符参考:

A popular response online is to recompile PHP, but that only works if you’re running your own server. For paid hosting (especially paid hosting that costs less than a dollar a month) this method is kinda stumped. But imagettftext() also accepts another way for representing characters, similar to HTML’s character references. “Similar” because it only accepts numeric references, so named references converted by internal functions (like mb_convert_encoding) is of no use. The function below converts UTF-8 into character references:

//created by Kakurady
//no rights reserved
//no warranties explicit or implicit either
function to_entities($string){
    $len = strlen($string);
    $buf = "";
    for($i = 0; $i < $len; $i++){
        if (ord($string[$i]) <= 127){
            $buf .= $string[$i];
        } else if (ord ($string[$i]) <192){
            //unexpected 2nd, 3rd or 4th byte
            $buf .= "&#xfffd";
        } else if (ord ($string[$i]) <224){
            //first byte of 2-byte seq
            $buf .= sprintf("&#%d;",
                ((ord($string[$i + 0]) & 31) << 6) +
                (ord($string[$i + 1]) & 63)
            );
            $i += 1;
        } else if (ord ($string[$i]) <240){
            //first byte of 3-byte seq
            $buf .= sprintf("&#%d;",
                ((ord($string[$i + 0]) & 15) << 12) +
                ((ord($string[$i + 1]) & 63) << 6) +
                (ord($string[$i + 2]) & 63)
            );
            $i += 2;
        } else {
            //first byte of 4-byte seq
            $buf .= sprintf("&#%d;",
                ((ord($string[$i + 0]) & 7) << 18) +
                ((ord($string[$i + 1]) & 63) << 12) +
                ((ord($string[$i + 2]) & 63) << 6) +
                (ord($string[$i + 3]) & 63)
            );
            $i += 3;
        }
    }
    return $buf;
}

imagettftext($im, 11, 0, 5, 11, $black, $font,  to_entities($text));

应该复习,却鼓捣这东西……

Published by

Kakurady

正太兽冒险者训练中!

Leave a Reply

Your email address will not be published. Required fields are marked *