user1796160
user1796160

Reputation: 597

How to paste an image onto a larger image using Pillow?

I've got a fairly simple code file:

from PIL import Image
til = Image.new("RGB",(50,50))
im = Image.open("tile.png") #25x25
til.paste(im)
til.paste(im,(23,0))
til.paste(im,(0,23))
til.paste(im,(23,23))
til.save("testtiles.png")

However, when I attempt to run it, I get the following error:

Traceback (most recent call last):
    til.paste(im)
  File "C:\Python27\lib\site-packages\PIL\Image.py", line 1340, in paste
    self.im.paste(im, box)
ValueError: images do not match

What is causing this error? They are both RGB images, the docs don't say anything about this error.

Upvotes: 20

Views: 48995

Answers (2)

JH_WK
JH_WK

Reputation: 71

So I might be a little late, but maybe it helps the people coming after a little:

When I had the same issue I couldn't find much about it. So I wrote a snippet which pastes one image into another.

def PasteImage(source, target, pos):

    # Usage:
    # tgtimg = PIL.Image.open('my_target_image.png')
    # srcimg = PIL.Image.open('my_source_image.jpg')
    # newimg = PasteImage(srcimg, tgtimg, (5, 5))
    # newimg.save('some_new_image.png')
    #

    smap = source.load()
    tmap = target.load()
    for i in range(pos[0], pos[0] + source.size[0]): # Width
        for j in range(pos[1], pos[1] + source.size[1]): # Height
            # For the paste position in the image the position from the top-left
            # corner is being used. Therefore 
            # range(pos[x] - pos[x], pos[x] + source.size[x] - pos[x])
            # = range(0, source.size[x]) can be used for navigating the source image.

            sx = i - pos[0]
            sy = j - pos[1]

            # Change color of the pixels
            tmap[i, j] = smap[sx, sy]

    return target

Not necessarely the best approach, since it takes roughly O(N^2), but it works for small images. Maybe someone can improve the code to be more efficient.

I made it in a hurry, so it doesnt have input validation either. just know that the width and height of the source image MUST be smaller or equal to width and height of the target image, otherwise it will crash. You can also only paste the whole image, and not sections or non-rectangular images.

Upvotes: 1

rayt
rayt

Reputation: 590

The problem is in the first pasting - according to the PIL documentation (http://effbot.org/imagingbook/image.htm), if no "box" argument is passed, images' sizes must match.

EDIT: I actually misunderstood the documentation, you are right, it's not there. But from what I tried here, it seems like passing no second argument, sizes must match. If you want to keep the second image's size and place it in the upper-left corner of the first image, just do:

...
til.paste(im,(0,0))
...

Upvotes: 31

Related Questions