import numpy as np
from PIL import Image, ImageDraw
import os
import random


def generate_curve(start, end, height, num_points=10):
    """
    生成一条随机曲线，用于拼图边界。
    :param start: 曲线起点坐标 (x, y)
    :param end: 曲线终点坐标 (x, y)
    :param height: 曲线的最大上下偏移高度
    :param num_points: 曲线的弯点数量
    :return: 曲线坐标列表
    """
    points = [start]
    for i in range(1, num_points):
        x = start[0] + (end[0] - start[0]) * i / num_points
        y = start[1] + (end[1] - start[1]) * i / num_points + random.randint(-height, height)
        points.append((x, y))
    points.append(end)
    return points


def create_jigsaw_with_curves(image_path, output_dir, rows=5, cols=5, curve_height=20, num_points=10):
    """
    用曲线切割图片成拼图块。
    :param image_path: 输入图片路径
    :param output_dir: 输出拼图块保存目录
    :param rows: 拼图的行数
    :param cols: 拼图的列数
    :param curve_height: 曲线的最大偏移高度
    :param num_points: 每条曲线的弯点数量
    """
    # 加载图片
    img = Image.open(image_path)
    img_width, img_height = img.size

    # 每块的宽和高
    piece_width = img_width // cols
    piece_height = img_height // rows

    # 创建输出目录
    os.makedirs(output_dir, exist_ok=True)

    # 生成拼图
    for row in range(rows):
        for col in range(cols):
            # 创建掩码
            mask = Image.new("L", (img_width, img_height), 0)
            draw = ImageDraw.Draw(mask)

            # 定义拼图块的四个边界
            left = col * piece_width
            top = row * piece_height
            right = (col + 1) * piece_width
            bottom = (row + 1) * piece_height

            # 上边界
            top_curve = generate_curve((left, top), (right, top), curve_height, num_points)
            # 下边界
            bottom_curve = generate_curve((right, bottom), (left, bottom), curve_height, num_points)
            # 左边界
            left_curve = generate_curve((left, bottom), (left, top), curve_height, num_points)
            # 右边界
            right_curve = generate_curve((right, top), (right, bottom), curve_height, num_points)

            # 构造拼图块路径
            path = top_curve + bottom_curve + left_curve + right_curve

            # 绘制掩码
            draw.polygon(path, fill=255)

            # 裁剪拼图块
            piece = Image.composite(img, Image.new("RGBA", img.size, (255, 255, 255, 0)), mask)
            piece_cropped = piece.crop((left, top, right, bottom))

            # 保存拼图块
            piece_path = os.path.join(output_dir, f"piece_{row}_{col}.png")
            piece_cropped.save(piece_path)

    print(f"拼图已生成，共 {rows * cols} 块，保存到：{output_dir}")


# 示例调用
image_path = "input.jpg"  # 输入图片路径
output_dir = "output_jigsaw"  # 输出目录
create_jigsaw_with_curves(image_path, output_dir, rows=5, cols=5, curve_height=30, num_points=10)
