python制作fnt字体打包工具
当前fnt打包工具现状
当前打包fnt字体很麻烦,特别是要使用美术字生成字体集的情况,如果有一个工具可以一键打包美术字体该多好,此文章主要是参考同事许波的分享来完成,非常感谢。
制作fnt配置文件
根据之前的经验,咋们知道必须要有配置文件才能编码对应的图片,比如:a.png与A.png是不一样的,但是如果在windows目录下,这两个文件是不能同时存在的,也就是如果咋们的美术字中有这两个文件,咋们得用不同的名字来进行命名,所以需要配置文件,目录结构如下:
fnt.py中的代码如下:
运行后可以输出:
咋们words.ini中的内容如下:
开始读取这个配置文件
如下是输出内容:
配置文件保存成功
遍历工具所在目录下的所有字体文件
目录下加入字体文件夹,开始对文件夹中的图片进行遍历
需要在python头部加入库
improt os
遍历文件夹
def main():
# 读取配置文件
readWordIni()
# 设定遍历路径
resourePath = "./"
for parent,dirnames,filenames in os.walk(resourePath):
print(parent,"||",dirnames,"||",filenames)
# dirnames为当前目录下的文件夹列表,遍历她
for dir_list in dirnames:
srcpath = resourePath + dir_list
print("start dir name:",srcpath)
# 创建一个输出目录
output_path_name = srcpath+os.sep+"output"
# print(output_path_name)
if not os.path.exists(output_path_name):
os.makedirs(output_path_name)
# 只取第一层
break
就会再每个字体的目录下创建output输出文件夹,开始遍历字体,如果匹配到字体的命名与配置中的相同,则用对应的配置来取代原有图片的名字作为id
# 创建转化列表
convert_list=dict()
fnt_name = os.path.basename(srcpath)
# 存对应的ascii码
list = os.listdir(srcpath)
#列出文件夹下所有的目录与文件
for i in range(0,len(list)):
basename = list[i]
# 判断是否是png
isPng = basename[-4:]
if isPng != ".png":
continue
# 保存图片的完整路径,后面为生成图片集做准备
filename = srcpath+os.sep+basename
# 取出文件名
font=basename[:basename.rfind(".")]
# 查找文件名在配置中是否有相关设定
if str(font) in fnt_convert_word :
# print("font",font,fnt_convert_word[str(font)])
font = fnt_convert_word[str(font)]
# 将对应的font(有可能是文件名也有可能是配置的名字)转化为ascii码
try:
ascii_code = ord(font)
except TypeError as e:
print("font define name:" + font + " error !!")
return
# 存储路径对应的ascii码
convert_list[filename]=ascii_code
continue
开始根据文件的路径及对应的ascii码来计算图片总面积
读取目录下所有图片,计算出其中最大尺寸的图片,根据max_width与max_height计算出所有图片所占用的最大图片尺寸,而对面积求平方根就是相同面积的正方行的边长
def createFntSet(fnt_name,convert_list,output_path_name):
if len(convert_list)>=1 :
# 存储单张图片的最大高度与最大宽度
global max_width
global max_height
global colCount
global rowCount
max_height=0
max_width=0
# 存储图片的相关定义
fnt_define_item = list()
# 存储图片的相关定义的字典
fnt_define_dic = {}
# 遍历列表中的所有图片,找到最大宽度与高度
for key in convert_list.keys():
image = Image.open(key)
image_size= image.size
max_width=max(max_width,image_size[0])
max_height=max(max_height,image_size[1])
# 存储数据
fnt_define_item_data=dict()
fnt_define_item.append(fnt_define_item_data)
fnt_define_dic[key] = fnt_define_item_data
fnt_define_item_data["id"]=convert_list[key]
fnt_define_item_data["width"]=str(image_size[0])
fnt_define_item_data["height"]=str(image_size[1])
fnt_define_item_data["xoffset"]=str(0)
fnt_define_item_data["yoffset"]=str(0)
fnt_define_item_data["xadvance"]=str(image_size[0])
fnt_define_item_data["page"]=str(0)
fnt_define_item_data["chnl"]=str(0)
# 去除图片的ascii转成字母
fnt_define_item_data["letter"]=chr(int(convert_list[key]))
# 计算图片的横向与纵向的数量
totalCount = len(convert_list)
# 长*宽是面积,这里算的是最大方块面积再乘以数量就是总面积,总面积开平方根是指该面积所构成的正方形的边长
# 边长除以宽度则是数量
colCount = int(math.ceil(math.sqrt(max_height*max_width*totalCount*1.0)/max_width))
rowCount = int(math.ceil(len(convert_list)*1.0/colCount))
print("计算出图片横向纵向的数量:",colCount,rowCount)
# 图片的索引,代表当前是处理的第几张图片
index=0
# 上面存储完图片的相关数据后,没有存储路径,下面再次计算图片的位置
for key in convert_list.keys():
fnt_item_data = fnt_define_dic[key]
# 开始计算位置
fnt_item_data["x"]=str((index%colCount)*max_width)
fnt_item_data["y"]=str(int(index/colCount)*max_height)
index += 1
fnt_define=dict()
fnt_define["data"]=fnt_define_item
fnt_define["size"]=str(max_width)
fnt_define["lineHeight"]=str(max_height)
fnt_define["base"]=str(max_width)
fnt_define["scaleW"]=str(max_width*colCount)
fnt_define["scaleH"]=str(max_height*rowCount)
image_name=fnt_name+".png"
fnt_define["file"]=image_name
fnt_define["count"]=len(convert_list)
# 保存fnt数据文件
fnt_name=output_path_name+"/"+fnt_name+".fnt"
saveFntData(fnt_name,fnt_define)
# 保存png图片文件
image_name=output_path_name+"/"+image_name
print("ajdkj",max_width,max_height,colCount)
savePng(image_name,convert_list,fnt_define_dic)
生成fnt数据文件
def saveFntData(fnt_name,fnt_define):
# 创建一个文件
write_file=open(fnt_name,"w")
write_file = codecs.open(fnt_name,"w","utf-8")
#face="Arial”,字体为”Arial”
# size=32:大小为32像素
# bold=0 :不加粗
# italic=0:不使用斜体
# charset="": charset是编码字符集,这里没有填写值即使用默认,
# unicode=0:不使用Unicode
# stretchH=100:纵向缩放百分比
# smooth=1 :开启平滑
# aa=1:开启抗锯齿
# padding=0,0,0,0:内边距,文字与边框的空隙。
# spacing=1,1 :外边距,就是相临边缘的距离。
head_msg1="""info face="%s" size=%s bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=2,2 outline=0\n""" % (face,fnt_define["size"])
write_file.write(head_msg1)
# lineHeight=37:行高,如果遇到换行符时,绘制字的位置坐标的Y值在换行后增加的像素值。
# base=28 :字的基本大小
# scaleW=512 :图片大小
# scaleH=512:图片大小
# pages=1 :此种字体共用到几张图。
# packed=0:图片不压缩
head_msg2 ="""common lineHeight=%s base=%s scaleW=%s scaleH=%s pages=1 packed=0 alphaChnl=0 redChnl=0 greenChnl=0 blueChnl=0\n""" % (fnt_define["lineHeight"],fnt_define["base"],fnt_define["scaleW"],fnt_define["scaleH"])
write_file.write(head_msg2)
# //第一页,文件名称是”bitmapFontChinese.png”
# page id=0 file="bitmapFontChinese.png"
head_msg3 = """page id=0 file="%s"\n""" % (fnt_define["file"])
write_file.write(head_msg3)
# 第四行是当前贴图中所容纳的文字数量
head_msg4 = """chars count=%s\n""" % (fnt_define["count"])
write_file.write(head_msg4)
for i in range(0,int(fnt_define["count"])):
data=fnt_define["data"][i]
line="char id=%s x=%s y=%s width=%s height=%s xoffset=%s yoffset=%s xadvance=%s page=%s chnl=%s letter=\"%s\"\n" %(data["id"],data["x"],data["y"],data["width"],data["height"],data["xoffset"],data["yoffset"],data["xadvance"],data["page"],data["chnl"],data["letter"])
write_file.write(line)
保存图片
def savePng(image_name,convert_list,fnt_define_dic):
# 计算图片的最大尺寸
outW=max_width*colCount
outH=max_height*rowCount
# 创建输出图片
toImage = Image.new('RGBA', (outW, outH))
# 开始保存图片
index = 0
for key in convert_list.keys():
fromImage=Image.open(key)
item_def = fnt_define_dic[key]
toImage.paste(fromImage,( int(item_def["x"]),int(item_def["y"])))
toImage.save(image_name)
效果如下: