Je crée des images de la Chine seal script . Je dispose de trois polices true type pour cette tâche ( Jin_Wen_Da_Zhuan_Ti.7z , Zhong_Guo_Long_Jin_Shi_Zhuan.7z , Zhong_Yan_Yuan_Jin_Wen.7z (uniquement à des fins de test). Voici les apparences dans Microsoft Word
du caractère chinois "" (je/moi). Voici mon script :
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')
où l'extrait de base est
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)
Par exemple, si vous placez ces polices dans le dossier ./fonts
et le suivre avec
create_testing_images([''], 'fonts/.ttf', save_to_folder='test')
le script créera ./test//.gif
dans votre système de fichiers.
Le problème est que, bien que cela fonctionne bien avec la première police .ttf (dans Jin_Wen_Da_Zhuan_Ti.7z), le script ne fonctionne pas avec les deux autres polices, même si elles peuvent être rendues correctement dans Microsoft Word : pour .ttf (dans Zhong_Guo_Long_Jin_Shi_Zhuan.7z), il ne dessine rien de la façon suivante bbox
sera None
; pour .ttf (dans Zhong_Yan_Yuan_Jin_Wen.7z), il dessinera un cadre noir sans aucun caractère dans l'image.
et ne passe donc pas le test de la criterion
dont le but est de tester une sortie entièrement noire. J'ai utilisé FontForge pour vérifier les propriétés des polices, et j'ai trouvé que la première police .ttf (dans Jin_Wen_Da_Zhuan_Ti.7z) utilise UnicodeBmp
tandis que les deux autres utilisent Big5hkscs
ce qui n'est pas le schéma d'encodage de mon système. C'est peut-être la raison pour laquelle les noms des polices sont méconnaissables dans mon système :
En fait, j'essaie aussi de résoudre ce problème en essayant d'obtenir la police avec le nom de police en désordre. J'ai essayé pycairo
après avoir installé ces polices :
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')
Cela fonctionne à nouveau avec .ttf (dans Jin_Wen_Da_Zhuan_Ti.7z) :
mais toujours pas avec les autres. Par exemple : ni ctx.select_font_face('')
(qui rapporte _cairo_win32_scaled_font_ucs4_to_index:GetGlyphIndicesW
) ni ctx.select_font_face('¤¤°êÀsª÷¥f')
(qui dessine avec la police par défaut) fonctionne. (Ce dernier nom est le code désordonné affiché dans le visualisateur de polices comme indiqué ci-dessus, obtenu par une ligne de code Mathematica ToCharacterCode["", "CP950"] // FromCharacterCode
donde CP950
est la page de code de Big5).
Je pense donc avoir fait de mon mieux pour résoudre ce problème, mais je n'y suis toujours pas parvenu. J'ai également trouvé d'autres solutions comme renommer le nom de la police avec FontForge ou changer l'encodage du système en Big5, mais je préférerais toujours une solution qui n'implique que Python et qui nécessite donc moins d'actions supplémentaires de la part de l'utilisateur. Toute indication sera grandement appréciée. Je vous remercie.
Aux modérateurs de stackoverflow ce problème peut sembler "trop localisé" à première vue, mais il peut se produire dans d'autres langues / d'autres encodages / d'autres polices, et la solution peut être généralisée à d'autres cas, alors s'il vous plaît ne le fermez pas pour cette raison. Je vous remercie de votre attention.
MISE À JOUR : Bizarrement Mathematica peut reconnaître le nom de la police en CP936 (GBK, qui peut être considéré comme l'encodage de mon système). Prenons l'exemple du .ttf (dans Zhong_Guo_Long_Jin_Shi_Zhuan.7z) :
Mais la mise en place ctx.select_font_face('ÖÐøý½ð*')
ne fonctionne pas non plus, car elle crée l'image du caractère avec la police par défaut.