Spaces:
Running
Running
import os, sys, json, re, time, base64, random, requests, shutil | |
import gradio as gr | |
from datetime import datetime | |
import urllib.parse | |
from groq import Groq | |
from exif import Image | |
from PIL import Image as PILImage, ExifTags as PILExifTags | |
import colorsys | |
# MARK: INIT | |
MAX_SEED = 9999 | |
MAX_IMAGE_SIZE = 2048 | |
GROQ_APIKEY_PROMPTENHANCE = os.environ["GROQ_APIKEY_PROMPTENHANCE"] | |
# delete cache folder if exist and create new | |
CACHE_DIR = os.path.join(os.path.dirname(__file__), "cache") | |
IMAGE_DIR = os.path.join(CACHE_DIR, "images") | |
if os.path.exists(CACHE_DIR): | |
shutil.rmtree(CACHE_DIR) | |
os.makedirs(CACHE_DIR) | |
os.makedirs(IMAGE_DIR) | |
RES = os.path.join(os.path.dirname(__file__), "_res") | |
gr.set_static_paths(paths=["_res/assets/", "_res/assets/emojis/", "_res/assets/favicons/"]) | |
custom_css = RES + "/_custom.css" | |
custom_js = RES + "/_custom.js" | |
custom_head = f""" | |
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/all.min.css"/> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/js/all.min.js"></script> | |
<link rel="apple-touch-icon" sizes="180x180" href="file=_res/assets/favicons/apple-touch-icon.png"> | |
<link rel="icon" type="image/png" sizes="32x32" href="file=_res/assets/favicons/favicon-32x32.png"> | |
<link rel="icon" type="image/png" sizes="16x16" href="file=_res/assets/favicons/favicon-16x16.png"> | |
<link rel="icon" type="image/x-icon" href="file=_res/assets/favicons/favicon.ico"> | |
<link rel="manifest" href="file=_res/assets/favicons/site.webmanifest"> | |
""" | |
# <link rel="stylesheet" href="{catppuccin_css}"> | |
theme = gr.themes.Soft( | |
primary_hue="orange", | |
radius_size="sm", | |
neutral_hue=gr.themes.Color(c100="#a6adc8", c200="#9399b2", c300="#7f849c", c400="#6c7086", c50="#cdd6f4", c500="#585b70", c600="#45475a", c700="#313244", c800="#1e1e2e", c900="#181825", c950="#11111b"), | |
) | |
title = "Bilder Builder" | |
# MARK: READ EXIF | |
def read_exif(image_path): | |
with open(image_path, "rb") as src: | |
img = Image(src) | |
img_comment = json.loads(img.user_comment) | |
# checking if the key exists before removing | |
if "concept" in img_comment: | |
img_comment.pop("concept") | |
return img_comment | |
def read_image_exfi_data(image_path): | |
print("Imagepath:", image_path) | |
img_exif_make, img_exif_comment = read_exif(image_path) | |
return None, image_path, img_exif_comment | |
# MARK: GROQ PROMPT ENHANCE | |
def groq_enhance_process(Prompt=""): | |
client = Groq(api_key=GROQ_APIKEY_PROMPTENHANCE) | |
Prompt = "random prompt" if Prompt == "" else Prompt | |
SYSTEMPROMPT = os.path.join(RES, "groq_systemmessage_prompt_enhance.json") | |
with open(SYSTEMPROMPT, "r") as f: | |
SYSTEMPROMPT = json.load(f) | |
completion = client.chat.completions.create( | |
model="llama-3.1-70b-versatile", | |
messages=[SYSTEMPROMPT, {"role": "user", "content": Prompt}], | |
temperature=0.8, | |
max_tokens=1024, | |
top_p=0.9, | |
stream=False, | |
stop=None, | |
) | |
if completion.choices[0].message.content != "": | |
enhanced_prompt = completion.choices[0].message.content | |
enhanced_prompt = re.sub(r"[\.\"]+", "", enhanced_prompt) | |
return enhanced_prompt | |
def image_get_size(image_path): | |
img = PILImage.open(image_path) | |
print("Image size:", img.size) | |
width, height = img.size | |
return width, height | |
# MARK: DOMINANT COLOR | |
def image_get_dominant_color(image_path): | |
img = PILImage.open(image_path) | |
img = img.convert("RGB") | |
img = img.resize((100, 100), resample=0) | |
pixels = list(img.getdata()) | |
# Erzeuge eine Liste mit den Häufigkeiten der Farben | |
colors = [] | |
for pixel in pixels: | |
r, g, b = pixel | |
h, s, v = colorsys.rgb_to_hsv(r / 255, g / 255, b / 255) | |
if v > 0.5: # Filteriere hellere Farben aus | |
continue | |
if v > 0.99: # Filteriere Weiß aus | |
continue | |
colors.append((h, s, v)) | |
# Ermittle die dominante Farbe | |
dominant_color = max(colors, key=lambda x: x[2]) | |
dominant_color_rgb = colorsys.hsv_to_rgb(dominant_color[0], dominant_color[1], dominant_color[2]) | |
dominant_color_rgb = [int(c * 255) for c in dominant_color_rgb] | |
dominant_color_rgb = f"rgb({dominant_color_rgb[0]}, {dominant_color_rgb[1]}, {dominant_color_rgb[2]})" | |
print(dominant_color_rgb) | |
return dominant_color_rgb | |
# MARK: PROCESS IMAGE | |
def process(Prompt, image_width, image_height, image_seed, randomize_seed): | |
if Prompt == "": | |
gr.Info("Kein Prompt angegeben, es wird ein zufälliger Prompt generiert.", duration=8) | |
Prompt = groq_enhance_process("random prompt") | |
used_seed = random.randint(0, MAX_SEED) if image_seed == 0 or randomize_seed else image_seed | |
used_model = "turbo" if int(image_width) > 1024 or int(image_height) > 1024 else "flux" # turbo, flux | |
timestamp = datetime.now().strftime("%Y-%m-%d-%H-%M-%S") | |
filename_prompt = re.sub(r"[^\w\s-]", "", Prompt).strip().replace(" ", "_") | |
filename = timestamp + "_" + filename_prompt[:100] + ".png" | |
file_path = os.path.join(IMAGE_DIR, filename) | |
encode_prompt = urllib.parse.quote(Prompt) | |
request_url = f"https://image.pollinations.ai/prompt/{encode_prompt}?model={used_model}&width={image_width}&height={image_height}&nologo=true&enhance=false&nofeed=true&seed={used_seed}" | |
print(request_url) | |
response = requests.get(request_url) | |
if response.status_code == 200: | |
with open(file_path, "wb") as f: | |
f.write(response.content) | |
img_exif_comment = read_exif(file_path) | |
img_dominant_color = image_get_dominant_color(file_path) | |
img_width, img_height = image_get_size(file_path) | |
return ({"value": Prompt, "__type__": "update"}, {"value": file_path, "__type__": "update"}, {"value": None, "visible": False, "__type__": "update"}, img_exif_comment, {"visible": True, "__type__": "update"}, {"value": Prompt, "visible": True, "__type__": "update"}, img_width, img_height, used_seed, {"value": file_path, "visible": True, "__type__": "update"}, img_dominant_color, used_seed) | |
# MARK: Gradio BLOCKS UI | |
with gr.Blocks(theme=theme, head=custom_head, css=custom_css, js=custom_js, title=title) as demo: | |
with gr.Row(): | |
gr.Markdown(""" """) | |
with gr.Tab("Image Generator"): | |
with gr.Row(): | |
with gr.Column(scale=2): # min_width=420, | |
with gr.Row(): | |
placeholder_text = "[???] Generiert dir einen zufälligen Prompt.\n[STERN] optimiert deinen eignen Prompt.\n[RUN] generiert dein Bild." | |
text_prompt = gr.Textbox(label="Prompt", show_label=False, lines=12, max_lines=18, placeholder=placeholder_text, elem_id="prompt_input", elem_classes="prompt-input hide-progress", autofocus=True) | |
with gr.Row(): | |
random_prompt_button = gr.Button("", variant="secondary", elem_id="random_prompt_btn", elem_classes="random-prompt-btn", icon="_res/assets/star_light_48.png") | |
enhance_prompt_button = gr.Button("", variant="secondary", elem_id="enhance_prompt_btn", elem_classes="enhance-prompt-btn", icon="_res/assets/star_light_48.png") | |
run_button = gr.Button("Erstellen", variant="primary", elem_id="run_btn", elem_classes="run-btn") | |
with gr.Row(elem_classes="image_size_selctor_wrapper"): | |
with gr.Column(scale=1): | |
with gr.Row(): | |
image_width = gr.Number(label="Breite", minimum=256, maximum=MAX_IMAGE_SIZE, value=1024, step=128, elem_id="image_width_selector", elem_classes="image-width-selector", scale=1) | |
image_height = gr.Number(label="Höhe", minimum=256, maximum=MAX_IMAGE_SIZE, value=683, step=128, elem_id="image_height_selector", elem_classes="image-height-selector", scale=1) | |
with gr.Row(): | |
image_ratio_buttons = gr.Radio(["16:9", "4:3", "3:2", "1:1"], value="3:2", label="Querformat", show_label=True, info="Die gängigsten Seitenverhältnissen.", interactive=True, elem_id="image_ratio_buttons", elem_classes="image-ratio-buttons", container=True, scale=2) | |
switch_width_height = gr.Button("", size="sm", elem_id="switch_width_height", elem_classes="switch-ratio-btn", variant="primary", scale=1) | |
with gr.Column(): | |
image_seed = gr.Slider(label="Seed", info="Jeder Seed generiert ein anderes Bild mit dem selben Prompt", minimum=0, step=1, value=4321, maximum=MAX_SEED, elem_id="image_seed", elem_classes="image-seed hide-progress") | |
randomize_seed = gr.Checkbox(label="Randomize seed", value=False) | |
with gr.Column(scale=4): # min_width=600, | |
with gr.Row(): | |
with gr.Column(scale=1): | |
with gr.Row(): | |
output_image = gr.Image(show_label=False, min_width=320, scale=3, elem_id="output_image", elem_classes="output-image", type="filepath") | |
with gr.Column(scale=1, visible=False, elem_classes="image-info-wrapper") as image_info_wrapper: | |
# with gr.Group(visible=False) as image_info_wrapper: | |
with gr.Group(): | |
image_informations = gr.Markdown("""## Bildinformationen""", visible=True) | |
# textbox_your_prompt = gr.Textbox(label="Dein Prmopt", lines=2, max_lines=4, interactive=False, show_copy_button=True) | |
with gr.Row(elem_classes="img-size-wrapper"): | |
image_info_tb_width = gr.Textbox(label="Breite", lines=1, max_lines=1, interactive=False, show_copy_button=True, elem_classes="image-info-tb-width") | |
image_info_tb_height = gr.Textbox(label="Höhe", lines=1, max_lines=1, interactive=False, show_copy_button=True, elem_classes="image-info-tb-height") | |
with gr.Row(elem_classes="img-seed-wrapper"): | |
image_info_tb_seed = gr.Textbox(label="Seed", lines=1, max_lines=1, interactive=False, show_copy_button=True, elem_classes="image-info-tb-seed") | |
image_info_tb_prompt = gr.Textbox("Bild Prompt", lines=4, max_lines=8, interactive=False, elem_classes="hide-progress", show_copy_button=True, visible=False) | |
# image_info_tb_prompt = gr.Textbox("Bild Prompt", lines=4, max_lines=8, interactive=False, show_copy_button=True, visible=True) | |
image_download_button = gr.DownloadButton("Bild herunterladen", value=None, elem_classes="download-button", variant="primary", visible=False) | |
output_url = gr.Textbox(label="Output URL", show_label=True, interactive=False, visible=False) | |
outpu_image_comment = gr.Json(visible=False) | |
output_dominant_image_color = gr.Textbox(show_label=False, elem_id="dominant_image_color", visible=True, elem_classes="output-dominant-image-color") | |
def switch_image_size_values(image_width, image_height): | |
return image_height, image_width | |
def switch_image_ratio_buttons(ratio_value): | |
ratio_value = ratio_value.split(":") | |
ratio_value_new = f"{int(ratio_value[1])}:{int(ratio_value[0])}" | |
if ratio_value[1] > ratio_value[0]: | |
# Querformat | |
new_choises = ["16:9", "4:3", "3:2", "1:1"] | |
new_label = "Querformat" | |
elif ratio_value[1] < ratio_value[0]: | |
# Hochformat | |
new_choises = ["9:16", "3:4", "2:3", "1:1"] | |
new_label = "Hochformat" | |
return {"choices": new_choises, "value": ratio_value_new, "label": new_label, "__type__": "update"} | |
def calculate_ratio_values(image_ratio_buttons, image_width, image_height): | |
ratio_value = image_ratio_buttons.split(":") | |
if int(ratio_value[0]) > int(ratio_value[1]): | |
a = 1024 | |
b = int(a * int(ratio_value[1]) / int(ratio_value[0])) | |
new_width = a | |
new_height = b | |
elif int(ratio_value[0]) < int(ratio_value[1]): | |
b = 1024 | |
a = int(b * int(ratio_value[0]) / int(ratio_value[1])) | |
new_width = a | |
new_height = b | |
else: | |
new_width = 1024 | |
new_height = 1024 | |
return new_width, new_height | |
switch_width_height.click(fn=switch_image_size_values, inputs=[image_width, image_height], outputs=[image_width, image_height], show_progress="hidden") | |
switch_width_height.click(fn=switch_image_ratio_buttons, inputs=[image_ratio_buttons], outputs=[image_ratio_buttons], show_progress="hidden") | |
image_ratio_buttons.input(fn=calculate_ratio_values, inputs=[image_ratio_buttons, image_width, image_height], outputs=[image_width, image_height], show_progress="hidden") | |
run_button.click(fn=lambda: {"interactive": False, "__type__": "update"}, outputs=[run_button]).then(fn=process, inputs=[text_prompt, image_width, image_height, image_seed, randomize_seed], outputs=[text_prompt, output_image, output_url, outpu_image_comment, image_informations, image_info_tb_prompt, image_info_tb_width, image_info_tb_height, image_info_tb_seed, image_download_button, output_dominant_image_color, image_seed]).then( | |
fn=lambda: {"interactive": True, "__type__": "update"}, outputs=[run_button] | |
) | |
enhance_prompt_button.click(fn=groq_enhance_process, inputs=[text_prompt], outputs=[text_prompt]) | |
random_prompt_button.click(fn=groq_enhance_process, inputs=None, outputs=[text_prompt]) | |
# MARK: Gradio LAUNCH | |
demo.launch() | |