PIL - Image Paste On Another Image With Alpha

13,771

Solution 1

The closest I got was to use the alpha_composite function found here. Works really rather well!

Solution 2

I usually revolve to numpy/scipy for the image processing tasks, though my first experience (a good one) was with PIL. As such I am not sure if the below will meet your needs.

given a particular pixel1, with alpha1 from image1, and pixel2, with alpha2, from image2, outputPixel will be the following.

alpha1>=alpha2 then outputPixel = (alpha1-alpha2)*pixel1 + alpha2*pixel2
alpha1==alpha2 then outputPixel = 0*pixel1 + alpha2*pixel2 note in this case alpha1-alpha2 equals 0
alpha1<alpha2 then outputPixel = 0*pixel1 + alpha2*pixel2

Using the above definitions we will basically compute the contribution from the first image for each pixel, then add this to the second image after applying its alpha map

we can directly get this from imshow as well

r1 = scipy.misc.imread('red.png')
b1 = scipy.misc.imread('blue.png')
r1 = r1.astype(numpy.float32)
b1 = b1.astype(numpy.float32)

alpha1 = r1[:,:,3]
alpha2 = b1[:,:,3]

#scale the alpha mattes to keep resulting alpha'd images in display range
alpha1Scaled = alpha1 / 255
alpha2Scaled = alpha2 / 255
diff1 = alpha1Scaled - alpha2Scaled

i1 = r1[:,:,0:3]
i2 = b1[:,:,0:3]
#create the alpha mapped images
d1 = numpy.zeros(i1.shape)
d2 = numpy.zeros(i2.shape)
for z in range(3):
    d1[:,:,z] =(diff1>=0)*diff1*i1[:,:,z] 
    d2[:,:,z] = i2[:,:,z]*alpha2Scaled

#belend the result
result = d1 + d2

#rescale in case of overflow
resultScaled = 255*(result/result.max())

#to display 
imshow(( resultScaled  ).astype(uint8))
show()

#note the below gives us the same result
figure()
imshow(red)
imshow(blue)
show()
Share:
13,771
DizzyDoo
Author by

DizzyDoo

Updated on June 04, 2022

Comments

  • DizzyDoo
    DizzyDoo about 2 years

    I'm struggling a touch with pasting one image with a transparent background on another, also with a transparent background, with the right alpha/colour blending.

    Here are some example images, red.png and blue.png:

    red.png blue.png

    I want to paste blue.png on top of red.png, and achieve this effect:

    Expected Result

    That image was made by combining the two images in Photoshop, simply as two layers.

    The closest I can get using the Python Imaging Library is:

    Actual Result

    with this code:

    from PIL import Image
    
    blue = Image.open("blue.png")
    red = Image.open("red.png")
    red.paste(blue, (0,0), blue)
    red.save("result.png")
    

    Do you see how the alpha and the colour is off where the two circles overlap? In the expected result image, the red and blue blends together in a purplish way, but there's an unwanted alpha halo in the actual result image.

    How can I achieve my ideal result in PIL?

  • DizzyDoo
    DizzyDoo over 10 years
    Thanks for the answer Paul, almost what I'm after, despite the black background I seem to get. The alpha composite algorithm I've posted a link to below seems to get where I wanted to go with slightly better results.
  • lapin
    lapin almost 5 years
    Actually alpha_composite is now a native fonction from Pillow 2.0. See here.