Spaces:
Running on Zero
Running on Zero
File size: 4,019 Bytes
f0d9a3e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | """Image processing utilities."""
import json
import zipfile
from pathlib import Path
from typing import Optional, List, Dict, Any
from datetime import datetime
from PIL import Image
import logging
from config.settings import OUTPUT_DIR
logger = logging.getLogger(__name__)
def save_image(
image: Image.Image,
prompt: str,
params: Dict[str, Any],
metadata: Optional[Dict[str, Any]] = None
) -> Path:
"""Save an image with metadata.
Args:
image: PIL Image object to save.
prompt: Prompt used to generate the image.
params: Generation parameters.
metadata: Additional metadata to include.
Returns:
Path to the saved image file.
"""
timestamp = datetime.now().timestamp()
filename = f"texture_{int(timestamp)}.png"
filepath = OUTPUT_DIR / filename
# Save image
image.save(filepath, "PNG")
logger.info(f"Saved image to {filepath}")
# Save metadata
metadata_path = filepath.with_suffix(".json")
metadata_dict = {
"timestamp": timestamp,
"prompt": prompt,
"params": params,
"image_path": str(filepath),
"filename": filename,
}
if metadata:
metadata_dict.update(metadata)
with open(metadata_path, "w", encoding="utf-8") as f:
json.dump(metadata_dict, f, indent=2)
return filepath
def create_thumbnail(image: Image.Image, size: tuple[int, int] = (256, 256)) -> Image.Image:
"""Create a thumbnail from an image.
Args:
image: PIL Image object.
size: Thumbnail size (width, height).
Returns:
Thumbnail Image object.
"""
thumb = image.copy()
thumb.thumbnail(size, Image.Resampling.LANCZOS)
return thumb
def validate_image_format(filepath: Path) -> bool:
"""Validate if a file is a valid image format.
Args:
filepath: Path to the image file.
Returns:
True if valid, False otherwise.
"""
valid_formats = {".png", ".jpg", ".jpeg", ".webp"}
return filepath.suffix.lower() in valid_formats
def create_zip(files: List[Path], output_path: Path) -> Path:
"""Create a ZIP archive from multiple files.
Args:
files: List of file paths to include.
output_path: Path for the output ZIP file.
Returns:
Path to the created ZIP file.
"""
with zipfile.ZipFile(output_path, "w", zipfile.ZIP_DEFLATED) as zipf:
for file in files:
if file.exists():
zipf.write(file, file.name)
logger.info(f"Added {file.name} to ZIP")
logger.info(f"Created ZIP archive at {output_path}")
return output_path
def optimize_image_for_web(image: Image.Image, max_size: int = 2048) -> Image.Image:
"""Optimize an image for web display.
Args:
image: PIL Image object.
max_size: Maximum dimension size.
Returns:
Optimized Image object.
"""
width, height = image.size
if width <= max_size and height <= max_size:
return image
# Calculate new dimensions maintaining aspect ratio
if width > height:
new_width = max_size
new_height = int(height * (max_size / width))
else:
new_height = max_size
new_width = int(width * (max_size / height))
return image.resize((new_width, new_height), Image.Resampling.LANCZOS)
def load_metadata(image_path: Path) -> Optional[Dict[str, Any]]:
"""Load metadata for an image.
Args:
image_path: Path to the image file.
Returns:
Metadata dictionary or None if not found.
"""
metadata_path = image_path.with_suffix(".json")
if not metadata_path.exists():
return None
try:
with open(metadata_path, "r", encoding="utf-8") as f:
return json.load(f)
except Exception as e:
logger.error(f"Error loading metadata: {e}")
return None
|