How do you composite an image onto another image with PIL in Python?

PythonImage ProcessingPython Imaging-Library

Python Problem Overview


I need to take an image and place it onto a new, generated white background in order for it to be converted into a downloadable desktop wallpaper. So the process would go:

  1. Generate new, all white image with 1440x900 dimensions
  2. Place existing image on top, centered
  3. Save as single image

In PIL, I see the ImageDraw object, but nothing indicates it can draw existing image data onto another image. Suggestions or links anyone can recommend?

Python Solutions


Solution 1 - Python

This can be accomplished with an Image instance's paste method:

from PIL import Image
img = Image.open('/path/to/file', 'r')
img_w, img_h = img.size
background = Image.new('RGBA', (1440, 900), (255, 255, 255, 255))
bg_w, bg_h = background.size
offset = ((bg_w - img_w) // 2, (bg_h - img_h) // 2)
background.paste(img, offset)
background.save('out.png')

This and many other PIL tricks can be picked up at Nadia Alramli's PIL Tutorial

Solution 2 - Python

Based on unutbus answer:

#!/usr/bin/env python

from PIL import Image
import math


def resize_canvas(old_image_path="314.jpg", new_image_path="save.jpg",
                  canvas_width=500, canvas_height=500):
    """
    Place one image on another image.

    Resize the canvas of old_image_path and store the new image in
    new_image_path. Center the image on the new canvas.
    """
    im = Image.open(old_image_path)
    old_width, old_height = im.size

    # Center the image
    x1 = int(math.floor((canvas_width - old_width) / 2))
    y1 = int(math.floor((canvas_height - old_height) / 2))

    mode = im.mode
    if len(mode) == 1:  # L, 1
        new_background = (255)
    if len(mode) == 3:  # RGB
        new_background = (255, 255, 255)
    if len(mode) == 4:  # RGBA, CMYK
        new_background = (255, 255, 255, 255)

    newImage = Image.new(mode, (canvas_width, canvas_height), new_background)
    newImage.paste(im, (x1, y1, x1 + old_width, y1 + old_height))
    newImage.save(new_image_path)

resize_canvas()

Remember to use Pillow (Documentation, GitHub, PyPI) instead of python-imaging as Pillow works with Python 2.X and Python 3.X.

Solution 3 - Python

This is to do something similar

Where I started was by generating that 'white background' in photoshop and exporting it as a PNG file. Thats where I got im1 (Image 1). Then used the paste function cause it's way easier.

from PIL import Image

im1 = Image.open('image/path/1.png')
im2 = Image.open('image/path/2.png')
area = (40, 1345, 551, 1625)  
im1.paste(im2, area)
                   l>(511+40) l>(280+1345)
         |    l> From 0 (move, 1345px down) 
          -> From 0 (top left, move 40 pixels right)

> Okay so where did these #'s come from? (40, 1345, 551, 1625) im2.size (511, 280) Because I added 40 right and 1345 down (40, 1345, 511, 280) I must add them to the original image size which = (40, 1345, 551, 1625)

im1.show() 

> to show your new image

Solution 4 - Python

Image.blend()? [link]

Or, better yet, Image.paste(), same link.

Solution 5 - Python

Maybe too late, but for such image operations, we do use ImageSpecField in model with original image.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSebastianView Question on Stackoverflow
Solution 1 - PythonunutbuView Answer on Stackoverflow
Solution 2 - PythonMartin ThomaView Answer on Stackoverflow
Solution 3 - PythonSteven JeffersView Answer on Stackoverflow
Solution 4 - PythonFelixView Answer on Stackoverflow
Solution 5 - PythonprofuelView Answer on Stackoverflow