You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Mac上使用Python实现JPG图片合并与拆分的方法问询

Absolutely! This is totally doable with Python on macOS using the Pillow library (the go-to tool for image manipulation in Python). Let’s walk through both merging your JPGs into a single large image and splitting that big image back into the original named files step by step.

1. Merging Multiple JPGs into a Single Large Image

First, you’ll need to install Pillow if you haven’t already. Open your Terminal and run:

pip3 install pillow

Here’s a script that will merge your JPGs into a grid-based large image, plus save a metadata file you’ll need later for splitting:

from PIL import Image
import os

def merge_jpgs(input_folder, output_path, cols=10):
    # Grab all JPG files, sorted by filename (adjust sorting if you need a specific order)
    jpg_files = sorted([f for f in os.listdir(input_folder) if f.lower().endswith('.jpg')])
    if not jpg_files:
        print("No JPG files found in the input folder.")
        return
    
    # Open each image and store it with its original filename
    images = []
    for file in jpg_files:
        img_path = os.path.join(input_folder, file)
        img = Image.open(img_path)
        images.append((img, file))
    
    # Calculate grid dimensions and merged image size
    max_width = max(img.width for img, _ in images)
    max_height = max(img.height for img, _ in images)
    cols = min(cols, len(images))  # Don't use more columns than we have images
    rows = (len(images) + cols - 1) // cols  # Round up to get total rows
    
    total_width = max_width * cols
    total_height = max_height * rows
    
    # Create a blank white background (change color to 'black' or a hex code if needed)
    merged_img = Image.new('RGB', (total_width, total_height), color='white')
    
    # Paste each image into the grid, centered in its cell
    for idx, (img, filename) in enumerate(images):
        row = idx // cols
        col = idx % cols
        x = col * max_width
        y = row * max_height
        
        # Center smaller images in their grid cell
        offset_x = (max_width - img.width) // 2
        offset_y = (max_height - img.height) // 2
        merged_img.paste(img, (x + offset_x, y + offset_y))
    
    # Save the merged image with high quality
    merged_img.save(output_path, format='JPEG', quality=95)
    print(f"Merged {len(images)} images into {output_path} successfully!")
    
    # Save metadata to remember filenames, positions, and original image sizes
    metadata_path = output_path.replace('.jpg', '_metadata.txt')
    with open(metadata_path, 'w') as f:
        f.write(f"cols:{cols}\n")
        f.write(f"max_width:{max_width}\n")
        f.write(f"max_height:{max_height}\n")
        for idx, (img, filename) in enumerate(images):
            f.write(f"{idx}:{filename}:{img.width}:{img.height}\n")
    print(f"Metadata saved to {metadata_path} — keep this file safe, you'll need it for splitting!")

# Example usage:
# merge_jpgs('/Users/yourname/Photos/MyJPGs', '/Users/yourname/merged_output.jpg', cols=10)

Notes for Merging:

  • Adjust the cols parameter to change how many images appear per row (e.g., cols=5 for a narrower grid).
  • If you want to sort images by modification time instead of filename, replace sorted(jpg_files) with sorted(jpg_files, key=lambda x: os.path.getmtime(os.path.join(input_folder, x))).
  • The white background can be changed to any color — use a hex code like #f0f0f0 for light gray, or 'black' for dark backgrounds.
2. Splitting the Merged Image Back into Original Files

This script uses the metadata file generated during merging to accurately crop the large image back into individual JPGs with their original filenames:

from PIL import Image
import os

def split_merged_image(merged_path, output_folder):
    # Check for the required metadata file
    metadata_path = merged_path.replace('.jpg', '_metadata.txt')
    if not os.path.exists(metadata_path):
        print("Error: Missing metadata file! You need the _metadata.txt file created during merging.")
        return
    
    # Parse metadata
    metadata = {}
    image_details = []
    with open(metadata_path, 'r') as f:
        for line in f:
            line = line.strip()
            if not line:
                continue
            parts = line.split(':', 1)
            key = parts[0]
            value = parts[1]
            if key == 'cols':
                metadata['cols'] = int(value)
            elif key == 'max_width':
                metadata['max_width'] = int(value)
            elif key == 'max_height':
                metadata['max_height'] = int(value)
            else:
                # Parse index, filename, original width, original height
                idx_str, filename, orig_width, orig_height = line.split(':', 3)
                image_details.append((int(idx_str), filename, int(orig_width), int(orig_height)))
    
    # Sort images back to their original order
    image_details.sort()
    
    # Open the merged image
    merged_img = Image.open(merged_path)
    
    # Create output folder if it doesn't exist
    os.makedirs(output_folder, exist_ok=True)
    
    # Crop and save each image
    for idx, filename, orig_width, orig_height in image_details:
        row = idx // metadata['cols']
        col = idx % metadata['cols']
        x = col * metadata['max_width']
        y = row * metadata['max_height']
        
        # Calculate the exact crop area (accounting for centered placement)
        offset_x = (metadata['max_width'] - orig_width) // 2
        offset_y = (metadata['max_height'] - orig_height) // 2
        crop_box = (
            x + offset_x,
            y + offset_y,
            x + offset_x + orig_width,
            y + offset_y + orig_height
        )
        
        cropped_img = merged_img.crop(crop_box)
        output_path = os.path.join(output_folder, filename)
        cropped_img.save(output_path, format='JPEG', quality=95)
        print(f"Saved: {output_path}")
    
    print(f"Done! Split merged image into {len(image_details)} files in {output_folder}.")

# Example usage:
# split_merged_image('/Users/yourname/merged_output.jpg', '/Users/yourname/SplitImages')

Notes for Splitting:

  • Don’t rename or delete the _metadata.txt file — it’s critical for mapping the cropped areas to original filenames.
  • The output folder will be created automatically if it doesn’t exist.
  • If you modified the background color during merging, it won’t affect the split result since we crop exactly to the original image dimensions.

内容的提问来源于stack exchange,提问作者Lyon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 09:32:32