How can I convert an partially alpha transparent image to have single (non-transparent) colour in PIL?

StackOverflow https://stackoverflow.com/questions/21404967

Frage

I have a logo which I need to make into a monochrome version, for example all red. For example, convert this:

enter image description here

to this:

enter image description here

I've tried various techniques in PIL (mainly Image.paste), but the results do not honour the partially alpha transparent pixels around the edges.

War es hilfreich?

Lösung

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

Andere Tipps

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

enter image description here

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

enter image description here

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top