ฉันใช้ PIL เพื่อแปลงภาพ PNG โปร่งใสที่อัปโหลดด้วย Django เป็นไฟล์ 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
ฟังก์ชั่นการไม่ประกอบอย่างง่ายเป็นวิธีแก้ปัญหาที่เร็วที่สุด แต่จะทิ้งเส้นขอบที่น่าเกลียดไว้เพราะไม่ได้จัดการกับพื้นที่กึ่งโปร่งใส
ทั้ง PIL บริสุทธิ์และโซลูชันการผสมที่เป็นตัวเลขให้ผลลัพธ์ที่ยอดเยี่ยม แต่alpha_composite_with_color
เร็วกว่า (8.93 มิลลิวินาที) มากกว่าpure_pil_alpha_to_color
(79.6 มิลลิวินาที) มากหากมี numpy ในระบบของคุณนั่นคือวิธีที่จะไป (อัปเดต: PIL รุ่นใหม่ที่เร็วที่สุดในบรรดาโซลูชันที่กล่าวถึงทั้งหมด)
$ 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
ของเป็นแน่นอน)