2012-06-19 23 views
7

イメージに中国語のテキストで注釈を付ける必要があり、今はImagickライブラリを使用しています。是がimagick annotateImageの中国語テキストの使い方は?

中文使用中国のフォントファイルがthis

もともと名前のファイル华文黑体

の.ttfある这

中国語テキストの例は

であることも可能Mac OSXの/ Library/Fontにあります

私は英語に名前を変更しました。STHeiTi.ttf th eファイルをphpで作成します。特定のthe Imagick::annotateImage function

私もusing the answer from "How can I draw wrapped text using Imagick in PHP?"ています。

私はそれを使用している理由は英語のテキストでは成功し、アプリケーションは英語と中国語の両方に注釈を付ける必要があるからです。

問題は、私が中国語のテキストを使用してannotateImageを実行したとき、私は罍

コードが含まように見える注釈を得ることであるhere

+1

中国語のテキスト?最初に中国のシンボルのグラフィックを作成し、イメージにマージするのはどうですか? – hakre

+0

どうすればいいのですか? –

+1

さて、それぞれの中国語文字について、それを表示する1つのイメージを作成してください。次に、これらの画像をまとめます。最善の方法ではないかもしれませんが、いくつかの中国語フォントを実際に使用するために問題を解決するかもしれません。 – hakre

答えて

2

完全なソリューション:

https://gist.github.com/2971092/232adc3ebfc4b45f0e6e8bb5934308d9051450a4

キーアイデア:

これら

header('Content-Type: text/html; charset=utf-8'); 
mb_internal_encoding('utf-8'); 

フォーム上のHTML文字セットと内部エンコーディングを設定し、処理ページでなければなりません行はphpファイルの先頭行になければなりません。

をテキストが中国人であるかどうかを判断し、右のフォントファイルを使用するには、この機能を使用
function isThisChineseText($text) { 
    return preg_match("/\p{Han}+/u", $text); 
} 

詳細についてのImagickDrawオブジェクト

$draw = new ImagickDraw(); 

// set utf 8 format 
$draw->setTextEncoding('UTF-8'); 
に適切 https://stackoverflow.com/a/11219301/80353

設定TextEncodingをチェックしてください

大文字のU TF。これは親切、ここで彼の答えにWalter Trossによって私に指摘された。この答えに触発され、英語の単語、中国の言葉とスペース

// separate the text by chinese characters or words or spaces 
preg_match_all('/([\w]+)|(.)/u', $text, $matches); 
$words = $matches[0]; 

を爆発するhttps://stackoverflow.com/a/11207521/80353

使用preg_match_allをhttps://stackoverflow.com/a/4113903/80353

作品ばかり英語のテキストも同様

+1

最後の正規表現は、文字列 "UTF-8"を3つの別々の "単語"に分割します。 wordWrapAnnotationの修正は間違っています。これは、2行目の先頭にスペースや句読点を返すことができるためです。私が気づいていない中国語の文章がいくつかあるのでなければ、 'explode( ''、...)'は正しい。私はあなたがそれに含まれている2つのコードの修正を使用して以来、私のソリューションを受け入れることができたとも思います。あなたが情報を追加したのは事実ですが、それはコメントで起こった可能性があります(私の解決策も編集できたかもしれません)。 –

+0

これで、中国語の「奇妙な」文章が出ているのが分かります。一般に、単語間にスペースはありません。 'preg_split(" /((?<=)|(?= \ p {Han})(?= \ pL))/ u "というように、あなたの目的のために"単語 " $ str、-1、PREG_SPLIT_NO_EMPTY) 'は空白の後、またはハン"文字 "(実際には単語)の前に文字列を"切り捨て "ますが、末尾のスペースは別々に扱われます(取り出され、発生する)。注: '?<='の後ろにスペースがあります。 –

+1

上記の正規表現は、特定の文字が行を終了しないようにするために拡張する必要があります(これらの文字は、通常はスペースで始まる西洋の文字と等価です。例:[here] //msdn.microsoft.com/en-us/goglobal/bb688158.aspx)) –

3

私はあなたが中国をサポートすることができますTTFを選択する必要があります怖いですコードポイント。これには多くの情報源は、ここでは、2つがあります:

http://www.wazu.jp/gallery/Fonts_ChineseTraditional.html

http://wildboar.net/multilingual/asian/chinese/language/fonts/unicode/non-microsoft/non-microsoft.html

+0

コードポイントはどういう意味ですか? –

+0

@kimsia http://inamidst.com/stuff/unidata/ –

+0

@kimsia:ウィキペディアの[Unicode](http://en.wikipedia.org/wiki/Unicode#Architecture_and_terminology) –

5

問題は、あなたがImageMagickのあなたがutf8_decode INGであるに「ラインスプリッタ」(wordWrapAnnotation)の出力を供給しているありますテキスト入力。あなたが中国語のテキストを扱っているなら、これは間違いです。 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なし)「であるとして」

  1. がテキストを渡すwordWrapAnnotationには、
  2. 変更"utf-8"からsetTextEncodingの引数に私はあなたのコード内のすべての変数は、それのいくつか欠けている部分に初期化されることを願っていますspecs

あたりとして"UTF-8" 。上記の2つの変更(2つ目は必要ではないかもしれませんが、あなたは決して知らないかもしれません...)、そして欠けている部分があると、あなたのTTFファイルが壊れていないか、 Imagickライブラリが壊れています(imagemagick、その上にImagickがあります。これは素晴らしいライブラリです。

EDIT:あなたの要求に続いて

、私は私の答えを更新

a)は、あなたのanswerに言うようmb_internal_encoding('utf-8')を設定すると、解決のために非常に重要であるという事実、そして

b)より良いラインスプリッタを提案しました。これは西洋言語と中国語の両方に対応しており、おそらく韓漢字(漢字と韓国語の漢字)を使用する他の言語の出発​​点です:

012すなわち
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として分類されないため、「先頭」の句読点を除いて、アルゴリズムによって改行記号を挿入することはできません。ここ

+0

これは、壊れたエンコーディングの最も可能性の高い理由です。 –

+0

こんにちはWalter、あなたの答えは私が最終的な解決に到達するのを助けました。ご協力いただきありがとうございます。 –

+0

私は途中でmb_convert_encodingソリューションを使用しませんでした。 –

関連する問題