Pillow: putalpha() added some black background to the output

Created on 13 Jun 2020  ·  8Comments  ·  Source: python-pillow/Pillow

What did you do?

I opened a .PNG image with PIL, then I've applicate some transparency and then saved it.

What did you expect to happen?

The image saved properly with the transparency.

What actually happened?

The image went saved with the trasparency as long with a black background.

What are your OS, Python and Pillow versions?

  • OS: Ubuntu 16.04.6 LTS
  • Python: 3.6
  • Pillow: 7.1.2
    logo = Image.open('files/logo.png').convert('RGBA')
    logo.putalpha(180)
    logo.save('files/output.png', format='PNG')

image

Most helpful comment

Checking with your deleted image from my email, I get a png with a semi-transparent black background as I would expect. Fully transparent pixels in images are often either black or white, but there is no requirement for either; putalpha just makes them semi-transparent.

If you only wish to modify the transparent pixels, the following code might help you:

from PIL import Image
with Image.open("file.png") as im:
    im2 = im.copy()
    im2.putalpha(180)
    im.paste(im2, im)
    im.save("file2.png")

All 8 comments

Can you please provide the original image? Running your code on the combined image in your post works properly for me.

fr2

@thekillgfx your second post looks like it's been deleted

Checking with your deleted image from my email, I get a png with a semi-transparent black background as I would expect. Fully transparent pixels in images are often either black or white, but there is no requirement for either; putalpha just makes them semi-transparent.

If you only wish to modify the transparent pixels, the following code might help you:

from PIL import Image
with Image.open("file.png") as im:
    im2 = im.copy()
    im2.putalpha(180)
    im.paste(im2, im)
    im.save("file2.png")

@nulano this code is working fine.
But why is this happening? Like operating directly on the image cause the problem, but doing the same thing on a copy let the problem away..

Like I said, putalpha modifies all pixels by setting their alpha value, so fully transparent pixels become only partially transparent. The code I posted above first sets (putalpha) all pixels to semi-transparent in a copy, then copies (paste) all pixels to the original image using the original alpha values as a mask. This means that fully transparent pixels in the original image are skipped during the paste.

Ok, I got it. Wouldn't be better if the putalpha function manage this kind of situations by itself without need to work on a copy to then merge the Images?

From the docs:

Image.putalpha(alpha)
Adds or replaces the alpha layer in this image. If the image does not have an alpha layer, it’s converted to “LA” or “RGBA”. The new layer must be either “L” or “1”.

So the function is designed to replace the layer, not multiply/blend it.

I can't find a function which only works on one colour band, most functions apply the same operation to each band. The only other way I can think of doing this, is to extract the alpha band from the image using getdata('A'), update the alpha band using e.g. eval or point, then replace the alpha band in the original image using putalpha. I haven't tested this to see which is faster.

You could probably use something like ImageChops.multiply(im, Image.new("RGBA", im.size, (255, 255, 255, 127))), but that feels less intuitive to me.

@thekillgfx are you happy for this to be closed? It seems to me like your problem has been solved and your question answered

Was this page helpful?
0 / 5 - 0 ratings

Related issues

FlowerCode picture FlowerCode  ·  4Comments

anonymous530 picture anonymous530  ·  3Comments

naaaargle picture naaaargle  ·  3Comments

thinrhino picture thinrhino  ·  3Comments

boskicthebrain picture boskicthebrain  ·  4Comments