目录
游戏素材的整理是一件挺麻烦的事情,但是只要用好了工具,便可以事半功倍。
问题来源
从网上找了一些游戏特效素材,其中包括很多批序列帧图集
一部分特效素材是所有子帧都拼在一张大图上的,
而另一部分是若干个单独的序列帧图片
这样使用起来极其不方便,需要把资源的形式统一。最终决定还是把零散的多个序列帧图片拼成一个大图比较方便管理。
代码解决
花了点时间用python写了一个转换脚本,
这个脚本会递归遍历给定目录下的所有子目录, 对于每一个末级目录,将其中的所有png图片合成一个大的序列图,保存到给定路径下相同结构的路径中,顺便输出这个序列图的信息到序列图同路径下的文本文件。
有需要的朋友可以拿去使用。
import os
import math
from PIL import Image
def pngfile2sequence(root_path_to_walk, root_path_to_save):
"""
递归遍历给定目录下的所有子目录,
对于每一个末级目录,将其中的所有png图片合成一个大的序列图,
保存到给定路径下相同结构的路径中,顺便输出这个序列图的信息到序列图同路径下的文本文件
Author: Rabbit_Gray
Source: https://blog.csdn.net/Rabbit_Gray
"""
# 递归遍历指定目录
for root, dirs, files in os.walk(root_path_to_walk):
if "SequenceMap.png" in files:
files.remove("SequenceMap.png")
if len(dirs) == 0 and len(files) != 0: # 如果某目录下只有文件没有文件夹,那么这是一个动画包
# 打开当前目录下的所有png文件
ani_imgs = [Image.open(os.path.join(root, file)) for file in files if file.endswith(".png")]
if len(ani_imgs) == 0: # 这个动画包中没有png文件
continue
# 获取动画序列信息
ani_w, ani_h = ani_imgs[0].size
ani_frame_num = len(ani_imgs)
mode = ani_imgs[0].mode
# 生成合理排列布局的序列图
for i in range(1, int(ani_frame_num**0.5)+1):
# 将ani_frame_num分解为2个尽可能接近的质因子的乘积
if ani_frame_num%i == 0:
prime_factor_1 = i
prime_factor_2 = int(ani_frame_num / i)
sequence_map_w_num = prime_factor_2
sequence_map_h_num = prime_factor_1
sequence_map_size = (ani_w * sequence_map_w_num, ani_h * sequence_map_h_num)
sequence_map_img = Image.new(mode, sequence_map_size)
# 向空白序列图粘贴子图
for i, img in enumerate(ani_imgs):
position = (i%sequence_map_w_num * ani_w, int(i/sequence_map_w_num) * ani_h)
sequence_map_img.paste(img, position)
# 在指定位置建立相同结构子目录
path_to_save = os.path.join(root_path_to_save, root.replace(root_path_to_walk, ""))
if not os.path.exists(path_to_save):
os.makedirs(path_to_save)
# 保存生成的序列图
sequence_map_img.save(os.path.join(path_to_save, "SequenceMap.png"))
delay_data = ""
if "delay.txt" in files:
with open(os.path.join(root,"delay.txt"), "r") as f:
data = f.read().replace("\n\nCreated By Monogatari.", "")
data = data.split("\n")
data = [d.split(":")[1].strip() for d in data]
delay_data = ",".join(data)
# 导出序列图的信息
with open(os.path.join(path_to_save, "ani_info.txt"), "w") as f:
f.write(f"file=SequenceMap.png\n")
f.write(f"SequenceMap_size_w=%d\n" % sequence_map_size[0])
f.write(f"SequenceMap_size_h=%d\n" % sequence_map_size[1])
f.write(f"ani_frame_cnt=%d\n" % ani_frame_num)
f.write(f"ani_w=%d\n" % ani_w)
f.write(f"ani_h=%d\n" % ani_h)
f.write(f"delay=%s\n" % delay_data)
print(f"保存到 %s" % path_to_save)
if __name__ == "__main__":
# 包含序列帧素材的根文件夹目录
animation_file_path = ".\\冒险岛光效合集\\"
# 生成序列大图的目标文件夹根目录
path_to_save = ".\\new_ani\\"
# 转换
pngfile2sequence(animation_file_path, path_to_save)
转换效果
有的素材会包含delay.txt来说明这个动画特效帧与帧之间的时间间隔,因此程序也试图提取了存在delay.txt文件的动画的帧间隔时长信息。