Skip to main content

image-grid-combine

Combine several images into one grid image, with Pillow.

Point it at a handful of photos and it lays them out on a single canvas: square-ish grid by default, equal cells, cover-cropped so nothing is distorted. The layout maths is plain Python with no Pillow import, so you can reuse the geometry on its own if you already have your own drawing code.

pip install image-grid-combine

Command line

image-grid-combine grid.png one.jpg two.jpg three.jpg four.jpg

Four images become a 2x2 grid. Add a gutter and a margin:

image-grid-combine grid.png *.jpg --columns 3 --gap 12 --padding 24

Transparent background, cells pinned to 512x512, letterboxed instead of cropped:

image-grid-combine grid.png *.png --cell-size 512 --fit contain --background none

Run image-grid-combine --help for the full list.

Option Default Meaning
--columns auto Cells per row. Auto keeps the grid as square as the count allows.
--gap 0 Pixels between neighbouring cells.
--padding 0 Pixels around the outside of the grid.
--background white #rgb, #rrggbb, #rrggbbaa, r,g,b[,a], a colour name, or none.
--fit cover cover crops to fill, contain letterboxes, stretch distorts.
--cell-size auto 512 or 512x384. Auto uses the largest source, capped by --max-width.
--max-width 2048 Width cap when the cell size is auto.
--max-height none Optional height cap when the cell size is auto.

Library

from image_grid_combine import combine

grid = combine(["a.jpg", "b.jpg", "c.jpg", "d.jpg"], columns=2, gap=12)
grid.save("grid.png")

Sources can be paths, bytes, binary file objects, or PIL.Image.Image instances — handy if the images came off the network or out of a database and you would rather not round-trip them through disk. The result is always an RGBA image; nothing you pass in is modified.

from io import BytesIO
from image_grid_combine import combine, combine_to_file

grid = combine([open("a.jpg", "rb"), BytesIO(response.content)], fit="contain")
combine_to_file("grid.jpg", ["a.jpg", "b.jpg"], gap=8)  # JPEG flattens onto white

combine_to_file picks the format from the file extension. JPEG has no alpha channel, so the grid is flattened onto the background before saving.

Layout on its own

If you are drawing somewhere other than a Pillow canvas — a PDF, a reportlab document, a matplotlib figure — the geometry is importable without Pillow:

from image_grid_combine.layout import auto_cell_size, compute_grid_layout, fit_rect

cell_w, cell_h, columns = auto_cell_size([(1600, 900), (900, 1600)], gap=12)
for cell in compute_grid_layout(2, columns, cell_w, cell_h, gap=12):
    rect = fit_rect(1600, 900, cell.width, cell.height, "cover")
    print(cell.x, cell.y, rect.sx, rect.sy, rect.sw, rect.sh)

fit_rect returns a FitResult naming both rectangles: the crop to take from the source (sx, sy, sw, sh) and the box to draw it into (dx, dy, dw, dh). Under cover the destination is the whole cell and the source is cropped; under contain it is the other way round.

Notes

  • Cell sizes are equal across the grid, so mixing a panorama with a portrait gives you two cropped images rather than a ragged layout. --fit contain trades the crop for letterboxing.
  • Cropping and scaling round to whole pixels, so the last row of a partial grid can differ by a pixel from the rows above it. That is deliberate — sub-pixel placement blurs edges.
  • Works on Python 3.8+. The only dependency is Pillow.
  • ai image combiner — a browser-based AI image combiner for when you would rather not write code: drop in two or more photos and merge them with AI blending, no install and no signup.

License

MIT

Metadata

Release files for image-grid-combine 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for image-grid-combine 1.0.0
File Size Uploaded
image_grid_combine-1.0.0.tar.gz 15.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for image-grid-combine 1.0.0
File Interpreter ABI Platform
image_grid_combine-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 27.4 kB

Release files / image_grid_combine-1.0.0.tar.gz

Download URL image_grid_combine-1.0.0.tar.gz
Size 15.7 kB
Tags Source
SHA-256 checksum
How to use checksums
e3c1dc51c1ec1418310d6e5ea378c3df50b772da9d409a8fdf7ac5915627d7f0
BLAKE2b-256 checksum
How to use checksums
99be81777391e7413885cf4fb8deaa4f23fe6f46e55a234bc8a2b9fa744dc43e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.6

Release files / image_grid_combine-1.0.0-py3-none-any.whl

Download URL image_grid_combine-1.0.0-py3-none-any.whl
Size 11.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c7f56841d1d9cd8b4eb2c7e429b7d90dcaf689befe40d80c0fe688eb1a46b51b
BLAKE2b-256 checksum
How to use checksums
b83d7561b341471393041c28499b2cc603e3151a1e0656f868dd65b071edfb4d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.6

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page