18

印鑑の画像を作成しています。このタスク用に 3 つの True Type フォントがあります ( Jin_Wen_Da_Zhuan_Ti.7zZhong_Guo_Long_Jin_Shi_Zhuan.7zZhong_Yan_Yuan_Jin_Wen.7z、テスト目的のみ)。以下は、Microsoft Word での外観です。

Word での外観

漢字の「我」のこと。ここに私のPythonスクリプトがあります:

import numpy as np
from PIL import Image, ImageFont, ImageDraw, ImageChops
import itertools
import os


def grey2binary(grey, white_value=1):
    grey[np.where(grey <= 127)] = 0
    grey[np.where(grey > 127)] = white_value
    return grey


def create_testing_images(characters,
                          font_path,
                          save_to_folder,
                          sub_folder=None,
                          image_size=64):
    font_size = image_size * 2
    if sub_folder is None:
        sub_folder = os.path.split(font_path)[-1]
        sub_folder = os.path.splitext(sub_folder)[0]
    sub_folder_full = os.path.join(save_to_folder, sub_folder)
    if not os.path.exists(sub_folder_full):
        os.mkdir(sub_folder_full)
    font = ImageFont.truetype(font_path,font_size)
    bg = Image.new('L',(font_size,font_size),'white')

    for char in characters:
        img = Image.new('L',(font_size,font_size),'white')
        draw = ImageDraw.Draw(img)
        draw.text((0,0), text=char, font=font)
        diff = ImageChops.difference(img, bg)
        bbox = diff.getbbox()
        if bbox:
            img = img.crop(bbox)
            img = img.resize((image_size, image_size), resample=Image.BILINEAR)

            img_array = np.array(img)
            img_array = grey2binary(img_array, white_value=255)

            edge_top = img_array[0, range(image_size)]
            edge_left = img_array[range(image_size), 0]
            edge_bottom = img_array[image_size - 1, range(image_size)]
            edge_right = img_array[range(image_size), image_size - 1]

            criterion = sum(itertools.chain(edge_top, edge_left, 
                                           edge_bottom, edge_right))

            if criteria > 255 * image_size * 2:
                img = Image.fromarray(np.uint8(img_array))
                img.save(os.path.join(sub_folder_full, char) + '.gif')

コア スニペットの場所

        font = ImageFont.truetype(font_path,font_size)
        img = Image.new('L',(font_size,font_size),'white')
        draw = ImageDraw.Draw(img)
        draw.text((0,0), text=char, font=font)

たとえば、これらのフォントをフォルダーに入れ、次のように./fonts呼び出す場合

create_testing_images(['我'], 'fonts/金文大篆体.ttf', save_to_folder='test')

スクリプトは./test/金文大篆体/我.gifファイル システムに作成されます。

ここでの問題は、最初のフォントである金文大篆体.ttf (Jin_Wen_Da_Zhuan_Ti.7z 内) では問題なく動作しますが、Microsoft Word で正しくレンダリングできる場合でも、スクリプトが他の 2 つのフォントでは動作しないことです。金石篆.ttf (Zhong_Guo_Long_Jin_Shi_Zhuan.7z) では何も描かないbboxのでNone; 中研院金文.ttf (Zhong_Yan_Yuan_Jin_Wen.7z) の場合、画像に文字のない黒い枠が描画されます。

ここに画像の説明を入力

criterionしたがって、すべての黒の出力をテストすることを目的とした のテストに合格できません。FontForgeを使用してフォントのプロパティを確認したところ、最初のフォント金文大篆体.ttf (Jin_Wen_Da_Zhuan_Ti.7z 内) が UnicodeBmp を使用していることがわかりました。

UnicodeBmp

他の2つはBig5hkscsを使用しています

Big5hkscs_中國龍金石篆 中研院金文"></p> <p>これは私のシステムのエンコード スキームではありません。これが原因で、私のシステムでフォント名が認識されない可能性があります:</p> <p><img src=

実際には、厄介なフォント名のフォントを取得しようとすることで、これを解決しようとしています。pycairoこれらのフォントをインストールした後に試しました:

import cairo

# adapted from
# http://heuristically.wordpress.com/2011/01/31/pycairo-hello-world/

# setup a place to draw
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 100, 100)
ctx = cairo.Context (surface)

# paint background
ctx.set_source_rgb(1, 1, 1)
ctx.rectangle(0, 0, 100, 100)
ctx.fill()

# draw text
ctx.select_font_face('金文大篆体')
ctx.set_font_size(80)
ctx.move_to(12,80)
ctx.set_source_rgb(0, 0, 0)
ctx.show_text('我')

# finish up
ctx.stroke() # commit to surface
surface.write_to_png('我.gif')

これは、金文大篆体.ttf (Jin_Wen_Da_Zhuan_Ti.7z 内) でもうまく機能します。

ここに画像の説明を入力

しかし、まだ他の人とは違います。例: ctx.select_font_face('中國龍金石篆')(報告する_cairo_win32_scaled_font_ucs4_to_index:GetGlyphIndicesW) もctx.select_font_face('¤¤°êÀsª÷¥Û½f')(デフォルトのフォントで描画する) も機能しません。(後者の名前は、上記のようにフォント ビューアに表示される乱雑なコードであり、Big5 のコード ページである Mathematica コードの行によって取得されます。ToCharacterCode["中國龍金石篆", "CP950"] // FromCharacterCode)CP950

そのため、この問題に取り組むために最善を尽くしたと思いますが、それでも解決できません。FontForge を使用してフォント名を変更したり、システム エンコーディングを Big5 に変更したりするなど、他の方法も考えましたが、Python のみを使用するため、ユーザーの追加操作が少なくて済むソリューションを希望します。どんなヒントでも大歓迎です。ありがとうございました。

stackoverflow のモデレーターへ: この問題は一見「局所的すぎる」ように見えるかもしれませんが、他の言語/他のエンコーディング/他のフォントで発生する可能性があり、解決策は他のケースに一般化できるため、閉じないでください。この理由で。ありがとうございました。

更新: 奇妙なことに、Mathematica は CP936 (GBK、私のシステム エンコーディングと考えることができます) のフォント名を認識できます。例として、中國龍金石篆.ttf (Zhong_Guo_Long_Jin_Shi_Zhuan.7z 内) を取り上げます。

マテマティカ

ただしctx.select_font_face('ÖÐøý½ðʯ*­')、デフォルトのフォントで文字イメージを作成する設定も機能しません。

4

2 に答える 2

4

問題は、フォントが TrueType 仕様に厳密に準拠していないことです。簡単な解決策は、FontForge を使用して (既に使用しています)、フォントをサニタイズすることです。

  1. フォントファイルを開く
  2. に移動しEncoding、選択しますReencode
  3. 選ぶISO 10646-1 (Unicode BMP)
  4. File次に行くGenerate Fonts
  5. TTF として保存
  6. 新しく生成されたフォントでスクリプトを実行します
  7. 出来上がり!我が美しいフォントで印刷されます!
于 2013-06-05T09:07:08.570 に答える