import random
from io import BytesIO
from PIL import Image, ImageFilter, ImageDraw, ImageStat, ImageFont
from PIL import ImageEnhance
from PIL import ImageChops
from PIL import ImageOps
import cv2
from nonebot import logger

from konabot.common.path import FONTS_PATH
from konabot.plugins.fx_process.color_handle import ColorHandle

import math

from konabot.plugins.fx_process.gradient import GradientGenerator
import numpy as np

from konabot.plugins.fx_process.image_storage import ImageStorager
from konabot.plugins.fx_process.math_helper import expand_contours
from konabot.plugins.fx_process.types import SenderInfo, StoredInfo

class ImageFilterImplement:
    @staticmethod
    def apply_blur(image: Image.Image, radius: float = 10) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')

        return image.filter(ImageFilter.GaussianBlur(radius))
    
    # 马赛克
    @staticmethod
    def apply_mosaic(image: Image.Image, pixel_size: int = 10) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')

        if pixel_size <= 0:
            pixel_size = 1
        # 缩小图像
        small_image = image.resize(
            (image.width // pixel_size, image.height // pixel_size),
            Image.Resampling.NEAREST
        )
        # 放大图像
        return small_image.resize(image.size, Image.Resampling.NEAREST)
    
    @staticmethod
    def apply_contour(image: Image.Image) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        return image.filter(ImageFilter.CONTOUR)
    
    @staticmethod
    def apply_sharpen(image: Image.Image) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        return image.filter(ImageFilter.SHARPEN)
    
    @staticmethod
    def apply_edge_enhance(image: Image.Image) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        return image.filter(ImageFilter.EDGE_ENHANCE)
    
    @staticmethod
    def apply_emboss(image: Image.Image) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        return image.filter(ImageFilter.EMBOSS)
    
    @staticmethod
    def apply_find_edges(image: Image.Image) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        return image.filter(ImageFilter.FIND_EDGES)
    
    @staticmethod
    def apply_smooth(image: Image.Image) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        return image.filter(ImageFilter.SMOOTH)
    
    # 反色
    @staticmethod
    def apply_invert(image: Image.Image) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        
        # 转换为 numpy 数组
        arr = np.array(image)
        
        # 只反转 RGB 通道，保持 Alpha 不变
        arr[:, :, :3] = 255 - arr[:, :, :3]
        
        return Image.fromarray(arr)
    
    # 黑白灰度
    @staticmethod
    def apply_black_white(image: Image.Image) -> Image.Image:
        # 保留透明度通道
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        r, g, b, a = image.split()
        gray = Image.merge('RGB', (r, g, b)).convert('L')
        return Image.merge('RGBA', (gray, gray, gray, a))
    
    # 阈值
    @staticmethod
    def apply_threshold(image: Image.Image, threshold: int = 128) -> Image.Image:
        # 保留透明度通道
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        r, g, b, a = image.split()
        gray = Image.merge('RGB', (r, g, b)).convert('L')
        bw = gray.point(lambda x: 255 if x >= threshold else 0, '1')
        return Image.merge('RGBA', (bw.convert('L'), bw.convert('L'), bw.convert('L'), a))
    
    # 对比度
    @staticmethod
    def apply_contrast(image: Image.Image, factor: float = 1.5) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        enhancer = ImageEnhance.Contrast(image)
        return enhancer.enhance(factor)
    
    # 亮度
    @staticmethod
    def apply_brightness(image: Image.Image, factor: float = 1.5) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        enhancer = ImageEnhance.Brightness(image)
        return enhancer.enhance(factor)
    
    # 色彩
    @staticmethod
    def apply_color(image: Image.Image, factor: float = 1.5) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        enhancer = ImageEnhance.Color(image)
        return enhancer.enhance(factor)
    
    # 三色调
    @staticmethod
    def apply_to_color(image: Image.Image, color: str = 'rgb(255,0,0)') -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        
        rgb_color = ColorHandle.parse_color(color)
        
        # 转换为灰度并获取数组
        gray = image.convert('L')
        lum = np.array(gray, dtype=np.float32) / 255.0  # 归一化到 [0,1]
        
        # 获取 alpha
        alpha = np.array(image.getchannel('A'))
        
        target_r = rgb_color[0] * lum
        target_g = rgb_color[1] * lum
        target_b = rgb_color[2] * lum
        
        # 堆叠通道
        result_rgb = np.stack([target_r, target_g, target_b], axis=-1)
        result_rgb = np.clip(result_rgb, 0, 255).astype(np.uint8)
        
        # 创建结果图像
        result = np.zeros((image.height, image.width, 4), dtype=np.uint8)
        result[:, :, :3] = result_rgb
        result[:, :, 3] = alpha
        
        return Image.fromarray(result, 'RGBA')
    
    # JPEG 损坏感压缩
    @staticmethod
    def apply_jpeg_damage(image: Image.Image, quality: int = 10) -> Image.Image:
        quality = max(1, min(95, int(quality)))

        alpha = None
        if image.mode in ('RGBA', 'LA') or (image.mode == 'P' and 'transparency' in image.info):
            rgba_image = image.convert('RGBA')
            alpha = rgba_image.getchannel('A')
            rgb_image = Image.new('RGB', rgba_image.size, (255, 255, 255))
            rgb_image.paste(rgba_image, mask=alpha)
        else:
            rgb_image = image.convert('RGB')

        output = BytesIO()
        rgb_image.save(output, format='JPEG', quality=quality, optimize=False)
        output.seek(0)
        damaged = Image.open(output).convert('RGB')

        if alpha is not None:
            return Image.merge('RGBA', (*damaged.split(), alpha))
        return damaged.convert('RGBA')

    # 缩放
    @staticmethod
    def apply_resize(image: Image.Image, scale: float = 1.5, scale_y: float = None) -> Image.Image:
        scale_x = float(scale)
        scale_y_value = float(scale_y) if scale_y is not None else None

        if scale_y_value is not None:
            if scale_y_value < 0:
                image = ImageOps.flip(image)
                scale_y_value = abs(scale_y_value)
            if scale_x < 0:
                image = ImageOps.mirror(image)
                scale_x = abs(scale_x)
            target_scale_y = scale_y_value
        else:
            if scale_x < 0:
                image = ImageOps.mirror(image)
                image = ImageOps.flip(image)
                scale_x = abs(scale_x)
            target_scale_y = scale_x

        new_width = max(1, round(image.width * scale_x))
        new_height = max(1, round(image.height * target_scale_y))
        return image.resize((new_width, new_height), Image.Resampling.LANCZOS)
    
    # 波纹
    @staticmethod
    def apply_wave(image: Image.Image, amplitude: float = 5, wavelength: float = 20) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        
        width, height = image.size
        arr = np.array(image)
        
        # 创建坐标网格
        y_coords, x_coords = np.mgrid[0:height, 0:width]
        
        # 计算偏移量（向量化）
        offset_x = (amplitude * np.sin(2 * np.pi * y_coords / wavelength)).astype(np.int32)
        offset_y = (amplitude * np.cos(2 * np.pi * x_coords / wavelength)).astype(np.int32)
        
        # 计算新坐标
        new_x = x_coords + offset_x
        new_y = y_coords + offset_y
        
        # 创建有效坐标掩码
        valid_mask = (new_x >= 0) & (new_x < width) & (new_y >= 0) & (new_y < height)
        
        # 创建结果图像（初始为透明）
        result = np.zeros((height, width, 4), dtype=np.uint8)
        
        # 只复制有效像素
        if valid_mask.any():
            # 使用花式索引复制像素
            result[valid_mask] = arr[new_y[valid_mask], new_x[valid_mask]]
        
        return Image.fromarray(result, 'RGBA')

    def apply_color_key(image: Image.Image, target_color: str = 'rgb(255,0,0)', tolerance: int = 60) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        
        target_rgb = ColorHandle.parse_color(target_color)
        arr = np.array(image)
        
        # 计算颜色距离（使用平方距离避免 sqrt）
        target_arr = np.array(target_rgb, dtype=np.int32)
        diff = arr[:, :, :3] - target_arr
        distance_sq = np.sum(diff * diff, axis=2)  # (r-r0)² + (g-g0)² + (b-b0)²
        
        # 创建掩码（距离 <= 容差）
        mask = distance_sq <= (tolerance * tolerance)
        
        # 复制原图，只修改 alpha 通道
        result = arr.copy()
        result[:, :, 3] = np.where(mask, 0, arr[:, :, 3])  # 符合条件的设为透明
        
        return Image.fromarray(result)
    
    # 暗角
    @staticmethod
    def apply_vignette(image: Image.Image, radius: float = 1.5) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        # 转换为 numpy 数组
        arr = np.array(image, dtype=np.float32)
        height, width = arr.shape[:2]       
        # 创建网格
        y_coords, x_coords = np.ogrid[:height, :width]
        # 计算中心距离
        center_x = width / 2
        center_y = height / 2
        max_distance = np.sqrt(center_x**2 + center_y**2)
        # 向量化距离计算
        distances = np.sqrt((x_coords - center_x)**2 + (y_coords - center_y)**2)
        # 计算暗角因子
        factors = 1 - (distances / max_distance) ** radius
        factors = np.clip(factors, 0, 1)
        # 应用暗角效果到 RGB 通道
        arr[:, :, :3] = arr[:, :, :3] * factors[:, :, np.newaxis]
        # 转换回 uint8
        result = np.clip(arr, 0, 255).astype(np.uint8)
        return Image.fromarray(result)
    
    # 发光
    @staticmethod
    def apply_glow(image: Image.Image, intensity: float = 0.5, blur_radius: float = 15) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        # 创建发光图层
        glow_layer = image.filter(ImageFilter.GaussianBlur(blur_radius))
        # 增强亮度
        enhancer = ImageEnhance.Brightness(glow_layer)
        glow_layer = enhancer.enhance(intensity)
        # 转换为 numpy 数组
        img_arr = np.array(image, dtype=np.float32)  # 使用 float32 避免溢出
        glow_arr = np.array(glow_layer, dtype=np.float32)
        
        # 向量化合并（只合并 RGB，A 保持不变）
        result_arr = np.zeros_like(img_arr, dtype=np.float32)
        
        # RGB 通道相加并限制到 255
        result_arr[:, :, :3] = np.clip(img_arr[:, :, :3] + glow_arr[:, :, :3], 0, 255)
        
        # Alpha 通道保持原图
        result_arr[:, :, 3] = img_arr[:, :, 3]
        
        return Image.fromarray(result_arr.astype(np.uint8))
    
    # RGB分离
    @staticmethod
    def apply_rgb_split(image: Image.Image, offset: int = 5) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        r, g, b, a = image.split()
        r_offset = r.transform(r.size, Image.AFFINE, 
                            (1, 0, offset, 0, 1, 0))
        g_offset = g.transform(g.size, Image.AFFINE,
                            (1, 0, 0, 0, 1, offset))
        return Image.merge('RGBA', (r_offset, g_offset, b, a))
    
    # 光学补偿
    @staticmethod
    def apply_optical_compensation(image: Image.Image, 
                                  amount: float = 100.0, reverse: bool = False) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        
        width, height = image.size
        arr = np.array(image)
        
        # 中心点
        center_x, center_y = width / 2, height / 2
        
        # 归一化amount
        amount_norm = amount / 100.0
        
        # 创建坐标网格
        y_coords, x_coords = np.mgrid[0:height, 0:width]
        
        # 计算相对中心的归一化坐标
        dx = (x_coords - center_x) / center_x
        dy = (y_coords - center_y) / center_y
        
        # 计算距离（避免除零）
        distance = np.sqrt(dx**2 + dy**2)
        
        # 创建掩码：中心点和其他点
        center_mask = distance == 0
        other_mask = ~center_mask
        
        # 初始化缩放因子
        scale_factor = np.ones_like(distance)
        
        if reverse:
            # 反鱼眼效果
            # 对于非中心点
            if other_mask.any():
                # 使用arcsin进行反鱼眼映射
                theta = np.arcsin(np.clip(distance[other_mask], 0, 0.999))
                new_distance = np.sin(theta * amount_norm)
                scale_factor[other_mask] = new_distance / distance[other_mask]
        else:
            # 鱼眼效果
            if other_mask.any():
                # 使用sin或tanh进行鱼眼映射
                theta = distance[other_mask] * amount_norm
                if amount_norm <= 1.0:
                    new_distance = np.sin(theta)
                else:
                    new_distance = np.tanh(theta)
                scale_factor[other_mask] = new_distance / distance[other_mask]
        
        # 计算源坐标
        src_x = center_x + dx * center_x * scale_factor
        src_y = center_y + dy * center_y * scale_factor
        
        # 裁剪坐标到有效范围
        src_x = np.clip(src_x, 0, width - 1)
        src_y = np.clip(src_y, 0, height - 1)
        
        # 准备插值
        # 获取整数和小数部分
        x0 = np.floor(src_x).astype(np.int32)
        x1 = np.minimum(x0 + 1, width - 1)
        y0 = np.floor(src_y).astype(np.int32)
        y1 = np.minimum(y0 + 1, height - 1)
        
        fx = src_x - x0
        fy = src_y - y0
        
        # 确保索引在范围内
        x0 = np.clip(x0, 0, width - 1)
        x1 = np.clip(x1, 0, width - 1)
        y0 = np.clip(y0, 0, height - 1)
        y1 = np.clip(y1, 0, height - 1)
        
        # 双线性插值 - 向量化版本
        # 获取四个角的像素值
        c00 = arr[y0, x0]
        c01 = arr[y0, x1]
        c10 = arr[y1, x0]
        c11 = arr[y1, x1]
        
        # 扩展fx, fy用于3D广播
        fx_3d = fx[:, :, np.newaxis]
        fy_3d = fy[:, :, np.newaxis]
        
        # 双线性插值公式
        top = c00 * (1 - fx_3d) + c01 * fx_3d
        bottom = c10 * (1 - fx_3d) + c11 * fx_3d
        result_arr = top * (1 - fy_3d) + bottom * fy_3d
        
        # 转换为uint8
        result_arr = np.clip(result_arr, 0, 255).astype(np.uint8)
        
        return Image.fromarray(result_arr, 'RGBA')
    
    # 球面化
    @staticmethod
    def apply_spherize(image: Image.Image, strength: float = 0.5) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        
        width, height = image.size
        arr = np.array(image)
        
        # 创建坐标网格
        y_coords, x_coords = np.mgrid[0:height, 0:width]
        
        # 计算中心点
        center_x = width / 2
        center_y = height / 2
        
        # 计算归一化坐标
        norm_x = (x_coords - center_x) / (width / 2)
        norm_y = (y_coords - center_y) / (height / 2)
        radius = np.sqrt(norm_x**2 + norm_y**2)
        
        # 计算球面化偏移（向量化）
        factor = 1 + strength * (radius**2)
        new_x = (norm_x * factor) * (width / 2) + center_x
        new_y = (norm_y * factor) * (height / 2) + center_y
        
        new_x = new_x.astype(np.int32)
        new_y = new_y.astype(np.int32)
        
        # 创建有效坐标掩码
        valid_mask = (new_x >= 0) & (new_x < width) & (new_y >= 0) & (new_y < height)
        
        # 创建结果图像（初始为透明）
        result = np.zeros((height, width, 4), dtype=np.uint8)
        
        # 只复制有效像素
        if valid_mask.any():
            # 使用花式索引复制像素
            result[valid_mask] = arr[new_y[valid_mask], new_x[valid_mask]]

        # 计算裁剪边界
        ys, xs = np.where(valid_mask)
        min_y, max_y = ys.min(), ys.max() + 1
        min_x, max_x = xs.min(), xs.max() + 1
        # 裁剪结果图像
        result = result[min_y:max_y, min_x:max_x]
        
        return Image.fromarray(result, 'RGBA')
    
    # 平移
    @staticmethod
    def apply_translate(image: Image.Image, x_offset: int = 10, y_offset: int = 10) -> Image.Image:
        return image.transform(image.size, Image.AFFINE,
                               (1, 0, x_offset, 0, 1, y_offset))
    
    # 拓展边缘
    @staticmethod
    def apply_expand_edges(image: Image.Image, border_size: int = 10) -> Image.Image:
        # 拓展边缘，填充全透明
        return ImageOps.expand(image, border=border_size, fill=(0, 0, 0, 0))

    # 旋转
    @staticmethod
    def apply_rotate(image: Image.Image, angle: float = 45) -> Image.Image:
        return image.rotate(angle, expand=True)
    
    # 透视变换
    @staticmethod
    def apply_perspective_transform(image: Image.Image, coeffs: list[float]) -> Image.Image:
        return image.transform(image.size, Image.PERSPECTIVE, coeffs, Image.Resampling.BICUBIC)
    
    # 裁剪
    @staticmethod
    def apply_crop(image: Image.Image, left: float = 0, upper: float = 0, right: float = 100, lower: float = 100) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        # 按百分比裁剪
        width, height = image.size
        left_px = int(width * left / 100)
        upper_px = int(height * upper / 100)
        right_px = int(width * right / 100)
        lower_px = int(height * lower / 100)
        # 如果为负数，则扩展边缘
        if left_px < 0 or upper_px < 0 or right_px > width or lower_px > height:
            border_left = max(0, -left_px)
            border_top = max(0, -upper_px)
            border_right = max(0, right_px - width)
            border_bottom = max(0, lower_px - height)
            image = ImageOps.expand(image, border=(border_left, border_top, border_right, border_bottom), fill=(0,0,0,0))
            left_px += border_left
            upper_px += border_top
            right_px += border_left
            lower_px += border_top
        return image.crop((left_px, upper_px, right_px, lower_px))
    
    # 噪点
    @staticmethod
    def apply_noise(image: Image.Image, amount: float = 0.05) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        
        arr = np.array(image)
        noise = np.random.randint(0, 256, arr.shape, dtype=np.uint8)
        
        # 为每个像素创建掩码，然后扩展到所有通道，除了 alpha 通道
        mask = np.random.rand(*arr.shape[:2]) < amount
        mask_3d = np.repeat(mask[:, :, np.newaxis], 4, axis=2)
        mask_3d[:, :, 3] = False  # 保持 alpha 通道不变
        
        # 混合噪点
        result = np.where(mask_3d, noise, arr)
        
        return Image.fromarray(result, 'RGBA')
    
    # 素描
    @staticmethod
    def apply_sketch(image: Image.Image) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        
        # 转为灰度图
        gray_image = image.convert('L')
        
        # 反相
        inverted_image = ImageChops.invert(gray_image)
        
        # 高斯模糊
        blurred_image = inverted_image.filter(ImageFilter.GaussianBlur(radius=10))
        
        # 混合
        def dodge(front, back):
            result = front * 255 / (255 - back)
            result[result > 255] = 255
            result[back == 255] = 255
            return result.astype(np.uint8)
        
        gray_arr = np.array(gray_image, dtype=np.float32)
        blurred_arr = np.array(blurred_image, dtype=np.float32)
        
        sketch_arr = dodge(gray_arr, blurred_arr)
        
        # 创建结果图像，保留原始 alpha 通道
        alpha_channel = np.array(image.getchannel('A'))
        result_arr = np.zeros((image.height, image.width, 4), dtype=np.uint8)
        result_arr[:, :, 0] = sketch_arr
        result_arr[:, :, 1] = sketch_arr
        result_arr[:, :, 2] = sketch_arr
        result_arr[:, :, 3] = alpha_channel
        
        return Image.fromarray(result_arr, 'RGBA')
    
    # 两张图像混合，可指定叠加模式
    @staticmethod
    def apply_blend(image1: Image.Image, image2: Image.Image, mode: str = 'normal', alpha: float = 0.5) -> Image.Image:
        if image1.mode != 'RGBA':
            image1 = image1.convert('RGBA')
        if image2.mode != 'RGBA':
            image2 = image2.convert('RGBA')
        
        image2 = image2.resize(image1.size, Image.Resampling.LANCZOS)
        
        arr1 = np.array(image1, dtype=np.float32)
        arr2 = np.array(image2, dtype=np.float32)
        
        if mode == 'normal':
            blended = arr1 * (1 - alpha) + arr2 * alpha
        elif mode == 'multiply':
            blended = (arr1 / 255.0) * (arr2 / 255.0) * 255.0
        elif mode == 'screen':
            blended = 255 - (1 - arr1 / 255.0) * (1 - arr2 / 255.0) * 255.0
        elif mode == 'overlay':
            mask = arr1 < 128
            blended = np.zeros_like(arr1)
            blended[mask] = (2 * (arr1[mask] / 255.0) * (arr2[mask] / 255.0)) * 255.0
            blended[~mask] = (1 - 2 * (1 - arr1[~mask] / 255.0) * (1 - arr2[~mask] / 255.0)) * 255.0
        else:
            blended = arr1
        
        blended = np.clip(blended, 0, 255).astype(np.uint8)
        
        return Image.fromarray(blended, 'RGBA')
    
    # 两张图像直接覆盖
    @staticmethod
    def apply_overlay(image1: Image.Image, image2: Image.Image) -> Image.Image:
        if image1.mode != 'RGBA':
            image1 = image1.convert('RGBA')
        if image2.mode != 'RGBA':
            image2 = image2.convert('RGBA')
        
        image2 = image2.resize(image1.size, Image.Resampling.LANCZOS)
        
        return Image.alpha_composite(image1, image2)

    # 叠加渐变色
    @staticmethod
    def apply_gradient_overlay(
        image: Image.Image,
        color_list: str = '[rgb(255,0,0)|(0,0),rgb(0,255,0)|(0,100),rgb(0,0,255)|(50,100)]',
        overlay_mode: str = 'overlay',
        ) -> Image.Image:
        gradient_gen = GradientGenerator()
        color_nodes = gradient_gen.parse_color_list(color_list)
        gradient = gradient_gen.create_gradient(image.size[0], image.size[1], color_nodes)
        return ImageFilterImplement.apply_blend(image, gradient, mode=overlay_mode, alpha=0.5)
    
    # 生成颜色，类似固态层
    @staticmethod
    def generate_solid(
        image: Image.Image,
        color_list: str = '[rgb(255,0,0)|(0,0),rgb(0,255,0)|(0,100),rgb(0,0,255)|(50,100)]'
    ):
        gradient_gen = GradientGenerator()
        color_nodes = gradient_gen.parse_color_list(color_list)
        gradient = gradient_gen.create_gradient(image.size[0], image.size[1], color_nodes)
        return gradient

    
    # 阴影
    @staticmethod
    def apply_shadow(image: Image.Image,
                     x_offset: int = 10,
                     y_offset: int = 10,
                     blur: float = 10, 
                     opacity: float = 0.5,
                     shadow_color: str = "black") -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        offset = (-x_offset, -y_offset)
        # 创建阴影图层
        shadow_rgb = ColorHandle.parse_color(shadow_color)
        logger.debug(f"Shadow color RGB: {shadow_rgb}")
        shadow = Image.new('RGBA', image.size, (0, 0, 0, 0))
        shadow_draw = ImageDraw.Draw(shadow)
        # 填充阴影颜色
        shadow_draw.rectangle([(0, 0), image.size], fill=(shadow_rgb[0], shadow_rgb[1], shadow_rgb[2], 255))
        # 应用遮罩
        alpha = image.split()[-1].point(lambda p: p * opacity)
        shadow.putalpha(alpha)
        # 移动
        shadow = shadow.transform(
            shadow.size,
            Image.AFFINE,
            (1, 0, offset[0], 0, 1, offset[1])
        )
        # 应用模糊
        shadow = shadow.filter(ImageFilter.GaussianBlur(blur))
        # 将阴影叠加在原图下方
        result = ImageFilterImplement.apply_overlay(shadow, image)
        
        return result
    
    @staticmethod
    def apply_radial_blur(image: Image.Image, strength: float = 3.0, samples: int = 6) -> Image.Image:
        """
        快速径向模糊 - 使用预计算网格和向量化
        """
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        
        width, height = image.size
        arr = np.array(image, dtype=np.uint8)
        
        # 转换为float32并归一化
        arr_float = arr.astype(np.float32) / 255.0
        
        # 计算中心点
        center_x = width / 2
        center_y = height / 2
        
        # 预计算坐标网格（只计算一次）
        x_indices = np.arange(width, dtype=np.float32)
        y_indices = np.arange(height, dtype=np.float32)
        x_grid, y_grid = np.meshgrid(x_indices, y_indices)
        
        # 预计算相对坐标和距离
        dx = x_grid - center_x
        dy = y_grid - center_y
        distance = np.sqrt(dx*dx + dy*dy + 1e-6)  # 避免除零
        max_dist = np.max(distance)
        
        # 生成采样强度
        if samples > 1:
            strengths = np.linspace(-strength/2, strength/2, samples) / 100
        else:
            strengths = np.array([0])
        
        # 初始化结果
        result = np.zeros_like(arr_float)
        
        for s in strengths:
            # 计算缩放因子
            scale = 1.0 + s * distance / max_dist
            
            # 计算变形坐标
            new_x = np.clip(center_x + dx * scale, 0, width - 1)
            new_y = np.clip(center_y + dy * scale, 0, height - 1)
            
            # 快速双线性插值
            x0 = np.floor(new_x).astype(np.int32)
            x1 = np.minimum(x0 + 1, width - 1)
            y0 = np.floor(new_y).astype(np.int32)
            y1 = np.minimum(y0 + 1, height - 1)
            
            # 计算权重
            wx = new_x - x0
            wy = new_y - y0
            w00 = (1 - wx) * (1 - wy)
            w01 = wx * (1 - wy)
            w10 = (1 - wx) * wy
            w11 = wx * wy
            
            # 向量化插值所有通道
            for c in range(4):
                result[:, :, c] += (
                    arr_float[y0, x0, c] * w00 +
                    arr_float[y0, x1, c] * w01 +
                    arr_float[y1, x0, c] * w10 +
                    arr_float[y1, x1, c] * w11
                )
        
        # 平均并转换
        result /= len(strengths)
        result = np.clip(result * 255, 0, 255).astype(np.uint8)
        
        return Image.fromarray(result, 'RGBA')
    
    @staticmethod
    def apply_spin_blur(image: Image.Image, strength: float = 30.0, samples: int = 6) -> Image.Image:
        """
        快速旋转模糊
        """
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        
        width, height = image.size
        arr = np.array(image, dtype=np.uint8)
        arr_float = arr.astype(np.float32) / 255.0
        
        # 计算中心点
        center_x = width / 2
        center_y = height / 2
        
        # 预计算坐标网格
        x_indices = np.arange(width, dtype=np.float32)
        y_indices = np.arange(height, dtype=np.float32)
        x_grid, y_grid = np.meshgrid(x_indices, y_indices)
        
        # 预计算相对坐标
        dx = x_grid - center_x
        dy = y_grid - center_y
        
        # 生成角度采样
        if samples > 1:
            angles = np.linspace(-strength/2, strength/2, samples) * np.pi / 180
        else:
            angles = np.array([0])
        
        result = np.zeros_like(arr_float)
        
        for angle in angles:
            # 预计算三角函数值
            cos_a = math.cos(angle)
            sin_a = math.sin(angle)
            
            # 计算旋转坐标
            new_x = center_x + dx * cos_a - dy * sin_a
            new_y = center_y + dx * sin_a + dy * cos_a
            
            # 边界裁剪
            new_x = np.clip(new_x, 0, width - 1)
            new_y = np.clip(new_y, 0, height - 1)
            
            # 快速双线性插值
            x0 = np.floor(new_x).astype(np.int32)
            x1 = np.minimum(x0 + 1, width - 1)
            y0 = np.floor(new_y).astype(np.int32)
            y1 = np.minimum(y0 + 1, height - 1)
            
            wx = new_x - x0
            wy = new_y - y0
            w00 = (1 - wx) * (1 - wy)
            w01 = wx * (1 - wy)
            w10 = (1 - wx) * wy
            w11 = wx * wy
            
            # 向量化插值
            for c in range(4):
                result[:, :, c] += (
                    arr_float[y0, x0, c] * w00 +
                    arr_float[y0, x1, c] * w01 +
                    arr_float[y1, x0, c] * w10 +
                    arr_float[y1, x1, c] * w11
                )
        
        result /= len(angles)
        result = np.clip(result * 255, 0, 255).astype(np.uint8)
        
        return Image.fromarray(result, 'RGBA')
    
    @staticmethod
    def apply_directional_blur(image: Image.Image, angle: float = 0.0, 
                              distance: int = 20, samples: int = 6) -> Image.Image:
        """
        快速方向模糊 - 使用累积缓冲区技术
        """
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        
        width, height = image.size
        arr = np.array(image, dtype=np.uint8)
        arr_float = arr.astype(np.float32) / 255.0
        
        # 计算角度和步长
        rad = math.radians(angle)
        cos_a = math.cos(rad)
        sin_a = math.sin(rad)
        
        # 生成偏移位置
        if samples > 1:
            offsets = np.linspace(-distance/2, distance/2, samples)
        else:
            offsets = np.array([0])
        
        result = np.zeros_like(arr_float)
        
        for offset in offsets:
            # 计算偏移量
            shift_x = offset * cos_a
            shift_y = offset * sin_a
            
            # 预计算变形坐标
            x_indices = np.arange(width, dtype=np.float32)
            y_indices = np.arange(height, dtype=np.float32)
            x_grid, y_grid = np.meshgrid(x_indices, y_indices)
            
            new_x = x_grid - shift_x
            new_y = y_grid - shift_y
            
            # 边界裁剪
            new_x = np.clip(new_x, 0, width - 1)
            new_y = np.clip(new_y, 0, height - 1)
            
            # 快速双线性插值
            x0 = np.floor(new_x).astype(np.int32)
            x1 = np.minimum(x0 + 1, width - 1)
            y0 = np.floor(new_y).astype(np.int32)
            y1 = np.minimum(y0 + 1, height - 1)
            
            wx = new_x - x0
            wy = new_y - y0
            w00 = (1 - wx) * (1 - wy)
            w01 = wx * (1 - wy)
            w10 = (1 - wx) * wy
            w11 = wx * wy
            
            # 向量化插值
            for c in range(4):
                result[:, :, c] += (
                    arr_float[y0, x0, c] * w00 +
                    arr_float[y0, x1, c] * w01 +
                    arr_float[y1, x0, c] * w10 +
                    arr_float[y1, x1, c] * w11
                )
        
        result /= len(offsets)
        result = np.clip(result * 255, 0, 255).astype(np.uint8)
        
        return Image.fromarray(result, 'RGBA')
    
    @staticmethod
    def apply_zoom_blur(image: Image.Image, strength: float = 0.1, samples: int = 6) -> Image.Image:
        """
        快速缩放模糊
        """
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        
        width, height = image.size
        arr = np.array(image, dtype=np.uint8)
        arr_float = arr.astype(np.float32) / 255.0
        
        # 计算中心点
        center_x = width / 2
        center_y = height / 2
        
        # 预计算坐标网格
        x_indices = np.arange(width, dtype=np.float32)
        y_indices = np.arange(height, dtype=np.float32)
        x_grid, y_grid = np.meshgrid(x_indices, y_indices)
        
        # 预计算相对坐标
        dx = x_grid - center_x
        dy = y_grid - center_y
        
        # 生成缩放因子
        if samples > 1:
            scales = np.linspace(1 - strength, 1 + strength, samples)
        else:
            scales = np.array([1.0])
        
        result = np.zeros_like(arr_float)
        
        for scale in scales:
            # 计算缩放坐标
            new_x = center_x + dx / scale
            new_y = center_y + dy / scale
            
            # 边界裁剪
            new_x = np.clip(new_x, 0, width - 1)
            new_y = np.clip(new_y, 0, height - 1)
            
            # 快速双线性插值
            x0 = np.floor(new_x).astype(np.int32)
            x1 = np.minimum(x0 + 1, width - 1)
            y0 = np.floor(new_y).astype(np.int32)
            y1 = np.minimum(y0 + 1, height - 1)
            
            wx = new_x - x0
            wy = new_y - y0
            w00 = (1 - wx) * (1 - wy)
            w01 = wx * (1 - wy)
            w10 = (1 - wx) * wy
            w11 = wx * wy
            
            # 向量化插值
            for c in range(4):
                result[:, :, c] += (
                    arr_float[y0, x0, c] * w00 +
                    arr_float[y0, x1, c] * w01 +
                    arr_float[y1, x0, c] * w10 +
                    arr_float[y1, x1, c] * w11
                )
        
        result /= len(scales)
        result = np.clip(result * 255, 0, 255).astype(np.uint8)
        
        return Image.fromarray(result, 'RGBA')

    # 中心清晰，边缘模糊
    @staticmethod
    def apply_focus_blur(image: Image.Image, radius: float = 10.0) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        
        width, height = image.size
        arr = np.array(image)
        
        # 创建坐标网格
        y_coords, x_coords = np.mgrid[0:height, 0:width]
        
        # 计算中心点
        center_x = width / 2
        center_y = height / 2
        
        # 计算归一化坐标
        norm_x = (x_coords - center_x) / (width / 2)
        norm_y = (y_coords - center_y) / (height / 2)
        distance = np.sqrt(norm_x**2 + norm_y**2)
        
        # 创建模糊图像
        blurred_image = image.filter(ImageFilter.GaussianBlur(radius))
        blurred_arr = np.array(blurred_image)
        
        # 创建结果图像（向量化）
        result = np.zeros_like(arr, dtype=np.float32)
        
        # 根据距离混合原图和模糊图
        for c in range(4):  # 对每个通道
            result[:, :, c] = arr[:, :, c] * (1 - distance) + blurred_arr[:, :, c] * distance
        
        return Image.fromarray(np.clip(result, 0, 255).astype(np.uint8), 'RGBA')
    
    # 复制画面
    @staticmethod
    def copy_area(image: Image.Image, 
                  dst_move: str = '(100,100)',
                  scale: float = 1.0,
                  src_area: str = '(0,0,100,100)') -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        result = image.copy()
        # 参数表示的是百分比
        width, height = image.size
        # 首先裁剪出源区域
        src_tuple = eval(src_area)
        src_area = ImageFilterImplement.apply_crop(image, src_tuple[0], src_tuple[1], src_tuple[2], src_tuple[3])
        # 计算目标位置
        dst_tuple = eval(dst_move)
        dst_x = int(width * dst_tuple[0] / 100)
        dst_y = int(height * dst_tuple[1] / 100)
        # 缩放源区域
        if scale != 1.0:
            new_width = int(src_area.width * scale)
            new_height = int(src_area.height * scale)
            src_area = src_area.resize((new_width, new_height), Image.Resampling.LANCZOS)
        # 粘贴到目标位置
        result.paste(src_area, (dst_x, dst_y), src_area)
        return result
    
    # 水平翻转
    @staticmethod
    def apply_flip_horizontal(image: Image.Image) -> Image.Image:
        return image.transpose(Image.Transpose.FLIP_LEFT_RIGHT)
    
    # 垂直翻转
    @staticmethod
    def apply_flip_vertical(image: Image.Image) -> Image.Image:
        return image.transpose(Image.Transpose.FLIP_TOP_BOTTOM)
    
    # 依方向镜像一半画面
    @staticmethod
    def apply_mirror_half(image: Image.Image, angle: float = 90) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        
        width, height = image.size
        arr = np.array(image, dtype=np.uint8)
        
        # 角度标准化
        angle = angle % 360
        
        # 计算折痕的斜率
        # 注意：我们的角度是折痕与水平线的夹角
        # 0° = 垂直线，90° = 水平线
        rad = math.radians(angle)
        
        # 计算中心点
        center_x = width / 2
        center_y = height / 2
        
        # 创建坐标网格
        y_coords, x_coords = np.mgrid[0:height, 0:width]
        
        # 计算折痕的方向向量
        # 折痕方向垂直于法向量
        # 对于角度θ，折痕方向向量为(cosθ, sinθ)
        direction_x = math.cos(rad)
        direction_y = math.sin(rad)
        
        # 计算法向量（垂直于折痕）
        # 旋转90度：(-sinθ, cosθ)
        normal_x = -direction_y
        normal_y = direction_x
        
        # 计算每个像素相对于折痕的位置
        # 点到直线的有向距离: (x-cx)*nx + (y-cy)*ny
        rel_x = x_coords - center_x
        rel_y = y_coords - center_y
        signed_distance = rel_x * normal_x + rel_y * normal_y
        
        source_mask = signed_distance >= 0
        
        # 创建结果图像
        result = arr.copy()
        
        # 获取镜像侧的像素（需要被替换的像素）
        mirror_mask = ~source_mask
        
        if mirror_mask.any():
            # 对于镜像侧的每个像素，计算其关于折痕的镜像点
            mirror_x = x_coords[mirror_mask]
            mirror_y = y_coords[mirror_mask]
            
            # 计算相对坐标
            mirror_rel_x = mirror_x - center_x
            mirror_rel_y = mirror_y - center_y
            
            # 计算到折痕的距离（带符号）
            dist_to_line = signed_distance[mirror_mask]
            
            # 计算镜像点的相对坐标
            # 镜像公式: p' = p - 2 * (p·n) * n
            # 其中p是相对中心点的向量，n是单位法向量
            mirror_target_rel_x = mirror_rel_x - 2 * dist_to_line * normal_x
            mirror_target_rel_y = mirror_rel_y - 2 * dist_to_line * normal_y
            
            # 计算镜像点的绝对坐标
            target_x = np.round(center_x + mirror_target_rel_x).astype(int)
            target_y = np.round(center_y + mirror_target_rel_y).astype(int)
            
            # 确保坐标在图像范围内
            valid = (target_x >= 0) & (target_x < width) & (target_y >= 0) & (target_y < height)
            
            if valid.any():
                # 将源侧的像素复制到镜像侧的位置
                valid_target_x = target_x[valid]
                valid_target_y = target_y[valid]
                valid_mirror_x = mirror_x[valid]
                valid_mirror_y = mirror_y[valid]
                
                # 获取源侧的像素值
                source_pixels = arr[valid_target_y, valid_target_x]
                
                # 复制到镜像位置
                result[valid_mirror_y, valid_mirror_x] = source_pixels
        
        return Image.fromarray(result, 'RGBA')
    
    # 随机画面整体晃动，对于动图会很有效
    @staticmethod
    def apply_random_wiggle(image: Image.Image, max_offset: int = 5, motion_blur = False) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        
        # 生成随机偏移
        x_offset = random.randint(-max_offset, max_offset)
        y_offset = random.randint(-max_offset, max_offset)
        # 画面平移
        translated_image = ImageFilterImplement.apply_translate(image, x_offset, y_offset)
        if motion_blur:
            # 添加运动模糊
            translated_image = ImageFilterImplement.apply_directional_blur(translated_image, 
                                                                          angle=random.uniform(0, 360), 
                                                                          distance=max_offset, 
                                                                          samples=6)
        return translated_image
    
    # 像素随机抖动
    @staticmethod
    def apply_pixel_jitter(image: Image.Image, max_offset: int = 2) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        
        width, height = image.size
        arr = np.array(image)

        # 创建结果图像
        result = np.zeros_like(arr)

        # numpy 向量化随机偏移
        x_indices = np.arange(width)
        y_indices = np.arange(height)
        x_grid, y_grid = np.meshgrid(x_indices, y_indices)
        x_offsets = np.random.randint(-max_offset, max_offset + 1, size=(height, width))
        y_offsets = np.random.randint(-max_offset, max_offset + 1, size=(height, width))
        new_x = np.clip(x_grid + x_offsets, 0, width - 1)
        new_y = np.clip(y_grid + y_offsets, 0, height - 1)
        result[y_grid, x_grid] = arr[new_y, new_x]
        
        return Image.fromarray(result, 'RGBA')
    
    # 描边
    @staticmethod
    def apply_stroke(image: Image.Image, stroke_width: int = 5, stroke_color: str = 'black') -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        
        # 基于图像的 alpha 通道创建描边
        alpha = image.split()[3]
        # 创建描边图像
        stroke_image = Image.new('RGBA', image.size, (0, 0, 0, 0))
        # 根据 alpha 通道的值，以每个像素为中心，扩大描边区域
        expanded_alpha = alpha.filter(ImageFilter.MaxFilter(size=stroke_width*2+1))
        draw = Image.new('RGBA', image.size, ColorHandle.parse_color(stroke_color) + (255,))
        stroke_image.paste(draw, (0, 0), expanded_alpha)
        # 将描边和原图合并
        result = Image.alpha_composite(stroke_image, image)
        return result
    
    # 基于形状的描边
    @staticmethod
    def apply_shape_stroke(image: Image.Image, stroke_width: int = 5, stroke_color: str = 'black', roughness: float = None) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        
        img = cv2.cvtColor(np.array(image), cv2.COLOR_RGBA2BGRA)

        # 提取alpha通道
        alpha = img[:, :, 3]

        # 应用阈值创建二值掩码
        _, binary_mask = cv2.threshold(alpha, 0.5, 255, cv2.THRESH_BINARY)

        # 寻找轮廓
        contours, hierarchy = cv2.findContours(
            binary_mask, 
            cv2.RETR_EXTERNAL,
            cv2.CHAIN_APPROX_SIMPLE
        )

        # 减少轮廓点数，以实现尖角效果
        if roughness is not None:
            epsilon = roughness * cv2.arcLength(contours[0], True)
            contours = [cv2.approxPolyDP(cnt, epsilon, True) for cnt in contours]

        # 将轮廓点沿法线方向外扩
        expanded_contours = expand_contours(contours, stroke_width)
        
        # 创建描边图像
        stroke_img = np.zeros_like(img)

        # 如果没有轮廓，直接返回原图
        if not expanded_contours[0].any():
            return image
        cv2.fillPoly(stroke_img, expanded_contours, ColorHandle.parse_color(stroke_color) + (255,))

        # 轮廓图像转为PIL格式
        stroke_pil = Image.fromarray(cv2.cvtColor(stroke_img, cv2.COLOR_BGRA2RGBA))
        # 合并描边和原图
        result = Image.alpha_composite(stroke_pil, image)
        
        return result

    # 半调
    @staticmethod
    def apply_halftone(image: Image.Image, dot_size: int = 5) -> Image.Image:
        if image.mode != 'L':
            grayscale = image.convert('L')
        else:
            grayscale = image.copy()
        
        # 获取图像尺寸
        width, height = grayscale.size
        
        # 计算网格数量
        grid_width = math.ceil(width / dot_size)
        grid_height = math.ceil(height / dot_size)
        
        # 创建输出图像（白色背景）
        output = Image.new('RGB', (width, height), 'white')
        draw = ImageDraw.Draw(output)
        
        # 遍历每个网格单元
        for gy in range(grid_height):
            for gx in range(grid_width):
                # 计算当前网格的边界
                left = gx * dot_size
                top = gy * dot_size
                right = min(left + dot_size, width)
                bottom = min(top + dot_size, height)
                
                # 获取当前网格的区域
                grid_region = grayscale.crop((left, top, right, bottom))
                
                # 计算网格内像素的平均亮度（0-255）
                stat = ImageStat.Stat(grid_region)
                avg_brightness = stat.mean[0]
                
                # 将亮度转换为网点半径
                # 亮度越高（越白），网点越小；亮度越低（越黑），网点越大
                max_radius = dot_size / 2
                radius = max_radius * (1 - avg_brightness / 255)
                
                # 如果半径太小，则不绘制网点
                if radius > 0.5:
                    # 计算网点中心坐标
                    center_x = left + (right - left) / 2
                    center_y = top + (bottom - top) / 2
                    
                    # 绘制黑色网点
                    draw.ellipse([
                        center_x - radius + 0.5,
                        center_y - radius + 0.5,
                        center_x + radius + 0.5,
                        center_y + radius + 0.5
                    ], fill='black')

        # 叠加 alpha 通道
        if image.mode == 'RGBA':
            alpha = image.split()[3]
            output.putalpha(alpha)
        
        return output
    
    # 设置通道
    @staticmethod
    def apply_set_channel(image: Image.Image, apply_image: Image.Image, channel: str = 'A') -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        
        if apply_image.mode != 'RGBA':
            apply_image = apply_image.convert('RGBA')
        
        # 将 apply_image 的通道设置给 image
        image_arr = np.array(image)
        apply_arr = np.array(apply_image.resize(image.size, Image.Resampling.LANCZOS))
        channel_index = {'R':0, 'G':1, 'B':2, 'A':3}.get(channel.upper(), 0)
        image_arr[:, :, channel_index] = apply_arr[:, :, channel_index]
        
        return Image.fromarray(image_arr, 'RGBA')
    
    # 设置遮罩
    def apply_set_mask(image: Image.Image, mask_image: Image.Image) -> Image.Image:
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        
        if mask_image.mode != 'L':
            mask_image = mask_image.convert('L')
        
        # 应用遮罩
        image.putalpha(mask_image.resize(image.size, Image.Resampling.LANCZOS))
        
        return image
    
    @staticmethod
    def generate_empty(image: Image.Image, images: list[Image.Image], width: int = 512, height: int = 512) -> Image.Image:
        # 生成空白图像
        empty_image = Image.new('RGBA', (width, height), (255, 255, 255, 0))
        images.append(empty_image)
        return image
    
    @staticmethod
    def generate_text(image: Image.Image, images: list[Image.Image], 
                      text: str = "请输入文本", 
                      font_size: int = 32, 
                      font_color: str = "black",
                      font_path: str = "HarmonyOS_Sans_SC_Regular.ttf") -> Image.Image:
        # 生成文本图像
        font = ImageFont.truetype(FONTS_PATH / font_path, font_size)
        # 获取文本边界框
        padding = 10
        temp_draw = ImageDraw.Draw(Image.new('RGBA', (1,1)))
        bbox = temp_draw.textbbox((0, 0), text, font=font)
        text_width = bbox[2] - bbox[0] + padding * 2
        text_height = bbox[3] - bbox[1] + padding * 2
        # 创建文本图像
        text_image = Image.new('RGBA', (text_width, text_height), (255, 255, 255, 0))
        draw = ImageDraw.Draw(text_image)
        draw_x = padding - bbox[0]
        draw_y = padding - bbox[1]
        draw.text((draw_x,draw_y), text, font=font, fill=ColorHandle.parse_color(font_color) + (255,))
        images.append(text_image)
        return image

    # Pixel Sort - 像素排序效果
    @staticmethod
    def apply_pixel_sort(
        image: Image.Image,
        direction: str = "horizontal",
        threshold: float = 0.0,
        auto_threshold: bool = True,
        sort_by: str = "brightness",
        mask_threshold: float = 128.0,
        reverse: bool = False,
        block_size: int = 1
    ) -> Image.Image:
        """
        Pixel Sort 效果
        
        参数:
            image: 输入图像
            direction: 排序方向，"horizontal"(水平) 或 "vertical"(垂直)
            threshold: 亮度阈值 (0-255)，低于此值的像素会被排序（仅在 auto_threshold=False 时生效）
            auto_threshold: 是否自动计算阈值（使用图像中位数）
            sort_by: 排序依据，"brightness"(亮度)、"hue"(色相)、"red"、"green"、"blue"
            mask_threshold: 遮罩阈值 (0-255)，决定哪些像素参与排序
            reverse: 是否反向排序
            block_size: 块大小，每 N 行/列作为一个整体排序单位
        """
        if image.mode != 'RGBA':
            image = image.convert('RGBA')
        
        arr = np.array(image)
        height, width = arr.shape[:2]
        
        # 获取排序属性
        def get_sort_value(pixel):
            r, g, b = pixel[0], pixel[1], pixel[2]
            if sort_by == "brightness":
                return 0.299 * r + 0.587 * g + 0.114 * b
            elif sort_by == "hue":
                max_c = max(r, g, b)
                min_c = min(r, g, b)
                diff = max_c - min_c
                if diff == 0:
                    return 0
                if max_c == r:
                    return 60 * (((g - b) / diff) % 6)
                elif max_c == g:
                    return 60 * ((b - r) / diff + 2)
                else:
                    return 60 * ((r - g) / diff + 4)
            elif sort_by == "red":
                return r
            elif sort_by == "green":
                return g
            elif sort_by == "blue":
                return b
            return 0.299 * r + 0.587 * g + 0.114 * b
        
        # 自动计算阈值
        if auto_threshold:
            # 使用图像亮度中位数作为阈值
            gray = np.array(image.convert('L'))
            mask_threshold = float(np.median(gray))
        
        # 创建遮罩：哪些像素需要排序
        mask = np.zeros((height, width), dtype=bool)
        for y in range(height):
            for x in range(width):
                brightness = 0.299 * arr[y, x, 0] + 0.587 * arr[y, x, 1] + 0.114 * arr[y, x, 2]
                mask[y, x] = brightness >= mask_threshold
        
        result = arr.copy()
        
        if direction.lower() in ["horizontal", "h", "水平"]:
            # 水平排序（逐行）
            for y in range(height):
                # 收集当前行中需要排序的像素
                if block_size > 1:
                    # 按块处理
                    for block_start in range(0, width, block_size):
                        block_end = min(block_start + block_size, width)
                        pixels = []
                        indices = []
                        for x in range(block_start, block_end):
                            if mask[y, x]:
                                pixels.append(arr[y, x].copy())
                                indices.append(x)
                        if len(pixels) > 1:
                            # 按指定属性排序
                            sorted_pixels = sorted(pixels, key=get_sort_value, reverse=reverse)
                            for i, x in enumerate(indices):
                                result[y, x] = sorted_pixels[i]
                else:
                    # 逐像素处理
                    pixels = []
                    indices = []
                    for x in range(width):
                        if mask[y, x]:
                            pixels.append(arr[y, x].copy())
                            indices.append(x)
                    if len(pixels) > 1:
                        sorted_pixels = sorted(pixels, key=get_sort_value, reverse=reverse)
                        for i, x in enumerate(indices):
                            result[y, x] = sorted_pixels[i]
        
        elif direction.lower() in ["vertical", "v", "垂直"]:
            # 垂直排序（逐列）
            for x in range(width):
                if block_size > 1:
                    # 按块处理
                    for block_start in range(0, height, block_size):
                        block_end = min(block_start + block_size, height)
                        pixels = []
                        indices = []
                        for y in range(block_start, block_end):
                            if mask[y, x]:
                                pixels.append(arr[y, x].copy())
                                indices.append(y)
                        if len(pixels) > 1:
                            sorted_pixels = sorted(pixels, key=get_sort_value, reverse=reverse)
                            for i, y in enumerate(indices):
                                result[y, x] = sorted_pixels[i]
                else:
                    pixels = []
                    indices = []
                    for y in range(height):
                        if mask[y, x]:
                            pixels.append(arr[y, x].copy())
                            indices.append(y)
                    if len(pixels) > 1:
                        sorted_pixels = sorted(pixels, key=get_sort_value, reverse=reverse)
                        for i, y in enumerate(indices):
                            result[y, x] = sorted_pixels[i]
        
        return Image.fromarray(result, 'RGBA')


    
class ImageFilterEmpty:
    # 空滤镜，不做任何处理，形式化参数用
    @staticmethod
    def empty_filter(image):
        return image
    
    @staticmethod
    def empty_filter_param(image, param = 10):
        return image

class ImageFilterStorage:
    # 用于暂存图像，存储在第一项的后面
    @staticmethod
    def temp_store_image(image: Image.Image, images: list[Image.Image]) -> Image.Image:
        images.insert(1, image.copy())
        return image
    
    # 用于交换移动索引
    @staticmethod
    def swap_image_index(image: Image.Image, images: list[Image.Image], src: int = 2, dest: int = 1) -> Image.Image:
        if len(images) == 0:
            return image
        # 将二者交换
        src -= 1
        dest -= 1
        if 0 <= src < len(images) and 0 <= dest < len(images):
            images[src], images[dest] = images[dest], images[src]
        return images[0]

    # 用于删除指定索引的图像
    @staticmethod
    def delete_image_by_index(image: Image.Image, images: list[Image.Image], index: int = 1) -> Image.Image:
        # 以 1 为基准
        index -= 1
        if len(images) == 1:
            # 只有一张图像，不能删除
            return image
        if 0 <= index < len(images):
            del images[index]
            return images[0]
    
    # 用于选择指定索引的图像为首图
    @staticmethod
    def select_image_by_index(image: Image.Image, images: list[Image.Image], index: int = 2) -> Image.Image:
        # 以 1 为基准
        index -= 1
        if 0 <= index < len(images):
            return images[index]
        return image

    # 用于存储图像
    @staticmethod
    def store_image(image: Image.Image, name: str, sender_info: SenderInfo) -> StoredInfo:
        ImageStorager.save_image_by_pil(image, name, sender_info.group_id, sender_info.qq_id)
        return StoredInfo(name=name)

    # 用于读取图像
    @staticmethod
    def load_image(image: Image.Image, name: str, images: list[Image.Image], sender_info: SenderInfo) -> Image.Image:
        loaded_image = ImageStorager.load_image(name, sender_info.group_id, sender_info.qq_id)
        if loaded_image is not None:
            images.append(loaded_image)
        return image