#!/usr/bin/env python3 # -*- encoding: utf-8 -*- import sys from pathlib import Path from typing import Tuple, List from PIL import Image, ImageDraw START = -(sys.maxsize // 2) + 0 END = -(sys.maxsize // 2) + 1 CENTER = -(sys.maxsize // 2) + 2 POS_TOP_LEFT = (START, START) POS_CENTER_LEFT = (START, CENTER) POS_BOTTOM_LEFT = (START, END) POS_TOP_CENTER = (CENTER, START) POS_CENTER_CENTER = (CENTER, CENTER) POS_BOTTOM_CENTER = (CENTER, END) POS_TOP_RIGHT = (END, START) POS_CENTER_RIGHT = (END, CENTER) POS_BOTTOM_RIGHT = (END, END) P_TL = POS_TOP_LEFT P_CL = POS_CENTER_LEFT P_BL = POS_BOTTOM_LEFT P_TC = POS_TOP_CENTER P_CC = POS_CENTER_CENTER P_BC = POS_BOTTOM_CENTER P_TR = POS_TOP_RIGHT P_CR = POS_CENTER_RIGHT P_BR = POS_BOTTOM_RIGHT def edge_propagation_scaling(image: Image.Image, desired_size: Tuple[int, int], paste_position: Tuple[int, int] = P_CC, ) -> Image.Image: image = image.copy() scaled = Image.new(image.mode, desired_size) new_placement_: List[int] = list() for isz, ssz, pp in zip(image.size, scaled.size, paste_position,): if pp == START: new_placement_.append(0) elif pp == END: new_placement_.append(ssz-isz) elif pp == CENTER: new_placement_.append((ssz-isz)//2) else: new_placement_.append(pp) new_placement: Tuple[int, int] = new_placement_[0], new_placement_[1] del new_placement_ scaled.paste(image, new_placement) parts = dict( # left, upper, right, lower t=image.copy().crop( (0, 0, image.size[0], 1)), b=image.copy().crop( (0, image.size[1]-1, image.size[0], image.size[1])), l=image.copy().crop( (0, 0, 1, image.size[1])), r=image.copy().crop( (image.size[0]-1, 0, image.size[0], image.size[1])), ) if (sz := new_placement[1]) > 0: part = parts['t'].copy() resized = part.resize((part.size[0], sz)) scaled.paste(resized, (new_placement[0], 0)) if (sz := scaled.size[1]-(dsp := new_placement[1]+image.size[1])) > 0: part = parts['b'].copy() resized = part.resize((part.size[0], sz)) scaled.paste(resized, (new_placement[0], dsp)) if (sz := new_placement[0]) > 0: part = parts['l'].copy() resized = part.resize((sz, part.size[1])) scaled.paste(resized, (0, new_placement[1])) if (sz := scaled.size[0]-(dsp := new_placement[0]+image.size[0])) > 0: part = parts['r'].copy() resized = part.resize((sz, part.size[1])) scaled.paste(resized, (dsp, new_placement[1])) del parts corners = dict( tl=image.getpixel((0, 0)), tr=image.getpixel((image.size[0]-1, 0)), bl=image.getpixel((0, image.size[1]-1)), br=image.getpixel((image.size[0]-1, image.size[1]-1)), ) draw: ImageDraw.ImageDraw = ImageDraw.Draw(scaled) szt = new_placement[1] szb = scaled.size[1]-(dspb := new_placement[1]+image.size[1]) szl = new_placement[0] szr = scaled.size[0]-(dspr := new_placement[0]+image.size[0]) if szt > 0 and szl > 0: draw.rectangle(((0, 0), (szl-1, szt-1)), corners['tl']) if szt > 0 and szr > 0: draw.rectangle(((dspr, 0), (scaled.size[0], szt-1)), corners['tr']) if szb > 0 and szl > 0: draw.rectangle(((0, dspb), (szl-1, scaled.size[1])), corners['bl']) if szb > 0 and szr > 0: draw.rectangle(((dspr, dspb), scaled.size), corners['br']) del dspr del dspb del szt del szb del szl del szr return scaled def main(path: Path = Path('eps_test.png')): im: Image.Image = Image.open(path) ptd = dict(a=START, b=CENTER, c=END) for xp in 'abc': for yp in 'abc': im2 = edge_propagation_scaling( im, tuple(map(lambda i: int(i*2.5), im.size)), (ptd[xp], ptd[yp]), ) im2.save(Path(f'{path.stem}_out_{yp}{xp}{path.suffix}')) if __name__ == "__main__": main()