Search code examples
pythonpython-imaging-library

Transparent Background PIL Python


I'm trying to paste a picture with transparent background into a picture using PIL. The problem is that I'm unable to remove the background and paste it without background onto the base picture

The picture I want to paste has a red background. I'm trying to remove the backround and paste the picture like this:

rm_image = Image.open("formations/testrm.png")

    rm_copy = rm_image.copy().convert("RGBA")

    background_color = (255, 0, 0, 255)

    for x in range(rm_copy.width):
        for y in range(rm_copy.height):
            r, g, b, a = rm_copy.getpixel((x, y))
            if (r, g, b, a) == background_color:
                rm_copy.putpixel((x, y), (0, 0, 0, 0))

    formation.paste(rm_copy, (1039, 396))

I also copied the base image and converted it to rgba like this:

    formation = Image.open(BytesIO(requests.get("LINK TO DISCORD ATTACHMENT").content))
    formation = formation.copy().convert("RGBA")

before I converted the base picture to RGBA the pasted Image had a completely black background. After converting the base picture to RGBA the background of the pasted Image is dark gray.

It would be really nice if someone could point out what is wrong and suggest possible ways to fix it.

Full code for recreation:

from io import BytesIO

import requests
from PIL import Image

formation = Image.open(BytesIO(requests.get("https://media.discordapp.net/attachments/1101171452377571428/1114864498424160316/FUSSBALL_4_3_3.png?width=1430&height=804").content))
formation = formation.copy().convert("RGBA")

rm_image = Image.open(BytesIO(requests.get("https://cdn.discordapp.com/attachments/1101171452377571428/1117737449716715570/testrm.png").content))

rm_copy = rm_image.copy().convert("RGBA")

background_color = (255, 0, 0, 255)

for x in range(rm_copy.width):
    for y in range(rm_copy.height):
        r, g, b, a = rm_copy.getpixel((x, y))
        if (r, g, b, a) == background_color:
            rm_copy.putpixel((x, y), (0, 0, 0, 0))

formation.paste(rm_copy, (1039, 396))

formation.show()

Solution

  • To enable transparency the trick is to pass to the paste method a mask as parameter (that is the same as the image to copy).
    Hoping is what you're looking for!

    from io import BytesIO
    import requests
    from PIL import Image
    
    #Load and convert as before (but convert directly the image without creating a copy)
    formation = Image.open(BytesIO(requests.get("https://media.discordapp.net/attachments/1101171452377571428/1114864498424160316/FUSSBALL_4_3_3.png?width=1430&height=804").content))
    formation = formation.convert("RGBA")
    rm_image = Image.open(BytesIO(requests.get("https://cdn.discordapp.com/attachments/1101171452377571428/1117737449716715570/testrm.png").content))
    rm_image = rm_image.convert("RGBA")
    
    #Create the copy with transparent background
    rm_copy = Image.new('RGBA', rm_image.size, (0, 0, 0, 0))
    
    for x in range(rm_image.width):
        for y in range(rm_image.height):
            r, g, b, a = rm_image.getpixel((x, y))
            if r != 255 or g != 0 or b != 0: #copy if it's not red
                rm_copy.putpixel((x, y), (r, g, b, a))
    
    formation.paste(rm_copy, (1045, 400), rm_copy) #slightly change the coordinates to overlap better
    formation.show()
    

    enter image description here