減色して透明色を設定する方法


■Pillowをインストール(Pythonの画像処理ライブラリ)

pip install pillow numpy


■pngquantのインストール(減色を使う場合)

  • macOS: brew install pngquant

  • Windows: https://pngquant.org/ からダウンロードしてPATHに追加

  • Linux: sudo apt install pngquant

■Pythonのソースコード(sprite_transparent.py)

from PIL import Image
import numpy as np
from collections import Counter
import argparse
import os
import sys
import subprocess

def detect_bg_color(img):
    """端の色から背景色を自動検出(ロバスト版)"""
    data = np.array(img.convert('RGB'))
    h, w = data.shape[:2]
    
    border_pixels = []
    # 上辺・下辺
    border_pixels.extend([tuple(p) for p in data[0, :]])
    border_pixels.extend([tuple(p) for p in data[-1, :]])
    # 左辺・右辺 (角は重複OK)
    border_pixels.extend([tuple(p) for p in data[:, 0]])
    border_pixels.extend([tuple(p) for p in data[:, -1]])
    
    # 最頻出色を背景色とする
    color_count = Counter(border_pixels)
    bg_color = color_count.most_common(1)[0][0]
    return bg_color

def optimize_with_pngquant(png_path, quality=90):
    """pngquantを使って最高品質の減色を行う"""
    try:
        subprocess.run([
            'pngquant', '--force', '--quality', f'{quality}-100',
            '--speed', '1', '--ext', '.png', png_path
        ], check=True, capture_output=True)
        print(f"✅ 高品質減色完了 (pngquant 256色最適化)")
        return True
    except FileNotFoundError:
        print("⚠️  pngquantが見つかりません。減色なしでRGBAのまま保存しました。")
        print("   インストール方法は上記の説明を参照してください。")
        return False
    except:
        print("pngquant実行中にエラーが発生しました。")
        return False

def create_transparent_sprite(input_path, output_path=None, tolerance=7, manual_bg=None, do_quantize=False):
    if not output_path:
        base = os.path.splitext(input_path)[0]
        output_path = f"{base}_transparent.png"
    
    img = Image.open(input_path).convert('RGBA')
    
    if manual_bg:
        bg_color = tuple(manual_bg)
        print(f"手動指定背景色: {bg_color}")
    else:
        bg_color = detect_bg_color(img)
        print(f"自動検出背景色: RGB{bg_color}")
    
    # Numpyで高速処理
    data = np.array(img, dtype=np.int16)
    rgb_part = data[:, :, :3]
    
    # 背景色との差分
    diff = np.abs(rgb_part - np.array(bg_color))
    mask = np.all(diff <= tolerance, axis=2)
    
    # 透明化
    data[mask, 3] = 0
    transparent_img = Image.fromarray(np.clip(data, 0, 255).astype(np.uint8))
    
    # まず保存
    transparent_img.save(output_path, 'PNG', optimize=True, compress_level=9)
    print(f"透明化完了: {output_path}")
    
    # 高品質減色(オプション)
    if do_quantize:
        optimize_with_pngquant(output_path, quality=90)
    
    return output_path

if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description='キャラクター/スプライトシート用 高品質透明化+減色ツール'
    )
    parser.add_argument('input', help='入力画像ファイル')
    parser.add_argument('-o', '--output', help='出力ファイル名')
    parser.add_argument('-t', '--tolerance', type=int, default=7,
                       help='透明化する色の許容範囲 (デフォルト:7。大きいほど多く透明化)')
    parser.add_argument('--bg', type=str, help='背景色を手動指定 (例: "255,0,255")')
    parser.add_argument('--quantize', action='store_true',
                       help='pngquantを使って高品質に256色減色する(超おすすめ)')
    
    args = parser.parse_args()
    
    bg = None
    if args.bg:
        try:
            bg = [int(x.strip()) for x in args.bg.split(',')]
            if len(bg) != 3:
                raise ValueError
        except:
            print("エラー: --bg は 'R,G,B' 形式で指定してください")
            sys.exit(1)
    
    create_transparent_sprite(
        args.input, 
        args.output, 
        args.tolerance, 
        bg, 
        args.quantize
    )

■使用例

# 基本(透明化だけ・高品質RGBApython sprite_transparent.py character.png

# 高品質減色も同時に(256色パレットPNGpython sprite_transparent.py character.png --quantize

# 許容範囲を広げたい場合(アンチエイリアスが多いとき)
python sprite_transparent.py character.png --quantize -t 20

# 出力ファイル名を指定
python sprite_transparent.py character.png -o my_sprite_fixed.png --quantize

いいなと思ったら応援しよう!

コメント

コメントするには、 ログイン または 会員登録 をお願いします。
減色して透明色を設定する方法|古井和雄
word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word word

mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1
mmMwWLliI0fiflO&1