|
|
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 |
|
|
|
|
|
|
|
|
with gr.Blocks(title="Pixabay ์ด๋ฏธ์ง ๊ฒ์๊ธฐ") as demo: |
|
|
gr.Markdown("# Pixabay ์ด๋ฏธ์ง ๊ฒ์ ๋ฐ๋ชจ") |
|
|
|
|
|
|
|
|
image_list_state = gr.State([]) |
|
|
|
|
|
with gr.Row(): |
|
|
with gr.Column(scale=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="๊ฒ์ ํค์๋") |
|
|
|
|
|
|
|
|
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): |
|
|
|
|
|
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] |
|
|
) |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
demo.launch() |
|
|
|