Question

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?

Was it helpful?

Solution

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

OTHER TIPS

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()

Use blend() to overlap two images. Below code overlap images in a folder. You can change the value of alpha to get the perfect blending

listing = os.listdir("images2/")
alpha = 2.0 
for file in listing:
    im = Image.open(path1 + file)  
    new_img = Image.blend(im, new_img, alpha) 
new_img.save("new008.png","PNG")
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top