在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
colsparameter to change how many images appear per row (e.g.,cols=5for a narrower grid). - If you want to sort images by modification time instead of filename, replace
sorted(jpg_files)withsorted(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
#f0f0f0for 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.txtfile — 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
相关产品推荐
相关产品推荐

