|
import streamlit as st |
|
import os |
|
from PIL import Image |
|
from io import BytesIO |
|
import zipfile |
|
from dotenv import load_dotenv |
|
|
|
|
|
from utils.helper_utilities import ( |
|
get_next_largest_aspect_ratio, draw_crop_preview, |
|
add_custom_message, generate_flux_image |
|
) |
|
|
|
|
|
from utils.configuration import ( |
|
default_guidance_scale, default_num_inference_steps, |
|
default_seed, holiday_border_prompts, example_holiday_messages, fonts |
|
) |
|
|
|
|
|
st.image("img/fireworksai_logo.png") |
|
st.title("π Holiday Card Customizer π
") |
|
|
|
st.markdown(""" |
|
β¨ Welcome to the **Holiday Card Generator**! Get ready to sprinkle some holiday magic onto your custom card with a festive border and a heartfelt message. Here's how you can spread the holiday cheer: |
|
|
|
1. π **Upload your image** β Select a photo or design to be the star of your holiday card. |
|
2. β¨ **Design your holiday card border** β Choose from seasonal prompts or create your own unique design. |
|
3. π **Add your personal holiday message** β Make it meaningful, funny, or warm-hearted! |
|
4. π¦ **Download your finished card** β Ready to send to friends and family. |
|
|
|
Letβs bring your holiday greetings to life! π |
|
""") |
|
|
|
|
|
if 'uploaded_file' not in st.session_state: |
|
st.session_state.uploaded_file = None |
|
if 'generated_image' not in st.session_state: |
|
st.session_state.generated_image = None |
|
if 'metadata' not in st.session_state: |
|
st.session_state.metadata = {} |
|
|
|
st.divider() |
|
st.subheader("π
Step 1: Load Your Fireworks API Key π") |
|
|
|
|
|
|
|
dotenv_path = os.path.join(os.path.dirname(__file__), '..', 'env', '.env') |
|
os.makedirs(os.path.dirname(dotenv_path), exist_ok=True) |
|
|
|
|
|
if not os.path.exists(dotenv_path): |
|
with open(dotenv_path, "w") as f: |
|
st.success(f"Created {dotenv_path}") |
|
|
|
|
|
load_dotenv(dotenv_path, override=True) |
|
|
|
|
|
fireworks_api_key = os.getenv("FIREWORKS_API_KEY") |
|
|
|
|
|
if not fireworks_api_key or fireworks_api_key.strip() == "": |
|
fireworks_api_key = st.text_input("Enter Fireworks API Key", type="password") |
|
|
|
|
|
if fireworks_api_key and st.checkbox("Save API key for future use"): |
|
with open(dotenv_path, "a") as f: |
|
f.write(f"FIREWORKS_API_KEY={fireworks_api_key}\n") |
|
st.success("API key saved to .env file.") |
|
else: |
|
st.success(f"API key loaded successfully: partial preview {fireworks_api_key[:5]}") |
|
|
|
|
|
st.subheader("π Step 2: Upload Your Festive Picture π¨") |
|
st.markdown(""" |
|
It's time to pick your image! This will be the centerpiece of your holiday card. |
|
- **Pro Tip**: Choose something that brings out the warmth and joy of the season! ππ
|
|
Upload a **PNG** or **JPEG** image to get started. |
|
""") |
|
uploaded_file = st.file_uploader("Upload an image", type=["png", "jpg", "jpeg"]) |
|
if uploaded_file is not None: |
|
st.session_state.uploaded_file = uploaded_file |
|
|
|
|
|
if st.session_state.uploaded_file is not None: |
|
try: |
|
original_image = Image.open(st.session_state.uploaded_file) |
|
st.image(original_image, caption="Uploaded Image", use_column_width=True) |
|
|
|
|
|
st.subheader("βοΈ Step 3: Trim Your Image Just Right! π") |
|
st.markdown(""" |
|
Adjust the crop sliders to capture the most festive part of your image. |
|
A preview will show you how your holiday card is shaping up! β¨ |
|
""") |
|
img_width, img_height = original_image.size |
|
col1, col2 = st.columns(2) |
|
with col1: |
|
x_pos = st.slider("X position (Left-Right)", 0, img_width, img_width // 4) |
|
crop_width = st.slider("Width", 10, img_width - x_pos, min(img_width // 2, img_width - x_pos)) |
|
with col2: |
|
y_pos = st.slider("Y position (Up-Down)", 0, img_height, img_height // 4) |
|
crop_height = st.slider("Height", 10, img_height - y_pos, min(img_height // 2, img_height - y_pos)) |
|
|
|
preview_image = draw_crop_preview(original_image.copy(), x_pos, y_pos, crop_width, crop_height) |
|
st.image(preview_image, caption="Crop Preview", use_column_width=True) |
|
|
|
|
|
st.subheader("π¨ Step 4: Design Your Holiday Border! π
") |
|
st.markdown(""" |
|
Choose from a range of holiday themes like snowflakes, cozy fireplaces, or fireworks! |
|
Want to create your own magical scene? Enter a **custom prompt** to make it truly unique! π |
|
""") |
|
selected_prompt = st.selectbox("Choose a holiday-themed prompt or enter your own", options=["Custom"] + holiday_border_prompts) |
|
custom_prompt = st.text_input("Enter your custom prompt") if selected_prompt == "Custom" else "" |
|
prompt = custom_prompt if selected_prompt == "Custom" else selected_prompt |
|
|
|
guidance_scale = st.slider("Guidance Scale", min_value=0.0, max_value=20.0, value=default_guidance_scale, step=0.1) |
|
num_inference_steps = st.slider("Number of Inference Steps", min_value=1, max_value=100, value=default_num_inference_steps, step=1) |
|
seed = st.slider("Random Seed", min_value=0, max_value=1000, value=default_seed) |
|
|
|
if st.button("Generate Holiday Card"): |
|
if not prompt.strip(): |
|
st.error("Please enter a prompt.") |
|
else: |
|
with st.spinner("Adding holiday magic..."): |
|
aspect_ratio = get_next_largest_aspect_ratio(img_width, img_height) |
|
generated_image = generate_flux_image( |
|
model_path="flux-1-schnell-fp8", |
|
api_key=fireworks_api_key, |
|
prompt=prompt, |
|
steps=num_inference_steps, |
|
guidance_scale=guidance_scale, |
|
seed=seed, |
|
aspect_ratio=f"{aspect_ratio[0]}:{aspect_ratio[1]}" |
|
) |
|
|
|
if generated_image is not None: |
|
generated_image = generated_image.resize(original_image.size) |
|
cropped_original = original_image.crop((x_pos, y_pos, x_pos + crop_width, y_pos + crop_height)) |
|
center_x = (generated_image.width - crop_width) // 2 |
|
center_y = (generated_image.height - crop_height) // 2 |
|
final_image = generated_image.copy() |
|
final_image.paste(cropped_original, (center_x, center_y)) |
|
st.session_state.generated_image = final_image |
|
|
|
|
|
st.session_state.metadata = { |
|
"Prompt": prompt, |
|
"Guidance Scale": guidance_scale, |
|
"Inference Steps": num_inference_steps, |
|
"Seed": seed |
|
} |
|
|
|
st.image(final_image, caption="π Final Holiday Card π", use_column_width=True) |
|
|
|
|
|
st.markdown("### β¨ Card Metadata") |
|
for key, value in st.session_state.metadata.items(): |
|
st.write(f"**{key}:** {value}") |
|
|
|
|
|
if 'generated_image' in st.session_state and st.session_state.generated_image is not None: |
|
st.subheader("π Step 5: Add Your Heartfelt Holiday Message! π
") |
|
st.markdown(""" |
|
Select a pre-written festive message or craft your own! |
|
Customize the font, size, and color to make it pop! π |
|
""") |
|
|
|
selected_message = st.selectbox("Choose an example holiday message or write your own", options=["Custom"] + example_holiday_messages) |
|
custom_message = st.text_input("Enter your holiday message") if selected_message == "Custom" else selected_message |
|
|
|
selected_font = st.selectbox("Choose a font for your message", options=list(fonts.keys())) |
|
font_size = st.slider("Adjust font size", min_value=1, max_value=500, value=100, step=5) |
|
|
|
max_chars = st.slider("Max characters per line:", min_value=20, max_value=100, value=40) |
|
font_path = fonts[selected_font] |
|
bg_color = st.color_picker("Pick a background color for the text", "#FFFFFF") |
|
font_color = st.color_picker("Pick a font color", "#000000") |
|
alpha = st.slider("Background transparency (0: fully transparent, 255: fully opaque)", 0, 255, 200) |
|
position_vertical = st.radio("Vertical position", ["Top", "Center", "Bottom"]) |
|
position_horizontal = st.radio("Horizontal position", ["Left", "Center", "Right"]) |
|
|
|
|
|
|
|
if st.button("Generate Holiday Card with Message"): |
|
final_image_with_message = st.session_state.generated_image.copy() |
|
|
|
final_image_with_message = add_custom_message( |
|
final_image_with_message, |
|
custom_message, |
|
font_path, |
|
font_size, |
|
position_vertical, |
|
position_horizontal, |
|
max_chars=max_chars, |
|
bg_color=bg_color, |
|
font_color=font_color, |
|
alpha=alpha |
|
) |
|
|
|
st.image(final_image_with_message, caption="π Holiday Card with Custom Message π", use_column_width=True) |
|
|
|
|
|
img_byte_arr = BytesIO() |
|
final_image_with_message.save(img_byte_arr, format="PNG") |
|
img_byte_arr.seek(0) |
|
|
|
|
|
zip_buffer = BytesIO() |
|
with zipfile.ZipFile(zip_buffer, "w") as zf: |
|
|
|
zf.writestr("holiday_card_with_message.png", img_byte_arr.getvalue()) |
|
|
|
|
|
metadata_str = "\n".join([f"{key}: {value}" for key, value in st.session_state.metadata.items()]) |
|
zf.writestr("metadata.txt", metadata_str) |
|
|
|
zip_buffer.seek(0) |
|
|
|
|
|
st.download_button( |
|
label="π Download Holiday Card and Metadata as ZIP π", |
|
data=zip_buffer, |
|
file_name="holiday_card_with_message.zip", |
|
mime="application/zip" |
|
) |
|
|
|
except OSError: |
|
st.error("The uploaded image seems to be truncated or corrupted. Please try with a different image.") |
|
else: |
|
st.warning("Please upload an image to get started.") |
|
|
|
|
|
|
|
st.divider() |
|
st.markdown( |
|
""" |
|
Thank you for using the Holiday Card Generator powered by **Fireworks**! π |
|
Share your creations with the world and spread the holiday cheer! |
|
Happy Holidays from the **Fireworks Team**. π₯ |
|
""" |
|
) |