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 - |
문제
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.
해결책
다른 팁
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])