简介PlistDumper 是一款面向游戏开发与资源逆向场景的拆图工具主要解决图集打包后子图难以还原的问题。游戏发布时通常采用图集提升运行效率而该工具能依据配置文件将合图拆分为独立子图片并还原图片真实尺寸。它支持 TexturePacker 各版本 plist 文件导出兼容部分 json 文件同时可处理 fnt 位图字体与 spine 的 atlas 文件覆盖常见图集与字体格式。工具使用 Go 语言开发跨平台运行于 Windows、Mac、Linux可通过 release 下载可执行程序或从源码安装命令行传入文件或目录即可批量处理还支持按后缀筛选导出。资源包共 11 个文件以 5 个 go 源码文件为核心辅以 mod、sum 依赖描述、README 说明文档、LICENSE 授权文件及一张预览图压缩包约 59KB结构轻量便于阅读与二次开发。目前已有 755 人学习下载适合需要拆解图集、还原素材或研究 Go 实现思路的开发者参考。1. 拆图这件事为什么值得单独找个工具手里拿到一个游戏素材包解压后全是.plist、.json、.fnt、.atlas这几种文件外加一两张几百 KB 到几 MB 的 PNG 大图——这是做 UI 还原、素材复用、二次开发时最常见的开局。图片被 TexturePacker 这类工具打成了一张大图集单张切图信息全藏在描述文件里直接拿 PS 手动切几十上百个碎片能耗掉一整天。PlistDumper 就是冲着这个场景来的它读取 plist、json、fnt、atlas 这几类图集描述文件把大图按记录好的坐标和尺寸重新裁成独立小图导出。用 Go 写的单文件可执行不依赖运行时环境Windows、macOS、Linux 都能直接跑。适合谁做游戏逆向分析、素材整理、UI 复刻、教学演示的从业者以及需要批量处理图集又不想装一堆商业软件的人。下面按「它到底怎么解析 → 怎么跑起来 → 参数怎么调 → 哪里会翻车」的顺序拆一遍。2. 图集描述文件的四种格式与解析原理2.1 plist 与 json坐标、旋转、偏移三件套TexturePacker 导出的 plist 本质是一个 XML 属性列表json 则是它的等价 JSON 表达。两者记录的核心字段一致每个子图的frame在大图中的矩形区域、rotated是否旋转了 90 度、sourceSize原始尺寸、offset相对原图中心的偏移。拆图时最容易忽略的是rotated——很多工具只按 frame 裁矩形结果旋转过的图方向是错的。PlistDumper 在解析阶段就把这几个字段读全裁剪时按 rotated 决定是否做旋转还原。一个典型的 plist 片段长这样keyhero_idle_01.png/key dict keyframe/key string{{2,4},{64,96}}/string keyrotated/key false/ keysourceSize/key string{64,96}/string keyoffset/key string{0,0}/string /dictframe的{{x,y},{w,h}}是图集坐标系注意 TexturePacker 默认原点在左上角但部分导出配置会翻转 Y 轴这就是后面避坑章节要说的第一个坑。2.2 fnt 与 atlas位图字体和 Spine 的差异.fnt是 BMFont 格式分文本和二进制两种。文本版每行一个字符记录字段是id、x、y、width、height、xoffset、yoffset、xadvance。它和 plist 的区别在于fnt 描述的是字体字形导出时通常要按字符编码命名而不是按原始文件名。.atlas则是 Spine 动画用的图集格式结构是「页文件名 若干 region 块」每个 region 有rotate、xy、size、orig、offset等字段语义和 plist 接近但键名不同。PlistDumper 对这两类的处理思路是统一抽象成「图集页 区域列表」的中间结构再走同一套裁剪逻辑。这样加新格式时只要写一个解析器不用动裁剪核心。常见做法是先用格式探测看文件头是?xml、{、还是纯文本键值对决定走哪个解析分支避免让用户手动指定格式。2.3 旋转与偏移还原拆图正确性的关键裁剪本身不难难的是还原。假设一个子图 frame 是{x:100, y:50, w:64, h:96}且rotated: true意味着它在大图里是横躺着的实际占用区域是 96 宽、64 高。正确做法是先从大图裁出(100,50,96,64)这块再逆时针旋转 90 度得到64x96的图。如果还带 offset比如offset: {2,-3}说明原始图在 sourceSize 画布里有偏移导出时要么补透明边要么按 sourceSize 建画布再贴回去。PlistDumper 默认按 sourceSize 建画布这样导出的图和原始单图尺寸完全一致后续做对齐不会错位。3. 把 PlistDumper 跑起来编译、命令与批量导出3.1 从源码编译到单文件可执行Go 项目的编译很直接前提是本地装了 Go 1.18 以上。拉下源码后进目录# 编译当前平台的可执行文件 go build -o plistdumper . # 交叉编译 Windows 版本在 mac/linux 上生成 exe GOOSwindows GOARCHamd64 go build -o plistdumper.exe . # 交叉编译 macOS ARM 版本 GOOSdarwin GOARCHarm64 go build -o plistdumper-mac .go build会把所有依赖静态链进一个二进制产物通常几 MB拷到别的机器不用装 Go 也能跑。GOOS和GOARCH是交叉编译的目标平台和架构常见组合是windows/amd64、darwin/arm64、linux/amd64。如果编译报缺模块先go mod tidy拉齐依赖再 build。3.2 单文件导出与输出目录控制最常用的调用方式是给一个描述文件加一张图集图# 基本用法指定 plist 和对应的 png ./plistdumper -i ui_atlas.plist -t ui_atlas.png -o ./output # 处理 json 格式 ./plistdumper -i atlas.json -t atlas.png -o ./output # 处理 fnt 位图字体 ./plistdumper -i font.fnt -t font.png -o ./output-i是输入描述文件-t是图集纹理图-o是输出目录。程序会读描述文件里的textureFileName字段自动找图找不到才需要-t显式指定。输出文件名默认用描述文件里的原始 key比如hero_idle_01.png这样导出后能直接和项目里的引用对上。如果 key 里带路径分隔符程序会按目录结构创建子文件夹避免同名覆盖。3.3 批量处理与命名冲突处理一个项目往往有十几张图集逐个跑太慢。常见做法是写个循环脚本#!/bin/bash # 遍历当前目录所有 plist自动匹配同名 png 并导出 for f in *.plist; do base${f%.plist} if [ -f ${base}.png ]; then ./plistdumper -i $f -t ${base}.png -o ./output/${base} fi done这段脚本用 bash 的参数展开去掉扩展名再拼出同名 png。-o按图集名分目录避免不同图集里的同名子图互相覆盖。如果描述文件里的 key 有重复PlistDumper 默认会在文件名后加序号而不是直接覆盖——这个行为比很多同类工具稳妥血泪经验是早期版本直接覆盖导完发现少了一半图。提示批量跑之前先拿一张小图集验证输出尺寸和方向确认无误再全量跑省得返工。4. 参数调优与输出格式选择4.1 输出格式PNG、JPEG 与透明通道默认导出 PNG保留透明通道。如果图集本身没有透明区域可以加-f jpg减小体积但要注意 JPEG 不支持透明边缘会有杂色。参数表如下参数含义默认值建议-f输出格式 png/jpgpng有透明必须 png-qJPEG 质量 1-10090低于 80 边缘明显-p保留 padding 像素0有描边需求设 1-2-s按 sourceSize 建画布true需要原尺寸对齐时开启-r强制旋转还原auto一般不用手动改-p这个参数容易被忽略。TexturePacker 打包时子图之间会留 1-2 像素透明边防止采样溢出拆图时如果按 frame 精确裁边缘可能带进相邻图的杂色。设-p 1会往外多裁 1 像素再裁掉实际是做个安全边。-s关掉的话导出尺寸就是 frame 尺寸不带 offset 补边适合只关心图块本身、不做原图对齐的场景。4.2 旋转还原与坐标翻转的开关前面说过 rotated 要还原但有些老版本 TexturePacker 导出的 plist 里 rotated 字段和实际不符或者 Y 轴做了翻转。PlistDumper 提供-r强制旋转和-y翻转 Y 轴两个开关# 强制所有子图按旋转 90 度还原 ./plistdumper -i atlas.plist -t atlas.png -o ./out -r true # 翻转 Y 轴坐标部分引擎导出需要 ./plistdumper -i atlas.plist -t atlas.png -o ./out -y true判断要不要开-y的方法先默认跑一遍看导出的图是不是上下颠倒。如果是加-y true再跑。-r一般不用手动开auto 模式会读 rotated 字段只有字段缺失或错误时才强制。4.3 大图集的内存与并发控制一张 4096x4096 的 RGBA 图集解码后占 64MB 内存如果同时开多个 goroutine 处理多张图集内存会飙。PlistDumper 默认单张串行处理加-c可以开并发# 并发处理最多同时 4 张图集 ./plistdumper -i ./atlases -t ./textures -o ./out -c 4-c的值建议不超过 CPU 核心数且要估算单张图集解码后的内存乘以并发数不超过物理内存。处理 8K 图集时-c设 2 就够设太高反而因为内存交换变慢。如果只是偶尔跑一次保持默认串行最稳。5. 拆图翻车现场五个高频坑与排查5.1 导出的图上下颠倒现象拆出来的图方向反了人物头朝下。原因描述文件用了 Y 轴向上坐标系而程序默认按 Y 轴向下解析。解决加-y true翻转 Y 轴或者用图像工具批量垂直翻转输出目录。判断依据是看 frame 的 y 值分布——如果 y 值从下往上递增基本就是坐标系反了。5.2 旋转图方向错误或尺寸不对现象部分图是横躺的或者宽高对调。原因rotated 字段没被正确读取或者描述文件里旋转标记用的是rotated: 90而不是布尔值。解决先用-r true强制旋转跑一遍对比如果对了说明是字段解析问题检查描述文件里 rotated 的实际写法。有些工具导出的是angle字段需要手动映射。5.3 边缘带杂色或相邻图残影现象导出图的边缘有相邻子图的颜色。原因图集打包时子图间距小于采样半径精确裁剪把邻居裁进来了。解决加-p 1或-p 2做安全边或者在图集源头重新打包时加大 padding。这个坑在缩放过的图集上尤其常见因为缩放会放大采样误差。5.4 文件名乱码或路径穿越现象导出的文件名是乱码或者报错说路径非法。原因描述文件里的 key 含非 ASCII 字符或../这类路径片段。解决PlistDumper 默认会过滤路径分隔符但遇到编码问题需要确认描述文件的字符集。常见做法是先用file命令看描述文件编码UTF-8 和 UTF-16 处理方式不同必要时转码后再跑。5.5 大图集导出到一半失败现象处理 4K 以上图集时程序中断报内存错误。原因单张图解码后内存占用超过可用内存或者输出目录所在磁盘空间不足。解决先确认磁盘剩余空间大于图集解码后尺寸的总和再考虑用-c 1串行跑。如果单张就超内存需要先切分图集再处理或者换 64 位环境跑。6. 进阶把拆图接进自动化流水线单次拆图只是起点真正省时间的是把它接进素材处理流水线。我一般会写一个校验脚本拆完自动比对导出数量和描述文件里的记录数数量对不上就报警——这个习惯帮我拦下过好几次解析漏项。校验逻辑很简单读描述文件里的 key 数量和输出目录的图片数量对比。import os, plistlib # 读 plist 里的子图数量 with open(ui_atlas.plist, rb) as f: data plistlib.load(f) expected len(data[frames]) # 数输出目录的图片数量 actual len([n for n in os.listdir(./output) if n.endswith(.png)]) if expected ! actual: print(f数量不符: 期望 {expected}, 实际 {actual}) else: print(校验通过)这段脚本用 Python 的plistlib读 frames 字典长度再数输出目录的 png 数量。plistlib.load直接吃二进制流不用管 XML 还是二进制 plist。数量对不上时优先检查是不是有子图因为尺寸为 0 被跳过或者 key 重复被加了序号导致计数偏差。再进一步可以把拆图、校验、格式转换串成一条命令。比如拆完统一转成 WebP 减小体积或者按用途分目录归档。我习惯在输出目录里留一个manifest.json记录每个子图的原始 key、frame、sourceSize后续做 UI 还原时直接读这个清单定位资源比翻描述文件快得多。PlistDumper 本身不生成 manifest但输出文件名保留了原始 key写个脚本扫一遍目录就能反推出来。从那以后我每次拆完图都强制走一遍数量校验和方向抽检宁可多花两分钟也不想到用的时候才发现少了几张或者方向反了。希望帮到你。本文还有配套的精品资源点击获取