๐จ Python์ผ๋ก Background Generator Tool ๋ง๋ค๊ธฐ (๋จ๊ณ๋ณ)
Iโm ready to translate the article for you, but Iโll need the full text youโd like translated. Could you please paste the content (excluding the source line you already provided) here? Once I have it, Iโll keep the source line unchanged and translate the rest into Korean while preserving all formatting, markdown, and code blocks.
๋๊ตฌ ๋ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
| Library | Purpose |
|---|---|
| Tkinter + ttkbootstrap | ๋คํฌ/๋ผ์ดํธ ํ ๋ง๋ฅผ ์ง์ํ๋ ํ๋์ ์ธ GUI |
| Pillow (PIL) | ์ด๋ฏธ์ง ์์ฑ ๋ฐ ์กฐ์ |
| NumPy | ๋น ๋ฅธ ํฝ์ โ๋ ๋ฒจ ๋ ธ์ด์ฆ ์์ฑ |
| random & time | ๋ฌด์์์ฑ ๋ฐ ํ์์คํฌํ๊ฐ ํฌํจ๋ ํ์ผ๋ช |
๐ ์ต์ข ํ๋ก์ ํธ (GitHub):
๐ What Youโll Learn
- How to generate gradients programmatically
- How to add noise & texture to images
- How to build a modern Tkinter GUI
- How to resize images for live previews
- How to export images with smart filenames
๐งฐ Stepโฏ1 โ ํ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์น
pip install ttkbootstrap pillow numpy
์ ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ๊ฐ์?
- ttkbootstrap โ Tkinter์ฉ ํ๋์ ์ธ ๋คํฌ/๋ผ์ดํธ ํ ๋ง
- Pillow โ ์ด๋ฏธ์ง ์์ฑ ๋ฐ ์กฐ์
- NumPy โ ๋น ๋ฅธ ํฝ์ โ๋ ๋ฒจ ๋ ธ์ด์ฆ ์์ฑ
๐ฆ Stepโฏ2 โ ํ์ํ ๋ชจ๋ ๊ฐ์ ธ์ค๊ธฐ
import ttkbootstrap as tb
from ttkbootstrap.constants import *
from tkinter import filedialog, messagebox
from tkinter import ttk
from PIL import Image, ImageDraw, ImageFilter, ImageTk
import numpy as np
import random
import time
๐น ์ด ์ค์ ์ GUI ์์, ์ด๋ฏธ์ง ์ฒ๋ฆฌ ๋ฐ ์ ํธ๋ฆฌํฐ ๋๊ตฌ๋ฅผ ์ค๋นํฉ๋๋ค.
๐ Stepโฏ3 โ Add Noise to an Image
def add_noise(img, intensity=10):
arr = np.array(img)
noise = np.random.randint(-intensity, intensity + 1, arr.shape, "int16")
noisy = np.clip(arr + noise, 0, 255).astype("uint8")
return Image.fromarray(noisy)
๐ง Whatโs happening?
- Convert the image to a NumPy array
- Add random pixel values
- Clamp values between 0โฏโโฏ255
- Convert back to a PIL image
๐ ๋จ๊ณโฏ4 โ ์์ง ๊ทธ๋ผ๋์ธํธ ์์ฑ
def generate_gradient(size):
w, h = size
top_color = (
random.randint(50, 255),
random.randint(50, 255),
random.randint(50, 255)
)
bottom_color = (
random.randint(50, 255),
random.randint(50, 255),
random.randint(50, 255)
)
img = Image.new("RGB", size)
draw = ImageDraw.Draw(img)
for y in range(h):
r = int(top_color[0] + (bottom_color[0] - top_color[0]) * y / h)
g = int(top_color[1] + (bottom_color[1] - top_color[1]) * y / h)
b = int(top_color[2] + (bottom_color[2] - top_color[2]) * y / h)
draw.line((0, y, w, y), fill=(r, g, b))
return add_noise(img, intensity=5)
๐จ ์ค๋ช : ๊ฐ ํ์ ์์ชฝ โ ์๋์ชฝ์ผ๋ก ์์ ๊ฐ์ ๋ณด๊ฐํฉ๋๋ค.
โจ Stepโฏ5 โ ํ ์ค์ฒ ์ค๋ฒ๋ ์ด ๋ง๋ค๊ธฐ
def generate_texture(size):
img = Image.new("RGBA", size)
draw = ImageDraw.Draw(img)
for _ in range(size[0] * size[1] // 50):
x = random.randint(0, size[0] - 1)
y = random.randint(0, size[1] - 1)
color = (
random.randint(100, 255),
random.randint(100, 255),
random.randint(100, 255),
random.randint(20, 50)
)
draw.point((x, y), fill=color)
return img
๐น ์ด ์ฝ๋๋ ์ด๋ฏธ์ง ์ ์ฒด์ ๋ฐํฌ๋ช ํฝ์ ์ ๋ฌด์์๋ก ํฉ๋ฟ๋ฆฝ๋๋ค.
๐งฉ 6๋จ๊ณ โ ๊ทธ๋ผ๋์ธํธ์ ํ ์ค์ฒ ๊ฒฐํฉ
def generate_background(size):
base = generate_gradient(size)
texture = generate_texture(size)
base.paste(texture, (0, 0), texture)
return base
โ ๊ทธ๋ผ๋์ธํธโโ ๋ ธ์ด์ฆโโ ํ ์ค์ฒโโ ์ต์ข ์ด๋ฏธ์ง
๐ฅ Stepโฏ7 โ Create the Main App Window
class BackgroundGenerator:
def __init__(self, root):
self.root = root
root.title("Background Generator Tool")
root.geometry("1200x700")
root.resizable(True, True)
์ด๊ฒ์ ์ฐฝ ์ ๋ชฉ, ํฌ๊ธฐ ๋ฐ ํฌ๊ธฐ ์กฐ์ ๊ฐ๋ฅ์ฑ์ ์ค์ ํฉ๋๋ค.
๐ Stepโฏ8 โ ๋ด๋ณด๋ด๊ธฐ ํด์๋ ์ ์
self.resolutions = {
"HD (1280x720)": (1280, 720),
"Full HD (1920x1080)": (1920, 1080),
"2K (2560x1440)": (2560, 1440),
"4K (3840x2160)": (3840, 2160),
"Ultra HD (6000x3375)": (6000, 3375)
}
์ฌ์ฉ์๋ ํ ๋ฒ์ ํด๋ฆญ์ผ๋ก ์ ๋ฌธ๊ฐ ์์ค์ ํฌ๊ธฐ๋ฅผ ์ ํํ ์ ์์ต๋๋ค.
๐ Stepโฏ9 โ Build the Control Panel (Left Side)
left = tb.Frame(root, width=300, bootstyle="secondary")
left.pack(side="left", fill="y", padx=10, pady=10)
Orientation Selector
self.orient_combo = ttk.Combobox(
left, values=["Landscape", "Portrait"], state="readonly"
)
self.orient_combo.current(0)
self.orient_combo.pack(fill=X)
Resolution Selector
self.res_var = tb.StringVar(value="Full HD (1920x1080)")
tb.OptionMenu(left, self.res_var, *self.resolutions.keys()).pack(fill=X)
๐ผ Stepโฏ10 โ ์ค์๊ฐ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์บ๋ฒ์ค
self.canvas = tb.Canvas(root, bg="black", highlightthickness=0)
self.canvas.pack(expand=True, fill="both")
์ด๊ฒ์ ์์ฑ๋ ๋ฐฐ๊ฒฝ์ ์ค์ผ์ผ๋ ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋ฅผ ํ์ํฉ๋๋ค.
๐ 11๋จ๊ณ โ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์์ฑ ๋ฐ ํฌ๊ธฐ ์กฐ์
def update_preview(self):
img = self.state["bg"].copy()
canvas_w = self.canvas.winfo_width()
canvas_h = self.canvas.winfo_height()
if canvas_w > 0 and canvas_h > 0:
ratio = min(canvas_w / img.width, canvas_h / img.height)
preview = img.resize(
(int(img.width * ratio), int(img.height * ratio)),
Image.ANTIALIAS
)
self.tk_img = ImageTk.PhotoImage(preview)
self.canvas.create_image(
canvas_w // 2, canvas_h // 2,
image=self.tk_img, anchor="center"
)
์ด ๋ฉ์๋๋ ๋ฏธ๋ฆฌ๋ณด๊ธฐ๊ฐ ์บ๋ฒ์ค ํฌ๊ธฐ์ ๋น๋กํ๋๋ก ์ ์งํฉ๋๋ค.
๐ผ๏ธ ๋จ๊ณโฏ11 (๋์) โ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ํ์
ratio = min(canvas_w / img.width, canvas_h / img.height)
new_size = (int(img.width * ratio), int(img.height * ratio))
preview = img.resize(new_size)
self.tk_img = ImageTk.PhotoImage(preview)
self.canvas.delete("all")
self.canvas.create_image(
canvas_w // 2, canvas_h // 2, image=self.tk_img
)
๐ง ์ด๋ฏธ์ง๋ฅผ ์ค์์ ์ ์งํ๊ณ ์ ์ ํ ํฌ๊ธฐ๋ฅผ ์กฐ์ ํฉ๋๋ค.
๐พ Stepโฏ12 โ ๋ฐฐ๊ฒฝ ๋ด๋ณด๋ด๊ธฐ
def save_bg(self):
w, h = self.state["size"]
timestamp = int(time.time())
filename = f"background_{w}x{h}_{timestamp}.png"
f = filedialog.asksaveasfilename(
initialfile=filename,
defaultextension=".png",
filetypes=[("PNG Image", "*.png"), ("JPEG Image", "*.jpg")]
)
if f:
self.state["bg"].save(f)
messagebox.showinfo("Success", "Background saved!")
โ ์๋ ํ์ผ๋ช
โ PNG ๋๋ JPG ์ง์
๐ ์ฑ ์คํ
if __name__ == "__main__":
root = tb.Window(themename="darkly") # or "flatly" for a light theme
app = BackgroundGenerator(root)
root.mainloop()
์ด์ ์์ ํ ๊ธฐ๋ฅ์ ๊ฐ์ถ ๋ฐฐ๊ฒฝ ์์ฑ๊ธฐ GUI๊ฐ ์ค๋น๋์์ต๋๋ค. ์ด GUI๋ฅผ ํตํด ๋ค์์ ํ ์ ์์ต๋๋ค:
- ๋ฐฉํฅ ์ ํ (๊ฐ๋ก/์ธ๋ก)
- ๋ฏธ๋ฆฌ ์ ์๋ ๋ชฉ๋ก์์ ํด์๋ ์ ํ
- ์ฆ์ ์ ๋ฐ์ดํธ๋๋ ์ค์๊ฐ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ํ์ธ
- ํ์์คํฌํ๊ฐ ํฌํจ๋ ํ์ผ๋ช ์ผ๋ก ์ต์ข ์ด๋ฏธ์ง ๋ด๋ณด๋ด๊ธฐ
ํ๋ก์ ํธ๋ฅผ ์ํด ์๋ฆ๋ต๊ณ ๋ฌด์์์ ์ธ ๋ฐฐ๊ฒฝ์ ๋ง๋๋ ์ฆ๊ฑฐ์์ ๋๋ฆฌ์ธ์!
๐ ์ต์ข ์๊ฐ
์ด ํ๋ก์ ํธ๋ ๋ค์๊ณผ ๊ฐ์ ๋ชฉํ์ ์๋ฒฝํฉ๋๋ค:
- ์ด๋ฏธ์ง ์ฒ๋ฆฌ ์ฐ์ต
- Tkinter GUI ๊ฐ๋ฐ ํ์ต
- ์ฐฝ์์ ์ธ Python ๋๊ตฌ ์ ์
๐ Source Code:
https://github.com/rogers-cyber/python-tiny-tools/tree/main/Background_Generator_Tool
์ด ํํ ๋ฆฌ์ผ์ด ๋ง์์ ๋์ จ๋ค๋ฉด, ๋ ํฌ์ โญ ๋ณํ๋ฅผ ๋ฌ๊ณ Dev.to์ ๊ณต์ ํด ์ฃผ์ธ์!
ํ๋ณตํ ์ฝ๋ฉ ๐จโ๐ป๐จ
