忍者ブログ
2017/09/24

指定ノード以下のテクスチャをリサイズ

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

コメント

ただいまコメントを受けつけておりません。

2016/07/04

指定ノード以下のテクスチャをリサイズ

MAYAでモデルに貼られているテクスチャがでかすぎる!
アニメーション作業だったらこんな高解像度のテクスチャはいらん!
という、そんなアナタ!!ピッタリなの作りましたよ!!!

指定ノード以下のテクスチャをリサイズして貼り直します。

# -*- coding: utf-8 -*-
from maya import cmds
from PIL import Image
import pymel.core as pm
import os
import stat


def get_shading_engines(root_node=None):
    '''
    指定ノード以下のshading_engineの重複しないリストを取得
    '''
    en_list = []
    if root_node is None:
        shapes = pm.ls(type="mesh")
    else:
        if isinstance(root_node, (str, unicode)): root_node = pm.PyNode(root_node)
        shapes = root_node.listRelatives(ad=True, type="mesh")
    file_nodes = []
    for i in shapes:
        shading_engines = i.shadingGroups()
        en_list+=shading_engines
    #重複をなくしてから戻す
    return list(set(en_list))

def get_all_texture_node(root_node=None):
    '''
    指定ノード以下に接続されている全テクスチャノードを取得
    '''
    file_nodes = []
    en_list = get_shading_engines(root_node)
    for en in en_list:
        file_nodes.extend(cmds.ls(cmds.listHistory(en.name()),type='file'))
    return list(set(file_nodes))

def get_truth_file_path(filepath, dir):
    '''
    パスの存在をしらべる。なければセットプロジェクトされているフォルダ以下にないか探しにいく。
    '''
    if os.path.exists(filepath):
        return filepath
    workpath =  pm.workspace( q=True, rootDirectory=True )
    if dir is not None:
        workpath = workpath + dir
    filename =  os.path.basename(filepath)

    for root, dirs, files in os.walk(workpath):
        for file in files:
            if filename == file:
                return root + r"/" +file

    return filepath

def get_use_texture_path_list(root_node=None):
    '''
    指定ノード以下に接続されているテクスチャパスのリスト
    '''
    file_nodes = get_all_texture_node(root_node)
    files = []
    for tex in file_nodes:
        path = cmds.getAttr(tex + '.fileTextureName')
        truth_path= get_truth_file_path(path, "sourceimages")
        if truth_path is None:continue;
        files.append(truth_path)
    files = list(set(files))
    return files
    
def set_texture_to_specified_dir(root_node=None, dir=""):
    '''
    指定ノード以下に接続されているテクスチャを指定のディレクトリに接続し直す
    '''
    file_nodes = get_all_texture_node(root_node)
    for tex in file_nodes:
        def_path = cmds.getAttr(tex + '.fileTextureName')
        base_name = os.path.basename(def_path)
        new_path = os.path.join(dir, base_name)
        if os.path.isfile(new_path):
            cmds.setAttr(tex + '.fileTextureName', new_path, type='string')

def resize_texture(root_node=None, dir="", magnification=1, width=None, height=None):
    '''
    指定ノード以下のテクスチャをリサイズ(別フォルダに出力)
    画像幅と高さが両方していされてればそっち優先
    
    root_node : テクスチャ書き出すルートノード
    export_dir : 書き出すフォルダ
    magnification : テクスチャの倍率
    width : 画像幅
    height: 画像高さ
    '''
    files = get_use_texture_path_list(root_node)
    if os.path.exists(dir) == False:
        os.makedirs(dir)

    # ペースト先のファイルが読み取り専用だった場合エラーになるので対処しとく
    for f in files:
        dir_path, file_name = os.path.split(f)
        save_file_path = dir+'\\'+file_name
        if os.path.exists(save_file_path):
            os.chmod(save_file_path, stat.S_IWRITE)
        im = Image.open(f)
        w = int(im.size[0]) * magnification
        h = int(im.size[1]) * magnification
        if width is not None and height is not None:
            w = width
            h = height
        im.resize((int(w),int(h))).save(save_file_path)
        
    set_texture_to_specified_dir(root_node=root_node, dir=dir)

使い方はこんな感じ。
resize_texture(root_node='root', dir=r'C:\temp\test', magnification=0.1)

magnificationで元画像からの倍率を指定します。
引数のwidthとheightで全て統一したサイズにもできます。(こっちのが優先される)
テクスチャは上書きはしたくなかったので、必ず別フォルダに書き出すようになってます。

また、pythonの画像処理ライブラリのPILを利用しています。
http://www.lifewithpython.com/2013/09/pil.html

が、MAYAだと普通にそこら辺から落としてきたものだとエラーで使えないので、mayaに合わせてビルドしたモジュールが必要ということです。
GitHubにて2014~2016用の各種モジュールを配布してくださっている方がいると教えていただきましたので、以下にリンク貼っておきます。ダウンロードしてパスを通しておきましょう。

https://github.com/zclongpop123/maya_python_packages


3D人さんの記事から手に入れたテストモデルに実行するとこんな感じです。


コードの中にはテクスチャパスを取得したりゴニョゴニョしたり、色々なパーツがあるので分解して利用してもそれなりに使えるところもあるかもしれません。

ちなみに、なにやらjpgをリサイズしようとすると「IOError: decoder jpeg not available」と出てエラーになるようでした。
libjpegってのが無いようですね。
自分はtgaさえ処理できれば良かったので、対処してませんが他の形式でも何かあるかもしれません。

拍手[0回]

PR

コメント

プロフィール

HN:
モチオ
性別:
非公開
自己紹介:
テクニカルアーティスト(アニメーション出身)サポート対象Softimage/MotionBuilder/Mayaなど 言語 javascript / PHP / Python / VBAなど Webアプリも少しだけ作れる

P R