else/BlurredLetterbox/blurredletterbox.py
2020-02-08 17:24:22 -08:00

102 lines
2.9 KiB
Python

import argparse
import os
import PIL.ImageFilter
import PIL.Image
import sys
def blur_letterbox(
image,
new_width=None,
new_height=None,
blurring=None,
):
(iw, ih) = image.size
new_width = new_width or iw
new_height = new_height or ih
if blurring is None:
blurring = (new_width * new_height) * 0.00001
print('Using bluriness', blurring)
background = image.resize(fit_over_bounds(iw, ih, new_width, new_height), PIL.Image.ANTIALIAS)
background = background.filter(PIL.ImageFilter.GaussianBlur(radius=blurring))
foreground = image.resize(fit_into_bounds(iw, ih, new_width, new_height), PIL.Image.ANTIALIAS)
background_offsets = offsets(background, new_width, new_height)
foreground_offsets = offsets(foreground, new_width, new_height)
final = PIL.Image.new(mode=image.mode, size=(new_width, new_height))
final.paste(background, (background_offsets))
final.paste(foreground, (foreground_offsets))
return final
def fit_into_bounds(iw, ih, fw, fh):
'''
Given the w+h of the image and the w+h of the frame,
return new w+h that fits the image into the frame
while maintaining the aspect ratio and leaving blank space
everywhere else
'''
ratio = min(fw/iw, fh/ih)
w = int(iw * ratio)
h = int(ih * ratio)
return (w, h)
def fit_over_bounds(iw, ih, fw, fh):
'''
Given the w+h of the image and the w+h of the frame,
return new w+h that covers the entire frame
while maintaining the aspect ratio
'''
ratio = max(fw/iw, fh/ih)
w = int(iw * ratio)
h = int(ih * ratio)
return (w, h)
def listget(li, index, fallback=None):
try:
return li[index]
except IndexError:
return fallback
def offsets(image, new_width, new_height):
'''
Calculate the horizontal and vertical offsets
needed to center the image in the given box
'''
horizontal = int((new_width - image.size[0]) / 2)
vertical = int((image.size[1] - new_height) / 2) * -1
return (horizontal, vertical)
def main(argv):
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('filename')
parser.add_argument('-w', '--width', dest='width', default=None)
parser.add_argument('-h', '--height', dest='height', default=None)
parser.add_argument('-b', '--blurring', dest='blurring', default=None)
args = parser.parse_args(argv)
if args.width is None and args.height is None:
print('Need a new width or height')
return
int_or_none = lambda x: int(x) if x else x
(base, extension) = os.path.splitext(args.filename)
new_name = base + '_blur' + extension
image = PIL.Image.open(args.filename)
image = blur_letterbox(
image,
int_or_none(args.width),
int_or_none(args.height),
int_or_none(args.blurring)
)
image.save(new_name)
if __name__ == '__main__':
raise SystemExit(main(sys.argv[1:]))