reddit-image-wall-getter/reddit_imgs/system/edge_propagation_scaler.py

132 lines
4.0 KiB
Python
Executable File

#!/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()