将目录中的所有图片按从名称从左到右合并到一张大的精灵图里。
新建: sprite_combine.py

#!/usr/bin/env python3
"""
Sprite Combine Tool
Combine all PNG images in a directory into a single horizontal strip.
"""

import argparse
import os
import sys
from pathlib import Path
from PIL import Image


def main():
    parser = argparse.ArgumentParser(
        description="Combine PNG images from a directory into a single horizontal image."
    )
    parser.add_argument(
        "directory",
        help="Directory containing PNG images to combine"
    )
    parser.add_argument(
        "-o", "--output",
        default="combined.png",
        help="Output filename (default: combined.png)"
    )
    parser.add_argument(
        "-s", "--spacing",
        type=int,
        default=0,
        help="Spacing between images in pixels (default: 0)"
    )
    parser.add_argument(
        "-b", "--background",
        default=None,
        help="Background color (hex format like #FFFFFF or transparent for none)"
    )

    args = parser.parse_args()

    dir_path = Path(args.directory)

    if not dir_path.exists():
        print(f"Error: Directory '{args.directory}' does not exist.", file=sys.stderr)
        sys.exit(1)

    if not dir_path.is_dir():
        print(f"Error: '{args.directory}' is not a directory.", file=sys.stderr)
        sys.exit(1)

    # Get all PNG files and sort by name
    png_files = sorted(dir_path.glob("*.png"), key=lambda x: x.name)

    if not png_files:
        print(f"Error: No PNG files found in '{args.directory}'.", file=sys.stderr)
        sys.exit(1)

    print(f"Found {len(png_files)} PNG image(s):")
    for f in png_files:
        print(f"  - {f.name}")

    # Load images
    images = []
    for filepath in png_files:
        try:
            img = Image.open(filepath)
            # Convert to RGBA to handle transparency properly
            img = img.convert("RGBA")
            images.append(img)
        except Exception as e:
            print(f"Warning: Could not load '{filepath}': {e}", file=sys.stderr)
            continue

    if not images:
        print("Error: No valid images could be loaded.", file=sys.stderr)
        sys.exit(1)

    # Calculate dimensions
    spacing = args.spacing
    max_height = max(img.height for img in images)
    total_width = sum(img.width for img in images) + spacing * (len(images) - 1)

    print(f"\nOutput dimensions: {total_width} x {max_height} pixels")

    # Parse background color
    bg_color = None
    if args.background:
        if args.background.lower() == "transparent":
            bg_color = None
        else:
            # Parse hex color
            hex_color = args.background.lstrip("#")
            if len(hex_color) == 6:
                bg_color = tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4)) + (255,)
            else:
                print(f"Warning: Invalid hex color '{args.background}', using transparent.", file=sys.stderr)

    # Create combined image
    if bg_color is not None:
        combined = Image.new("RGBA", (total_width, max_height), bg_color)
    else:
        combined = Image.new("RGBA", (total_width, max_height), (255, 255, 255, 0))

    # Paste images
    x_offset = 0
    for img in images:
        # Center vertically if different heights
        y_offset = (max_height - img.height) // 2
        combined.paste(img, (x_offset, y_offset), img)
        x_offset += img.width + spacing

    # Save result
    output_path = Path(args.output)
    combined.save(output_path, "PNG")
    print(f"\nSaved combined image to: {output_path.resolve()}")


if __name__ == "__main__":
    main()

依赖文件 requirements.txt

Pillow>=10.0.0

安装依赖:

pip install -r requirements.txt

运行方式:

python sprite_combine.py <folder_name>

可以改为bat文件spcomb.bat方便执行:

python sprite_combine.py %1

使用纯净css运行合并后的精灵图动画,可用于微信小程序:
wxml如下:

<view class="shutu-animation"></view>

wxss如下,假设精灵图为150x150px,合并后大小为9150x150px:


.shutu-animation {
  width: 150rpx;
  height: 150rpx;
  background-image: url('https://xxxxx/combine.png'); /* 单行图 */
  background-size: 9150rpx 150rpx; /* 总宽 x 高 */
  animation: play 6s steps(61) infinite; /* 30帧需要走29步 */
}

@keyframes play {
  100% {
    background-position: -9150rpx 0; 
  }
}

标签: none 阅读量: 16

添加新评论