pixapick / app.py
snowseol's picture
add resize
b2547eb
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()