注意这是核心算法讲解文章
主文请移步开源一个基于Unity的Plist解析工具——TextureUnpacker
一、从plist中筛选出有用的信息
1、MetadataPlist信息 formatplist类型、textureFileName大图名称、size大图大小。
2、Frame小图信息 textureName小图名称、startPos小图在大图中的起始位置左上角-左上角、size小图大小、sourceSize小图裁剪前的原大小、isRotated小图在大图中是否经过了旋转、offset小图裁剪前后中心点的偏移值。
注意 在不同的plist中字段的名称可能不同但要表达的含义是相同的。
二、分析数据
通过对plist的数据和大图进行比对和分析可以发现
1、size小图大小、sourceSize小图裁剪前的原大小都是小图未旋转前的宽高。
2、startPos小图在大图中的起始位置 以“向下”为Y轴正方向。
3、offset小图裁剪前后中心点的偏移值以“向上”为Y轴正方向。
其中第3条的分析过程如下
选用format为2的plist因为此类型的plist中小图的 “sourceColorRect” 字段标明了裁剪后的小图在原小图上的起始位置左上角-左上角这里且称它为 trimStartPos。trimStartPos可以和offset小图裁剪前后中心点的偏移值进行相互推导。如下图
将小图的数据format为2的plist数据充分且未经过旋转的小图避免干扰代入即可判断出offset的Y轴方向与startPos小图在大图中的起始位置的方向相反即以“向上”为Y轴正方向。
在此基础上代入旋转了的小图数据发现其依然满足 trimStartPos 与 offset的推导关系由此可得出结论裁剪与旋转与否无关即Texturepacker在合成大图时其步骤为先裁剪得出offset再旋转宽高调换最后拼入大图得到小图在大图中的位置startPos。
三、拆分大图为小图
仅拆分大图为小图不需要考虑offset逻辑非常简单。
思路 创建一张与小图大小相同的目标图然后根据 startPos小图在大图中的起始位置左上角-左上角、size小图大小得到采样区最后将采样区对应像素逐一赋值给目标图。
首先需要重新计算 startPos因为原startPos是以大图左上为起点向下为正方向的而将要使用的采集像素方法 GetPixels() 需要以大图左下为起点以向上为正方向。
变换保持startPos的x坐标不变新的y坐标大图高度-(startPos.y 采样高度)。
1、未旋转小图的拆分
目标图中的坐标(w, h),对应的采样区坐标为(w, h)直接逐一赋值即可。
2、旋转小图的拆分
采样宽高发生调换
目标图中的坐标(w, h)对应的采样区坐标为(h, sampleHeight -1- w )即顺时针旋转90度。这里减一是因为其高度范围实际为0~sampleHeight-1如下图
四、将拆分的小图还原为原大小
与拆分不同的是还原小图要用到offset还原的过程就是把当初合图时Trim掉的四周的透明像素加回去。不过这个offset不能直接使用因为它是小图中心点的偏移值而实际需要的是裁剪前后“左下角-左下角”的偏移值。换算过程如下注意两次因Y坐标轴相反而取反对n取反对DH向量的Y分量整体取反
1、未旋转小图的还原
目标图中的坐标(w, h),对应的采样区坐标为(w-offsetLX, h-ofsetTY)逐一赋值即可。
2、旋转小图的还原
这种情况虽然比较复杂但好在我们已经在 第二节 中得知 “合图顺序为先裁剪后旋转”。
因为是求 目标图等同原始图中的坐标与采样区坐标的对应关系就相当于将原始图执行一次正序的合图坐标变换因此按照这个顺序先裁剪得
w > w-offsetLX; h > h-offsetBY;
再旋转套用 三(2) 中的旋转得
w > h-offsetBY; w > sampleHeight-1-(w-offsetLX)
即目标图中的坐标(w, h),对应的采样区坐标为(h-offsetBY, sampleHeight-1-(w-offsetLX))。
按此对应坐标对目标图进行赋值就OK了。
【文章转自韩国多IP服务器 http://www.558idc.com/krzq.html 复制请保留原URL】