#!/usr/bin/env python3
"""
将用户提供的照片合成为遗照，烘焙到5张VR场景图中。
离线合成（非运行时叠加），效果更自然。
"""
from PIL import Image, ImageEnhance, ImageFilter, ImageDraw
import os

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PORTRAIT_PATH = os.path.join(BASE_DIR, '微信图片_2026-07-24_150330_404.jpg')

# 每个场景的遗照位置和大小（基于1368x768图片）
# x, y = 遗照中心点在场景图中的相对位置（0~1）
# w = 遗照宽度占场景图宽度的比例
SCENE_CONFIG = [
    {'file': 'vr-scene-1-buddhist.jpg',  'x': 0.50, 'y': 0.38, 'w': 0.10, 'frame': 'wood'},
    {'file': 'vr-scene-2-courtyard.jpg', 'x': 0.50, 'y': 0.40, 'w': 0.10, 'frame': 'wood'},
    {'file': 'vr-scene-3-chapel.jpg',    'x': 0.50, 'y': 0.38, 'w': 0.10, 'frame': 'gold'},
    {'file': 'vr-scene-4-modern.jpg',    'x': 0.50, 'y': 0.42, 'w': 0.09, 'frame': 'white'},
    {'file': 'vr-scene-5-islamic.jpg',   'x': 0.50, 'y': 0.38, 'w': 0.10, 'frame': 'gold'},
]

FRAME_COLORS = {
    'wood':  (60, 40, 20),
    'gold':  (180, 150, 60),
    'white': (220, 215, 210),
}

def extract_face(portrait_img):
    """从竖图中裁取人物上半身/面部区域"""
    w, h = portrait_img.size
    # 取上45%区域，横向居中裁取60%
    crop = portrait_img.crop((int(w*0.2), 0, int(w*0.8), int(h*0.45)))
    return crop

def apply_color_match(img, target_brightness):
    """调整图片亮度以匹配目标场景"""
    gray = img.convert('L')
    pixels = list(gray.get_flattened_data() if hasattr(gray, 'get_flattened_data') else gray.getdata())
    current_avg = sum(pixels) / len(pixels)
    if current_avg > 0:
        factor = target_brightness / current_avg
        factor = max(0.6, min(1.4, factor))  # 限制调整范围
        enhancer = ImageEnhance.Brightness(img)
        img = enhancer.enhance(factor)
    return img

def create_framed_portrait(face_img, frame_w, frame_h, frame_type, scene_brightness):
    """创建带相框的遗照图片"""
    # 调整面部亮度匹配场景
    face_adjusted = apply_color_match(face_img, scene_brightness)
    
    # 调整对比度，让遗照看起来像照片
    enhancer = ImageEnhance.Contrast(face_adjusted)
    face_adjusted = enhancer.enhance(1.05)
    
    # 略微降低饱和度（遗照通常色彩偏淡）
    enhancer = ImageEnhance.Color(face_adjusted)
    face_adjusted = enhancer.enhance(0.92)
    
    # 缩放到目标尺寸
    inner_w = frame_w - 6  # 相框边宽3px每边
    inner_h = frame_h - 6
    face_resized = face_adjusted.resize((inner_w, inner_h), Image.LANCZOS)
    
    # 创建带相框的完整图片
    framed = Image.new('RGBA', (frame_w, frame_h), (0, 0, 0, 0))
    
    # 相框外边（深色阴影）
    frame_color = FRAME_COLORS.get(frame_type, (60, 40, 20))
    
    # 绘制相框
    draw = ImageDraw.Draw(framed)
    # 外框
    draw.rectangle([0, 0, frame_w-1, frame_h-1], fill=frame_color + (255,))
    # 内框（稍亮的高光边）
    highlight = tuple(min(255, c + 30) for c in frame_color)
    draw.rectangle([2, 2, frame_w-3, frame_h-3], fill=highlight + (255,))
    draw.rectangle([3, 3, frame_w-4, frame_h-4], fill=frame_color + (255,))
    
    # 粘贴照片
    framed.paste(face_resized, (3, 3))
    
    # 添加微妙的高光（左上角，模拟室内光照）
    overlay = Image.new('RGBA', (frame_w, frame_h), (0, 0, 0, 0))
    od = ImageDraw.Draw(overlay)
    for i in range(8):
        alpha = max(0, 40 - i*5)
        od.line([(0, i), (frame_w, i)], fill=(255, 255, 240, alpha))
    framed = Image.alpha_composite(framed, overlay)
    
    return framed

def get_scene_brightness(scene_img, cx, cy, radius=50):
    """获取场景图中某点周围的平均亮度"""
    w, h = scene_img.size
    x1 = max(0, int(cx * w) - radius)
    y1 = max(0, int(cy * h) - radius)
    x2 = min(w, int(cx * w) + radius)
    y2 = min(h, int(cy * h) + radius)
    crop = scene_img.crop((x1, y1, x2, y2)).convert('L')
    pixels = list(crop.getdata())
    return sum(pixels) / len(pixels) if pixels else 128

def composite_scene(scene_path, face_img, config, output_path):
    """将遗照合成到场景图中"""
    scene = Image.open(scene_path).convert('RGBA')
    sw, sh = scene.size
    
    # 计算遗照尺寸和位置
    frame_w = int(sw * config['w'])
    frame_h = int(frame_w * 1.3)  # 竖版遗照
    cx = int(sw * config['x'])
    cy = int(sh * config['y'])
    
    # 获取该位置的场景亮度，用于匹配
    scene_brightness = get_scene_brightness(scene, config['x'], config['y'])
    
    # 创建带相框的遗照
    framed = create_framed_portrait(face_img, frame_w, frame_h, config['frame'], scene_brightness)
    
    # 创建阴影层
    shadow = Image.new('RGBA', (frame_w + 10, frame_h + 10), (0, 0, 0, 0))
    sd = ImageDraw.Draw(shadow)
    sd.rectangle([5, 7, frame_w + 4, frame_h + 6], fill=(0, 0, 0, 60))
    shadow = shadow.filter(ImageFilter.GaussianBlur(3))
    
    # 粘贴阴影
    px = cx - frame_w // 2
    py = cy - frame_h // 2
    scene.paste(shadow, (px - 5, py - 5), shadow)
    
    # 粘贴遗照
    scene.paste(framed, (px, py), framed)
    
    # 转回RGB保存
    result = scene.convert('RGB')
    result.save(output_path, 'JPEG', quality=92)
    print(f'  Saved: {output_path} ({result.size})')

def main():
    print('Loading portrait...')
    portrait = Image.open(PORTRAIT_PATH)
    face = extract_face(portrait)
    print(f'Face region: {face.size}')
    
    panorama_dir = os.path.join(BASE_DIR, 'src', 'assets', 'panorama')
    
    for config in SCENE_CONFIG:
        scene_path = os.path.join(panorama_dir, config['file'])
        backup_path = scene_path.replace('.jpg', '-orig.jpg')
        
        # 备份原图（仅第一次）
        if not os.path.exists(backup_path):
            import shutil
            shutil.copy2(scene_path, backup_path)
            print(f'  Backup: {backup_path}')
        
        print(f'Processing: {config["file"]}')
        composite_scene(backup_path, face, config, scene_path)
    
    print('Done!')

if __name__ == '__main__':
    main()
