Download app.py from ChBysk/Button: direct link, hf CLI and curl.
- Browser
- Download file 7.2 kB
-
https://huggingface.co/spaces/ChBysk/Button/resolve/main/app.py
- Command line
-
hf download hf://spaces/ChBysk/Button/app.py
-
curl -L -o app.py https://huggingface.co/spaces/ChBysk/Button/resolve/main/app.py
7.2 kB
| import gradio as gr | |
| import os | |
| from pathlib import Path | |
| from PIL import Image | |
| import json | |
| from datetime import datetime | |
| # Configuration | |
| UPLOAD_DIR = "images/uploads" | |
| GALLERY_DIR = "images/gallery" | |
| METADATA_FILE = "images/metadata.json" | |
| # Create directories if they don't exist | |
| os.makedirs(UPLOAD_DIR, exist_ok=True) | |
| os.makedirs(GALLERY_DIR, exist_ok=True) | |
| def load_metadata(): | |
| """Load metadata from JSON file""" | |
| if os.path.exists(METADATA_FILE): | |
| with open(METADATA_FILE, 'r') as f: | |
| return json.load(f) | |
| return {} | |
| def save_metadata(metadata): | |
| """Save metadata to JSON file""" | |
| with open(METADATA_FILE, 'w') as f: | |
| json.dump(metadata, f, indent=2) | |
| def get_gallery_images(): | |
| """Get all images from gallery directory""" | |
| images = [] | |
| if not os.path.exists(GALLERY_DIR): | |
| return images | |
| for file in sorted(os.listdir(GALLERY_DIR)): | |
| if file.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.webp')): | |
| filepath = os.path.join(GALLERY_DIR, file) | |
| images.append(filepath) | |
| return images | |
| def upload_image(file): | |
| """Handle image upload""" | |
| if file is None: | |
| return "No file uploaded", get_gallery_images() | |
| try: | |
| # Get filename | |
| if hasattr(file, 'name'): | |
| filename = os.path.basename(file.name) | |
| file_path = file.name | |
| else: | |
| filename = os.path.basename(str(file)) | |
| file_path = str(file) | |
| save_path = os.path.join(GALLERY_DIR, filename) | |
| # Use PIL to verify it's a valid image | |
| img = Image.open(file_path) | |
| img.save(save_path) | |
| # Update metadata | |
| metadata = load_metadata() | |
| metadata[filename] = { | |
| "uploaded": datetime.now().isoformat(), | |
| "size": f"{img.width}x{img.height}", | |
| "format": img.format | |
| } | |
| save_metadata(metadata) | |
| return f"β Image '{filename}' uploaded successfully!", get_gallery_images() | |
| except Exception as e: | |
| return f"β Error uploading image: {str(e)}", get_gallery_images() | |
| def delete_image(gallery_state): | |
| """Delete image from gallery - requires Gradio 6.20+ select callback""" | |
| if not gallery_state: | |
| return "No image selected", get_gallery_images() | |
| try: | |
| # Handle different gallery return formats | |
| image_path = gallery_state | |
| if isinstance(gallery_state, dict): | |
| image_path = gallery_state.get('name') or gallery_state.get('image') | |
| if image_path and os.path.exists(image_path): | |
| os.remove(image_path) | |
| # Update metadata | |
| filename = os.path.basename(image_path) | |
| metadata = load_metadata() | |
| if filename in metadata: | |
| del metadata[filename] | |
| save_metadata(metadata) | |
| return f"β Image deleted!", get_gallery_images() | |
| else: | |
| return "β Image not found", get_gallery_images() | |
| except Exception as e: | |
| return f"β Error: {str(e)}", get_gallery_images() | |
| def search_images(query): | |
| """Search images by filename""" | |
| all_images = get_gallery_images() | |
| if not query: | |
| return all_images | |
| query = query.lower() | |
| return [img for img in all_images if query in os.path.basename(img).lower()] | |
| # Create Gradio interface | |
| with gr.Blocks(title="Image Gallery", theme=gr.themes.Soft()) as demo: | |
| gr.Markdown("# πΌοΈ Image Gallery") | |
| gr.Markdown("A simple image gallery built with Gradio. Upload, organize, and view your images.") | |
| with gr.Tabs(): | |
| # Gallery Tab | |
| with gr.Tab("πΈ Gallery"): | |
| gallery_output = gr.Gallery( | |
| label="Images", | |
| value=get_gallery_images(), | |
| columns=4, | |
| rows=3, | |
| object_fit="scale-down", | |
| height="auto" | |
| ) | |
| with gr.Row(): | |
| search_input = gr.Textbox( | |
| label="Search", | |
| placeholder="Search images by filename..." | |
| ) | |
| search_btn = gr.Button("π Search") | |
| with gr.Row(): | |
| refresh_btn = gr.Button("π Refresh Gallery") | |
| search_btn.click( | |
| search_images, | |
| inputs=search_input, | |
| outputs=gallery_output | |
| ) | |
| refresh_btn.click( | |
| lambda: get_gallery_images(), | |
| outputs=gallery_output | |
| ) | |
| # Upload Tab | |
| with gr.Tab("β¬οΈ Upload"): | |
| gr.Markdown("### Upload New Images") | |
| with gr.Row(): | |
| file_input = gr.File( | |
| label="Select Image", | |
| file_count="single", | |
| file_types=["image"] | |
| ) | |
| upload_btn = gr.Button("Upload") | |
| upload_status = gr.Textbox(label="Status", interactive=False) | |
| uploaded_gallery = gr.Gallery( | |
| label="Recent Uploads", | |
| columns=4, | |
| rows=2, | |
| object_fit="scale-down" | |
| ) | |
| upload_btn.click( | |
| upload_image, | |
| inputs=file_input, | |
| outputs=[upload_status, uploaded_gallery] | |
| ) | |
| # Manage Tab | |
| with gr.Tab("βοΈ Manage"): | |
| gr.Markdown("### Manage Images") | |
| manage_gallery = gr.Gallery( | |
| value=get_gallery_images(), | |
| label="Gallery Images", | |
| columns=4, | |
| rows=3, | |
| object_fit="scale-down", | |
| interactive=True, | |
| show_label=True | |
| ) | |
| with gr.Row(): | |
| refresh_manage_btn = gr.Button("π Refresh") | |
| action_status = gr.Textbox(label="Status", interactive=False) | |
| refresh_manage_btn.click( | |
| lambda: get_gallery_images(), | |
| outputs=manage_gallery | |
| ) | |
| # Info Tab | |
| with gr.Tab("βΉοΈ Info"): | |
| gr.Markdown(""" | |
| ## About This Gallery | |
| **Features:** | |
| - π€ Upload images (PNG, JPG, GIF, WebP) | |
| - π Search and filter by filename | |
| - ποΈ Organize and manage images | |
| - π View image metadata (size, format) | |
| - π³ Run anywhere with Docker | |
| **Supported Formats:** | |
| - PNG | |
| - JPEG/JPG | |
| - GIF | |
| - WebP | |
| **Storage:** | |
| - Gallery: `images/gallery/` | |
| - Metadata: `images/metadata.json` | |
| **Version Info:** | |
| - Python: 3.13+ | |
| - Gradio: 6.20.0+ | |
| - Pillow: 10.2.0+ | |
| """) | |
| if __name__ == "__main__": | |
| demo.launch( | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| share=False | |
| ) | |