""" Heritage art style definitions for Indic Heritage Studio v2. Each style now carries: - id, display_name, region, description, prompt_tags, negative_tags (same as v1) - reference_image: IP-Adapter XL conditioning image - palette: hex colors for UI + PDF - lora_scale: per-style LoRA strength (some styles train tighter than others) - controlnet_hints: which ControlNet processors pair well with this style - svd_motion_bucket: how much motion to inject in image→video for this style (Tanjore = very subtle; Warli = can be more dynamic for tarpa dance) """ from __future__ import annotations from dataclasses import dataclass, field from typing import Dict, List, Optional @dataclass(frozen=True) class StyleSpec: id: str display_name: str region: str description: str prompt_tags: List[str] negative_tags: List[str] reference_image: str palette: List[str] # v2 additions lora_scale: float = 0.85 controlnet_hints: List[str] = field(default_factory=lambda: ["canny"]) svd_motion_bucket: int = 127 cultural_keywords: List[str] = field(default_factory=list) HERITAGE_STYLES: Dict[str, StyleSpec] = { "madhubani": StyleSpec( id="madhubani", display_name="Madhubani", region="Mithila, Bihar", description=( "A folk art form from the Mithila region, traditionally painted by women " "on freshly plastered mud walls. Characterized by dense geometric patterns, " "double-lined borders, natural pigments, and motifs from nature and mythology." ), prompt_tags=[ "madhubani painting style", "dense geometric patterns", "double-lined borders", "natural pigment colors", "mythological motifs", "fine linework", "flat perspective", "intricate fish and peacock motifs", ], negative_tags=["3d render", "photorealistic", "modern", "gradient", "blur", "soft shading", "realistic texture"], reference_image="madhubani_ref.png", palette=["#8B0000", "#FFD700", "#000000", "#228B22", "#FF6347"], lora_scale=0.9, # tight style — needs high LoRA strength controlnet_hints=["canny", "depth"], svd_motion_bucket=110, # subtle, ritual-like motion cultural_keywords=["mithila", "bihar folk art", "kohbar", "fish motif", "peacock motif", "sun and moon"], ), "warli": StyleSpec( id="warli", display_name="Warli", region="Maharashtra", description=( "Tribal art from the Warli people of the Western Ghats. White pigment on " "an earthy red or ochre background. Simple circular, triangular, and square " "shapes form figures engaged in dance, hunting, and daily life." ), prompt_tags=[ "warli tribal painting", "white pigment on ochre background", "stick figures", "circular triangular square shapes", "tarpa dance motif", "minimalist", "rural life scenes", "tarpa dance spiral composition", ], negative_tags=["colorful", "photorealistic", "modern", "3d", "realistic", "shading", "gradient"], reference_image="warli_ref.png", palette=["#F5DEB3", "#FFFFFF", "#8B4513", "#A0522D"], lora_scale=0.95, # very distinctive style — push LoRA hard controlnet_hints=["canny", "openpose"], # pose matters for tarpa dance svd_motion_bucket=180, # tarpa dance is dynamic — more motion cultural_keywords=["warli tribe", "maharashtra", "tarpa", "tarpa dance", "chauk", "dev chowk"], ), "pattachitra": StyleSpec( id="pattachitra", display_name="Pattachitra", region="Odisha", description=( "Cloth-based scroll painting from Odisha, depicting mythological narratives " "particularly of Lord Jagannath. Bold borders, floral motifs, and a limited " "but striking palette of red, yellow, and indigo." ), prompt_tags=[ "pattachitra painting", "cloth scroll art", "mythological narrative scene", "floral border motifs", "red yellow indigo palette", "fine brush detail", "traditional odisha style", "jagannath iconography", ], negative_tags=["photorealistic", "modern", "3d render", "gradient", "soft shading"], reference_image="pattachitra_ref.png", palette=["#DC143C", "#FFD700", "#000080", "#FFFFFF", "#000000"], lora_scale=0.88, controlnet_hints=["canny", "depth"], svd_motion_bucket=100, # scroll painting — very subtle motion cultural_keywords=["odisha", "jagannath", "puri", "raghurajpur", "palm leaf engraving"], ), "mughal": StyleSpec( id="mughal", display_name="Mughal Miniature", region="North India (Mughal Court)", description=( "Court painting style developed under Mughal patronage. Highly detailed " "figurative scenes with Persian and Indian influences. Gold leaf accents, " "elevated viewpoint, and intricate borders." ), prompt_tags=[ "mughal miniature painting", "court scene composition", "elevated viewpoint", "fine detail brushwork", "gold leaf accents", "persian-indian fusion", "intricate border decoration", "hamzanama style illustration", ], negative_tags=["photorealistic", "3d", "modern", "blur", "low detail", "impressionist"], reference_image="mughal_ref.png", palette=["#DAA520", "#8B0000", "#006400", "#4B0082", "#F5F5DC"], lora_scale=0.82, # finer detail — slightly lower LoRA keeps faces crisp controlnet_hints=["canny", "openpose", "depth"], svd_motion_bucket=90, # court scenes — minimal motion, dignified cultural_keywords=["mughal", "akbar", "jahangir", "hamzanama", "persian miniature", "mughal court"], ), "tanjore": StyleSpec( id="tanjore", display_name="Tanjore Painting", region="Tamil Nadu", description=( "Classical South Indian painting known for its rich colors, gold leaf " "overlay, and devotional iconography. Compositions are frontal and " "symmetrical, with deities as the central subject." ), prompt_tags=[ "tanjore painting style", "gold leaf overlay", "devotional deity portrait", "frontal symmetrical composition", "rich jewel tones", "semi-precious stone work", "south indian classical art", "arched prabhavali surrounding deity", ], negative_tags=["photorealistic", "3d", "modern", "blur", "minimalist", "asymmetric", "casual pose"], reference_image="tanjore_ref.png", palette=["#FFD700", "#8B0000", "#006400", "#800080", "#FFFFFF"], lora_scale=0.9, controlnet_hints=["canny", "openpose"], # symmetry matters — openpose for deity poses svd_motion_bucket=80, # devotional icon — barely any motion cultural_keywords=["tamil nadu", "thanjavur", "krishna", "lord vishnu", "prabhavali", "gilded"], ), } def get_style(style_id: str) -> StyleSpec: if style_id not in HERITAGE_STYLES: raise KeyError( f"Unknown style: {style_id!r}. Valid: {list(HERITAGE_STYLES.keys())}" ) return HERITAGE_STYLES[style_id] def list_styles() -> List[StyleSpec]: return list(HERITAGE_STYLES.values())