File size: 4,098 Bytes
338d95d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""
File handling utilities for CompI project.
"""

import json
import yaml
from pathlib import Path
from typing import Dict, Any, Union
from PIL import Image
import soundfile as sf
import numpy as np

from src.config import OUTPUTS_DIR

def save_image(image: Image.Image, filename: str, subfolder: str = "images") -> Path:
    """
    Save a PIL Image to the outputs directory.
    
    Args:
        image: PIL Image to save
        filename: Name of the file (with extension)
        subfolder: Subfolder within outputs directory
        
    Returns:
        Path to saved file
    """
    output_dir = OUTPUTS_DIR / subfolder
    output_dir.mkdir(parents=True, exist_ok=True)
    
    file_path = output_dir / filename
    image.save(file_path)
    
    return file_path

def save_audio(audio_data: np.ndarray, filename: str, 
               sample_rate: int = 22050, subfolder: str = "audio") -> Path:
    """
    Save audio data to the outputs directory.
    
    Args:
        audio_data: Audio data as numpy array
        filename: Name of the file (with extension)
        sample_rate: Audio sample rate
        subfolder: Subfolder within outputs directory
        
    Returns:
        Path to saved file
    """
    output_dir = OUTPUTS_DIR / subfolder
    output_dir.mkdir(parents=True, exist_ok=True)
    
    file_path = output_dir / filename
    sf.write(file_path, audio_data, sample_rate)
    
    return file_path

def load_config(config_path: Union[str, Path]) -> Dict[str, Any]:
    """
    Load configuration from JSON or YAML file.
    
    Args:
        config_path: Path to configuration file
        
    Returns:
        Configuration dictionary
    """
    config_path = Path(config_path)
    
    if not config_path.exists():
        raise FileNotFoundError(f"Configuration file not found: {config_path}")
    
    with open(config_path, 'r') as f:
        if config_path.suffix.lower() in ['.yml', '.yaml']:
            return yaml.safe_load(f)
        elif config_path.suffix.lower() == '.json':
            return json.load(f)
        else:
            raise ValueError(f"Unsupported config file format: {config_path.suffix}")

def ensure_dir(path: Union[str, Path]) -> Path:
    """
    Ensure directory exists, create if it doesn't.

    Args:
        path: Directory path

    Returns:
        Path object
    """
    path = Path(path)
    path.mkdir(parents=True, exist_ok=True)
    return path

def ensure_directory_exists(path: Union[str, Path]) -> Path:
    """
    Alias for ensure_dir for backward compatibility.

    Args:
        path: Directory path

    Returns:
        Path object
    """
    return ensure_dir(path)

def generate_filename(prompt: str, style: str = "", mood: str = "",
                     seed: int = 0, variation: int = 1,
                     has_audio: bool = False, max_length: int = 100) -> str:
    """
    Generate a descriptive filename for generated images.

    Args:
        prompt: Text prompt used for generation
        style: Art style
        mood: Mood/atmosphere
        seed: Random seed used
        variation: Variation number
        has_audio: Whether audio was used in generation
        max_length: Maximum filename length

    Returns:
        Generated filename (without extension)
    """
    import re
    from datetime import datetime

    # Clean and truncate prompt
    prompt_clean = re.sub(r'[^\w\s-]', '', prompt.lower())
    prompt_slug = "_".join(prompt_clean.split()[:6])[:30]

    # Clean style and mood
    style_slug = re.sub(r'[^\w]', '', style.lower())[:10] if style else ""
    mood_slug = re.sub(r'[^\w]', '', mood.lower())[:10] if mood else ""

    # Timestamp
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")

    # Audio indicator
    audio_tag = "_audio" if has_audio else ""

    # Combine all parts
    parts = [prompt_slug, style_slug, mood_slug, timestamp, f"seed{seed}", f"v{variation}"]
    filename = "_".join(filter(None, parts)) + audio_tag

    # Truncate if too long
    if len(filename) > max_length:
        filename = filename[:max_length]

    return filename