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