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

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

Domanda

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.

È stato utile?

Soluzione

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

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

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top