# 静止画から背景用の映像を作る（ゆっくり寄る）と、早送りの寄りの映像を作る
import subprocess, sys, os
from PIL import Image
W, H, FPS = 1920, 1080, 30
BG = (245, 245, 240)

def pipe(out, n, frame_fn):
    p = subprocess.Popen(['ffmpeg','-v','error','-y','-f','rawvideo','-pix_fmt','rgb24','-s',f'{W}x{H}','-r',str(FPS),'-i','-',
                          '-c:v','libx264','-pix_fmt','yuv420p','-crf','18','-preset','veryfast',out], stdin=subprocess.PIPE)
    for i in range(n):
        p.stdin.write(frame_fn(i).tobytes())
    p.stdin.close(); p.wait()

def place(img, box_w, box_h, cx, cy, crop):
    """crop=(x,y,w,h) を box に収めて、中心 (cx,cy) に置いた 1920x1080 の絵"""
    x, y, w, h = crop
    c = img.crop((int(x), int(y), int(x + w), int(y + h)))
    s = min(box_w / c.width, box_h / c.height)
    c = c.resize((max(1, int(c.width * s)), max(1, int(c.height * s))), Image.LANCZOS)
    f = Image.new('RGB', (W, H), BG); f.paste(c, (int(cx - c.width / 2), int(cy - c.height / 2)))
    return f

def still(src, out, sec=20, z0=1.0, z1=1.12, fill=True):
    img = Image.open(src).convert('RGB')
    n = int(sec * FPS)
    def fr(i):
        z = z0 + (z1 - z0) * i / n
        if fill:   # 画面いっぱいに（はみ出しは切る）
            s = max(W / img.width, H / img.height) * z
        else:
            s = min(1500 / img.width, 800 / img.height) * z
        r = img.resize((int(img.width * s), int(img.height * s)), Image.LANCZOS)
        f = Image.new('RGB', (W, H), BG); f.paste(r, ((W - r.width) // 2, (H - r.height) // 2 - (0 if fill else 40)))
        return f
    pipe(out, n, fr)

def ff_zoom(out, shots, per=0.55, tail=2.5):
    """shots=[(画像, 寄る所の中心x, y, 寄り始めの幅, 寄り終わりの幅)]。1つずつ寄りながら、ぱっと切り替える"""
    imgs = {}
    frames = []
    for path, cx, cy, w0, w1 in shots:
        if path not in imgs:
            o = Image.open(path).convert('RGB'); P = 500
            pad = Image.new('RGB', (o.width + 2 * P, o.height + 2 * P), BG); pad.paste(o, (P, P)); imgs[path] = pad
        n = int(per * FPS)
        for i in range(n):
            w = w0 + (w1 - w0) * (i / n)
            h = w * 9 / 16
            frames.append((path, (cx + 500 - w / 2, cy + 500 - h / 2, w, h)))
    last = shots[-1]
    for i in range(int(tail * FPS)):
        frames.append((last[0], (last[1] + 500 - last[3] / 2, last[2] + 500 - last[3] * 9 / 32, last[3], last[3] * 9 / 16)))
    pipe(out, len(frames), lambda k: place(imgs[frames[k][0]], 1500, 844, W / 2, H / 2 - 30, frames[k][1]))

if __name__ == '__main__':
    A, B = 'src/oshiro_first.png', 'src/oshiro_final.png'
    ff_zoom('src/ff_oshiro.mp4', [
        (A, 222, 85, 330, 230), (B, 1060 - 850, 85, 330, 230),       # 顔（目）
        (A, 222, 190, 520, 400), (B, 210, 190, 520, 400),            # 肩
        (A, 222, 150, 300, 220), (B, 210, 150, 300, 220),            # 首と Vネック
        (A, 640, 140, 360, 260), (B, 1480 - 850, 140, 360, 260),     # 横の首
        (A, 425, 390, 1500, 1420), (B, 425, 390, 1500, 1420),            # 全体
    ])
    sys.exit(0) if '--ff' in sys.argv else None
    still('src/oshiro_first.png', 'src/bg_oshiro_first.mp4', fill=False)
    still('src/hakobu_before.png', 'src/bg_hakobu_before.mp4', fill=False)
    still('src/sleeve_before_55.png', 'src/bg_sleeve55.mp4', fill=False)
    still('src/LOG496_06_nurse_poses.png', 'src/bg_poses.mp4', fill=False)
    print('ok')
