Skip to content

Commit 36db3d9

Browse files
authored
Create Background_Generator.py
1 parent 6d8c173 commit 36db3d9

1 file changed

Lines changed: 178 additions & 0 deletions

File tree

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
import ttkbootstrap as tb
2+
from ttkbootstrap.constants import *
3+
from tkinter import filedialog, messagebox
4+
from tkinter import ttk # For Combobox
5+
from PIL import Image, ImageDraw, ImageFilter, ImageTk
6+
import numpy as np
7+
import random
8+
import time
9+
10+
# =========================
11+
# UTILITY FUNCTIONS
12+
# =========================
13+
def add_noise(img, intensity=10):
14+
"""Add random noise to an image."""
15+
arr = np.array(img)
16+
noise = np.random.randint(-intensity, intensity + 1, arr.shape, "int16")
17+
noisy = np.clip(arr + noise, 0, 255).astype("uint8")
18+
return Image.fromarray(noisy)
19+
20+
def generate_gradient(size):
21+
"""Generate a simple vertical gradient with optional noise."""
22+
w, h = size
23+
top_color = (
24+
random.randint(50, 255),
25+
random.randint(50, 255),
26+
random.randint(50, 255)
27+
)
28+
bottom_color = (
29+
random.randint(50, 255),
30+
random.randint(50, 255),
31+
random.randint(50, 255)
32+
)
33+
img = Image.new("RGB", size)
34+
draw = ImageDraw.Draw(img)
35+
for y in range(h):
36+
r = int(top_color[0] + (bottom_color[0] - top_color[0]) * y / h)
37+
g = int(top_color[1] + (bottom_color[1] - top_color[1]) * y / h)
38+
b = int(top_color[2] + (bottom_color[2] - top_color[2]) * y / h)
39+
draw.line((0, y, w, y), fill=(r, g, b))
40+
return add_noise(img, intensity=5)
41+
42+
def generate_texture(size):
43+
"""Generate a random texture overlay."""
44+
img = Image.new("RGBA", size)
45+
draw = ImageDraw.Draw(img)
46+
for _ in range(size[0] * size[1] // 50):
47+
x = random.randint(0, size[0] - 1)
48+
y = random.randint(0, size[1] - 1)
49+
color = (
50+
random.randint(100, 255),
51+
random.randint(100, 255),
52+
random.randint(100, 255),
53+
random.randint(20, 50)
54+
)
55+
draw.point((x, y), fill=color)
56+
return img
57+
58+
def generate_background(size):
59+
"""Combine gradient and texture to produce the final background."""
60+
base = generate_gradient(size)
61+
texture = generate_texture(size)
62+
base.paste(texture, (0, 0), texture)
63+
return base
64+
65+
# =========================
66+
# MAIN APP CLASS
67+
# =========================
68+
class BackgroundGenerator:
69+
def __init__(self, root):
70+
self.root = root
71+
root.title("Background Generator Tool")
72+
root.geometry("1200x700")
73+
root.resizable(True, True)
74+
75+
self.resolutions = {
76+
"HD (1280x720)": (1280, 720),
77+
"Full HD (1920x1080)": (1920, 1080),
78+
"2K (2560x1440)": (2560, 1440),
79+
"4K (3840x2160)": (3840, 2160),
80+
"Ultra HD (6000x3375)": (6000, 3375)
81+
}
82+
83+
self.state = {
84+
"size": (1920, 1080),
85+
"bg": generate_background((1920, 1080))
86+
}
87+
88+
# LEFT PANEL
89+
left = tb.Frame(root, width=300, bootstyle="secondary")
90+
left.pack(side="left", fill="y", padx=10, pady=10)
91+
92+
# Orientation Selector
93+
tb.Label(left, text="Orientation:", font=("Segoe UI", 10, "bold")).pack(anchor="w", pady=(5, 2))
94+
self.orient_combo = ttk.Combobox(left, values=["Landscape", "Portrait"], state="readonly")
95+
self.orient_combo.current(0) # Default to Landscape
96+
self.orient_combo.pack(fill=X, pady=(0, 10))
97+
98+
# Resolution Selector
99+
tb.Label(left, text="Export Resolution:", font=("Segoe UI", 10, "bold")).pack(anchor="w", pady=(5, 2))
100+
self.res_var = tb.StringVar(value="Full HD (1920x1080)")
101+
tb.OptionMenu(left, self.res_var, *self.resolutions.keys(), bootstyle="secondary").pack(fill=X, pady=(0, 10))
102+
103+
# Buttons
104+
tb.Button(left, text="🔄 Generate Background", bootstyle=INFO, command=self.generate_bg).pack(fill=X, pady=5)
105+
tb.Button(left, text="💾 Export", bootstyle=SUCCESS, command=self.save_bg).pack(fill=X, pady=5)
106+
107+
# RIGHT PANEL - Canvas Preview
108+
self.canvas_frame = tb.Frame(root)
109+
self.canvas_frame.pack(side="right", fill="both", expand=True, padx=10, pady=10)
110+
self.canvas = tb.Canvas(self.canvas_frame, bg="black", highlightthickness=0)
111+
self.canvas.pack(expand=True, fill="both")
112+
self.canvas_frame.bind("<Configure>", self.on_resize)
113+
114+
self.update_preview()
115+
116+
# =========================
117+
# EVENT METHODS
118+
# =========================
119+
def on_resize(self, event):
120+
self.update_preview()
121+
122+
# =========================
123+
# STATE HANDLERS
124+
# =========================
125+
def generate_bg(self):
126+
w, h = self.resolutions.get(self.res_var.get(), (1920, 1080))
127+
orientation = self.orient_combo.get()
128+
if orientation == "Portrait":
129+
w, h = h, w
130+
self.state["size"] = (w, h)
131+
self.state["bg"] = generate_background((w, h))
132+
self.update_preview()
133+
134+
def update_preview(self):
135+
img = self.state["bg"].copy()
136+
canvas_w = self.canvas.winfo_width()
137+
canvas_h = self.canvas.winfo_height()
138+
if canvas_w > 0 and canvas_h > 0:
139+
img_w, img_h = img.size
140+
ratio = min(canvas_w / img_w, canvas_h / img_h)
141+
new_w = max(1, int(img_w * ratio))
142+
new_h = max(1, int(img_h * ratio))
143+
preview = img.resize((new_w, new_h))
144+
self.tk_img = ImageTk.PhotoImage(preview)
145+
self.canvas.delete("all")
146+
self.canvas.create_image(canvas_w // 2, canvas_h // 2, image=self.tk_img)
147+
148+
def save_bg(self):
149+
# Get current background info
150+
w, h = self.state["size"]
151+
orientation = self.orient_combo.get()
152+
153+
# Generate automatic filename
154+
timestamp = int(time.time()) # simple timestamp
155+
filename = f"background_{w}x{h}_{orientation}_{timestamp}.png"
156+
157+
# Ask user where to save, default filename pre-filled
158+
f = filedialog.asksaveasfilename(
159+
initialfile=filename,
160+
defaultextension=".png",
161+
filetypes=[("PNG Image", "*.png"), ("JPEG Image", "*.jpg")]
162+
)
163+
164+
if f:
165+
ext = f.split('.')[-1].lower()
166+
if ext in ["jpg", "jpeg"]:
167+
self.state["bg"].save(f, quality=85)
168+
else:
169+
self.state["bg"].save(f, optimize=True)
170+
messagebox.showinfo("Success", f"Background saved as {f}!")
171+
172+
# =========================
173+
# RUN APP
174+
# =========================
175+
if __name__ == "__main__":
176+
root = tb.Window(themename="darkly")
177+
app = BackgroundGenerator(root)
178+
root.mainloop()

0 commit comments

Comments
 (0)