def put_highlight(image, highlight, resample_highlight, opacity, cache=None): if cache is None: cache = {} resample_highlight = getattr(Image, resample_highlight) id = 'highlight_%s_w%d_h%d_o%d'\ % (highlight, image.size[0], image.size[1], opacity) try: highlight = cache[id] except KeyError: highlight = open_image(highlight)\ .convert('RGBA').resize(image.size, resample_highlight) if opacity < 100: #apply opacity highlight_alpha = imtools.get_alpha(highlight) opacity = (255 * opacity) / 100 highlight.putalpha(ImageMath.eval("convert((a * o) / 255, 'L')", a=highlight_alpha, o=opacity)) #store in cache cache[id] = highlight if not has_transparency(image): image = image.convert('RGBA') else: if has_transparency(image): image = image.convert('RGBA') alpha = imtools.get_alpha(image) highlight = highlight.copy() highlight_alpha = imtools.get_alpha(highlight) highlight.putalpha(ImageMath.eval("convert(min(a, b), 'L')", a=alpha, b=highlight_alpha)) overlay = highlight.convert('RGB') paste(image, overlay, mask=highlight) return image
def grayscale(image, amount=100): grayscaled = ImageOps.grayscale(image) if amount < 100: grayscaled = imtools.blend(image, grayscaled, amount / 100.0) if image.mode == "RGBA": grayscaled.putalpha(imtools.get_alpha(image)) return grayscaled
def warmup(image, midtone, brighten, amount=100): """Apply a toning filter. Move the midtones to the desired color while preserving blacks and whites with optional mixing with original image - amount: 0-100%""" mode = image.mode info = image.info if image.mode != "L": im = imtools.convert(image, "L") else: im = image if image.mode != "RGBA" and imtools.has_transparency(image): image = imtools.convert(image, "RGBA") luma = imtools.convert(imtools.split(im)[0], "F") o = [] m = ImageColor.getrgb(midtone) b = brighten / 600.0 # Calculate channels separately for l in range(3): o.append(ImageMath.eval("m*(255-i)*i+i", i=luma, m=4 * ((m[l] / 255.0) - 0.5 + b) / 255.0).convert("L")) colorized = Image.merge("RGB", tuple(o)) if imtools.has_alpha(image): imtools.put_alpha(colorized, imtools.get_alpha(image)) if amount < 100: colorized = imtools.blend(image, colorized, amount / 100.0) return colorized
def put_contour(image, size=1, offset=0, contour_color=0, fill_color=0, opacity=100, include_image=True): if not has_transparency(image): return put_border( image, size, offset, contour_color, fill_color, opacity, include_image) image = image.convert('RGBA') mask = imtools.get_alpha(image) w, h = image.size outer_mask = mask.resize( (w + 2 * (size + offset), h + 2 * (size + offset)), Image.ANTIALIAS) inner_mask = mask.resize( (w + 2 * offset, h + 2 * offset), Image.ANTIALIAS) inner_mask = ImageOps.expand(inner_mask, border=size, fill=0) paste(outer_mask, (255 * opacity) / 100, mask=inner_mask) if include_image: image = ImageOps.expand(image, border=size + offset, fill=(0, 0, 0, 0)) mask = ImageOps.expand(mask, border=size + offset, fill=0) paste(outer_mask, 255, mask=mask) contour = ImageOps.colorize(outer_mask, (255, 255, 255), contour_color) paste(contour, fill_color, mask=inner_mask) if include_image: paste(contour, image, mask=image) contour.putalpha(outer_mask) return contour
def brightness(image, amount=50): """Adjust brightness from black to white - amount: -1(black) 0 (unchanged) 1(white) - repeat: how many times it should be repeated""" if amount == 0: return image image = imtools.convert_safe_mode(image) if amount < 0: #fade to black im = imtools.blend( image, Image.new(image.mode, image.size, 0), -amount / 100.0) else: #fade to white im = imtools.blend( image, Image.new(image.mode, image.size, ImageColor.getcolor('white', image.mode)), amount / 100.0) #fix image transparency mask if imtools.has_alpha(image): im.putalpha(imtools.get_alpha(image)) return im
def grayscale(image, amount=100): grayscaled = ImageOps.grayscale(image) if amount < 100: grayscaled = imtools.blend(image, grayscaled, amount / 100.0) if image.mode == 'RGBA': grayscaled.putalpha(imtools.get_alpha(image)) return grayscaled
def put_contour(image, size=1, offset=0, contour_color=0, fill_color=0, opacity=100, include_image=True): if not has_transparency(image): return put_border(image, size, offset, contour_color, fill_color, opacity, include_image) image = image.convert('RGBA') mask = imtools.get_alpha(image) w, h = image.size outer_mask = mask.resize( (w + 2 * (size + offset), h + 2 * (size + offset)), Image.ANTIALIAS) inner_mask = mask.resize((w + 2 * offset, h + 2 * offset), Image.ANTIALIAS) inner_mask = ImageOps.expand(inner_mask, border=size, fill=0) paste(outer_mask, (255 * opacity) / 100, mask=inner_mask) if include_image: image = ImageOps.expand(image, border=size + offset, fill=(0, 0, 0, 0)) mask = ImageOps.expand(mask, border=size + offset, fill=0) paste(outer_mask, 255, mask=mask) contour = ImageOps.colorize(outer_mask, (255, 255, 255), contour_color) paste(contour, fill_color, mask=inner_mask) if include_image: paste(contour, image, mask=image) contour.putalpha(outer_mask) return contour
def invert(image, amount=100): image = imtools.convert_safe_mode(image) inverted = ImageChops.invert(image) if amount < 100: inverted = imtools.blend(image, inverted, amount / 100.0) if imtools.has_alpha(image): inverted.putalpha(imtools.get_alpha(image)) return inverted
def solarize(image, treshold, amount=100): """Apply a filter - amount: 0-1""" image = imtools.convert_safe_mode(image) solarized = image.convert('RGB') solarized = ImageOps.solarize(solarized, treshold) if imtools.has_alpha(image): imtools.put_alpha(solarized, imtools.get_alpha(image)) if amount < 100: return imtools.blend(image, solarized, amount / 100.0) return solarized
def posterize(image, bits, amount=100): """Apply a filter - amount: 0-1""" image = imtools.convert_safe_mode(image) posterized = imtools.remove_alpha(image) posterized = ImageOps.posterize(posterized, bits) if imtools.has_alpha(image): imtools.put_alpha(posterized, imtools.get_alpha(image)) if amount < 100: return imtools.blend(image, posterized, amount / 100.0) return posterized
def equalize(image, amount=100): image = imtools.convert_safe_mode(image) if imtools.has_alpha(image): equalized = imtools.remove_alpha(image) else: equalized = image equalized = ImageOps.equalize(equalized) if imtools.has_alpha(image): imtools.put_alpha(equalized, imtools.get_alpha(image)) if amount < 100: equalized = imtools.blend(image, equalized, amount / 100.0) return equalized
def colorize(image, black, white, amount=100): """Apply a filter - amount: 0-1""" if image.mode != 'L': im = image.convert('L') else: im = image colorized = ImageOps.colorize(im, black, white) if image.mode == 'RGBA': colorized = colorized.convert('RGBA') colorized.putalpha(imtools.get_alpha(image)) if amount < 100: return imtools.blend(image, colorized, amount / 100.0) return colorized
def autocontrast(image, amount=100.0, cutoff=0): """Apply a filter - amount: 0-1 - repeat: how many times it should be repeated""" image = imtools.convert_safe_mode(image) if imtools.has_transparency(image): im = imtools.remove_alpha(image) else: im = image contrasted = ImageOps.autocontrast(im, cutoff) if imtools.has_transparency(image): imtools.put_alpha(contrasted, imtools.get_alpha(image)) if amount < 100: return imtools.blend(image, contrasted, amount / 100.0) return contrasted
def effect(image, filter, amount=100, repeat=1): """Apply a filter - amount: 0-1 - repeat: how many times it should be repeated""" filter = getattr(ImageFilter, filter) image = imtools.convert_safe_mode(image) for i in range(repeat): filtered = image.filter(filter) if imtools.has_alpha(image) and \ filter in [ImageFilter.CONTOUR, ImageFilter.EMBOSS]: filtered.putalpha(imtools.get_alpha(image)) if amount < 100: image = imtools.blend(image, filtered, amount / 100.0) else: image = filtered return image
def put_mask(image, mask, resample_mask, cache=None): if cache is None: cache = {} resample_mask = getattr(Image, resample_mask) id = mask + "_w%d_h%d" % image.size try: mask = cache[id] except KeyError: mask = cache[id] = open_image(mask).convert("L").resize(image.size, resample_mask) if not has_transparency(image): image = image.convert("RGBA") else: if has_transparency(image): image = image.convert("RGBA") alpha = imtools.get_alpha(image) mask = ImageMath.eval("convert(min(a, b), 'L')", a=alpha, b=mask) image.putalpha(mask) return image
def put_mask(image, mask, resample_mask, cache=None): if cache is None: cache = {} resample_mask = getattr(Image, resample_mask) id = mask + '_w%d_h%d' % image.size try: mask = cache[id] except KeyError: mask = cache[id] = open_image(mask).convert('L').resize( image.size, resample_mask) if not has_transparency(image): image = image.convert('RGBA') else: if has_transparency(image): image = image.convert('RGBA') alpha = imtools.get_alpha(image) mask = (ImageMath.eval("convert(min(a, b), 'L')", a=alpha, b=mask)) image.putalpha(mask) return image
def saturation(image, amount=50): """Adjust brightness from black to white - amount: -1(black) 0 (unchanged) 1(white) - repeat: how many times it should be repeated""" if amount == 0: return image amount /= 100.0 grey = image.convert("L").convert(image.mode) if amount < 0: #grayscale im = imtools.blend(image, grey, -amount) else: #overcolored = Image - (alpha * Grey) / (1 - alpha) alpha = 0.7 alpha_g = grey.point(lambda x: x * alpha) i_minus_alpha_g = ImageChops.subtract(image, alpha_g) overcolored = i_minus_alpha_g.point(lambda x: x / (1 - alpha)) im = imtools.blend(image, overcolored, amount) #fix image transparency mask if image.mode == 'RGBA': im.putalpha(imtools.get_alpha(image)) return im
def contrast(image, amount=50): """Adjust brightness from black to white - amount: -1(black) 0 (unchanged) 1(white) - repeat: how many times it should be repeated""" if amount == 0: return image elif amount < 0: #low contrast mean = reduce(lambda a, b: a + b, image.convert("L").histogram()) / 256.0 im = imtools.blend( image, Image.new("L", image.size, mean).convert(image.mode), -amount / 100.0) else: #high contrast im = imtools.blend(image, image.point(lambda x: x > 128 and 255), amount / 100.0) #fix image transparency mask if image.mode == 'RGBA': im.putalpha(imtools.get_alpha(image)) return im
def warmup(image, midtone, brighten, amount=100): """Apply a toning filter. Move the midtones to the desired color while preserving blacks and whites with optional mixing with original image - amount: 0-100%""" mode = image.mode info = image.info if image.mode != 'L': im = imtools.convert(image, 'L') else: im = image if image.mode != 'RGBA' and imtools.has_transparency(image): image = imtools.convert(image, 'RGBA') luma = imtools.convert(imtools.split(im)[0], 'F') o = [] m = ImageColor.getrgb(midtone) b = brighten / 600.0 # Calculate channels separately for l in range(3): o.append( ImageMath.eval("m*(255-i)*i+i", i=luma, m=4 * ((m[l] / 255.0) - 0.5 + b) / 255.0).convert('L')) colorized = Image.merge('RGB', tuple(o)) if imtools.has_alpha(image): imtools.put_alpha(colorized, imtools.get_alpha(image)) if amount < 100: colorized = imtools.blend(image, colorized, amount / 100.0) return colorized
def brightness(image, amount=50): """Adjust brightness from black to white - amount: -1(black) 0 (unchanged) 1(white) - repeat: how many times it should be repeated""" if amount == 0: return image image = imtools.convert_safe_mode(image) if amount < 0: #fade to black im = imtools.blend(image, Image.new(image.mode, image.size, 0), -amount / 100.0) else: #fade to white im = imtools.blend( image, Image.new(image.mode, image.size, ImageColor.getcolor('white', image.mode)), amount / 100.0) #fix image transparency mask if imtools.has_alpha(image): im.putalpha(imtools.get_alpha(image)) return im
def contrast(image, amount=50): """Adjust brightness from black to white - amount: -1(black) 0 (unchanged) 1(white) - repeat: how many times it should be repeated""" if amount == 0: return image elif amount < 0: #low contrast mean = reduce(lambda a, b: a + b, image.convert("L").histogram()) / 256.0 im = imtools.blend( image, Image.new("L", image.size, mean).convert(image.mode), -amount / 100.0) else: #high contrast im = imtools.blend( image, image.point(lambda x: x > 128 and 255), amount / 100.0) #fix image transparency mask if image.mode == 'RGBA': im.putalpha(imtools.get_alpha(image)) return im
def drop_shadow(image, horizontal_offset=5, vertical_offset=5, background_color=(255, 255, 255, 0), shadow_color=0x444444, border=8, shadow_blur=3, force_background_color=False, cache=None): """Add a gaussian blur drop shadow to an image. :param image: The image to overlay on top of the shadow. :param type: PIL Image :param offset: Offset of the shadow from the image as an (x,y) tuple. Can be positive or negative. :type offset: tuple of integers :param background_color: Background color behind the image. :param shadow_color: Shadow color (darkness). :param border: Width of the border around the image. This must be wide enough to account for the blurring of the shadow. :param shadow_blur: Number of times to apply the filter. More shadow_blur produce a more blurred shadow, but increase processing time. """ if cache is None: cache = {} if has_transparency(image) and image.mode != 'RGBA': # Make sure 'LA' and 'P' with trasparency are handled image = image.convert('RGBA') #get info size = image.size mode = image.mode back = None #assert image is RGBA if mode != 'RGBA': if mode != 'RGB': image = image.convert('RGB') mode = 'RGB' #create cache id id = ''.join([str(x) for x in ['shadow_', size, horizontal_offset, vertical_offset, border, shadow_blur, background_color, shadow_color]]) #look up in cache if id in cache: #retrieve from cache back, back_size = cache[id] if back is None: #size of backdrop back_size = (size[0] + abs(horizontal_offset) + 2 * border, size[1] + abs(vertical_offset) + 2 * border) #create shadow mask if mode == 'RGBA': image_mask = imtools.get_alpha(image) shadow = Image.new('L', back_size, 0) else: image_mask = Image.new(mode, size, shadow_color) shadow = Image.new(mode, back_size, background_color) shadow_left = border + max(horizontal_offset, 0) shadow_top = border + max(vertical_offset, 0) paste(shadow, image_mask, (shadow_left, shadow_top, shadow_left + size[0], shadow_top + size[1])) del image_mask # free up memory #blur shadow mask #Apply the filter to blur the edges of the shadow. Since a small #kernel is used, the filter must be applied repeatedly to get a decent #blur. n = 0 while n < shadow_blur: shadow = shadow.filter(ImageFilter.BLUR) n += 1 #create back if mode == 'RGBA': back = Image.new('RGBA', back_size, shadow_color) back.putalpha(shadow) del shadow # free up memory else: back = shadow cache[id] = back, back_size #Paste the input image onto the shadow backdrop image_left = border - min(horizontal_offset, 0) image_top = border - min(vertical_offset, 0) if mode == 'RGBA': paste(back, image, (image_left, image_top), image) if force_background_color: mask = imtools.get_alpha(back) paste(back, Image.new('RGB', back.size, background_color), (0, 0), ImageChops.invert(mask)) back.putalpha(mask) else: paste(back, image, (image_left, image_top)) return back