मैं PIL का उपयोग Django फ़ाइल के साथ अपलोड की गई पारदर्शी PNG छवि को JPG फ़ाइल में बदलने के लिए कर रहा हूँ। आउटपुट टूटा हुआ दिखता है।
मूल फाइल
कोड
Image.open(object.logo.path).save('/tmp/output.jpg', 'JPEG')
या
Image.open(object.logo.path).convert('RGB').save('/tmp/output.png')
परिणाम
दोनों तरीके, परिणामी छवि इस तरह दिखती है:
क्या इसे ठीक करने का कोई तरीका है? मुझे सफ़ेद पृष्ठभूमि पसंद है जहाँ पारदर्शी पृष्ठभूमि हुआ करती थी।
उपाय
महान जवाब के लिए धन्यवाद, मैं निम्नलिखित समारोह संग्रह के साथ आया हूं:
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
प्रदर्शन
सरल गैर-कंपोज़िटिंग alpha_to_color
फ़ंक्शन सबसे तेज़ समाधान है, लेकिन बदसूरत सीमाओं को पीछे छोड़ देता है क्योंकि यह अर्ध पारदर्शी क्षेत्रों को नहीं संभालता है।
शुद्ध पीआईएल और सुन्न कंपोजिट सॉल्यूशन दोनों शानदार परिणाम देते हैं, लेकिन (79.6 एमएसएक्स alpha_composite_with_color
) की तुलना में बहुत तेज (8.93 मिसे) है pure_pil_alpha_to_color
।यदि आपके सिस्टम पर सुन्नता उपलब्ध है, तो जाने का रास्ता है। (अपडेट: नया शुद्ध पीआईएल संस्करण सभी उल्लिखित समाधानों में सबसे तेज है।)
$ 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
im = image.copy()
हटाया जा सकता हैpure_pil_alpha_to_color_v2
। (बाद के बाद के उदाहरणों को बदलनेim
के लिएimage
, निश्चित रूप से।)