Files
inventory/test.py
2026-07-21 16:11:09 +05:00

100 lines
4.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
Делает обои: размытый затемнённый фон + исходник в квадрате со скруглёнными углами.
Установка зависимости:
pip install pillow
Использование:
python make_wallpaper.py photo.jpg
python make_wallpaper.py photo.jpg -o wall.jpg --size 600
python make_wallpaper.py photo.jpg -W 2560 -H 1440 --size 800 --offset 0.35
"""
import argparse
from PIL import Image, ImageFilter, ImageEnhance, ImageDraw
def make_wallpaper(src_path, out_path, W=1920, H=1080, square=600,
radius_ratio=0.178, offset=0.5, blur=40, dim=0.6,
rim=True, shadow=True):
src = Image.open(src_path).convert("RGB")
sw, sh = src.size
# --- фон: масштабируем с запасом, обрезаем по центру, размываем и затемняем
scale = max(W / sw, H / sh) * 1.15
bg = src.resize((int(sw * scale), int(sh * scale)), Image.LANCZOS)
left, top = (bg.width - W) // 2, (bg.height - H) // 2
bg = bg.crop((left, top, left + W, top + H))
bg = bg.filter(ImageFilter.GaussianBlur(blur))
bg = ImageEnhance.Brightness(bg).enhance(dim)
# --- квадратный кроп из исходника
side = min(sw, sh)
if sh >= sw: # вертикальное фото — двигаем по вертикали
y = int((sh - side) * offset)
box = (0, y, side, y + side)
else: # горизонтальное — по горизонтали
x = int((sw - side) * offset)
box = (x, 0, x + side, side)
S = min(square, W, H)
R = int(S * radius_ratio)
fg = src.crop(box).resize((S, S), Image.LANCZOS)
fg = fg.filter(ImageFilter.UnsharpMask(radius=2, percent=40, threshold=3))
# --- маска со скруглением (рисуем крупно и уменьшаем = гладкие края)
SS = 4
mask = Image.new("L", (S * SS, S * SS), 0)
ImageDraw.Draw(mask).rounded_rectangle(
[0, 0, S * SS - 1, S * SS - 1], radius=R * SS, fill=255)
mask = mask.resize((S, S), Image.LANCZOS)
px, py = (W - S) // 2, (H - S) // 2
# --- мягкая тень
if shadow:
sh_layer = Image.new("L", (W, H), 0)
sh_layer.paste(mask.point(lambda v: int(v * 0.55)), (px, py + max(4, S // 40)))
sh_layer = sh_layer.filter(ImageFilter.GaussianBlur(max(8, S // 22)))
bg = Image.composite(Image.new("RGB", (W, H), (0, 0, 8)), bg, sh_layer)
bg.paste(fg, (px, py), mask)
# --- тонкая светлая рамка
if rim:
layer = Image.new("RGBA", (W, H), (0, 0, 0, 0))
ImageDraw.Draw(layer).rounded_rectangle(
[px, py, px + S - 1, py + S - 1], radius=R,
outline=(255, 255, 255, 45), width=2)
bg = Image.alpha_composite(bg.convert("RGBA"), layer).convert("RGB")
bg.save(out_path, quality=95)
return out_path
def main():
p = argparse.ArgumentParser(description="Обои с размытым фоном и скруглённым квадратом")
p.add_argument("input")
p.add_argument("-o", "--output", default="wallpaper.jpg")
p.add_argument("-W", "--width", type=int, default=1920)
p.add_argument("-H", "--height", type=int, default=1080)
p.add_argument("--size", type=int, default=600, help="сторона квадрата в пикселях")
p.add_argument("--radius", type=float, default=0.178,
help="радиус скругления как доля стороны (0.178 ≈ стиль iOS)")
p.add_argument("--offset", type=float, default=0.5,
help="сдвиг кропа 0..1 (0 — верх/лево, 1 — низ/право)")
p.add_argument("--blur", type=int, default=40)
p.add_argument("--dim", type=float, default=0.6, help="яркость фона, 1.0 = без затемнения")
p.add_argument("--no-rim", action="store_true")
p.add_argument("--no-shadow", action="store_true")
a = p.parse_args()
out = make_wallpaper(a.input, a.output, a.width, a.height, a.size,
a.radius, a.offset, a.blur, a.dim,
rim=not a.no_rim, shadow=not a.no_shadow)
print("Сохранено:", out)
if __name__ == "__main__":
main()