portfolio_image / app.py
Shekarss's picture
Update app.py
e35fe0b verified
import gradio as gr
import os
import time
from pathlib import Path
from PIL import Image
import base64
from io import BytesIO
# --- Setup ---
# Create a directory to store uploaded images
IMAGE_DIR = Path("gallery_images")
IMAGE_DIR.mkdir(exist_ok=True)
# --- Backend Functions ---
def cleanup_old_images():
"""Deletes images older than 60 minutes to save space."""
now = time.time()
for f in IMAGE_DIR.iterdir():
if f.is_file():
# Check if file is older than 3600 seconds (60 minutes)
if now - f.stat().st_mtime > 3600:
print(f"Cleaning up old image: {f.name}")
f.unlink()
def show_gallery():
"""
Cleans up old files and returns a sorted list of all current image paths.
This is called by the frontend to refresh the gallery view.
"""
cleanup_old_images()
# Sort files by creation time, newest first
files = sorted(IMAGE_DIR.iterdir(), key=os.path.getmtime, reverse=True)
return [str(f) for f in files]
def clear_gallery():
"""Deletes all files in the image directory."""
if IMAGE_DIR.exists():
for file_path in IMAGE_DIR.iterdir():
if file_path.is_file():
file_path.unlink() # Deletes the file
print("Gallery cleared successfully.")
# Return an empty list to update the gallery UI
return []
def upload_via_ui(image_from_ui):
"""
Handles image uploads directly from the Gradio UI interface.
The 'image_from_ui' is a PIL Image object.
"""
if image_from_ui is not None:
timestamp = int(time.time())
filename = f"ui_{timestamp}.png"
path = IMAGE_DIR / filename
image_from_ui.save(path)
print(f"Image saved from UI to {path}")
return show_gallery()
def upload_via_data_url(data_url_string):
"""
Handles image uploads from our JavaScript frontend.
The 'data_url_string' is a base64 encoded string.
"""
if not data_url_string:
raise gr.Error("No image data received.")
try:
# The string is "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ..."
# We need to strip the header to get just the base64 part.
header, encoded = data_url_string.split(",", 1)
# Decode the base64 string
img_data = base64.b64decode(encoded)
# Open the image using Pillow
image = Image.open(BytesIO(img_data))
# Generate a unique filename
timestamp = int(time.time())
filename = f"capture_{timestamp}.jpeg"
path = IMAGE_DIR / filename
# Save the image
image.save(path, "JPEG")
print(f"Image saved from camera to {path}")
except Exception as e:
print(f"Error processing image: {e}")
raise gr.Error("Server failed to process image.")
# After saving, return the updated list of all images
return show_gallery()
# --- Gradio UI & API ---
with gr.Blocks(title="Shekar's Portfolio Gallery") as demo:
gr.Markdown("## 📸 Portfolio Image Gallery")
# Main gallery display
gallery = gr.Gallery(
label="Uploaded Images",
show_label=False,
elem_id="gallery_component", # Use a unique elem_id
columns=4,
height="auto"
)
# --- Section for manual uploads via the Gradio UI ---
with gr.Accordion("Manual Upload (for testing)", open=False):
image_input = gr.Image(type="pil", label="Upload an Image")
upload_button = gr.Button("Upload from UI")
upload_button.click(
fn=upload_via_ui,
inputs=image_input,
outputs=gallery
)
with gr.Accordion("Admin Controls", open=False):
clear_btn = gr.Button("⚠️ Clear All Gallery Images")
# --- Hidden components to create the API endpoints ---
with gr.Row(visible=False):
# Textbox to receive the base64 data URL from the JS client
data_url_input = gr.Textbox()
# The upload function will output the new gallery list to our main gallery component
# This creates the /upload_via_data_url endpoint
data_url_input.submit(
fn=upload_via_data_url,
inputs=data_url_input,
outputs=gallery,
api_name="upload_via_data_url"
)
clear_btn.click(fn=clear_gallery, inputs=None, outputs=gallery)
# Load and refresh the gallery when the app starts.
# This also creates the /show_gallery endpoint for the JS client.
demo.load(
fn=show_gallery,
inputs=None,
outputs=gallery,
api_name="show_gallery"
)
# --- Launch the App ---
demo.launch()