游戏素材处理:利用Python把多个序列帧合并为一个大序列图

目录

问题来源

代码解决


游戏素材的整理是一件挺麻烦的事情,但是只要用好了工具,便可以事半功倍。

问题来源

从网上找了一些游戏特效素材,其中包括很多批序列帧图集

一部分特效素材是所有子帧都拼在一张大图上的,

 

而另一部分是若干个单独的序列帧图片

这样使用起来极其不方便,需要把资源的形式统一。最终决定还是把零散的多个序列帧图片拼成一个大图比较方便管理。

 

代码解决

花了点时间用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文件的动画的帧间隔时长信息。

 

 

 

 

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值