👻 Check our latest review to choose the best laptop for Machine Learning engineers and Deep learning tasks!
I"m using PIL to convert a transparent PNG image uploaded with Django to a JPG file. The output looks broken.
Source file
Code
Image.open(object.logo.path).save("/tmp/output.jpg", "JPEG")
or
Image.open(object.logo.path).convert("RGB").save("/tmp/output.png")
Result
Both ways, the resulting image looks like this:
Is there a way to fix this? I"d like to have white background where the transparent background used to be.
Solution
Thanks to the great answers, I"ve come up with the following function collection:
import Image
import numpy as np
def alpha_to_color(image, color=(255, 255, 255)):
"""Set all fully transparent pixels of an RGBA image to the specified color.
This is a very simple solution that might leave over some ugly edges, due
to semi-transparent areas. You should use alpha_composite_with color instead.
Source: http://stackoverflow.com/a/9166671/284318
Keyword Arguments:
image -- PIL RGBA Image object
color -- Tuple r, g, b (default 255, 255, 255)
"""
x = np.array(image)
r, g, b, a = np.rollaxis(x, axis=-1)
r[a == 0] = color[0]
g[a == 0] = color[1]
b[a == 0] = color[2]
x = np.dstack([r, g, b, a])
return Image.fromarray(x, "RGBA")
def alpha_composite(front, back):
"""Alpha composite two RGBA images.
Source: http://stackoverflow.com/a/9166671/284318
Keyword Arguments:
front -- PIL RGBA Image object
back -- PIL RGBA Image object
"""
front = np.asarray(front)
back = np.asarray(back)
result = np.empty(front.shape, dtype="float")
alpha = np.index_exp[:, :, 3:]
rgb = np.index_exp[:, :, :3]
falpha = front[alpha] / 255.0
balpha = back[alpha] / 255.0
result[alpha] = falpha + balpha * (1 - falpha)
old_setting = np.seterr(invalid="ignore")
result[rgb] = (front[rgb] * falpha + back[rgb] * balpha * (1 - falpha)) / result[alpha]
np.seterr(**old_setting)
result[alpha] *= 255
np.clip(result, 0, 255)
# astype("uint8") maps np.nan and np.inf to 0
result = result.astype("uint8")
result = Image.fromarray(result, "RGBA")
return result
def alpha_composite_with_color(image, color=(255, 255, 255)):
"""Alpha composite an RGBA image with a single color image of the
specified color and the same size as the original image.
Keyword Arguments:
image -- PIL RGBA Image object
color -- Tuple r, g, b (default 255, 255, 255)
"""
back = Image.new("RGBA", size=image.size, color=color + (255,))
return alpha_composite(image, back)
def pure_pil_alpha_to_color_v1(image, color=(255, 255, 255)):
"""Alpha composite an RGBA Image with a specified color.
NOTE: This version is much slower than the
alpha_composite_with_color solution. Use it only if
numpy is not available.
Source: http://stackoverflow.com/a/9168169/284318
Keyword Arguments:
image -- PIL RGBA Image object
color -- Tuple r, g, b (default 255, 255, 255)
"""
def blend_value(back, front, a):
return (front * a + back * (255 - a)) / 255
def blend_rgba(back, front):
result = [blend_value(back[i], front[i], front[3]) for i in (0, 1, 2)]
return tuple(result + [255])
im = image.copy() # don"t edit the reference directly
p = im.load() # load pixel array
for y in range(im.size[1]):
for x in range(im.size[0]):
p[x, y] = blend_rgba(color + (255,), p[x, y])
return im
def pure_pil_alpha_to_color_v2(image, color=(255, 255, 255)):
"""Alpha composite an RGBA Image with a specified color.
Simpler, faster version than the solutions above.
Source: http://stackoverflow.com/a/9459208/284318
Keyword Arguments:
image -- PIL RGBA Image object
color -- Tuple r, g, b (default 255, 255, 255)
"""
image.load() # needed for split()
background = Image.new("RGB", image.size, color)
background.paste(image, mask=image.split()[3]) # 3 is the alpha channel
return background
Performance
The simple non-compositing alpha_to_color
function is the fastest solution, but leaves behind ugly borders because it does not handle semi transparent areas.
Both the pure PIL and the numpy compositing solutions give great results, but alpha_composite_with_color
is much faster (8.93 msec) than pure_pil_alpha_to_color
(79.6 msec). If numpy is available on your system, that"s the way to go. (Update: The new pure PIL version is the fastest of all mentioned solutions.)
$ python -m timeit "import Image; from apps.front import utils; i = Image.open(u"logo.png"); i2 = utils.alpha_to_color(i)"
10 loops, best of 3: 4.67 msec per loop
$ python -m timeit "import Image; from apps.front import utils; i = Image.open(u"logo.png"); i2 = utils.alpha_composite_with_color(i)"
10 loops, best of 3: 8.93 msec per loop
$ python -m timeit "import Image; from apps.front import utils; i = Image.open(u"logo.png"); i2 = utils.pure_pil_alpha_to_color(i)"
10 loops, best of 3: 79.6 msec per loop
$ python -m timeit "import Image; from apps.front import utils; i = Image.open(u"logo.png"); i2 = utils.pure_pil_alpha_to_color_v2(i)"
10 loops, best of 3: 1.1 msec per loop
👻 Read also: what is the best laptop for engineering students?
Convert RGBA PNG to RGB with PIL __del__: Questions
How can I make a time delay in Python?
5 answers
I would like to know how to put a time delay in a Python script.
Answer #1
import time
time.sleep(5) # Delays for 5 seconds. You can also use a float value.
Here is another example where something is run approximately once a minute:
import time
while True:
print("This prints once a minute.")
time.sleep(60) # Delay for 1 minute (60 seconds).
Answer #2
You can use the sleep()
function in the time
module. It can take a float argument for sub-second resolution.
from time import sleep
sleep(0.1) # Time in seconds
Convert RGBA PNG to RGB with PIL __del__: Questions
How to delete a file or folder in Python?
5 answers
How do I delete a file or folder in Python?
Answer #1
os.remove()
removes a file.os.rmdir()
removes an empty directory.shutil.rmtree()
deletes a directory and all its contents.
Path
objects from the Python 3.4+ pathlib
module also expose these instance methods:
pathlib.Path.unlink()
removes a file or symbolic link.pathlib.Path.rmdir()
removes an empty directory.
We hope this article has helped you to resolve the problem. Apart from Convert RGBA PNG to RGB with PIL, check other __del__-related topics.
Want to excel in Python? See our review of the best Python online courses 2023. If you are interested in Data Science, check also how to learn programming in R.
By the way, this material is also available in other languages:
- Italiano Convert RGBA PNG to RGB with PIL
- Deutsch Convert RGBA PNG to RGB with PIL
- Français Convert RGBA PNG to RGB with PIL
- Español Convert RGBA PNG to RGB with PIL
- Türk Convert RGBA PNG to RGB with PIL
- Русский Convert RGBA PNG to RGB with PIL
- Português Convert RGBA PNG to RGB with PIL
- Polski Convert RGBA PNG to RGB with PIL
- Nederlandse Convert RGBA PNG to RGB with PIL
- 中文 Convert RGBA PNG to RGB with PIL
- 한국어 Convert RGBA PNG to RGB with PIL
- 日本語 Convert RGBA PNG to RGB with PIL
- हिन्दी Convert RGBA PNG to RGB with PIL
Milan | 2023-02-04
imp Python module is always a bit confusing 😭 Convert RGBA PNG to RGB with PIL is not the only problem I encountered. I am just not quite sure it is the best method
Singapore | 2023-02-04
Thanks for explaining! I was stuck with Convert RGBA PNG to RGB with PIL for some hours, finally got it done 🤗. Checked yesterday, it works!
Paris | 2023-02-04
Maybe there are another answers? What Convert RGBA PNG to RGB with PIL exactly means?. Checked yesterday, it works!