@DataArgs.register(_DESERIALIZER_TYPE)
class SyntheticImageDataArgs(SyntheticVisionDataArgs):
"""Model for synthetic image dataset deserializer arguments."""
kind: Literal["synthetic_image"] = Field( # type: ignore[assignment]
default="synthetic_image",
description="Type identifier for the synthetic image dataset configuration.",
)
width: int | None = Field(
description="Image width in pixels.",
gt=0,
default=None,
)
height: int | None = Field(
description="Image height in pixels.",
gt=0,
default=None,
)
resolution: str | None = Field(
description="Resolution shortcut such as '720p' or '1080p'.",
default=None,
)
aspect_ratio: str | None = Field(
description="Aspect ratio override, e.g. '16:9' or '4:3'.",
default=None,
)
format: Literal["jpeg", "png"] = Field(
description="Encoded image format.",
default="jpeg",
)
jpeg_quality: int = Field(
description="JPEG quality 1..100. Ignored when format='png'.",
ge=1,
le=100,
default=85,
)
content: Literal["gradient", "noise", "solid", "checkerboard"] = Field(
description="Pixel content to synthesize.",
default="gradient",
)
images_per_request: int = Field(
description="Number of images per emitted row.",
ge=1,
default=1,
)
@model_validator(mode="after")
def _resolve_dimensions(self) -> SyntheticImageDataArgs:
w = self.width
h = self.height
if self.resolution is not None:
preset = RESOLUTION_PRESETS.get(self.resolution.lower())
if preset is None:
raise ValueError(
f"Unknown resolution '{self.resolution}'. Known: "
f"{sorted(RESOLUTION_PRESETS)}"
)
preset_w, preset_h = preset
if h is None:
h = preset_h
if w is None:
w = (
int(round(h * parse_aspect_ratio(self.aspect_ratio)))
if self.aspect_ratio is not None
else preset_w
)
elif self.aspect_ratio is not None:
if h is not None and w is None:
w = int(round(h * parse_aspect_ratio(self.aspect_ratio)))
elif w is not None and h is None:
h = int(round(w / parse_aspect_ratio(self.aspect_ratio)))
if w is None or h is None:
raise ValueError(
"synthetic_image config requires width and height, either "
"explicitly or via resolution/aspect_ratio."
)
self.width = int(w) - (int(w) % 2)
self.height = int(h) - (int(h) % 2)
if self.width <= 0 or self.height <= 0:
raise ValueError(
f"Resolved image dims must be positive, got {self.width}x{self.height}"
)
return self