How to merge a transparent png image with another image using PIL
Solution 1
from PIL import Image
background = Image.open("test1.png")
foreground = Image.open("test2.png")
background.paste(foreground, (0, 0), foreground)
background.show()
First parameter to .paste()
is the image to paste. Second are coordinates, and the secret sauce is the third parameter. It indicates a mask that will be used to paste the image. If you pass a image with transparency, then the alpha channel is used as mask.
Check the docs.
Solution 2
Image.paste
does not work as expected when the background image also contains transparency. You need to use real Alpha Compositing.
Pillow 2.0 contains an alpha_composite
function that does this.
background = Image.open("test1.png")
foreground = Image.open("test2.png")
Image.alpha_composite(background, foreground).save("test3.png")
EDIT: Both images need to be of the type RGBA. So you need to call convert('RGBA')
if they are paletted, etc.. If the background does not have an alpha channel, then you can use the regular paste method (which should be faster).
Solution 3
As olt already pointed out, Image.paste
doesn't work properly, when source and destination both contain alpha.
Consider the following scenario:
Two test images, both contain alpha:
layer1 = Image.open("layer1.png")
layer2 = Image.open("layer2.png")
Compositing image using Image.paste
like so:
final1 = Image.new("RGBA", layer1.size)
final1.paste(layer1, (0,0), layer1)
final1.paste(layer2, (0,0), layer2)
produces the following image (the alpha part of the overlayed red pixels is completely taken from the 2nd layer. The pixels are not blended correctly):
Compositing image using Image.alpha_composite
like so:
final2 = Image.new("RGBA", layer1.size)
final2 = Image.alpha_composite(final2, layer1)
final2 = Image.alpha_composite(final2, layer2)
produces the following (correct) image:
Solution 4
One can also use blending:
im1 = Image.open("im1.png")
im2 = Image.open("im2.png")
blended = Image.blend(im1, im2, alpha=0.5)
blended.save("blended.png")
Solution 5
def trans_paste(bg_img,fg_img,box=(0,0)):
fg_img_trans = Image.new("RGBA",bg_img.size)
fg_img_trans.paste(fg_img,box,mask=fg_img)
new_img = Image.alpha_composite(bg_img,fg_img_trans)
return new_img
Related videos on Youtube
Comments
-
Arackna over 2 years
I have a transparent png image "foo.png" and I've opened another image with
im = Image.open("foo2.png");
now what i need is to merge foo.png with foo2.png.
( foo.png contains some text and I want to print that text on foo2.png )
-
nosklo about 13 yearsDon't use
;
at the end of your commands in python: It's ugly... -
Arackna about 13 yearsI'll keep that in my mind , thanks !!
-
-
Mark Ransom over 11 yearsTo make sure the foreground contains transparency in all cases, use
foreground.convert('RGBA')
for the mask parameter. -
Peter Hansen almost 11 yearsI just used paste() to overlay one semi-transparent image on another, with PIL, and it worked as I expected. In what way doesn't it work as you expected?
-
Silouane Gerin over 10 yearsThanks. I was too missing the third parameter.
-
homm over 9 years@PeterHansen, paste() doesn't work as expected "when the background image also contains transparency".
-
homm over 9 years@PeterHansen There is example: github.com/python-pillow/Pillow/issues/…
-
Peter Hansen over 9 years@homm thanks. That was so long ago I have no memory of what I tried. It seems likely I did miss the part you quoted about the background image also having transparency.
-
physicalattraction almost 9 yearsWow! This solution did the trick instantly two weeks ago, but now I totally forgot it already, and now I see it again, it again does the trick!
-
Deniz Ozger about 8 yearsI'm getting
ValueError: bad transparency mask
-
William H. Hooper almost 8 yearsDepending on your version, you may have to install the Python Image Library, and:' from PIL import Image`
-
Beatriz Fonseca over 7 yearsAmazing, you can use image as mask. But can I use vectorial images like svg?
-
digitaldavenyc over 7 yearsI get
ValueError: image has wrong made
as well @DenizOzger -
Viet about 7 yearsThanks for the screenshots! Really helps!
-
Lian almost 7 yearsThis worked for me whereas paste was punching a "transparent hole" through my background.
-
Mithril almost 7 yearsBut
alpha_composite
can not set the offset, would you mind to give an example to completely replacepaste
function? -
P.Melch almost 7 yearsI guess you would have to create a new empty image with the same size as the garget image, paste the layer at the proper position and use alpha_compositing to blend the new image over the target image.
-
Liviu Sosu over 6 yearsThis one ascetically worked for me. The images must have exactly the same size, but it is ok. The paste function did not quite cut it for me ...
-
AFP_555 about 6 yearsThe secret sauce was tasty
-
Schütze almost 6 years'ValueError: images do not match'
-
Schütze almost 6 years
TypeError: paste() got an unexpected keyword argument 'alpha'
-
nvd over 5 yearsPossibly, they are of different dimensions. You may need to scale or crop one of those.
-
Mingwei Samuel over 5 years@DenizOzger To fix
ValueError: bad transparency mask
usebg.paste(fg, (0, 0), fg.convert('RGBA'))
-
MilkyWay90 about 5 years@Schütze see nvd's comment because he/she didn't ping (using @blahblah) you
-
jimf about 5 yearsHi, can you possibly add a little more context to your answer? Otherwise the requestor is not likely to learn the "why" behind it.
-
lllllllllllll about 5 years
ValueError: images do not match
-
user3613932 almost 5 yearsThank you for indicating the information about the mask and the link to the documentation appreciate it.
-
Trect over 4 yearsOMG!! I was trying some stupid login on
cv2
to do this. In fact, spent 3 days on this. Love the secret sause -
Trect over 4 years
ValueError: images do not match
. Because this method works only when the image sizes are same -
yota about 4 yearsthis does not work as expected, it is not a proper overlay for a transparent image. fading transparency gives ugly results. It transparency is ON/OFF you should get what you expect though
-
Luis Jose almost 4 yearsThank you for sharing. In my case "import Image" doesn't work. I had to use "from PIL import Image" instead.
-
Student almost 3 yearsI get: ValueError: images do not match
-
P.Melch almost 3 yearsImages need to have the same size
-
Jordan The Genius about 2 years@Schütze I had to add these lines to avoid "images do not match": ` cloud_as_img.convert("RGBA") cloud_as_img.putalpha(255) cloud_as_img.save(temp_file_name) `