1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

(Python製)テクスチャ編集ユーティリティ:Tex-Tool

Last updated at Posted at 2018-11-13

#説明
コンソールからTexToolGUI.pywを起動して、GUIを表示させてから、
結合対象のテクスチャマスクの場所を指定してから、RUNボタンを押すことで、
s1.png s2.png
複数枚のテクスチャマスクを、一枚のテクスチャに結合することが出来る。
Result_RGBA.png
また、コンソールから直接モジュールを起動して、CUIを表示させてから、
テクスチャの場所を指定しておいたcsvを読み込ませることで、
s3.png
s4.png
テクスチャを、各チャンネルに分離することが出来る。
RGB_R.png RGB_G.png RGB_B.png
他にも、テクスチャを左右・上下反転させたり、
flip.png mirror.png
あるチャンネルを、別のチャンネルに移動させることも出来る。
move-B.png move-G.png move-R.png

#動機
テクスチャマスクを纏めるの意外とめんどい
s5.png
これまでは、以下の手順で、テクスチャマスクを纏めていた。

  1. Kritaにテクスチャマスクをインポート
  2. 各チャンネルのグループレイヤーを追加
  3. 各チャンネルのグループレイヤーに、テクスチャマスクを移動させる
  4. 各チャンネルの色を設定した、塗りつぶしレイヤーを追加
  5. グループレイヤーは加算、塗りつぶしレイヤーは乗算に変更
  6. 出来上がったテクスチャをエクスポート

手間と時間が非常に掛かる。あとAチャンネルが使い物にならない。

Python3でこういうのを制作しているけど、まともなツールも制作できる事を証明したかった。

#仕様

  • Pillow(画像編集モジュール)を活用する。
  • カラーモードはモノクロ・RGB・RGBAのみ。
  • モジュールとしての組み込みを前提とする。基本的にはPyQt5製のGUIから呼び出す。
  • 単独で使用したときは、バッチ処理を行えるようにcsvを読み込めるようにする。1
  • csvは指定可能。(デフォルトでは、同ディレクトリの同名のcsvを指定)

#CSVの読み込み

csvを読み込んで、モジュールを実行する。(各モジュールにおける実装の違いはほとんど無い2

  1. 入力の取得
  2. ファイルの読み込み(入力が空欄であれば、既定のcsv[BondTexture.csv]を使用)
  3. csvの読み込み
  4. 出力先が指定されている事を確認してから実行
BondTexture.py
if __name__ == '__main__': #単独で呼び出した時のみ実行(モジュールとして呼び出した時には実行しない)
    #1 入力の取得
    print("Please enter the location of 'BondTexture.csv'");
    name_csv = input()

    try:            #2 ファイルの読み込み
        csv_input = pd.read_csv(name_csv if name_csv else '../csv/BondTexture.csv', dtype=str)
    except IOError: #読み込み失敗
        print("File can't be found")
    else:           #読み込み成功
        for i in range(len(csv_input)):
            row    = csv_input.iloc[i].tolist() #3 csvの読み込み
            Output = row[4]     
            if (Output == Output): #4 出力先が指定されている事を確認してから実行
                Bond(row[0:4], Output)
            else:                  #空欄ならエラーメッセージを出力
                print('Output not specified / Row:{}'.format(i))

#テクスチャマスクの結合

単一のチャンネルを持つテクスチャマスクを結合し、
複数のチャンネル(__RGB__A)を持っているテクスチャとして出力する。

  1. テクスチャマスクの読み込み(空欄ならNone)
  2. サイズの確認(Noneなら0)3
  3. 前処理
  4. テクスチャマスクの結合4
  5. 画像データに変換して出力
BondTexture.py
def Bond(texture, Output):
    #1 テクスチャマスクの読み込み
    img = [Image.open(i) if i==i else None for i in texture]

    #2 サイズの確認(Noneなら0と判定)
    tex_size = max([i.size if i else (0,0) for i in img]) 

    #3 前処理
    def Convert(p):
        #空欄(None)なら、空のテクスチャを生成。
        if   (p == None):     return Image.new("L", tex_size, 0)
        #モノクロなら、変換せずに出力。
        elif (p.mode == "L"): return p
        #カラーなら、赤チャンネルを抽出。
        else:                 return p.split()[0]

    #4 テクスチャマスクの結合
    #5 画像データに変換して出力
    if None == img[-1]: #RGB
        del img[-1] #リストの最後尾を削除してRGBに合わせる
        Image.merge("RGB",  [Convert(i) for i in img]).save(Output)
    else: #RGBA
        Image.merge("RGBA", [Convert(i) for i in img]).save(Output)

#テクスチャの分離

複数のチャンネル(__RGB__A)を持っているテクスチャを、
単一のチャンネルを持つテクスチャマスクに分離して出力する。

  1. テクスチャの読み込み
  2. テクスチャの分離
  3. チャンネル別に画像データに変換して出力(出力先が空欄なら無視)
BondTexture.py(解説版)
def UnBond(Target, Input):
    #1 テクスチャの読み込み
    image = Image.open(Input)

    #2 テクスチャの分離
    img = image.split()

    #3 チャンネル別に画像データに変換して出力
    if (image.mode == 'RGBA') or (image.mode == 'RGB'):
        [img[i].save(Target[i]) for i in range(len(img)) if Target[i]==Target[i]]
    else: #RGBA・RGB以外
        print("Can UnBond 'RGB(A)-Texture' only")

#左右反転・上下反転・チャンネル移動

テクスチャの各チャンネル(__RGB__A)に対し、左右反転・上下反転・チャンネルの移動5を行う。

  1. テクスチャの読み込み・分離
  2. 左右反転・上下反転
  3. チャンネル移動6
  4. テクスチャマスクの結合
  5. 画像データに変換して出力
BondTexture.py
def Frip(Input, Output, mode, mirror, flip, Order):
    #1 テクスチャの読み込み・分離
    image_splited = Image.open(Input).split()

    #左右反転
    def _mirror(p): return ImageOps.mirror(p) if mirror[len(img)] else p

    #上下反転
    def _flip(p)  : return ImageOps.  flip(p) if flip  [len(img)] else p

    #2 左右反転・上下反転
    img = [];  [img.append(_flip(_mirror(t))) for t in image_splited]

    #3 チャンネル移動
    #4 テクスチャマスクの結合
    #5 画像データに変換して出力
    if   (mode == "RGBA") and (len(image_splited) == 4): #RGBA mode
        Image.merge("RGBA", [img[i] for i in Order[0:4]]).save(Output)
    elif (mode == "RGB")  or  (len(image_splited) == 3): #RGB  mode
        Image.merge("RGB",  [img[i] for i in Order[0:3]]).save(Output)

#まとめ
やっていることは非常にシンプルである。なぜ今まで誰もやらなかったのか?
これからは、テクスチャマスクを纏めることは、一瞬で出来るようになる。
作者としては、「出来れば多くの場所で使われて欲しい」と願っている。

  1. jsonよりも、csvのほうが、デザイナーでも扱いやすいため

  2. 引数が各モジュールで違うので、csvのデータの解釈が違ってくる。

  3. 前処理でのテクスチャ生成時に、テクスチャサイズが必要

  4. texture[3]がNoneの時は、Aチャンネルが減らせるので、RGBモードで出力できる。

  5. 例えば、RチャンネルをGチャンネルに移動させて、GチャンネルをRチャンネルに移動できる。

  6. RGBAモードでの出力は、テクスチャのカラーモードがRGBAモードかつ、mode = 'RGBA'と指定されている時のみ。

1
3
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?