贴图


选择ab文件

首先我们需要找到一个包含贴图资源的ab文件,如果你不确定是哪个ab满足要求,那么可以使用list命令收集所有进包的资源路径,然后反过来从贴图资源的路径查找相应的ab文件。

find AssetBundles -iname '*.god' | xargs abtool list -r

从结果里面我们选择artresource_captainpbr_captain_202.god作为演示资源。

提取贴图资源

通过abtool的savetex命令可以一次性保存ab文件里面所有的贴图资源,默认输出到当前目录的__textures目录,也可以添加--output参数指定其他存放目录。

abtool savetex AssetBundles/Android/artresource_captainpbr_captain_202.god

需要说明的是:savetex保存的贴图有着固定命名规范,其格式为[filename].[宽]x[高].[贴图格式].tex,除了filename,其余文件名内容是不能修改的,否则在接下来的贴图转码操作会失败。

贴图格式转换

从上一步骤得到的贴图都是*.tex格式的文件,并非用普通图片浏览工具可以直接查看文件格式,它们被做了特殊编码编码以便GPU渲染时可以被正常读取,所以还需要做贴图转码。在工程根目录放置了python脚本工具textool.py,它可以批量地把*.tex文件转换成项目中常见的*.tga文件。

import re, struct
from tex2img import decompress_astc, decompress_etc, decompress_pvrtc
from PIL import Image

def main():
    import sys
    pattern = re.compile(r'[^/]+\.(\d+x\d+)\.([^.]+)\.tex$')
    for filename in sys.argv[1:]:
        match = pattern.search(filename)
        if not match: continue
        # print('>>> {}'.format(filename))
        fp = open(filename, 'rb')
        texture_size = [int(x) for x in match.group(1).split('x')]
        texture_format = match.group(2)
        mode = 'RGBA'
        if texture_format.startswith('etc_'):
            image = decompress_etc(fp.read(), texture_size[0], texture_size[1], 0)
            mode = 'RGB'
        elif texture_format.startswith('etc2_'):
            image = decompress_etc(fp.read(), texture_size[0], texture_size[1], 3 if texture_format.startswith('etc2_rgba') else 1)
            if not texture_format.startswith('etc2_rgba'): mode = 'RGB'
        elif texture_format.startswith('astc_rgb'):
            block_size = [int(x) for x in texture_format.split('_')[-1].split('x')]
            image = decompress_astc(fp.read(), texture_size[0], texture_size[1], block_size[0], block_size[1], False)
        elif texture_format.startswith('pvrtc'):
            # https://github.com/powervr-graphics/Native_SDK/blob/3f88b0f3735774ab9fb718da0aeadd06acf68d21/framework/PVRCore/texture/PVRTDecompress.cpp#L574
            image = decompress_pvrtc(fp.read(), texture_size[0], texture_size[1], 0 if texture_format[-1] == '4' else 1)
        elif texture_format.startswith('rgba32'):
            image = fp.read()
        elif texture_format.startswith('rgb24'):
            image = fp.read()
            mode = 'RGB'
        elif texture_format.startswith('rgb565'):
            width, height = texture_size
            image = bytearray(width * height * 3)
            index = 0
            for r in range(height):
                for c in range(width):
                    v, = struct.unpack('<H', fp.read(2))
                    image[index+0] = (v >> 11 & 0x1F) * 255 // 0x1F # red
                    image[index+1] = (v >>  5 & 0x3F) * 255 // 0x3F # green
                    image[index+2] = (v >>  0 & 0x1F) * 255 // 0x1F # blue
                    index += 3
            image = bytes(image)
            mode = 'RGB'
        elif texture_format.startswith('rgba4444'):
            width, height = texture_size
            image = bytearray(width * height * 4)
            index = 0
            for r in range(height):
                for c in range(width):
                    v, = struct.unpack('<H', fp.read(2))
                    image[index+0] = (v >> 12 & 0xF) * 255 // 0xF # red
                    image[index+1] = (v >>  8 & 0xF) * 255 // 0xF # green
                    image[index+2] = (v >>  4 & 0xF) * 255 // 0xF # blue
                    image[index+3] = (v >>  0 & 0xF) * 255 // 0xF # alpha
                    index += 4
            image = bytes(image)
        elif texture_format.startswith('alpha8'):
            image = fp.read()
            mode = 'L'
        else: continue
        result = Image.frombytes(mode, tuple(texture_size), image, 'raw')
        savename = re.sub(r'(\.[^.]+){3}$', '', filename) + '.tga'
        result.save(savename)
        print('+ {} => {}'.format(filename, savename))

if __name__ == '__main__':
    main()

在使用前建议把textool放到/usr/bin/local/目录下,这样好处是不用每次都用一个很长的路径来访问这个工具了。

cp -fv textool.py /usr/local/bin/textool

接下来通过textool转换*.tex贴图格式,转换后的图片文件存储在源*.tex文件的同级目录。

textool __textures/*.tex

打开__textures目录见证奇迹时刻。

textool工具依赖第三方贴图解码库tex2img1,该工具封装了BinomialLLC/basis_universal2Ericsson/ETCPACK3powervr-graphics/Native_SDK4,感谢老哥K0lb35提供的便利。笔者在此基础上增加了RGBA32RGBA4444RGB24RGB565Alpha8贴图格式的转码,经过这么一番整合,应该可以应付绝大部分的贴图转码。

1. https://github.com/K0lb3/tex2img.git
2. https://github.com/BinomialLLC/basis_universal/
3. https://github.com/Ericsson/ETCPACK
4. https://github.com/powervr-graphics/Native_SDK/tree/master/framework/PVRCore/texture
5. https://github.com/K0lb3

results matching ""

    No results matching ""