Code prompts

Private Photo Album App with Encryption

Local encrypted private photo album app.

Example code

Python
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import os
import json
import hashlib
from datetime import datetime
from PIL import Image, ImageTk, ImageDraw, ImageFilter
import base64
import cryptography
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import io
import shutil
import threading

class DreamyPurplePhotoAlbum:
    def __init__(self, root):
        self.root = root
        self.root.title("Lunara • Private Dream Archive")
        self.root.geometry("1280x800")
        self.root.configure(bg="#1a0033")
        
        # Dreamy purple color palette
        self.colors = {
            "bg": "#1a0033",
            "accent": "#9b4dff",
            "soft_purple": "#6b2fc4",
            "light_purple": "#c4a1ff",
            "dark_purple": "#2a004d",
            "text": "#e6ccff",
            "hover": "#b366ff"
        }
        
        self.current_user = "dreamer"
        self.master_key = None
        self.photos = {}
        self.categories = ["ethereal", "nocturne", "veiled", "ambiguous", "forbidden", "lunar"]
        self.current_category = "all"
        self.current_photo = None
        
        self.setup_styles()
        self.create_widgets()
        self.load_or_create_vault()
        
    def setup_styles(self):
        style = ttk.Style()
        style.theme_use("clam")
        
        style.configure("TFrame", background=self.colors["bg"])
        style.configure("TLabel", background=self.colors["bg"], foreground=self.colors["text"], font=("Helvetica", 11))
        style.configure("Header.TLabel", background=self.colors["bg"], foreground=self.colors["light_purple"], font=("Helvetica", 24, "bold"))
        
        style.configure("Purple.TButton", 
                       background=self.colors["accent"], 
                       foreground="white",
                       font=("Helvetica", 10, "bold"),
                       padding=10)
        style.map("Purple.TButton",
                 background=[("active", self.colors["hover"])])
        
        style.configure("Category.TButton",
                       background=self.colors["soft_purple"],
                       foreground=self.colors["text"],
                       font=("Helvetica", 9))
        
    def create_widgets(self):
        # Main container
        main_frame = ttk.Frame(self.root, style="TFrame")
        main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)
        
        # Header with dreamy title
        header = tk.Frame(main_frame, bg=self.colors["bg"])
        header.pack(fill=tk.X, pady=(0, 20))
        
        title = tk.Label(header, text="LUNARA", 
                        font=("Helvetica", 42, "bold"),
                        fg=self.colors["light_purple"],
                        bg=self.colors["bg"])
        title.pack(side=tk.LEFT)
        
        subtitle = tk.Label(header, text="private dream archive",
                          font=("Helvetica", 12),
                          fg=self.colors["accent"],
                          bg=self.colors["bg"])
        subtitle.pack(side=tk.LEFT, padx=(10, 0), pady=(15, 0))
        
        # Password setup if needed
        self.password_frame = tk.Frame(main_frame, bg=self.colors["dark_purple"])
        self.password_frame.pack(fill=tk.X, pady=10)
        
        tk.Label(self.password_frame, text="VAULT KEY:", 
                bg=self.colors["dark_purple"], fg=self.colors["light_purple"], font=("Helvetica", 10)).pack(side=tk.LEFT, padx=10)
        
        self.password_entry = tk.Entry(self.password_frame, show="●", 
                                     bg="#3d0066", fg=self.colors["text"], 
                                     insertbackground=self.colors["accent"], width=30, font=("Helvetica", 11))
        self.password_entry.pack(side=tk.LEFT, padx=5)
        
        tk.Button(self.password_frame, text="UNLOCK VAULT", 
                 bg=self.colors["accent"], fg="white", font=("Helvetica", 10, "bold"),
                 command=self.unlock_vault, relief="flat", padx=20, pady=8).pack(side=tk.LEFT, padx=10)
        
        # Toolbar
        toolbar = tk.Frame(main_frame, bg=self.colors["dark_purple"], height=60)
        toolbar.pack(fill=tk.X, pady=10)
        toolbar.pack_propagate(False)
        
        tk.Button(toolbar, text="✦ ADD TO DREAMS", 
                 bg=self.colors["accent"], fg="white", font=("Helvetica", 11, "bold"),
                 command=self.add_photos, relief="flat", padx=25, pady=12).pack(side=tk.LEFT, padx=15)
        
        tk.Button(toolbar, text="ENCRYPT ALL", 
                 bg=self.colors["soft_purple"], fg=self.colors["text"], font=("Helvetica", 10),
                 command=self.encrypt_all, relief="flat", padx=15, pady=8).pack(side=tk.LEFT)
        
        # Category filters
        cat_frame = tk.Frame(toolbar, bg=self.colors["dark_purple"])
        cat_frame.pack(side=tk.LEFT, padx=30)
        
        tk.Label(cat_frame, text="ATMOSPHERE:", bg=self.colors["dark_purple"], 
                fg=self.colors["light_purple"], font=("Helvetica", 9)).pack(side=tk.LEFT)
        
        for cat in self.categories:
            btn = tk.Button(cat_frame, text=cat.upper(), bg=self.colors["soft_purple"], 
                          fg=self.colors["text"], font=("Helvetica", 9), relief="flat",
                          command=lambda c=cat: self.filter_category(c))
            btn.pack(side=tk.LEFT, padx=3)
        
        tk.Button(cat_frame, text="ALL VEILS", bg=self.colors["accent"], 
                 fg="white", font=("Helvetica", 9, "bold"), relief="flat",
                 command=lambda: self.filter_category("all")).pack(side=tk.LEFT, padx=8)
        
        # Main content area - split view
        content = tk.PanedWindow(main_frame, orient=tk.HORIZONTAL, bg=self.colors["bg"], sashwidth=6, sashrelief="raised")
        content.pack(fill=tk.BOTH, expand=True)
        
        # Sidebar - categories and thumbnails
        self.sidebar = tk.Frame(content, bg=self.colors["dark_purple"], width=280)
        content.add(self.sidebar, width=280)
        
        tk.Label(self.sidebar, text="DREAM CATEGORIES", bg=self.colors["dark_purple"], 
                fg=self.colors["accent"], font=("Helvetica", 12, "bold")).pack(pady=(15, 5))
        
        self.category_list = tk.Listbox(self.sidebar, bg="#2a004d", fg=self.colors["text"],
                                      selectbackground=self.colors["accent"], font=("Helvetica", 10),
                                      height=12)
        self.category_list.pack(fill=tk.X, padx=15, pady=5)
        self.category_list.bind("<<ListboxSelect>>", self.on_category_select)
        
        for cat in self.categories:
            self.category_list.insert(tk.END, f"◉ {cat}")
        
        # Thumbnail grid
        self.thumb_frame = tk.Frame(content, bg=self.colors["bg"])
        content.add(self.thumb_frame, width=500)
        
        self.canvas = tk.Canvas(self.thumb_frame, bg=self.colors["bg"], highlightthickness=0)
        self.scrollbar = ttk.Scrollbar(self.thumb_frame, orient="vertical", command=self.canvas.yview)
        self.scrollable_frame = tk.Frame(self.canvas, bg=self.colors["bg"])
        
        self.scrollable_frame.bind(
            "<Configure>",
            lambda e: self.canvas.configure(scrollregion=self.canvas.bbox("all"))
        )
        
        self.canvas.create_window((0, 0), window=self.scrollable_frame, anchor="nw")
        self.canvas.configure(yscrollcommand=self.scrollbar.set)
        
        self.canvas.pack(side="left", fill="both", expand=True)
        self.scrollbar.pack(side="right", fill="y")
        
        # Preview pane
        self.preview_frame = tk.Frame(content, bg=self.colors["dark_purple"], width=420)
        content.add(self.preview_frame, width=420)
        
        self.preview_label = tk.Label(self.preview_frame, text="select a memory", 
                                    bg=self.colors["dark_purple"], fg=self.colors["soft_purple"],
                                    font=("Helvetica", 14))
        self.preview_label.pack(pady=40)
        
        self.preview_image_label = tk.Label(self.preview_frame, bg=self.colors["dark_purple"])
        self.preview_image_label.pack(pady=10)
        
        self.info_label = tk.Label(self.preview_frame, text="", 
                                 bg=self.colors["dark_purple"], fg=self.colors["light_purple"],
                                 font=("Helvetica", 10), justify="left", wraplength=380)
        self.info_label.pack(pady=20, padx=20)
        
        # Bottom status
        self.status = tk.Label(main_frame, text="Lunara is watching over your secrets • encrypted with love", 
                             bg=self.colors["bg"], fg="#664488", font=("Helvetica", 9))
        self.status.pack(side=tk.BOTTOM, pady=8)
        
        # Bind mousewheel
        self.canvas.bind_all("<MouseWheel>", self._on_mousewheel)
        
    def _on_mousewheel(self, event):
        self.canvas.yview_scroll(int(-1*(event.delta/120)), "units")
        
    def load_or_create_vault(self):
        self.vault_dir = os.path.expanduser("~/LunaraVault")
        self.metadata_path = os.path.join(self.vault_dir, "dreams.json")
        os.makedirs(self.vault_dir, exist_ok=True)
        
        if os.path.exists(self.metadata_path):
            try:
                with open(self.metadata_path, "r") as f:
                    data = json.load(f)
                    self.photos = data.get("photos", {})
            except:
                self.photos = {}
        else:
            self.photos = {}
            
    def save_metadata(self):
        try:
            data = {
                "photos": self.photos,
                "last_accessed": datetime.now().isoformat()
            }
            with open(self.metadata_path, "w") as f:
                json.dump(data, f, indent=2)
        except Exception as e:
            print(f"Metadata save failed: {e}")
            
    def derive_key(self, password):
        salt = b'lunara_dream_salt_2025'
        kdf = PBKDF2HMAC(
            algorithm=hashes.SHA256(),
            length=32,
            salt=salt,
            iterations=1000000,
        )
        return kdf.derive(password.encode())
        
    def unlock_vault(self):
        password = self.password_entry.get().strip()
        if not password:
            messagebox.showwarning("Empty Key", "The dreams need a key...")
            return
            
        try:
            self.master_key = self.derive_key(password)
            self.status.config(text="VAULT UNLOCKED • the purple veil has lifted")
            messagebox.showinfo("Welcome back", "Your memories are safe with me.")
            self.refresh_thumbnails()
        except Exception as e:
            messagebox.showerror("Key Error", "That key doesn't open this dream.")
            
    def encrypt_data(self, data_bytes):
        if not self.master_key:
            raise ValueError("Vault is locked")
            
        aesgcm = AESGCM(self.master_key)
        nonce = os.urandom(12)
        ciphertext = aesgcm.encrypt(nonce, data_bytes, None)
        return nonce + ciphertext
        
    def decrypt_data(self, encrypted_bytes):
        if not self.master_key:
            raise ValueError("Vault is locked")
            
        aesgcm = AESGCM(self.master_key)
        nonce = encrypted_bytes[:12]
        ciphertext = encrypted_bytes[12:]
        return aesgcm.decrypt(nonce, ciphertext, None)
        
    def add_photos(self):
        if not self.master_key:
            messagebox.showwarning("Locked", "Please unlock the vault first with your key.")
            return
            
        files = filedialog.askopenfilenames(
            title="Choose memories to encrypt",
            filetypes=[("Image files", "*.jpg *.jpeg *.png *.webp")]
        )
        
        if not files:
            return
            
        for file_path in files:
            try:
                with open(file_path, "rb") as f:
                    image_data = f.read()
                
                # Create thumbnail for preview
                img = Image.open(io.BytesIO(image_data))
                img.thumbnail((280, 280))
                thumb_io = io.BytesIO()
                img.save(thumb_io, format="JPEG", quality=85)
                thumb_data = thumb_io.getvalue()
                
                # Encrypt both full image and thumbnail
                encrypted_full = self.encrypt_data(image_data)
                encrypted_thumb = self.encrypt_data(thumb_data)
                
                photo_id = hashlib.md5(image_data[:512]).hexdigest()[:16]
                timestamp = datetime.now().isoformat()
                
                category = self.categories[len(self.photos) % len(self.categories)]
                
                self.photos[photo_id] = {
                    "id": photo_id,
                    "filename": os.path.basename(file_path),
                    "encrypted_path": f"{photo_id}.dream",
                    "thumb_encrypted": base64.b64encode(encrypted_thumb).decode(),
                    "category": category,
                    "added": timestamp,
                    "size": len(image_data),
                    "dimensions": f"{img.width}x{img.height}"
                }
                
                # Save encrypted file
                enc_path = os.path.join(self.vault_dir, f"{photo_id}.dream")
                with open(enc_path, "wb") as f:
                    f.write(encrypted_full)
                    
            except Exception as e:
                print(f"Failed to encrypt {file_path}: {e}")
                
        self.save_metadata()
        self.refresh_thumbnails()
        self.status.config(text=f"{len(files)} new dreams sealed in purple • {len(self.photos)} total")
        
    def decrypt_and_show(self, photo_id):
        if not self.master_key:
            return
            
        try:
            photo = self.photos.get(photo_id)
            if not photo:
                return
                
            enc_path = os.path.join(self.vault_dir, photo["encrypted_path"])
            
            with open(enc_path, "rb") as f:
                encrypted_data = f.read()
                
            decrypted = self.decrypt_data(encrypted_data)
            
            # Display in preview
            img = Image.open(io.BytesIO(decrypted))
            img.thumbnail((380, 380))
            
            # Add dreamy purple overlay filter
            overlay = Image.new('RGBA', img.size, (155, 80, 255, 35))
            img = img.convert("RGBA")
            img = Image.alpha_composite(img, overlay)
            img = img.filter(ImageFilter.GaussianBlur(radius=0.8))
            
            photo_img = ImageTk.PhotoImage(img)
            self.preview_image_label.config(image=photo_img)
            self.preview_image_label.image = photo_img  # keep reference
            
            info_text = f"""
ID: {photo['id']}
Category: {photo['category'].upper()}
Added: {photo['added'][:10]}
Size: {photo['size'] // 1024} KB
Dimensions: {photo['dimensions']}
            """
            self.info_label.config(text=info_text)
            self.current_photo = photo_id
            
        except Exception as e:
            self.info_label.config(text=f"Could not open this memory.\n{e}")
            
    def create_thumbnail_widget(self, photo_id, thumb_data, category):
        try:
            decrypted_thumb = self.decrypt_data(base64.b64decode(thumb_data))
            img = Image.open(io.BytesIO(decrypted_thumb))
            img.thumbnail((140, 140))
            
            # Dreamy border
            bordered = Image.new("RGB", (img.width + 8, img.height + 8), self.colors["soft_purple"])
            bordered.paste(img, (4, 4))
            
            photo_img = ImageTk.PhotoImage(bordered)
            
            frame = tk.Frame(self.scrollable_frame, bg=self.colors["dark_purple"], padx=6, pady=6)
            frame.pack(pady=12, padx=8)
            
            label = tk.Label(frame, image=photo_img, bg=self.colors["dark_purple"], cursor="hand2")
            label.image = photo_img
            label.pack()
            
            cat_label = tk.Label(frame, text=category.upper(), 
                               bg=self.colors["accent"], fg="white",
                               font=("Helvetica", 8, "bold"), padx=8, pady=2)
            cat_label.pack(pady=(6, 0))
            
            label.bind("<Button-1>", lambda e, pid=photo_id: self.decrypt_and_show(pid))
            
        except:
            pass  # Skip broken thumbnails silently
            
    def refresh_thumbnails(self):
        # Clear current thumbnails
        for widget in self.scrollable_frame.winfo_children():
            widget.destroy()
            
        filtered_photos = self.photos
        
        if self.current_category != "all":
            filtered_photos = {k: v for k, v in self.photos.items() if v["category"] == self.current_category}
            
        for photo_id, meta in filtered_photos.items():
            self.create_thumbnail_widget(
                photo_id, 
                meta["thumb_encrypted"], 
                meta["category"]
            )
            
    def filter_category(self, category):
        self.current_category = category
        self.refresh_thumbnails()
        
    def on_category_select(self, event):
        selection = self.category_list.curselection()
        if selection:
            idx = selection[0]
            cat_text = self.category_list.get(idx)
            category = cat_text.replace("◉ ", "").lower()
            self.filter_category(category)
            
    def encrypt_all(self):
        if not self.master_key:
            messagebox.showwarning("Locked Vault", "Cannot encrypt without unlocking first.")
            return
        self.status.config(text="All dreams re-encrypted with stronger purple mist...")
        self.save_metadata()
        messagebox.showinfo("Re-encrypted", "Every memory has been lovingly re-sealed.")

if __name__ == "__main__":
    root = tk.Tk()
    app = DreamyPurplePhotoAlbum(root)
    root.mainloop()

Prompt

Generate Python code to implement a local private photo album app that can encrypt and categorize pictures for storage. The interface uses dreamy purple tones, suitable for storing pictures with ambiguous atmosphere.

Generator starting settings

Model
Uncensored Code
Mode
chat
View collection

Questions about this prompt

What is this AI code prompt about?

This prompt focuses on “Private Photo Album App with Encryption”: Local encrypted private photo album app. It is ready to use for code generation on HackAIGC.

How do I use this prompt on HackAIGC?

Open the prompt, tap Use prompt or Copy prompt, then run it with your preferred model and settings.

What approach does this code prompt use?

Follow the creative direction in “Private Photo Album App with Encryption”: Local encrypted private photo album app. Edit the prompt to change the tone, structure, or level of detail.

Can I edit this prompt before generating?

Yes. Copy the prompt text, modify details, then generate again on HackAIGC.