Last active
August 1, 2020 05:34
-
-
Save mieki256/524a34aea97611a6434c to your computer and use it in GitHub Desktop.
Shoeboxで生成したBMFont(ビットマップフォント)テクスチャを等幅フォントのように配置し直すPythonスクリプト
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- mode: python; Encoding: utf-8; coding: utf-8 -*- | |
# Last updated: <2015/07/13 07:48:16 +0900> | |
""" | |
Shoeboxで出力したBMFont画像を読み込んで、 | |
等幅フォントのように配置し直した画像を作成するスクリプト | |
usage: | |
python conv_monospc.py BMFONT.png BMFONT.fnt [OUTPUT.png] | |
by mieki256 | |
2015/07/13 ver. 0.0.1 とりあえず作成 | |
LICENSE : CC0 / Public Domain | |
""" | |
import sys | |
import os | |
from PIL import Image | |
OUTPUT_FILENAME_DEF = "output.png" | |
ASCII_SPC = 0x020 | |
ASCII_END = 0x07f | |
TEST_BMFONT = "font-export.png" | |
TEST_FNT = "font-export.fnt" | |
USAGE_MSGS = [ | |
"Usage:", | |
" Python conv_monospc.py BMFONT.png BMFONT.fnt [OUTPUT.png]" | |
] | |
class CharData(): | |
"""char data""" | |
def __init__(self, arg): | |
self.arg = arg | |
self.data = {} | |
for s in arg.split(" "): | |
if s == "char": | |
continue | |
if s == "\"": | |
continue | |
if "letter=" in s: | |
if s == 'letter="': | |
self.data['letter'] = ' ' | |
else: | |
self.data['letter'] = s[8] | |
else: | |
k, v = s.split("=") | |
self.data[k] = int(v) | |
def get_size(self): | |
return (self.data['width'], self.data['height']) | |
def get_charcode(self): | |
return ord(self.data['letter']) | |
def paste_image(self, src, dst, tx, ty, max_w, max_h): | |
sx = self.data['x'] | |
sy = self.data['y'] | |
sw = self.data['width'] | |
sh = self.data['height'] | |
box = (sx, sy, sx + sw, sy + sh) | |
region = src.copy().crop(box) | |
w, h = region.size | |
tx += (max_w - w) / 2 | |
ty += (max_h - h) / 2 | |
dst.paste(region, (tx, ty)) | |
def print_usage(): | |
for s in USAGE_MSGS: | |
print s | |
sys.exit | |
def main(): | |
bmfont = "" | |
fnt_file = "" | |
out_file = OUTPUT_FILENAME_DEF | |
if len(sys.argv) == 3: | |
bmfont = sys.argv[1] | |
fnt_file = sys.argv[2] | |
elif len(sys.argv) == 4: | |
bmfont = sys.argv[1] | |
fnt_file = sys.argv[2] | |
out_file = sys.argv[3] | |
elif len(sys.argv) == 1: | |
# test | |
if os.path.isfile(TEST_BMFONT): | |
bmfont = TEST_BMFONT | |
if os.path.isfile(TEST_FNT): | |
fnt_file = TEST_FNT | |
if bmfont == "" or fnt_file == "": | |
print_usage() | |
sys.exit() | |
objs = {} | |
# .fntを読み込み | |
f = open(fnt_file) | |
for line in f: | |
line = line.rstrip() | |
p = line.split(" ") | |
if p[0] != "char": | |
continue | |
id = int(p[1].split("=")[1]) | |
objs[id] = CharData(line) | |
f.close() | |
# 一番大きい文字サイズを取得 | |
max_w, max_h = 0, 0 | |
for key in objs: | |
w, h = objs[key].get_size() | |
if w > max_w: | |
max_w = w | |
if h > max_h: | |
max_h = h | |
# 画像読み込み | |
src_im = Image.open(bmfont, "r") | |
# 新しい画像を作成 | |
img_w = max_w * 16 | |
img_h = max_h * (ASCII_END + 1 - ASCII_SPC) / 16 | |
new_im = Image.new('RGBA', (img_w, img_h)) | |
# 文字を並び替え | |
for key in objs: | |
o = objs[key] | |
code = o.get_charcode() | |
if code > ASCII_SPC and code <= ASCII_END: | |
c = code - ASCII_SPC | |
x = (c % 16) * max_w | |
y = (c / 16) * max_h | |
# print "code=%s x,y = %d,%d" % (code, x, y) | |
o.paste_image(src_im, new_im, x, y, max_w, max_h) | |
# new_im.show() | |
new_im.save(out_file) | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
ShoeBox は以下から入手できます。
http://renderhjs.net/shoebox/