from __future__ import annotations from dataclasses import dataclass from enum import Enum from typing import List, Optional class Implementation(Enum): VECT = "Vectorised" class MatchSpace(Enum): LAB = "Lab (perceptual)" RGB = "RGB (euclidean)" @dataclass class Config: """Runtime configuration for the Lab 5 mosaic generator pipeline.""" # Core grid: int = 32 out_w: int = 768 out_h: int = 768 tile_size: int = 32 # Hugging Face tile source (always used) hf_dataset: str = "Kratos-AI/KAI_car-images" hf_split: str = "train" hf_limit: int = 200 # Increased for better tile diversity hf_cache_dir: Optional[str] = None # Pipeline impl: Implementation = Implementation.VECT match_space: MatchSpace = MatchSpace.LAB # Quantization use_uniform_q: bool = False q_levels: int = 8 use_kmeans_q: bool = False k_colors: int = 8 # Creative tile_norm_brightness: bool = False allow_rotations: bool = False # Caching tiles_cache_dir: Optional[str] = None # Benchmark do_bench: bool = False bench_grids: Optional[List[int]] = None def __post_init__(self) -> None: self._validate() def validate(self) -> None: """Public wrapper that re-validates the current configuration.""" self._validate() def _validate(self) -> None: """Validate numeric parameters so incorrect grids fail fast.""" if self.grid <= 0: raise ValueError("grid must be a positive integer") if self.tile_size <= 0: raise ValueError("tile_size must be a positive integer") if self.out_w <= 0 or self.out_h <= 0: raise ValueError("out_w and out_h must be positive integers") if self.out_w % self.grid != 0 or self.out_h % self.grid != 0: raise ValueError("out_w and out_h must be divisible by grid to maintain whole tiles") if self.hf_limit <= 0: raise ValueError("hf_limit must be positive")