Files
danieljanata-ComfyUI-Prompt…/utils/metadata_extractor.py
T
Claude 4a24994b70 Add complete ComfyUI Prompting System implementation
Implemented comprehensive prompt management system with the following features:

🎨 Core Nodes:
- Prompt Saver: Save prompts with metadata, lock/unlock mechanism
- Smart Text Input: Automatic change detection (new vs edit)
- Prompt Library Browser: Search, filter, load prompts
- Export Manager: Export/import database, statistics, cleanup

💾 Database Features:
- JSON storage with base64-encoded thumbnails (150x150px)
- Cross-platform path handling (Windows/Linux/macOS)
- Automatic deduplication by hash
- Merge functionality with conflict resolution
- Auto-cleanup of old unrated prompts

🖼️ Thumbnail System:
- Up to 3 thumbnails per prompt
- Lock/unlock mechanism for preserving favorite images
- Automatic thumbnail updates on generation
- Base64 encoding for single-file portability

🎯 Key Features:
- Category and tag management
- Rating system (0-5 stars)
- Generation history tracking
- PNG metadata extraction
- Search and filter capabilities
- Statistics and analytics

🌐 UI Components:
- JavaScript extensions for visual feedback
- CSS styling for modern interface
- Pulsing unlock button animation
- Color-coded change detection
- Custom node styling

📚 Documentation:
- Comprehensive README with usage examples
- Troubleshooting guide
- Advanced configuration options
- Merge logic explanation

All components are fully functional and ready for testing.
2026-01-14 08:25:24 +00:00

142 lines
3.8 KiB
Python

"""Extract metadata and prompts from ComfyUI generated images"""
import json
from pathlib import Path
from typing import Optional, Dict, Any
from PIL import Image
from PIL.PngImagePlugin import PngInfo
def extract_prompt_from_png(image_path: str) -> Optional[Dict[str, Any]]:
"""
Extract prompt information from ComfyUI generated PNG file.
Args:
image_path: Path to the PNG file
Returns:
Dictionary with prompt data or None if not found
"""
try:
img = Image.open(image_path)
# ComfyUI stores prompt in 'prompt' metadata field
if 'prompt' in img.info:
prompt_data = json.loads(img.info['prompt'])
return prompt_data
return None
except Exception as e:
print(f"[PromptSystem] Error extracting prompt from {image_path}: {e}")
return None
def extract_workflow_from_png(image_path: str) -> Optional[Dict[str, Any]]:
"""
Extract workflow information from ComfyUI generated PNG file.
Args:
image_path: Path to the PNG file
Returns:
Dictionary with workflow data or None if not found
"""
try:
img = Image.open(image_path)
# ComfyUI stores workflow in 'workflow' metadata field
if 'workflow' in img.info:
workflow_data = json.loads(img.info['workflow'])
return workflow_data
return None
except Exception as e:
print(f"[PromptSystem] Error extracting workflow from {image_path}: {e}")
return None
def extract_all_text_from_prompt_data(prompt_data: Dict[str, Any]) -> str:
"""
Extract all text prompts from prompt data structure.
Concatenates all text inputs found in the workflow.
Args:
prompt_data: Prompt data dictionary from PNG metadata
Returns:
Concatenated prompt text
"""
texts = []
try:
# Prompt data structure: {node_id: {class_type, inputs: {...}}}
for node_id, node_data in prompt_data.items():
if isinstance(node_data, dict) and 'inputs' in node_data:
inputs = node_data['inputs']
# Look for text inputs
for key, value in inputs.items():
if isinstance(value, str) and key in ['text', 'prompt', 'positive', 'negative']:
if value.strip():
texts.append(value.strip())
return ', '.join(texts)
except Exception as e:
print(f"[PromptSystem] Error extracting text from prompt data: {e}")
return ""
def get_image_creation_time(image_path: str) -> Optional[float]:
"""
Get image file creation time.
Args:
image_path: Path to the image file
Returns:
Timestamp or None
"""
try:
path = Path(image_path)
if path.exists():
return path.stat().st_mtime
return None
except Exception as e:
print(f"[PromptSystem] Error getting creation time: {e}")
return None
def scan_output_directory(output_dir: Path, limit: int = 100) -> list:
"""
Scan output directory for recent images.
Args:
output_dir: Path to output directory
limit: Maximum number of images to return
Returns:
List of tuples (image_path, timestamp) sorted by newest first
"""
images = []
try:
# Supported image formats
extensions = ['.png', '.jpg', '.jpeg', '.webp']
for ext in extensions:
for img_path in output_dir.glob(f'*{ext}'):
timestamp = img_path.stat().st_mtime
images.append((str(img_path), timestamp))
# Sort by timestamp (newest first)
images.sort(key=lambda x: x[1], reverse=True)
return images[:limit]
except Exception as e:
print(f"[PromptSystem] Error scanning output directory: {e}")
return []