tags:

views:

2679

answers:

5

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.

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

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

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

Copy of phpinfo() from my webhost server: 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);
A: 

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.

  • GD Version on your local machine: 2.0 or higher
  • GD Version on your webhost server: bundled (2.0.34 compatible)

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.

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

Treb
A: 

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

Jordan S. Jones
+4  A: 

Here's the solution that finally worked for me:

// 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
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,

&#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 and accented latin characters for Portuguese), but I'm not 100% sure it will work in all cases.

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

+2  A: 
amphetamachine
A: 

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

obi