115

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?

Sebastian
  • 2,470
  • 4
  • 21
  • 27
  • FYI, [difference between Image.blend, paste, composite and alpha_composite in Pillow](https://stackoverflow.com/q/72362114/5101148) – Simba May 27 '22 at 17:09

6 Answers6

189

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

unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • 1
    You may need to import depending on your module/system/version: from PIL import Image – Nuno Aniceto Apr 24 '15 at 10:57
  • 3
    Thanks @NunoAniceto, I've changed it to `from PIL import Image` to make the code more [compatible with Pillow](http://pillow.readthedocs.org/en/latest/porting-pil-to-pillow.html). – unutbu Apr 24 '15 at 11:46
  • If you're using Python 3.x, check https://stackoverflow.com/a/17530159/7326714 to fix the 'offeset' tuple integer error. – LucSpan Mar 09 '18 at 10:04
9

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.

Martin Thoma
  • 124,992
  • 159
  • 614
  • 958
5

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

0

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

Jenia
  • 374
  • 1
  • 4
  • 15
profuel
  • 128
  • 5
0

Image.blend()? [link]

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

Felix
  • 88,392
  • 43
  • 149
  • 167
0

Try this code below

from PIL import Image

# Load the existing image
existing_image = Image.open("existing_image.png")

# Create a new white image with 1440x900 dimensions
new_image = Image.new("RGB", (1440, 900), (255, 255, 255))

# Calculate the center position for the existing image
x = (new_image.width - existing_image.width) // 2
y = (new_image.height - existing_image.height) // 2

# Paste the existing image onto the new white image at the center position
new_image.paste(existing_image, (x, y))

# Save the new image as a PNG file
new_image.save("new_wallpaper.png")