File size: 11,628 Bytes
1d8fdb7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
"""
Dispatch AI — UAE Heritage Art Generator
Themes: falconry, pearl diving, Bedouin life, modern Dubai, wind towers.
FLUX generates art, branded with Dispatch AI.
"""

import os
import io
import gradio as gr
from huggingface_hub import InferenceClient
from PIL import Image, ImageDraw, ImageFont

# --- Configuration -----------------------------------------------------------
HF_TOKEN = os.environ.get("HF_TOKEN", None)
MODEL_ID = "black-forest-labs/FLUX.1-schnell"

client = InferenceClient(model=MODEL_ID, token=HF_TOKEN)

BG_COLOR = "#0A0F1A"
ACCENT = "#1FE0E6"

# Heritage themes
THEMES = {
    "Falconry": {
        "emoji": "🦅",
        "prompt": (
            "A majestic falcon perched on a gloved Emirati falconer's hand in the desert at golden hour, "
            "piercing eyes, intricate feather detail, warm sunset light, sand dunes, "
            "traditional Emirati heritage, ultra detailed wildlife photography, 4k"
        ),
        "description": "Falconry (Al Qanas) — the UAE's most revered traditional sport, practiced for centuries in the desert.",
    },
    "Pearl Diving": {
        "emoji": "🦪",
        "prompt": (
            "An ancient Emirati pearl diver in traditional dress underwater in the Arabian Gulf, "
            "holding an oyster shell with a glowing pearl, traditional dhow boat above, "
            "bioluminescent water, dreamlike ethereal lighting, orientalist painting, ultra detailed"
        ),
        "description": "Pearl diving (Al Ghaus) — the foundation of UAE's economy before oil, with divers holding their breath for minutes.",
    },
    "Bedouin Life": {
        "emoji": "⛺",
        "prompt": (
            "A traditional Bedouin camp in the Arabian desert at night, woven goat-hair tent, "
            "campfire glowing, camels resting, an elder telling stories, stars overhead, "
            "warm intimate atmosphere, orientalist painting style, ultra detailed"
        ),
        "description": "Bedouin life (Al Badu) — the nomadic desert lifestyle, with hospitality, poetry, and survival in the harsh environment.",
    },
    "Modern Dubai": {
        "emoji": "🏙️",
        "prompt": (
            "A breathtaking view of modern Dubai at sunset, Burj Khalifa towering above skyscrapers, "
            "Sheikh Zayed Road with luxury cars, golden and pink sky, palm trees, "
            "cinematic, ultra detailed cityscape photography, 4k"
        ),
        "description": "Modern Dubai — from fishing village to global metropolis in 50 years, the UAE's vision realized.",
    },
    "Wind Towers": {
        "emoji": "🏛️",
        "prompt": (
            "Traditional Arabian wind tower (barjeel) architecture in old Dubai's Bastakiya district, "
            "intricate coral-stone walls, narrow alleyways, warm golden afternoon sunlight, "
            "historic Emirati architecture, orientalist painting, ultra detailed"
        ),
        "description": "Wind towers (Barjeel) — ancient Emirati air conditioning, capturing breezes to cool homes before electricity.",
    },
    "Camel Caravan": {
        "emoji": "🐪",
        "prompt": (
            "A caravan of camels crossing the vast Empty Quarter desert at dawn, "
            "long shadows on rippled sand dunes, golden light, distant haze, "
            "epic scale, Lawrence of Arabia aesthetic, ultra detailed landscape, 4k"
        ),
        "description": "Camel caravans — the ships of the desert, carrying goods and people across the Arabian Peninsula for millennia.",
    },
    "Dhow Racing": {
        "emoji": "⛵",
        "prompt": (
            "Traditional Emirati dhow boats racing on Dubai Creek, white sails billowing, "
            "dramatic sky, splashing water, action shot, golden hour, "
            "ultra detailed maritime photography, 4k"
        ),
        "description": "Dhow racing — traditional wooden boats that carried the UAE's maritime trade, still raced in fierce competition today.",
    },
    "Date Palm Oasis": {
        "emoji": "🌴",
        "prompt": (
            "A lush date palm oasis in the UAE desert, green palm fronds against golden sand, "
            "traditional falaj water channel, sunlight filtering through palms, peaceful, "
            "ultra detailed landscape painting, orientalist style"
        ),
        "description": "Date palm oases (Al Nakheel) — the 'tree of life' sustaining desert communities, with sophisticated water systems.",
    },
    "Arabian Oryx": {
        "emoji": "🦌",
        "prompt": (
            "A majestic white Arabian oryx standing in the UAE desert at sunrise, "
            "elegant long horns, pristine white coat, golden sand dunes, "
            "wildlife photography, ultra detailed, 4k"
        ),
        "description": "Arabian Oryx — the UAE's national animal, saved from extinction through the late Sheikh Zayed's conservation program.",
    },
}

# Art styles
ART_STYLES = {
    "Photorealistic": "photorealistic, ultra detailed, 4k",
    "Oil Painting": "oil painting style, rich brushstrokes, orientalist art",
    "Watercolor": "delicate watercolor painting, soft washes, artistic",
    "Digital Art": "modern digital art, concept art style, vibrant colors",
    "Vintage Photograph": "vintage sepia photograph, aged, historical feel",
    "Cinematic": "cinematic, dramatic lighting, film still, movie poster style",
}

# Font for watermark
FONT_CANDIDATES = [
    "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
    "/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf",
    "C:\\Windows\\Fonts\\arialbd.ttf",
    "arial.ttf",
]


def load_font(size):
    for path in FONT_CANDIDATES:
        if os.path.exists(path):
            return ImageFont.truetype(path, size)
    return ImageFont.load_default()


def add_watermark(img):
    """Add Dispatch AI watermark to bottom-right corner."""
    draw = ImageDraw.Draw(img)
    W, H = img.size
    font_size = max(16, int(W / 40))
    font = load_font(font_size)

    text = "Dispatch AI"
    # Get text bounding box
    bbox = draw.textbbox((0, 0), text, font=font)
    tw = bbox[2] - bbox[0]
    th = bbox[3] - bbox[1]

    x = W - tw - 20
    y = H - th - 20

    # Background bar
    draw.rectangle([x - 8, y - 4, x + tw + 8, y + th + 4], fill=BG_COLOR)

    # Outline
    for dx in (-1, 1):
        for dy in (-1, 1):
            draw.text((x + dx, y + dy), text, fill="black", font=font)
    # Text
    draw.text((x, y), text, fill=ACCENT, font=font)

    return img


def generate_heritage_art(theme, art_style, custom_prompt, add_brand):
    """Generate UAE heritage art with FLUX.1-schnell."""
    theme_data = THEMES.get(theme, THEMES["Falconry"])
    style_suffix = ART_STYLES.get(art_style, ART_STYLES["Photorealistic"])

    if custom_prompt and custom_prompt.strip():
        final_prompt = f"{custom_prompt.strip()}, {style_suffix}"
    else:
        final_prompt = f"{theme_data['prompt']}, {style_suffix}"

    w, h = 1024, 1024

    try:
        image = client.text_to_image(final_prompt, width=w, height=h)
        if not isinstance(image, Image.Image):
            image = Image.open(io.BytesIO(image)) if hasattr(image, "read") else Image.open(image)

        if add_brand:
            image = add_watermark(image)

        status = f"✅ Generated '{theme}' art in {art_style} style"
        if add_brand:
            status += " · Branded with Dispatch AI"

        info = f"### {theme_data['emoji']} {theme}\n\n{theme_data['description']}\n\n**Art Style:** {art_style}"

        return image, status, info
    except Exception as e:
        img = Image.new("RGB", (w, h), BG_COLOR)
        d = ImageDraw.Draw(img)
        d.text((w // 4, h // 2), f"Error: {str(e)[:50]}", fill=ACCENT)
        return img, f"❌ Error: {str(e)}", ""


# --- UI -----------------------------------------------------------------------
CSS = """
#dispatch-header h1 {
    color: #FFFFFF; font-size: 2.2rem; margin: 0;
    background: linear-gradient(90deg, #1FE0E6 0%, #FFFFFF 60%);
    -webkit-background-clip: text; -webkit-text-fill-color: transparent;
}
#dispatch-header p { color: #1FE0E6; font-size: 1.05rem; margin: 6px 0 0 0; }
.dispatch-footer { text-align: center; color: #8A8F9C; font-size: 0.9rem; padding-top: 8px; }
"""

with gr.Blocks(
    title="Dispatch AI — UAE Heritage Art Generator",
    theme=gr.themes.Base(
        primary_hue="cyan", secondary_hue="cyan", neutral_hue="slate",
        font=[gr.themes.GoogleFont("Inter"), "ui-sans-serif", "system-ui"],
    ).set(
        body_background_fill="#0A0F1A", body_background_fill_dark="#0A0F1A",
        body_text_color="#FFFFFF", body_text_color_dark="#FFFFFF",
        block_background_fill="#0E1424", block_background_fill_dark="#0E1424",
        block_border_color="#1FE0E6", block_border_width="1px",
        block_label_text_color="#1FE0E6", block_title_text_color="#1FE0E6",
        button_primary_background_fill="#1FE0E6", button_primary_background_fill_dark="#1FE0E6",
        button_primary_text_color="#0A0F1A", button_primary_border_color="#1FE0E6",
        input_background_fill="#0E1424", input_background_fill_dark="#0E1424",
        input_border_color="#1FE0E6", input_border_width="1px",
    ),
    css=CSS,
) as demo:
    with gr.Column(elem_id="dispatch-header"):
        gr.Markdown(
            """
            # Dispatch AI — UAE Heritage Art Generator
            Generate art inspired by UAE heritage · Falconry, Pearl Diving, Bedouin Life & more · Dispatch AI (FZE) · UAE
            """
        )

    with gr.Row():
        with gr.Column(scale=1):
            theme_select = gr.Dropdown(
                list(THEMES.keys()),
                label="Heritage Theme",
                value="Falconry",
                info="Choose a UAE heritage theme",
            )
            art_style_select = gr.Dropdown(
                list(ART_STYLES.keys()),
                label="Art Style",
                value="Photorealistic",
            )
            custom_prompt = gr.Textbox(
                label="Custom Prompt (optional — overrides theme prompt)",
                placeholder="Leave empty to use the theme's default prompt",
                lines=2,
            )
            add_brand_check = gr.Checkbox(
                label="Add 'Dispatch AI' watermark",
                value=True,
            )
            generate_btn = gr.Button("🎨 Generate Heritage Art", variant="primary")

        with gr.Column(scale=2):
            output_image = gr.Image(
                label="Generated Heritage Art",
                type="pil",
                show_download_button=True,
            )
            status_box = gr.Textbox(label="Status", interactive=False)
            theme_info = gr.Markdown()

    # Theme info updates
    def get_theme_info(theme):
        td = THEMES.get(theme, {})
        return f"### {td.get('emoji', '🎨')} {theme}\n\n{td.get('description', '')}"

    theme_select.change(fn=get_theme_info, inputs=theme_select, outputs=theme_info)
    # Initialize
    theme_info.value = get_theme_info("Falconry")

    # Events
    generate_btn.click(
        generate_heritage_art,
        inputs=[theme_select, art_style_select, custom_prompt, add_brand_check],
        outputs=[output_image, status_box, theme_info],
    )

    gr.Markdown(
        """
        <div class="dispatch-footer">
        © 2026 Dispatch AI (FZE) · Sharjah, UAE · License 10818 ·
        Model: FLUX.1-schnell · Celebrating UAE heritage through AI art
        </div>
        """
    )

if __name__ == "__main__":
    demo.queue()
    demo.launch()