|
import gradio as gr |
|
from gradio.themes.utils.colors import Color |
|
import random, time, shared, argparse, modules.path, fooocus_version, modules.html |
|
import modules.async_worker as worker |
|
from math import floor |
|
from PIL import Image, ImageDraw, ImageFont |
|
|
|
from modules.sdxl_styles import style_keys, aspect_ratios |
|
|
|
QM_LOGO = Image.open("resources/qm_logo.png") |
|
QM_COLOR = Color(name="qm", c50="#effaed",c100="#def5db",c200="#64b445",c300="#c6eec0",c400="#b9ebb3",c500="#64b445",c600="#55993b",c700="#467e30",c800="#325a23",c900="#233f18",c950="#192d11") |
|
PROMPT_EXAMPLES = [["Der Weihnachtsmann mit seinem Sack voller Geschenke", "Santa Claus with his sack full of gifts"], |
|
["Malerisches Winterdorf in einer Schneekugel", "Scenic winter village inside a snow globe"], |
|
["Niedliche Pinguine in Schals und Mützen eingewickelt", "Cute penguins wrapped up in scarves and hats"]] |
|
EXAMPLE_GREETINGS = [ |
|
"Ich wünsche dir von Herzen ein frohes Fest.", |
|
"Frohes Fest und viele glückliche Momente mit deinen Liebsten!", |
|
"Zauberhafte Weihnachten für dich!" |
|
] |
|
INIT_IMAGE_PATH = "resources/init.png" |
|
|
|
def generate(*args): |
|
yield gr.HTML(value=modules.html.make_progress_html(1, "0/30")), \ |
|
gr.Image(), \ |
|
gr.Text() |
|
|
|
while worker.is_working: |
|
time.sleep(0.1) |
|
|
|
worker.buffer=[list(args)] |
|
worker.outputs = [] |
|
|
|
finished=False |
|
while not finished: |
|
time.sleep(0.01) |
|
if len(worker.outputs) > 0: |
|
flag, product = worker.outputs.pop(0) |
|
if flag == 'preview': |
|
percentage, title, image = product |
|
yield gr.HTML(value=modules.html.make_progress_html(percentage, title)), \ |
|
gr.Image(value=image) if image is not None else gr.Image(), \ |
|
gr.Text() |
|
if flag == 'results': |
|
image, image_path = product |
|
yield gr.HTML(value=""), \ |
|
gr.Image(value=image), \ |
|
gr.Text(value=image_path) |
|
finished = True |
|
return |
|
|
|
def translate_promt_example(prompt_de): |
|
return [x for x in PROMPT_EXAMPLES if x[0] == prompt_de][0][1] |
|
|
|
def toggle_greet_visibility(is_visible): |
|
return gr.Row(visible=is_visible) |
|
|
|
def __toggle_generate_state(is_preview): |
|
return gr.Image(visible=is_preview), gr.Image(visible=not is_preview), gr.Button(interactive=not is_preview) |
|
|
|
def prepare_generate(): |
|
return __toggle_generate_state(True) |
|
|
|
def finish_generate(): |
|
return __toggle_generate_state(False) |
|
|
|
def debounce(): |
|
time.sleep(0.5) |
|
return |
|
|
|
def overlay_image(image_path, toggle_greet, greet): |
|
image = ImageDraw.Draw(Image.open(image_path), "RGBA") |
|
HEIGHT, TEXT_PADDING, TEXTBOX_HEIGHT = 100, 32, 56 |
|
TEXTBOX_WIDTH = 1280-HEIGHT-4*TEXT_PADDING |
|
|
|
X_RECT=1280-HEIGHT-2*TEXT_PADDING |
|
image.rectangle(((X_RECT, 768-HEIGHT), (1280, 766)), fill=(0, 0, 0, 50)) |
|
image._image.paste(QM_LOGO, (1148,687), QM_LOGO) |
|
if (toggle_greet): |
|
image.rectangle(((0, 768-HEIGHT), (X_RECT-1, 768)), fill=(255, 255, 255, 166)) |
|
txt_image = Image.new('RGBA', (4*1280, 4*TEXTBOX_HEIGHT), (255,255,255,0)) |
|
ImageDraw.Draw(txt_image).text(xy=(0,0), text=greet, font=ImageFont.truetype('resources/Neuton-ExtralightItalic.ttf', floor(1.5*TEXTBOX_HEIGHT)), fill=(0, 0, 0)) |
|
image_box = txt_image.getbbox() |
|
txt_image = txt_image.crop(image_box) |
|
width, height = txt_image.size |
|
if (height > 0 and width/height < TEXTBOX_WIDTH/TEXTBOX_HEIGHT): |
|
txt_image = txt_image.resize((floor((TEXTBOX_HEIGHT/height)*width), TEXTBOX_HEIGHT)) |
|
else: |
|
txt_image = txt_image.resize((TEXTBOX_WIDTH, floor((TEXTBOX_WIDTH/width)*height))) |
|
_, height = txt_image.size |
|
image._image.paste(txt_image, (TEXT_PADDING, 768 - floor((HEIGHT+height)/2)), txt_image) |
|
|
|
return image._image |
|
|
|
def make_overlay(image, toggle_greet, greet): |
|
return gr.Image(value=overlay_image(image, toggle_greet, greet)), gr.Textbox(value=greet) |
|
|
|
def verify_latest_overlay(image, toggle_greet, greet, greet_active): |
|
if greet != greet_active: |
|
return make_overlay(image, toggle_greet, greet) |
|
else: |
|
return gr.Image(), gr.Textbox() |
|
|
|
shared.gradio_root = gr.Blocks(title='QualityMinds AI Christmas Card Maker', css=modules.html.css, theme=gr.themes.Default(primary_hue=QM_COLOR)) |
|
with shared.gradio_root: |
|
gr.Markdown( |
|
""" |
|
# QualityMinds KI Weihnachtskarten-Generator |
|
""") |
|
with gr.Accordion("Info", elem_classes='panel-container', open=False): |
|
with gr.Column(): |
|
gr.Markdown(""" |
|
* Beschreibe das Motiv der Weihnachtskarte in einem Prompt (Englisch), wähle ggf. Stil und los! |
|
* Zur Übersetzung einer Beschreibung ins Englische eignet sich beispielsweise [deepl.com](https://www.deepl.com/translator#de/Schneekugeln) helfen. |
|
* Kurze persönliche Weihnachtsgrüße (bis 2 Zeilen) lassen sich auf der Vorderseite hinzufügen. |
|
Längere Texte können nach Druck handschriftlich zur Rückseite hinzugefügt werden. |
|
* Chat-KIs wie [Bing Chat](https://www.bing.com/search?q=Bing+AI&showconv=1) können bei der Erstellung persönlicher Weihnachtsgrüße helfen, z.B. mit Prompts wie |
|
* Erstelle fünf unterschiedliche persönliche Weihnachtsgrüße für meinen Vater Anakin (je ca. 120 Zeichen). Erwähne dabei unseren gemeinsamen Urlaub auf Tatooine. |
|
* Erstelle drei unterschiedliche persönliche Weihnachtsgrüße für meinen geschätzten Arbeitskollegen Michael (je ca. 150 Zeichen). Gehe dabei Schritt für Schritt vor. |
|
* Erstelle fünf unterschiedliche persönliche Weihnachtsgrüße für eine Weihnachtskarte, auf der eine Schneekugel abgebildet ist (je ca. 133 Zeichen) und erkläre diese. |
|
* Dieses Werkzeug basiert auf [Stable Diffusion XL](https://stability.ai/stable-diffusion) v1.0 und der Oberfläche [Fooocus](https://github.com/lllyasviel/Fooocus), der Code ist OpenSource auf [HuggingFace](https://huggingface.co/spaces/QualityMinds/Weihnachtskarten/tree/main) verfügbar. |
|
""") |
|
|
|
with gr.Row(elem_classes='panel-container'): |
|
with gr.Column(): |
|
with gr.Row(): |
|
with gr.Column(scale=5): |
|
gr.Markdown("##### Prompt (Englisch)", elem_classes="input-label") |
|
prompt = gr.Textbox(value="", placeholder="Was möchtest Du auf der Weihnachtskarte abbilden?", |
|
autofocus=True, container=False, show_label=False, lines=2) |
|
with gr.Column(scale=1, min_width="80px"): |
|
gr.Markdown("##### Stil", elem_classes="input-label") |
|
style_selection = gr.Dropdown(choices=style_keys, value='Kinofilm', container=False, show_label=False, elem_id="style-selection") |
|
with gr.Column(scale=1, min_width="80px"): |
|
progress_html = gr.HTML(visible=True, elem_id='progress-bar', elem_classes='progress-bar') |
|
run_button = gr.Button(value="Weihnachtskarte\nerstellen", variant='primary', elem_id='generate-button', ) |
|
with gr.Row(): |
|
promt_example_de = gr.Textbox(visible=False, container=False, show_label=False) |
|
gr.Examples(elem_id="prompt-examples", examples=PROMPT_EXAMPLES, inputs=[promt_example_de], cache_examples=False) |
|
|
|
toggle_greet = gr.Checkbox(label="Persönliche Weihnachtsgrüße hinzufügen", elem_id="toggle-greet-checkbox", |
|
container=False, value=True, interactive=True) |
|
|
|
greeting_row=gr.Row(elem_classes='panel-container') |
|
with greeting_row: |
|
with gr.Column(): |
|
greet = gr.Textbox(value=EXAMPLE_GREETINGS[0], placeholder="", interactive=True, container=False, lines=2, max_lines=2, show_label=False) |
|
greet_active = gr.Textbox(value=EXAMPLE_GREETINGS[0], visible=False, container=False, show_label=False) |
|
greet_examples = gr.Examples(elem_id="greet-examples", examples=EXAMPLE_GREETINGS, inputs=[greet]) |
|
generated_image = gr.Image(visible=False, type='pil', label="Erstelle Weihnachtskarte...", elem_classes="generated-image", width=1280, |
|
value=INIT_IMAGE_PATH, interactive=False, show_share_button=False, show_download_button=False) |
|
generated_image_overlayed = gr.Image(label="Weihnachtskarte", type='pil', elem_classes="generated-image", width=1280, |
|
value=overlay_image(INIT_IMAGE_PATH, toggle_greet.value, greet.value)) |
|
generated_image_path = gr.Text(visible=False, value=INIT_IMAGE_PATH, container=False, show_label=False) |
|
|
|
promt_example_de.change(fn=translate_promt_example, inputs=[promt_example_de], outputs=[prompt], queue=False) |
|
toggle_greet.change(fn=toggle_greet_visibility, inputs=[toggle_greet], outputs=[greeting_row], queue=False, show_progress=False)\ |
|
.then(fn=make_overlay, inputs=[generated_image_path, toggle_greet, greet], outputs=[generated_image_overlayed, greet_active], show_progress=False, queue=False) |
|
greet.input(fn=None, inputs=[greet], outputs=[greet], _js="(greet) => { return greet.split('\\n').slice(0,2).join('\\n') }") |
|
greet.change(fn=debounce, queue=False, show_progress=False)\ |
|
.then(fn=make_overlay, inputs=[generated_image_path, toggle_greet, greet], outputs=[generated_image_overlayed, greet_active], queue=False, show_progress=False) |
|
greet_active.change(fn=verify_latest_overlay, inputs=[generated_image_path, toggle_greet, greet, greet_active], outputs=[generated_image_overlayed, greet_active], queue=False, show_progress=False) |
|
run_button.click(fn=prepare_generate, outputs=[generated_image, generated_image_overlayed, run_button], queue=False)\ |
|
.then(fn=generate, inputs=[prompt, style_selection], outputs=[progress_html, generated_image, generated_image_path], queue=True)\ |
|
.then(fn=make_overlay, inputs=[generated_image_path, toggle_greet, greet], outputs=[generated_image_overlayed, greet_active], queue=False)\ |
|
.then(fn=finish_generate, outputs=[generated_image, generated_image_overlayed, run_button], queue=False) |
|
|
|
shared.gradio_root.queue(concurrency_count=1, api_open=False) |
|
shared.gradio_root.launch(server_name="0.0.0.0", show_api=False) |
|
|