6

PHP GD ライブラリで作成した画像内で Verdana フォントを使用しています。

imagettftext($image, $fontSize, 0, 70, $y, $color, $font, $username );

ほとんどの場合、imagettftext は文字列に対して非常にうまく機能します。
しかし、一部のユーザーは、名前に奇妙な文字/記号を使用しています。
そのため、名前を画像に印刷しようとすると。例えば:
ここに画像の説明を入力

このユーザーはɦɪɲɣƙƨєʌɾ 記号を使用しています。そのため、Verdana では印刷できません。

私はこれを使用しました:

$username=iconv('UTF-8', 'ASCII//TRANSLIT', $username);

出力は次のとおりです。
ここに画像の説明を入力

(現在のロケールは英語とドイツ語で異なります。したがって、現在のロケールではこれらの文字を処理できない可能性があります: ɦɪɲɣƙƨєʌɾ)

非常に大きなブロックを書かずに、に音訳ɦすることはできないようです。このように。hɲnstr_replace()

  • そこで、フォント(Verdana)がこれらの記号を表示できるかどうかを確認できるかどうか疑問に思っています。いずれかの文字を文字列内に表示できない場合は、空の文字列をimagettftextメソッドに渡すことができます。font 内のサポートされている文字を確認できますか? または、Verdana でサポートされている記号を含む文字マップを作成し、文字列にサポートされていない記号が含まれていないかどうかを確認しますか? (この質問
    のせいで無理だと思います)

  • または、別の解決策として、で複数のフォントを使用することは可能imagettftext()ですか?
    たとえば、最初に Verdana を試してください。Verdana がシンボルをカバーしていない場合は、Arial sans serif などを使用します。

  • または他の解決策はありますか?

編集:
Verdana は私のテキストでこれらの Unicode 文字をサポートしていないようです。
Verdana 対応文字: http://www.fileformat.info/info/unicode/font/verdana/grid.htm
Verdana 非対応文字: http://www.fileformat.info/info/unicode/font/verdana/missing.htm

4

4 に答える 4

4

私の最初の選択は、処理できるようにしたい文字のすべての範囲をサポートするフォントに切り替えることです. しかし、単一のフォントがUTF-8 で可能な数百万の文字を実装するとは思わないでください。

さて、(怠惰な;)音訳ルートを取りたい場合は、Kemal Dağからのこの回答を参照します。

私は現在 v5.4 を手元に持っていないので については言えませんTransliteratorが、Kemal Dağ の移植版JTransliterationはかなりうまく機能します:

<?php
    require 'transliteration/JTransliteration.php';

    $input = 'ɦɪɲɣƙƨєʌɾ';
    echo JTransliteration::transliterate($input); // output: hIngk2ie^r

    $input = 'Хეλлఒ Wओრলद';
    echo JTransliteration::transliterate($input);

最後に、特定のフォントが特定の文字をサポートしているかどうかを確認したい場合は、もう少し複雑になります。このライブラリは大いに役立ちます。>= 5.3 が必要です (名前空間の使用):

<?php
    $fontFile = 'arial.ttf';
    $charToCheck = 'ɣ';

    require_once 'php-font-lib-master/src/FontLib/Autoloader.php';

    use FontLib\Font;
    use FontLib\TrueType\Collection;


    $font = Font::load($fontFile);
    if ($font instanceof Collection) {
        $font = $font->getFont(0);
    }
    $subtable = null;
    foreach($font->getData("cmap", "subtables") as $_subtable) {
        if ($_subtable["platformID"] == 3 && $_subtable["platformSpecificID"] == 1) {
            $subtable = $_subtable;
            break;
        }
    }

    if (isset($subtable["glyphIndexArray"][ord_utf8($charToCheck)])) {
        $supported = 'Supported';
    } else {
        $supported = 'Not Supported';
    }

    echo "$charToCheck is $supported by font $fontFile";


    function ord_utf8($c) {
        $b0 = ord($c[0]);
        if ( $b0 < 0x10 ) {
            return $b0;
        }
        $b1 = ord($c[1]);
        if ( $b0 < 0xE0 ) {
            return (($b0 & 0x1F) << 6) + ($b1 & 0x3F);
        }
        return (($b0 & 0x0F) << 12) + (($b1 & 0x3F) << 6) + (ord($c[2]) & 0x3F);
    }

font_info.phpR. Hill のコードを恥知らずに略奪するord_utf8()

PS文字列 "ɦɪɲɣƙƨєʌɾ" は、国際音声記号の文字で構成されています。どのロケールでもこれらの文字がサポートされているかどうかはわかりません (これらの文字は実際の人間の言語では使用されないため、実際には必要ないため)。

于 2014-03-11T19:50:50.347 に答える
0

正しいロケールを設定しましたか? iconv が必要な場合があります - http://cz1.php.net/manual/en/function.iconv.php#74101

于 2014-03-09T13:40:23.460 に答える
0

あなたが説明した問題には、失敗する可能性のある複数の場所があり、これを最適に解決する方法について正しい決定を行うために最初に知っておくことが重要です。

非常に多くのことがうまくいかない可能性があるため、入力が期待どおりでない場合に備えて、早期に失敗する必要があります。そのため、まず、その関数を呼び出す前に、文字列が使用する正しいエンコーディングであることを検証する必要があります。imagettftext()

if (!preg_match('//u', $username)) {
    throw new Exception(
        sprintf(
            "Username string %s can not be used with imagettftext()"
            , var_export($username, true)
        )
    );
}

これを行わないと、そもそも正しい結果が得られません。次に、このチェックが失敗した場合、これを渡すための解決策は、文字列が UTF-8 でエンコードされていることを確認することです。文字列はすでに UTF-8 でエンコードされているため、これは多かれ少なかれサニティ チェックです。ただし、エンコーディングに誤りがあり、それが有効でない場合 (簡単に発生する可能性があります) に備えて、このチェックにより、間違った場所を探すことが防止されます。

質問に入力した出力が既に示しているように、エンコードを間違えた可能性が最も高いです。そうしないと、サポートされている文字が少なくとも正しく表示されるためです。ただし、一部の文字が省略されているだけでなく、の文字が表示されていることさえあります. 間違ったエンコーディングの明確な兆候:

ここに画像の説明を入力

そのため、必要な文字列のエンコーディングを実際に検証するために、この手順をスキップしないでください。

これは、次のことにとって特に重要です。

フォントフェイスがその文字列の文字をサポートしていることを確認する必要があります。Verdana フォントは 794 個の Unicode 文字をサポートしています (完全なリスト)。探している文字が含まれていない場合imagettftext()、フォントに文字がないため、関数はそれらを表示できません。その場合、代わりに探している Unicode 文字をサポートするフォントを選択する必要があります。ウィキペディアには、さまざまなフォントの概要表があります。

適切なフォントの選択に関する詳細なガイダンスは、Stackoverflow で見つけることができます。

文字列変数で正しいエンコーディングを使用し、その文字列でエンコードされたすべての Unicode 文字のグリフを持つフォントを使用すると、imagettftextニーズが満たされます。

最初に書いたように、うまくいかない可能性がある場所がたくさんあります: エンコーディング チェックに合格しフォントが既にすべての文字をサポートしている場合、ここで失敗する追加の場所があります: 文字列は UTF-8 でエンコードされていますが、エンコードされていますあなたが考える文字が含まれていません。

于 2014-03-16T13:51:16.577 に答える