日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

【游戏开发小技】TexturePacker生成的图集逆向切分成精灵小图(json | python | PIL | TextureUnPacker | 逆向 | 切图)

發布時間:2023/12/3 python 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【游戏开发小技】TexturePacker生成的图集逆向切分成精灵小图(json | python | PIL | TextureUnPacker | 逆向 | 切图) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

      • 一、前言
      • 二、TexturePacker
        • 1、特別說明
        • 2、TexturePacker下載
        • 3、準備精靈散圖(小圖)
        • 4、使用TexturePacker打圖集
        • 5、json結構分析
      • 三、圖集逆向切分精靈圖
        • 1、環境準備
        • 2、python代碼:TextureUnpacker.py
        • 3、代碼講解
          • 3.1、PIL.Image.open方法
          • 3.2、PIL.Image.new方法
          • 3.3、PIL.Image.crop方法
          • 3.4、PIL.Image.paste方法
          • 3.5、PIL.Image.save方法
        • 4、執行python腳本

一、前言

嗨,大家好,我是林新發。
之前有同事找我問我能不能通過json逆向切分圖集,我之前寫過一個python腳本,但是沒有存起來,

直到最近又有同事找我,給我發了json和png圖集,

我決定寫篇文章講一下,也方便下次又有同事問我的時候直接丟出這篇文章~

二、TexturePacker

1、特別說明

首先,本文的python代碼是針對TexturePacker工具Phaser 3框架生成出來的圖集進行逆向切分,不過只要你懂了原理,其他格式的配置都可以一通百通。
如何知道圖集是使用TexturePacker工具制作的呢?我們可以打開圖集同名的配置文件,如果能看到texturepacker的字樣,就說明是使用TexturePacker工具生成的,例:

2、TexturePacker下載

TexturePacker官網地址:https://www.codeandweb.com/texturepacker

下載下來后,我們進入bin目錄,可以看到TexturePackerGUI.exe,雙擊即可打開,

如下

為了演示,我先使用搞一些散圖,然后使用TexturePacker打個圖集出來。

3、準備精靈散圖(小圖)

以下是我隨便搜的一些精靈小圖,

4、使用TexturePacker打圖集

首先點擊界面右側的 框架,根據需求選擇一個框架,

它支持非常多的框架,如下

我選擇的是通用的Phaser 3,如下,(因為我那兩個同事發給我的圖集格式都是用的這個-_-,那我就用這個來做演示吧)

接著,我們把小圖的整個文件夾拖到界面左側中,它自動幫我們執行了圖集排版,如下,


接著,我們點擊發布精靈表,

填寫保存路徑,即可生成圖集png和一個json配置文件,如下

5、json結構分析

其中test.atlas.json配置表內容如下:

{"textures": [{"image": "test_atlas.png","format": "RGBA8888","size": {"w": 309,"h": 118},"scale": 1,"frames": [{"filename": "car.png","rotated": false,"trimmed": true,"sourceSize": {"w": 128,"h": 128},"spriteSourceSize": {"x": 0,"y": 6,"w": 128,"h": 116},"frame": {"x": 1,"y": 1,"w": 128,"h": 116},"anchor": {"x": 0.5,"y": 0.5}},{"filename": "bookcase.png","rotated": false,"trimmed": true,"sourceSize": {"w": 64,"h": 64},"spriteSourceSize": {"x": 8,"y": 0,"w": 55,"h": 64},"frame": {"x": 131,"y": 1,"w": 55,"h": 64},"anchor": {"x": 0.5,"y": 0.5}},{"filename": "table_tennis.png","rotated": false,"trimmed": false,"sourceSize": {"w": 48,"h": 48},"spriteSourceSize": {"x": 0,"y": 0,"w": 48,"h": 48},"frame": {"x": 131,"y": 67,"w": 48,"h": 48},"anchor": {"x": 0.5,"y": 0.5}},{"filename": "pencil.png","rotated": false,"trimmed": true,"sourceSize": {"w": 48,"h": 48},"spriteSourceSize": {"x": 3,"y": 3,"w": 42,"h": 42},"frame": {"x": 188,"y": 1,"w": 42,"h": 42},"anchor": {"x": 0.5,"y": 0.5}},{"filename": "cate.png","rotated": false,"trimmed": true,"sourceSize": {"w": 48,"h": 48},"spriteSourceSize": {"x": 5,"y": 3,"w": 39,"h": 41},"frame": {"x": 232,"y": 1,"w": 39,"h": 41},"anchor": {"x": 0.5,"y": 0.5}},{"filename": "stone.png","rotated": false,"trimmed": true,"sourceSize": {"w": 48,"h": 48},"spriteSourceSize": {"x": 6,"y": 4,"w": 35,"h": 40},"frame": {"x": 273,"y": 1,"w": 35,"h": 40},"anchor": {"x": 0.5,"y": 0.5}},{"filename": "brinjaul.png","rotated": false,"trimmed": true,"sourceSize": {"w": 48,"h": 48},"spriteSourceSize": {"x": 2,"y": 6,"w": 42,"h": 36},"frame": {"x": 188,"y": 45,"w": 42,"h": 36},"anchor": {"x": 0.5,"y": 0.5}},{"filename": "carota.png","rotated": false,"trimmed": true,"sourceSize": {"w": 48,"h": 48},"spriteSourceSize": {"x": 5,"y": 6,"w": 38,"h": 36},"frame": {"x": 232,"y": 44,"w": 38,"h": 36},"anchor": {"x": 0.5,"y": 0.5}},{"filename": "bulb.png","rotated": false,"trimmed": true,"sourceSize": {"w": 48,"h": 48},"spriteSourceSize": {"x": 6,"y": 4,"w": 36,"h": 40},"frame": {"x": 272,"y": 44,"w": 36,"h": 40},"anchor": {"x": 0.5,"y": 0.5}},{"filename": "pizza.png","rotated": false,"trimmed": true,"sourceSize": {"w": 48,"h": 48},"spriteSourceSize": {"x": 4,"y": 6,"w": 41,"h": 34},"frame": {"x": 181,"y": 83,"w": 41,"h": 34},"anchor": {"x": 0.5,"y": 0.5}},{"filename": "coconut.png","rotated": false,"trimmed": true,"sourceSize": {"w": 48,"h": 48},"spriteSourceSize": {"x": 3,"y": 10,"w": 42,"h": 27},"frame": {"x": 224,"y": 83,"w": 42,"h": 27},"anchor": {"x": 0.5,"y": 0.5}}]}],"meta": {"app": "https://www.codeandweb.com/texturepacker","version": "3.0","smartupdate": "$TexturePacker:SmartUpdate:79dd9a57d14f6938f1ea38d2225ac0ce:6ec25dea8a4c4491ba119c28bbdefaf3:2a084c904c80f72428569743fdf0f51d$"} }

我們分析一下json配置的結構,畫個圖方便一目了然,
(注意:這個json結構僅針對Phaser 3這個框架,其他框架的格式需要自行分析)

知道了json的結構,以及每個字段的含義,我們就可以開始逆向了~

三、圖集逆向切分精靈圖

1、環境準備

人生苦短,我用python,不要跟我爭辯~
如果你沒有python環境,安裝一下,我用的是python 3。
另外因為要進行圖形處理,需要安裝Pillow庫(PIL)。
通過pip命令進行安裝

pip install Pillow

如果在python中import PIL沒有報錯,則說明安裝PIL庫成功。

2、python代碼:TextureUnpacker.py

這里我先直接上代碼,注釋我寫得比較詳細,大家應該能看懂,下文我會講解核心的步驟,

# TexturePacker圖集逆向工具,本代碼只針對Phaser 3框架的json配置 # 只要你知道原理,其他配置都可自行分析處理,希望你能有自行修改和優化的能力 # Author: 林新發 https://blog.csdn.net/linxinfa # Create: 2022-03-24import os from PIL import Image import json# 封裝一個TextureUnpacker類 class TextureUnpacker(object):@classmethoddef split_with_json(cls, f_json, save_dir=None):f_json = os.path.abspath(f_json)if save_dir is None:save_dir = f_json + '_split'else:save_dir = os.path.abspath(save_dir)# 讀取json配置表f = open(f_json, 'r')txt = f.read()dt = json.loads(txt)f.close()# 大圖集文件名big_texture_file_name = dt['textures'][0]['image']# 小圖序列frames = dt['textures'][0]['frames']# 打開大圖big_img = Image.open(big_texture_file_name)# 遍歷生成小圖for index in range(0, len(frames)):info = frames[index]# 解析配置info = cls.parse_as_json(info)print(info)# 小圖的保存路徑little_image_save_path = os.path.join(save_dir, info['filename'])# 生成小圖cls.generate_little_image(big_img, info, little_image_save_path)@classmethoddef generate_little_image(cls, big_img, info, path):# 創建小圖little_img = Image.new('RGBA', info['sz'])# PIL.Image.crop()方法用于裁剪任何圖像的矩形部分# box –定義左,上,右和下像素坐標的4元組region = big_img.crop(info['box'])if info['rotated']:region = region.transpose(Image.ROTATE_90)# 把裁剪出來的圖片粘貼到小圖上little_img.paste(region, info['xy'])save_dir = os.path.dirname(path)if not os.path.exists(save_dir):os.makedirs(save_dir)# 保存little_img.save(path)@classmethoddef parse_as_json(cls, info):""""filename": "player_1.png","rotated": false,"trimmed": false,"sourceSize": { "w": 1, "h": 1 },"spriteSourceSize": { "x": 0, "y": 0, "w": 1, "h": 1 },"frame": { "x": 1, "y": 1, "w": 1, "h": 1 }"""# 小圖寬高width = info['sourceSize']['w']height = info['sourceSize']['h']# 小圖矩形信息frame = info['frame'] # 是否旋轉 (順時針方向90度)rotated = info['rotated']if rotated:# box 定義左、上、右和下像素坐標的4元組box = (frame['x'], frame['y'], frame['x'] + frame['h'],frame['y'] + frame['w'])else:box = (frame['x'], frame['y'],frame['x'] + frame['w'],frame['y'] + frame['h'])# 圖形在小圖中的偏移x = int((width - frame['w']) / 2)y = int((height - frame['h']) / 2)return {'box': box,'rotated': rotated,'sz': [width, height],'xy': (x, y),'filename' : info['filename']}if __name__ == '__main__':unpacker = TextureUnpacker()unpacker.split_with_json('test_atlas.json')print('done')

3、代碼講解

核心就是封裝的TextureUnpacker類,它做了以下幾件事情,其中用到的PIL庫的API我標注了黃色出來,如下

其中json配置的小圖解析,我封裝在parse_as_json方法中,如下,需要注意rotated旋轉,

生成小圖的邏輯封裝在generate_little_image方法中,這個方法中用到了PIL庫的一些API,

關于PIL的API可以參見官方文檔:https://pillow.readthedocs.io/en/latest/

這里我幫大家貼以下我用到的API的文檔吧。

3.1、PIL.Image.open方法


打開圖像,返回圖像對象,
示例:

from PIL import Image big_img = Image.open('test_atlas.png')
3.2、PIL.Image.new方法


創建image對象,示例:

from PIL import Image little_img = Image.new('RGBA', (48, 48))
3.3、PIL.Image.crop方法


裁剪圖像的某個矩形區域,示例

from PIL import Image with Image.open("test_atlas.png") as im:(left, upper, right, lower) = (20, 20, 100, 100)im_crop = im.crop((left, upper, right, lower))
3.4、PIL.Image.paste方法


粘貼另一個image到自身image上,示例:

this_img.paste(other_image)
3.5、PIL.Image.save方法


講image保存為文件,示例:

img_obj.save('test.png')

4、執行python腳本

把python代碼保存為TextureUnpacker.py,放在圖集文件同級目錄中,

執行python腳本,它會解析test_atlas.json并生成小圖精靈,

if __name__ == '__main__':unpacker = TextureUnpacker()unpacker.split_with_json('test_atlas.json')print('done')

執行輸出log如下

{'box': (1, 1, 129, 117), 'rotated': False, 'sz': [128, 128], 'xy': (0, 6), 'filename': 'car.png'} {'box': (131, 1, 186, 65), 'rotated': False, 'sz': [64, 64], 'xy': (4, 0), 'filename': 'bookcase.png'} {'box': (131, 67, 179, 115), 'rotated': False, 'sz': [48, 48], 'xy': (0, 0), 'filename': 'table_tennis.png'} {'box': (188, 1, 230, 43), 'rotated': False, 'sz': [48, 48], 'xy': (3, 3), 'filename': 'pencil.png'} {'box': (232, 1, 271, 42), 'rotated': False, 'sz': [48, 48], 'xy': (4, 3), 'filename': 'cate.png'} {'box': (273, 1, 308, 41), 'rotated': False, 'sz': [48, 48], 'xy': (6, 4), 'filename': 'stone.png'} {'box': (188, 45, 230, 81), 'rotated': False, 'sz': [48, 48], 'xy': (3, 6), 'filename': 'brinjaul.png'} {'box': (232, 44, 270, 80), 'rotated': False, 'sz': [48, 48], 'xy': (5, 6), 'filename': 'carota.png'} {'box': (272, 44, 308, 84), 'rotated': False, 'sz': [48, 48], 'xy': (6, 4), 'filename': 'bulb.png'} {'box': (181, 83, 222, 117), 'rotated': False, 'sz': [48, 48], 'xy': (3, 7), 'filename': 'pizza.png'} {'box': (224, 83, 266, 110), 'rotated': False, 'sz': [48, 48], 'xy': (3, 10), 'filename': 'coconut.png'} done

可以看到生成了一個文件夾,

文件夾里就可以看到生成出來的精靈小圖啦

完美,收工~
我是林新發,https://blog.csdn.net/linxinfa
一個在小公司默默奮斗的Unity開發者,希望可以幫助更多想學Unity的人,共勉~

總結

以上是生活随笔為你收集整理的【游戏开发小技】TexturePacker生成的图集逆向切分成精灵小图(json | python | PIL | TextureUnPacker | 逆向 | 切图)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。