import gradio as gr
import cv2
import numpy as np
from PIL import Image, ImageEnhance

def apply_filter(image, filter_type, intensity):
    # 강도를 0.0에서 1.0 사이로 정규화
    normalized_intensity = intensity / 100.0

    if filter_type == "Grayscale":
        return convert_to_grayscale(image)
    elif filter_type == "Soft Glow":
        # 기본 10% 강도에서 시작하여 최대 100% 강도까지 조절
        base_intensity = 0.1
        adjusted_intensity = base_intensity + (normalized_intensity * (1 - base_intensity))
        
        gaussian = cv2.GaussianBlur(image, (15, 15), 0)
        soft_glow = cv2.addWeighted(image, 1 - adjusted_intensity, gaussian, adjusted_intensity, 0)
        return soft_glow
    elif filter_type == "Portrait Enhancer":
        # 기본 50% 강도에서 시작하여 최대 100% 강도까지 조절
        base_intensity = 0.5
        adjusted_intensity = base_intensity + (normalized_intensity * (1 - base_intensity))
        
        image_pil = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
        
        enhancer = ImageEnhance.Sharpness(image_pil)
        image_pil = enhancer.enhance(1 + 0.1 * adjusted_intensity)
        
        enhancer = ImageEnhance.Color(image_pil)
        image_pil = enhancer.enhance(1 + 0.1 * adjusted_intensity)
        
        enhanced_image = cv2.cvtColor(np.array(image_pil), cv2.COLOR_RGB2BGR)
        return enhanced_image
    elif filter_type == "Warm Tone":
        increase_red = np.array([[1.0 + 0.2 * normalized_intensity, 0.0, 0.0],
                                 [0.0, 1.0, 0.0],
                                 [0.0, 0.0, 1.0 - 0.2 * normalized_intensity]])
        warm_image = cv2.transform(image, increase_red)
        return warm_image
    elif filter_type == "Cold Tone":
        increase_blue = np.array([[1.0 - 0.2 * normalized_intensity, 0.0, 0.0],
                                  [0.0, 1.0, 0.0],
                                  [0.0, 0.0, 1.0 + 0.2 * normalized_intensity]])
        cold_image = cv2.transform(image, increase_blue)
        return cold_image
    elif filter_type == "High-Key":
        high_key = cv2.convertScaleAbs(image, alpha=1.0 + 0.2 * normalized_intensity, beta=30)
        return high_key
    elif filter_type == "Low-Key":
        low_key = cv2.convertScaleAbs(image, alpha=1.0 - 0.3 * normalized_intensity, beta=-30)
        return low_key
    elif filter_type == "Haze":
        haze = cv2.addWeighted(image, 1.0 - 0.3 * normalized_intensity, np.full(image.shape, 255, dtype=np.uint8), 0.3 * normalized_intensity, 0)
        return haze
    else:
        return image

def convert_to_grayscale(image):
    gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    return gray_image

def convert_and_save(image, filter_type, intensity):
    filtered_image = apply_filter(image, filter_type, intensity)
    output_path = "output.jpg"
    cv2.imwrite(output_path, filtered_image)
    return filtered_image, output_path

def get_filter_description(filter_type):
    descriptions = {
        "Grayscale": "이미지를 흑백으로 변환합니다.",
        "Soft Glow": "부드러운 빛을 추가하여 이미지를 은은하게 만듭니다.",
        "Portrait Enhancer": "피부 톤을 균일하게 하고 선명도를 조절하여 인물을 더욱 돋보이게 만듭니다.",
        "Warm Tone": "따뜻한 색조를 추가하여 이미지에 온기를 더합니다.",
        "Cold Tone": "차가운 색조를 추가하여 이미지에 시원함을 더합니다.",
        "High-Key": "밝고 화사한 이미지를 만들어냅니다.",
        "Low-Key": "어두운 톤을 강조하여 분위기 있는 이미지를 만듭니다.",
        "Haze": "부드럽고 흐릿한 효과를 추가하여 몽환적인 이미지를 만듭니다."
    }
    return descriptions.get(filter_type, "")

with gr.Blocks() as iface:
    with gr.Row():
        with gr.Column():
            image_input = gr.Image(type="pil", label="이미지 업로드")
            filter_input = gr.Radio(
                ["Grayscale", "Soft Glow", "Portrait Enhancer", "Warm Tone", "Cold Tone", "High-Key", "Low-Key", "Haze"], 
                label="필터 선택",
                value="Soft Glow"
            )
            intensity_slider = gr.Slider(1, 100, value=50, label="필터 강도")
            description_output = gr.Markdown(get_filter_description("Soft Glow"))

        with gr.Column():
            output_image = gr.Image(type="pil", label="결과 이미지")

    filter_input.change(fn=lambda filter_type: get_filter_description(filter_type), inputs=filter_input, outputs=description_output)
    process_button = gr.Button("필터 적용")
    process_button.click(fn=convert_and_save, inputs=[image_input, filter_input, intensity_slider], outputs=output_image)

iface.launch()