File size: 10,434 Bytes
33adbe7
03fc011
b47a274
796cb1f
b47a274
 
796cb1f
 
 
347eac7
 
cc1aefe
 
 
 
35f1465
 
cc1aefe
 
347eac7
b47a274
34a218b
1291091
347eac7
 
796cb1f
34a218b
 
 
 
 
796cb1f
34a218b
796cb1f
 
 
 
 
 
1291091
347eac7
 
796cb1f
347eac7
1291091
347eac7
 
796cb1f
 
 
cc1aefe
 
 
99a9568
1291091
99a9568
41b1d8d
1291091
41b1d8d
 
 
 
 
 
 
99a9568
45b14e8
1291091
99a9568
347eac7
 
b47a274
 
 
fc2a9f2
3eb4ddb
 
b47a274
fc2a9f2
b47a274
fc2a9f2
b47a274
 
 
 
 
 
 
 
 
 
 
99a9568
b47a274
347eac7
1291091
 
 
 
 
 
b47a274
 
0276c07
34a218b
 
03fc011
34a218b
cc1aefe
 
 
 
 
f72182b
7b55e59
cc1aefe
 
 
 
 
 
 
 
 
 
 
 
725fd8a
 
cc1aefe
 
725fd8a
cc1aefe
 
41b1d8d
cc1aefe
725fd8a
cc1aefe
99a9568
cc1aefe
 
 
 
 
 
725fd8a
 
cc1aefe
347eac7
725fd8a
cc1aefe
347eac7
725fd8a
34a218b
cc1aefe
41b1d8d
347eac7
7b55e59
45b14e8
347eac7
 
 
 
 
 
34a218b
 
 
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
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)