Skip to content

Instantly share code, notes, and snippets.

@mieki256
Last active August 1, 2020 05:34
Show Gist options
  • Save mieki256/524a34aea97611a6434c to your computer and use it in GitHub Desktop.
Save mieki256/524a34aea97611a6434c to your computer and use it in GitHub Desktop.
Shoeboxで生成したBMFont(ビットマップフォント)テクスチャを等幅フォントのように配置し直すPythonスクリプト
#!/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()
@mieki256
Copy link
Author

ShoeBox は以下から入手できます。

http://renderhjs.net/shoebox/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment