from PIL import Image
image = Image.open('logo.png')
assert im.mode.endswith('A'), 'This will only work with images having alpha!'
image.load()
alpha = image.split()[-1]
image2 = Image.new(image.mode, image.size, (255, 0, 0, 0))
image2.putalpha(alpha)
image2.save('logo-red.png')
How can I convert an partially alpha transparent image to have single (non-transparent) colour in PIL?
-
03-10-2022 - |
Domanda
I have a logo which I need to make into a monochrome version, for example all red. For example, convert this:
to this:
I've tried various techniques in PIL (mainly Image.paste), but the results do not honour the partially alpha transparent pixels around the edges.
Soluzione
Altri suggerimenti
After some searching around, I've found that altering the image data, pixel-by-pixel achieves the result, e.g.
from PIL import Image
image = Image.open('logo.png')
assert image.mode == 'RGBA', 'This will only work with RGBA images!'
width = image.size[0]
for index, (r, g, b, a) in enumerate(image.getdata()):
if a > 0:
y, x = divmod(index, width)
image.putpixel((x, y), (255, 0, 0, a))
image.save('logo-red.png')
This works pretty quickly for the small example image, but I'm not sure how it would work with larger files, so any alternatives would be welcomed!
With matplotlib use a mask to search for all the pixels are not completely transparent. .imread
loads this as a RGBA where A is the alpha channel, making the mask simple. From there simply use the mask to change the pixels to the desired color. In this case red is [1,0,0,1]
.
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
img = mpimg.imread('1EQ07.png')
opaque_idx = img[:,:,3]>0
img[opaque_idx] = [1,0,0,1]
plt.axis('off')
plt.imshow(img)
plt.show()
Edit: If you want to leave the alpha channel untouched, you can create a custom filter and apply it over the matched pixels.
def custom_filter((r,g,b,a)):
return (1,0,0,a)
img[opaque_idx] = np.apply_along_axis(custom_filter,1,img[opaque_idx])