File size: 4,201 Bytes
dfa38f5
 
b2547eb
 
dfa38f5
 
b2547eb
dfa38f5
b2547eb
dfa38f5
 
 
 
b2547eb
dfa38f5
b2547eb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
dfa38f5
 
 
b2547eb
 
 
dfa38f5
 
 
 
 
 
 
 
b2547eb
 
 
 
 
dfa38f5
b2547eb
 
dfa38f5
b2547eb
 
 
 
 
 
dfa38f5
 
b2547eb
 
dfa38f5
 
b2547eb
 
 
dfa38f5
b2547eb
 
 
 
dfa38f5
b2547eb
 
dfa38f5
 
b2547eb
 
dfa38f5
 
 
b2547eb
 
dfa38f5
b2547eb
 
dfa38f5
b2547eb
 
 
 
 
dfa38f5
 
 
b2547eb
 
dfa38f5
b2547eb
 
dfa38f5
 
 
 
b2547eb
 
dfa38f5
 
 
 
b2547eb
 
dfa38f5
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import random
import requests
from PIL import Image
from io import BytesIO
import gradio as gr

# --- ์ƒ์ˆ˜ ๋ฐ ์„ค์ • ---
MEDIA_TYPE_TO_API = {
    "none": None,
    "illustrations": "illustration",
    "photos": "photo",
    "vectors": "vector"
}
DEFAULT_LANGUAGE = "ko"

# --- ๋ฐฑ์—”๋“œ ํ•จ์ˆ˜ ---

def get_best_image_url(hit):
    """์ตœ์ƒ์˜ ํ™”์งˆ ์ˆœ์„œ๋Œ€๋กœ ์ด๋ฏธ์ง€ URL์„ ๋ฐ˜ํ™˜"""
    return hit.get("fullHDURL") or hit.get("imageURL") or hit.get("largeImageURL") or hit.get("webformatURL")

def fetch_image(url):
    """URL์—์„œ ์ด๋ฏธ์ง€๋ฅผ ๋ถˆ๋Ÿฌ์™€ PIL ๊ฐ์ฒด๋กœ ๋ฐ˜ํ™˜"""
    try:
        response = requests.get(url)
        response.raise_for_status()
        return Image.open(BytesIO(response.content))
    except:
        return None

def pixabay_search(api_key, media_type, keyword, width, height):
    """API ํ˜ธ์ถœ, ์ด๋ฏธ์ง€ ๊ฒ€์ƒ‰ ๋ฐ ๋ฆฌ์‚ฌ์ด์ฆˆ๋ฅผ ํ•œ ๋ฒˆ์— ์ฒ˜๋ฆฌ"""
    if not api_key or not keyword:
        return [], None
    
    params = {"key": api_key, "q": keyword, "lang": DEFAULT_LANGUAGE, "per_page": 200}
    if media_type != "none":
        params["image_type"] = MEDIA_TYPE_TO_API.get(media_type)

    try:
        response = requests.get("https://pixabay.com/api/", params=params)
        response.raise_for_status()
        data = response.json()

        if not data.get("hits"):
            return [], None
            
        image_urls = [get_best_image_url(hit) for hit in data["hits"] if get_best_image_url(hit)]
        
        if not image_urls:
            return [], None

        url = random.choice(image_urls)
        img = fetch_image(url)

        if img and width and height and int(width) > 0 and int(height) > 0:
            img = img.resize((int(width), int(height)))
        
        return image_urls, img

    except (requests.exceptions.RequestException, Exception):
        return [], None

def pixabay_next_image(current_images, width, height):
    """์ €์žฅ๋œ ๋ชฉ๋ก์—์„œ ๋‹ค์Œ ์ด๋ฏธ์ง€๋ฅผ ๊ฐ€์ ธ์™€ ๋ฆฌ์‚ฌ์ด์ฆˆ"""
    if not current_images:
        return None
        
    url = random.choice(current_images)
    img = fetch_image(url)

    if isinstance(width, int) and isinstance(height, int) and width > 0 and height > 0:
        img = img.resize((int(width), int(height)))
        
    return img

# --- Gradio ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌ์„ฑ ---
with gr.Blocks(title="Pixabay ์ด๋ฏธ์ง€ ๊ฒ€์ƒ‰๊ธฐ") as demo:
    gr.Markdown("# Pixabay ์ด๋ฏธ์ง€ ๊ฒ€์ƒ‰ ๋ฐ๋ชจ")

    # ์ด๋ฏธ์ง€ URL ๋ชฉ๋ก์„ ์ €์žฅํ•˜๋Š” ๋ณด์ด์ง€ ์•Š๋Š” ์ƒํƒœ ๋ณ€์ˆ˜
    image_list_state = gr.State([])

    with gr.Row():
        with gr.Column(scale=1):
            # --- 1. ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ ๊ทธ๋ฃน ---
            gr.Markdown("### 1. ์ด๋ฏธ์ง€ ๊ฒ€์ƒ‰")
            api_key_input = gr.Textbox(label="Pixabay API Key", type="password")
            media_type_input = gr.Radio(choices=["none", "illustrations", "photos", "vectors"], label="๋ฏธ๋””์–ด ์œ ํ˜•", value="none")
            keyword_input = gr.Textbox(label="๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ")
            
            # --- 2. ๋ฆฌ์‚ฌ์ด์ฆˆ ์˜ต์…˜ ---
            with gr.Accordion("์ด๋ฏธ์ง€ ๋ฆฌ์‚ฌ์ด์ฆˆ (์„ ํƒ ์‚ฌํ•ญ)", open=False):
                with gr.Row():
                    width_input = gr.Number(label="๊ฐ€๋กœ(px)", step=1, value=None)
                    height_input = gr.Number(label="์„ธ๋กœ(px)", step=1, value=None)
            
            with gr.Row():
                search_btn = gr.Button("๊ฒ€์ƒ‰")
                next_btn = gr.Button("๋‹ค๋ฅธ ์ด๋ฏธ์ง€ ๋ณด๊ธฐ")
            
        with gr.Column(scale=2):
            # ๐Ÿ“Œ ํ•ต์‹ฌ: show_download_button=True ๋กœ ์ด๋ฏธ์ง€ ์ž์ฒด ๋‹ค์šด๋กœ๋“œ ๋ฒ„ํŠผ ํ™œ์„ฑํ™”
            image_output = gr.Image(type="pil", label="๊ฒฐ๊ณผ ์ด๋ฏธ์ง€", height=600, show_download_button=True)

    # --- ๋ฒ„ํŠผ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ---
    search_btn.click(
        fn=pixabay_search,
        inputs=[api_key_input, media_type_input, keyword_input, width_input, height_input],
        outputs=[image_list_state, image_output]
    )

    next_btn.click(
        fn=pixabay_next_image,
        inputs=[image_list_state, width_input, height_input],
        outputs=[image_output]
    )

# Gradio ์•ฑ ์‹คํ–‰
if __name__ == "__main__":
    demo.launch()