Peiser
Peiser

Reputation: 45

How to set image transparent for non-transparent part from another image?

I have two images: img1 and img2, and img2 is transparent except for one part of the image.

Using Pillow, how to crop the non-transparent part of img2 from img1? As a result, I would like to get img1 with transparent part, where img2 is non-transparent.

img1 and img2 are the same size.

Upvotes: 1

Views: 932

Answers (1)

HansHirse
HansHirse

Reputation: 18905

You can convert your Pillow images to NumPy arrays and make use of vectorized operations to speed up your processing.

Having img1.png (fully opaque random pixels)

img1

and img2.png (fully transparent background pixels, fully opaque red pixels)

img

one could use this approach to achieve the described behaviour:

import numpy as np
from PIL import Image

# Open images via Pillow
img1 = Image.open('img1.png')
img2 = Image.open('img2.png')

# Convert images to NumPy arrays
img1_np = np.array(img1)
img2_np = np.array(img2)

# Get (only full) opaque pixels in img2 as mask
mask = img2_np[:, :, 3] == 255

# Make pixels in img1 within mask transparent
img1_np[mask, 3] = 0

# Convert image back to Pillow
img1 = Image.fromarray(img1_np)

# Save image
img1.save('img1_mod.png')

The modified img1_mod.png would look like this (fully opaque random background pixels, transparent pixels where there's the red square in img2.png):

img1_mod

If you have "smooth" transparency, i.e. your alpha channel has values from the whole range of [0 ... 255], we could modify the code. Having such an img2_smooth.png

img2_smooth

that'd be the modified code:

import numpy as np
from PIL import Image

# Open images via Pillow
img1 = Image.open('img1.png')
img2 = Image.open('img2_smooth.png')

# Convert images to NumPy arrays
img1_np = np.array(img1)
img2_np = np.array(img2)

# Get (also partially) opaque pixels in img2 as mask         # <--
mask = img2_np[:, :, 3] > 0                                  # <--

# Make pixels in img1 within mask (partially) transparent    # <--
img1_np[mask, 3] = 255 - img2_np[mask, 3]                    # <--

# Convert image back to Pillow
img1 = Image.fromarray(img1_np)

# Save image
img1.save('img1_smooth_mod.png')

And that'd be new output img1_smooth_mod.png:

img2_smooth_mod

Hope that helps!

----------------------------------------
System information
----------------------------------------
Platform:    Windows-10-10.0.16299-SP0
Python:      3.8.1
NumPy:       1.18.1
Pillow:      7.0.0
----------------------------------------

Upvotes: 3

Related Questions