Skip to content

Instantly share code, notes, and snippets.

@zvchei
Created September 2, 2025 16:52
Show Gist options
  • Select an option

  • Save zvchei/015075e07433e373b568f3f8f7b53dd8 to your computer and use it in GitHub Desktop.

Select an option

Save zvchei/015075e07433e373b568f3f8f7b53dd8 to your computer and use it in GitHub Desktop.
Script to arrange images two by two on A4 landscape pages. Each page will contain up to 2 images side by side with spacing between them.
#!/usr/bin/env python3
"""
MIT-0 License
Copyright (c) 2025
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
---
This script was generated by Claude Sonnet 4 via GitHub Copilot.
## Original prompt:
"Create a Python script that will process all images in the current directory
by arranging them two by two on A4 pages in a landscape orientation, so that
the images are side by side with a little space between. Preserve the aspect
ratio of the images. If the number of images is odd, one page will contain a
single image. The images may have different sizes, so white borders of various
widths are expected to be around them."
---
## Description:
Script to arrange images two by two on A4 landscape pages.
Each page will contain up to 2 images side by side with spacing between them.
## Usage:
1. Place this script in the directory containing your images.
2. Create a virtual environment and install dependencies:
python3 -m venv venv
source venv/bin/activate
python3 -m pip install --upgrade pip
pip install -r requirements.txt
3. Run the script: python arrange_images.py
4. The output PDF "arranged_images.pdf" will be created in the same directory.
"""
import os
import glob
from PIL import Image
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4, landscape
from reportlab.lib.utils import ImageReader
import io
def get_image_files(directory):
"""Get all image files from the directory."""
image_extensions = ['*.jpg', '*.jpeg', '*.png', '*.gif', '*.bmp', '*.tiff']
image_files = []
for extension in image_extensions:
image_files.extend(glob.glob(os.path.join(directory, extension)))
image_files.extend(glob.glob(os.path.join(directory, extension.upper())))
return sorted(image_files)
def resize_image_to_fit(image, max_width, max_height):
"""Resize image to fit within max dimensions while maintaining aspect ratio."""
img_width, img_height = image.size
# Calculate scaling factor
width_ratio = max_width / img_width
height_ratio = max_height / img_height
scale_factor = min(width_ratio, height_ratio)
# Calculate new dimensions
new_width = int(img_width * scale_factor)
new_height = int(img_height * scale_factor)
return image.resize((new_width, new_height), Image.Resampling.LANCZOS)
def create_page_with_images(image_paths, page_width, page_height):
"""Create a page with 1 or 2 images arranged side by side."""
# Convert points to pixels (assuming 72 DPI)
page_width_px = int(page_width * 2) # Higher resolution for better quality
page_height_px = int(page_height * 2)
# Create a white background
page_image = Image.new('RGB', (page_width_px, page_height_px), 'white')
# Define margins and spacing
margin = int(page_width_px * 0.05) # 5% margin
spacing = int(page_width_px * 0.02) # 2% spacing between images
if len(image_paths) == 1:
# Single image - center it on the page
img = Image.open(image_paths[0])
# Available space for the image
available_width = page_width_px - 2 * margin
available_height = page_height_px - 2 * margin
# Resize image to fit
resized_img = resize_image_to_fit(img, available_width, available_height)
# Calculate position to center the image
x = (page_width_px - resized_img.width) // 2
y = (page_height_px - resized_img.height) // 2
page_image.paste(resized_img, (x, y))
elif len(image_paths) == 2:
# Two images side by side
available_width = (page_width_px - 2 * margin - spacing) // 2
available_height = page_height_px - 2 * margin
for i, img_path in enumerate(image_paths):
img = Image.open(img_path)
resized_img = resize_image_to_fit(img, available_width, available_height)
# Calculate position
if i == 0: # Left image
x = margin + (available_width - resized_img.width) // 2
else: # Right image
x = margin + available_width + spacing + (available_width - resized_img.width) // 2
y = margin + (available_height - resized_img.height) // 2
page_image.paste(resized_img, (x, y))
return page_image
def create_pdf_with_images(image_files, output_filename):
"""Create a PDF with images arranged two per page."""
# A4 landscape dimensions in points
page_width, page_height = landscape(A4)
# Create PDF canvas
c = canvas.Canvas(output_filename, pagesize=landscape(A4))
# Process images in pairs
for i in range(0, len(image_files), 2):
# Get 1 or 2 images for this page
page_images = image_files[i:i+2]
print(f"Processing page {i//2 + 1} with images: {[os.path.basename(img) for img in page_images]}")
# Create page image
page_img = create_page_with_images(page_images, page_width, page_height)
# Convert PIL image to bytes for reportlab
img_buffer = io.BytesIO()
page_img.save(img_buffer, format='PNG', dpi=(150, 150))
img_buffer.seek(0)
# Add image to PDF
c.drawImage(ImageReader(img_buffer), 0, 0, width=page_width, height=page_height)
# Start new page if not the last page
if i + 2 < len(image_files):
c.showPage()
# Save PDF
c.save()
print(f"PDF saved as: {output_filename}")
def main():
"""Main function to arrange images in PDF."""
current_dir = os.path.dirname(os.path.abspath(__file__))
# Get all image files in the current directory
image_files = get_image_files(current_dir)
if not image_files:
print("No image files found in the current directory!")
return
print(f"Found {len(image_files)} image files:")
for img in image_files:
print(f" - {os.path.basename(img)}")
# Create output filename
output_filename = os.path.join(current_dir, "arranged_images.pdf")
# Create PDF
create_pdf_with_images(image_files, output_filename)
# Calculate number of pages
num_pages = (len(image_files) + 1) // 2
print(f"\nCreated {num_pages} page(s) with {len(image_files)} images")
print(f"Output file: {output_filename}")
if __name__ == "__main__":
main()
Pillow>=10.0.0
reportlab>=4.0.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment