cropping/rotation: caller must opt into transparency:
image_from_page, image_from_segment, image_from_polygon:
add parameter ``transparency``, independent of ``fill``
an alpha channel with the mask will be added iff ``transparency``,
colour in ``fill`` will be used regardless (for consumers which
cannot handle alpha channels)
@@ -301,7 +301,7 @@ def get_local_filename(url, start=None):
url = url[len(start):]
return url
-def image_from_polygon(image, polygon, fill='transparent'):
+def image_from_polygon(image, polygon, fill='background', transparency=False):
""""Mask an image with a polygon.
Given a PIL.Image ``image`` and a numpy array ``polygon``
@@ -309,30 +309,30 @@ def image_from_polygon(image, polygon, fill='transparent'):
outside the polygon hull to a color according to ``fill``:
- if ``background`` (the default), then use the median color
of the image;
- - if ``white``, then use white;
- - if ``transparent``, then add a transparency channel from
- the polygon mask (i.e. everything outside the polygon will
- be transparent).
+ - if ``white``, then use white.
+ Moreover, if ``transparent`` is true, then add an alpha channel
+ from the polygon mask (i.e. everything outside the polygon will
+ be transparent for those that can interpret alpha channels).
Return a new PIL.Image.
"""
mask = polygon_mask(image, polygon)
- if fill == 'transparent' and image.mode in ['RGB', 'L', 'RGBA', 'LA']:
- # ensure no information is lost by adding transparency channel
- # initialized to fully transparent outside the mask
- # (so consumers do not have to rely on background estimation):
- # ensure transparency maximizes (i.e. parent mask AND mask):
- if image.mode in ['RGBA', 'LA']:
- mask = ImageChops.darker(mask, image.getchannel('A')) # min opaque
- new_image = image.copy()
- new_image.putalpha(mask)
- return new_image
if fill == 'background':
background = ImageStat.Stat(image).median[0]
else:
background = 'white'
new_image = Image.new(image.mode, image.size, background)
new_image.paste(image, mask=mask)
+ if transparency and image.mode in ['RGB', 'L', 'RGBA', 'LA']:
+ # ensure no information is lost by adding transparency channel
+ # initialized to fully transparent outside the mask
+ # (so consumers do not have to rely on background estimation,
+ # which can fail on foreground-dominated segments, or white,
+ # which can be inconsistent on unbinarized images):
+ if image.mode in ['RGBA', 'LA']:
+ # ensure transparency maximizes (i.e. parent mask AND mask):
+ mask = ImageChops.darker(mask, image.getchannel('A')) # min opaque
+ new_image.putalpha(mask)
return new_image
def is_local_filename(url):
