Underground-Digital/Code-Cooker
0
1import gradio as gr2from PIL import Image3import qrcode4from pathlib import Path5import requests6import io7import os8from PIL import Image9import numpy as np10import cv211from pyzxing import BarCodeReader12from PIL import ImageOps, ImageEnhance, ImageFilter13from huggingface_hub import hf_hub_download, snapshot_download14from PIL import ImageEnhance15import replicate16from dotenv import load_dotenv17 18# Load environment variables from .env file19load_dotenv()20 21USERNAME = os.getenv("USERNAME")22PASSWORD = os.getenv("PASSWORD")23REPLICATE_API_TOKEN = os.getenv("REPLICATE_API_TOKEN")24 25# Set the Replicate API token26os.environ["REPLICATE_API_TOKEN"] = REPLICATE_API_TOKEN27 28qrcode_generator = qrcode.QRCode(29 version=1,30 error_correction=qrcode.ERROR_CORRECT_H,31 box_size=10,32 border=4,33)34 35 36# Define available models37CONTROLNET_MODELS = {38 "QR Code Monster": "monster-labs/control_v1p_sd15_qrcode_monster/v2/",39 "QR Code": "DionTimmer/controlnet_qrcode-control_v1p_sd15",40 # Add more ControlNet models here41}42 43DIFFUSION_MODELS = {44 "GhostMix": "digiplay/GhostMixV1.2VAE",45 "Stable v1.5": "Jiali/stable-diffusion-1.5",46 # Add more diffusion models here47}48 49# Global variables to store loaded models50loaded_controlnet = None51loaded_pipe = None52 53# def load_models_on_launch():54# global loaded_controlnet, loaded_pipe55# print("Loading models on launch...")56 57# Download the main repository58# main_repo_path = snapshot_download("monster-labs/control_v1p_sd15_qrcode_monster")59 60# Construct the path to the subfolder61# controlnet_path = os.path.join(main_repo_path, "v2")62 63# loaded_controlnet = ControlNetModel.from_pretrained(64# controlnet_path,65# torch_dtype=torch.float1666# ).to("mps")67 68# diffusion_path = snapshot_download(DIFFUSION_MODELS["GhostMix"])69# loaded_pipe = StableDiffusionControlNetImg2ImgPipeline.from_pretrained(70# diffusion_path,71# controlnet=loaded_controlnet,72# torch_dtype=torch.float16,73# safety_checker=None,74# ).to("mps")75# print("Models loaded successfully!")76 77# Modify the load_models function to use global variables78#def load_models(controlnet_model, diffusion_model):79# global loaded_controlnet, loaded_pipe80# if loaded_controlnet is None or loaded_pipe is None:81# load_models_on_launch()82# return loaded_pipe83 84# Add new functions for image adjustments85def adjust_image(image, brightness, contrast, saturation):86 if image is None:87 return None88 89 img = Image.fromarray(image) if isinstance(image, np.ndarray) else image90 91 if brightness != 1:92 img = ImageEnhance.Brightness(img).enhance(brightness)93 if contrast != 1:94 img = ImageEnhance.Contrast(img).enhance(contrast)95 if saturation != 1:96 img = ImageEnhance.Color(img).enhance(saturation)97 98 return np.array(img)99 100def resize_for_condition_image(input_image: Image.Image, resolution: int):101 input_image = input_image.convert("RGB")102 W, H = input_image.size103 k = float(resolution) / min(H, W)104 H *= k105 W *= k106 H = int(round(H / 64.0)) * 64107 W = int(round(W / 64.0)) * 64108 img = input_image.resize((W, H), resample=Image.LANCZOS)109 return img110 111 112# SAMPLER_MAP = {113# "DPM++ Karras SDE": lambda config: DPMSolverMultistepScheduler.from_config(config, use_karras=True, algorithm_type="sde-dpmsolver++"),114# "DPM++ Karras": lambda config: DPMSolverMultistepScheduler.from_config(config, use_karras=True),115# "Heun": lambda config: HeunDiscreteScheduler.from_config(config),116# "Euler": lambda config: EulerDiscreteScheduler.from_config(config),117# "DDIM": lambda config: DDIMScheduler.from_config(config),118# "DEIS": lambda config: DEISMultistepScheduler.from_config(config),119#}120 121def scan_qr_code(image):122 # Convert gradio image to PIL Image if necessary123 if isinstance(image, np.ndarray):124 image = Image.fromarray(image)125 126 # Convert to grayscale127 gray_image = image.convert('L')128 129 # Convert to numpy array130 np_image = np.array(gray_image)131 132 # Method 1: Using qrcode library133 try:134 qr = qrcode.QRCode()135 qr.add_data('')136 qr.decode(gray_image)137 return qr.data.decode('utf-8')138 except Exception:139 pass140 141 # Method 2: Using OpenCV142 try:143 qr_detector = cv2.QRCodeDetector()144 retval, decoded_info, points, straight_qrcode = qr_detector.detectAndDecodeMulti(np_image)145 if retval:146 return decoded_info[0]147 except Exception:148 pass149 150 # Method 3: Fallback to zxing-cpp151 try:152 reader = BarCodeReader()153 results = reader.decode(np_image)154 if results:155 return results[0].parsed156 except Exception:157 pass158 159 return None160 161def invert_image(image):162 if image is None:163 return None164 if isinstance(image, np.ndarray):165 return 255 - image166 elif isinstance(image, Image.Image):167 return ImageOps.invert(image.convert('RGB'))168 else:169 raise ValueError("Unsupported image type")170 171def invert_displayed_image(image):172 if image is None:173 return None174 inverted = invert_image(image)175 if isinstance(inverted, np.ndarray):176 return Image.fromarray(inverted)177 return inverted178 179 180#@spaces.GPU()181def inference(182 qr_code_content: str,183 prompt: str,184 negative_prompt: str,185 guidance_scale: float = 9.0,186 qr_conditioning_scale: float = 1.47,187 num_inference_steps: int = 20,188 seed: int = -1,189 image_resolution: int = 512,190 scheduler: str = "K_EULER",191 eta: float = 0.0,192 num_outputs: int = 1,193 low_threshold: int = 100,194 high_threshold: int = 200,195 guess_mode: bool = False,196 disable_safety_check: bool = False,197):198 try:199 progress = gr.Progress()200 progress(0, desc="Generating QR code...")201 202 # Generate QR code image203 qr = qrcode.QRCode(204 version=1,205 error_correction=qrcode.constants.ERROR_CORRECT_H,206 box_size=10,207 border=4,208 )209 qr.add_data(qr_code_content)210 qr.make(fit=True)211 qr_image = qr.make_image(fill_color="black", back_color="white")212 213 # Save QR code image to a temporary file214 temp_qr_path = "temp_qr.png"215 qr_image.save(temp_qr_path)216 217 progress(0.3, desc="Running inference...")218 219 # Ensure num_outputs is within the allowed range220 num_outputs = max(1, min(num_outputs, 10))221 222 # Ensure seed is an integer and not null223 seed = int(seed) if seed != -1 else None224 225 # Ensure high_threshold is at least 1226 high_threshold = max(1, int(high_threshold))227 228 # Prepare the input dictionary229 input_dict = {230 "prompt": prompt,231 "qr_image": open(temp_qr_path, "rb"),232 "negative_prompt": negative_prompt,233 "guidance_scale": float(guidance_scale),234 "qr_conditioning_scale": float(qr_conditioning_scale),235 "num_inference_steps": int(num_inference_steps),236 "image_resolution": int(image_resolution),237 "scheduler": scheduler,238 "eta": float(eta),239 "num_outputs": num_outputs,240 "low_threshold": int(low_threshold),241 "high_threshold": high_threshold,242 "guess_mode": guess_mode,243 "disable_safety_check": disable_safety_check,244 }245 246 # Only add seed to input_dict if it's not None247 if seed is not None:248 input_dict["seed"] = seed249 250 # Run inference using Replicate API251 output = replicate.run(252 "anotherjesse/multi-control:76d8414a702e66c84fe2e6e9c8cbdc12e53f950f255aae9ffa5caa7873b12de0",253 input=input_dict254 )255 256 progress(0.9, desc="Processing results...")257 258 # Download the generated image259 response = requests.get(output[0])260 img = Image.open(io.BytesIO(response.content))261 262 # Clean up temporary file263 os.remove(temp_qr_path)264 265 progress(1.0, desc="Done!")266 return img, seed if seed is not None else -1267 except Exception as e:268 print(f"Error in inference: {str(e)}")269 return Image.new('RGB', (512, 512), color='white'), -1270 271 272 273def invert_init_image_display(image):274 if image is None:275 return None276 inverted = invert_image(image)277 if isinstance(inverted, np.ndarray):278 return Image.fromarray(inverted)279 return inverted280 281def adjust_color_balance(image, r, g, b):282 # Convert image to RGB if it's not already283 image = image.convert('RGB')284 285 # Split the image into its RGB channels286 r_channel, g_channel, b_channel = image.split()287 288 # Adjust each channel289 r_channel = r_channel.point(lambda i: i + (i * r))290 g_channel = g_channel.point(lambda i: i + (i * g))291 b_channel = b_channel.point(lambda i: i + (i * b))292 293 # Merge the channels back294 return Image.merge('RGB', (r_channel, g_channel, b_channel))295 296def apply_qr_overlay(image, original_qr, overlay, opacity):297 if not overlay or original_qr is None:298 return image299 300 # Resize original QR to match the generated image301 original_qr = original_qr.resize(image.size)302 303 # Create a new image blending the generated image and the QR code304 return Image.blend(image, original_qr, opacity)305 306def apply_edge_enhancement(image, strength):307 if strength == 0:308 return image309 310 # Apply edge enhancement311 enhanced = image.filter(ImageFilter.EDGE_ENHANCE)312 313 # Blend the original and enhanced images based on strength314 return Image.blend(image, enhanced, strength / 5.0)315 316 317css = """318h1, h2, h3, h4, h5, h6, p, li, ul, ol, a {319 text-align: left;320}321.centered-image {322 display: block;323 margin-left: auto;324 margin-right: auto;325 max-width: 100%;326 height: auto;327}328"""329 330def login(username, password):331 if username == USERNAME and password == PASSWORD:332 return gr.update(visible=True), gr.update(visible=False), gr.update(visible=False), gr.update(value="Login successful! You can now access the QR Code Art Generator tab.", visible=True)333 else:334 return gr.update(visible=False), gr.update(visible=True), gr.update(visible=True), gr.update(value="Invalid username or password. Please try again.", visible=True)335 336# Add login elements to the Gradio interface337with gr.Blocks(theme='Hev832/Applio', css=css, fill_width=True, fill_height=True) as blocks:338 generated_images = gr.State([])339 340 with gr.Tab("Welcome"):341 with gr.Row():342 with gr.Column(scale=2): 343 gr.Markdown(344 """345 <img src="https://cdn-uploads.huggingface.co/production/uploads/64740cf7485a7c8e1bd51ac9/29sj9LyPQItG5uBOO2x3r.webp" alt="UGD Logo" width="250" class="centered-image">346 347 # Underground Digital's QR Code Art Generator348 349 ## Transform Your QR Codes into Brand Masterpieces350 351 This cutting-edge tool empowers our creative team to craft visually stunning,352 on-brand QR codes that perfectly blend functionality with artistic expression.353 ## How It Works:354 355 1. **Enter Your QR Code Content**: Start by inputting the URL or text for your QR code.356 2. **Craft Your Prompt**: Describe the artistic style or theme you envision for your QR code.357 3. **Fine-tune with Advanced Settings**: Adjust parameters to perfect your creation (see tips below).358 4. **Generate and Iterate**: Click 'Run' to create your art, then refine as needed.359 """360 )361 362 with gr.Column(scale=1):363 364 with gr.Row():365 gr.Markdown(366 """367 Login below using the internal<br>368 username and password to access the full app.<br>369 370 Once logged in, a new tab will appear named<br>371 "QR Code Art Generator" allowing you to access.372 """373 )374 375 with gr.Row():376 username = gr.Textbox(label="Username", placeholder="Enter your username", value="ugd")377 with gr.Row():378 password = gr.Textbox(label="Password", type="password", placeholder="Enter your password", value="ugd!")379 with gr.Row():380 login_button = gr.Button("Login", size="sm")381 login_message = gr.Markdown(visible=False)382 383 384 with gr.Tab("QR Code Art Generator", visible=False) as app_container:385 with gr.Row():386 with gr.Column():387 qr_code_content = gr.Textbox(388 label="QR Code Content",389 placeholder="Enter URL or text for your QR code",390 info="This is what your QR code will link to or display when scanned.",391 value="https://www.go-yamamoto.com/",392 lines=1,393 )394 395 prompt = gr.Textbox(396 label="Artistic Prompt",397 placeholder="Describe the style or theme for your QR code art (For best results, keep the prompt to 75 characters or less as seen below)",398 value="A high-res, photo-realistic minimalist rendering of Mount Fuji as a sharp, semi-realistic silhouette on the horizon. The mountain conveys strength and motion with clean, crisp lines and natural flow. Features detailed snow textures, subtle ridge highlights, and a powerful yet serene atmosphere. Emphasizes strength with clarity and precision in texture and light.",399 info="Describe the style or theme for your QR code art (For best results, keep the prompt to 75 characters or less as seen in the example)",400 lines=8,401 )402 negative_prompt = gr.Textbox(403 label="Elements to Avoid",404 placeholder="Describe what you don't want in the image",405 value="ugly, disfigured, low quality, blurry, nsfw, bad_pictures, poorly drawn, distorted, overexposed, flat shading, bad proportions, deformed, pixelated, messy details, lack of contrast, unrealistic textures, bad anatomy, rough edges, low resolution",406 info="List elements or styles you want to avoid in your QR code art.",407 lines=4,408 )409 410 run_btn = gr.Button("๐จ Create Your QR Art", variant="primary") 411 412 with gr.Accordion(label="Needs Some Prompting Help?", open=False, visible=True):413 gr.Markdown(414 """415 ## ๐ Tips for Spectacular Results:416 - Use concise details in your prompt to help the AI understand your vision.417 - Use negative prompts to avoid unwanted elements in your image.418 - Experiment with different ControlNet models and diffusion models to find the best combination for your prompt.419 ## ๐ญ Prompt Ideas to Spark Your Creativity:420 - "A serene Japanese garden with cherry blossoms and a koi pond"421 - "A futuristic cityscape with neon lights and flying cars"422 - "An abstract painting with swirling colors and geometric shapes"423 - "A vintage-style travel poster featuring iconic landmarks"424 Remember, the magic lies in the details of your prompt and the fine-tuning of your settings. 425 Happy creating!426 """427 )428 429 with gr.Accordion("Set Custom QR Code Colors", open=False, visible=False):430 bg_color = gr.ColorPicker(431 label="Background Color", 432 value="#FFFFFF",433 info="Choose the background color for the QR code"434 )435 qr_color = gr.ColorPicker(436 label="QR Code Color", 437 value="#000000",438 info="Choose the color for the QR code pattern"439 )440 invert_final_image = gr.Checkbox(441 label="Invert Final Image", 442 value=False,443 info="Check this to invert the colors of the final image",444 visible=False,445 )446 with gr.Accordion("AI Model Selection", open=False, visible=False):447 controlnet_model_dropdown = gr.Dropdown(448 choices=list(CONTROLNET_MODELS.keys()),449 value="QR Code Monster",450 label="ControlNet Model",451 info="Select the ControlNet model for QR code generation"452 )453 diffusion_model_dropdown = gr.Dropdown(454 choices=list(DIFFUSION_MODELS.keys()),455 value="GhostMix",456 label="Diffusion Model",457 info="Select the main diffusion model for image generation"458 )459 460 461 with gr.Accordion(label="QR Code Image (Optional)", open=False, visible=False):462 qr_code_image = gr.Image(463 label="QR Code Image (Optional). Leave blank to automatically generate QR code",464 type="pil",465 )466 467 with gr.Column():468 gr.Markdown("### Your Generated QR Code Art")469 result_image = gr.Image(470 label="Your Artistic QR Code", 471 show_download_button=True, 472 show_fullscreen_button=True, 473 container=False474 )475 gr.Markdown("๐พ Right-click and save the image to download your QR code art. **Note:** Images are currently not stored when generated, meaning each new generation deletes the previous one. Make sure to save your images as you go.")476 477 scan_button = gr.Button("Verify QR Code Works", visible=False)478 scan_result = gr.Textbox(label="Validation Result of QR Code", interactive=False, visible=False)479 used_seed = gr.Number(label="Seed Used", interactive=False)480 481 with gr.Accordion(label="Use Your Own Image as a Reference", open=True, visible=True) as init_image_acc:482 init_image = gr.Image(label="Reference Image", type="pil")483 with gr.Row():484 use_qr_code_as_init_image = gr.Checkbox(485 label="Uncheck to use your own image for generation", 486 value=True, 487 interactive=True,488 info="Allows you to use your own image for generation, otherwise a generic QR Code is created automatically as the base image"489 )490 reference_image_strength = gr.Slider(491 minimum=0.0,492 maximum=5.0,493 step=0.05,494 value=0.6,495 label="Reference Image Influence",496 info="Controls how much the reference image influences the final result (0 = ignore, 5 = copy exactly)",497 visible=False498 )499 invert_init_image_button = gr.Button("Invert Init Image", size="sm", visible=False)500 501 with gr.Tab("Advanced Settings"):502 with gr.Accordion("Advanced Art Controls", open=True):503 with gr.Row():504 qr_conditioning_scale = gr.Slider(505 minimum=0.0,506 maximum=5.0,507 step=0.01,508 value=1.47,509 label="QR Code Visibility",510 )511 with gr.Accordion("QR Code Visibility Explanation", open=False):512 gr.Markdown(513 """514 **QR Code Visibility** controls how prominent the QR code is in the final image:515 516 - **Low (0.0-1.0)**: QR code blends more with the art, potentially harder to scan.517 - **Medium (1.0-3.0)**: Balanced visibility, usually scannable while maintaining artistic quality.518 - **High (3.0-5.0)**: QR code stands out more, easier to scan but less artistic.519 520 Start with 1.47 for a good balance between art and functionality.521 """522 )523 524 with gr.Row():525 guidance_scale = gr.Slider(526 minimum=0.1,527 maximum=30.0,528 step=0.1,529 value=9.0,530 label="Prompt Adherence",531 )532 with gr.Accordion("Prompt Adherence Explanation", open=False):533 gr.Markdown(534 """535 **Prompt Adherence** determines how closely the AI follows your prompt:536 537 - **Low (0.1-5.0)**: More creative freedom, may deviate from prompt.538 - **Medium (5.0-15.0)**: Balanced between prompt and AI creativity.539 - **High (15.0-30.0)**: Strictly follows the prompt, less creative freedom.540 541 A value of 9.0 provides a good balance between creativity and prompt adherence.542 """543 )544 545 with gr.Row():546 num_inference_steps = gr.Slider(547 minimum=1,548 maximum=100,549 step=1,550 value=20,551 label="Generation Steps",552 )553 with gr.Accordion("Generation Steps Explanation", open=False):554 gr.Markdown(555 """556 **Generation Steps** affects the detail and quality of the generated image:557 558 - **Low (1-10)**: Faster generation, less detailed results.559 - **Medium (11-30)**: Good balance between speed and quality.560 - **High (31-100)**: More detailed results, slower generation.561 562 20 steps is a good starting point for most generations.563 """564 )565 566 with gr.Row():567 image_resolution = gr.Slider(568 minimum=256,569 maximum=1024,570 step=64,571 value=512,572 label="Image Resolution",573 )574 with gr.Accordion("Image Resolution Explanation", open=False):575 gr.Markdown(576 """577 **Image Resolution** determines the size and detail of the generated image:578 579 - **Low (256-384)**: Faster generation, less detailed.580 - **Medium (512-768)**: Good balance of detail and generation time.581 - **High (832-1024)**: More detailed, slower generation.582 583 512x512 is a good default for most use cases.584 """585 )586 587 with gr.Row():588 seed = gr.Slider(589 minimum=-1,590 maximum=9999999999,591 step=1,592 value=-1,593 label="Generation Seed",594 )595 with gr.Accordion("Generation Seed Explanation", open=False):596 gr.Markdown(597 """598 **Generation Seed** controls the randomness of the generation:599 600 - **-1**: Random seed each time, producing different results.601 - **Any positive number**: Consistent results for the same inputs.602 603 Use -1 to explore various designs, or set a specific seed to recreate a particular result.604 """605 )606 607 with gr.Row():608 scheduler = gr.Dropdown(609 choices=["DDIM", "K_EULER", "DPMSolverMultistep", "K_EULER_ANCESTRAL", "PNDM", "KLMS"],610 value="K_EULER",611 label="Sampling Method",612 )613 with gr.Accordion("Sampling Method Explanation", open=False):614 gr.Markdown(615 """616 **Sampling Method** affects the image generation process:617 618 - **K_EULER**: Good balance of speed and quality.619 - **DDIM**: Can produce sharper results but may be slower.620 - **DPMSolverMultistep**: Often produces high-quality results.621 - **K_EULER_ANCESTRAL**: Can introduce more variations.622 - **PNDM**: Another quality-focused option.623 - **KLMS**: Can produce smooth results.624 625 Experiment with different methods to find what works best for your specific prompts.626 """627 )628 629 with gr.Row():630 eta = gr.Slider(631 minimum=0.0,632 maximum=1.0,633 step=0.01,634 value=0.0,635 label="ETA (Noise Level)",636 )637 with gr.Accordion("ETA Explanation", open=False):638 gr.Markdown(639 """640 **ETA (Noise Level)** controls the amount of noise in the generation process:641 642 - **0.0**: No added noise, more deterministic results.643 - **0.1-0.5**: Slight variations in output.644 - **0.6-1.0**: More variations, potentially more creative results.645 646 Start with 0.0 and increase if you want more variation in your outputs.647 """648 )649 650 with gr.Row():651 low_threshold = gr.Slider(652 minimum=1,653 maximum=255,654 step=1,655 value=100,656 label="Edge Detection Low Threshold",657 )658 high_threshold = gr.Slider(659 minimum=1,660 maximum=255,661 step=1,662 value=200,663 label="Edge Detection High Threshold",664 )665 with gr.Accordion("Edge Detection Thresholds Explanation", open=False):666 gr.Markdown(667 """668 **Edge Detection Thresholds** affect how the QR code edges are processed:669 670 - **Low Threshold**: Lower values detect more edges, higher values fewer.671 - **High Threshold**: Determines which edges are strong. Higher values result in fewer strong edges.672 673 Default values (100, 200) work well for most QR codes. Adjust if you need more or less edge definition.674 """675 )676 677 with gr.Row():678 guess_mode = gr.Checkbox(679 label="Guess Mode",680 value=False,681 )682 with gr.Accordion("Guess Mode Explanation", open=False):683 gr.Markdown(684 """685 **Guess Mode**, when enabled, allows the AI to interpret the input image more freely:686 687 - **Unchecked**: AI follows the QR code structure more strictly.688 - **Checked**: AI has more freedom to interpret the input, potentially leading to more creative results.689 690 Use this if you want more artistic interpretations of your QR code.691 """692 )693 694 with gr.Row():695 disable_safety_check = gr.Checkbox(696 label="Disable Safety Check",697 value=False,698 )699 with gr.Accordion("Safety Check Explanation", open=False):700 gr.Markdown(701 """702 **Disable Safety Check** removes content filtering from the generation process:703 704 - **Unchecked**: Normal content filtering applied.705 - **Checked**: No content filtering, may produce unexpected or inappropriate results.706 707 Use with caution and only if necessary for your specific use case.708 """709 )710 with gr.Tab("Image Editing"):711 with gr.Column():712 image_selector = gr.Dropdown(label="Select Image to Edit", choices=[], interactive=True, visible=False)713 image_to_edit = gr.Image(label="Your Artistic QR Code", show_download_button=True, show_fullscreen_button=True, container=True)714 715 with gr.Row():716 qr_overlay = gr.Checkbox(label="Overlay Original QR Code", value=False, visible=False)717 qr_opacity = gr.Slider(minimum=0.1, maximum=1.0, step=0.1, value=0.5, label="QR Overlay Opacity", visible=False)718 edge_enhance = gr.Slider(minimum=0.0, maximum=5.0, step=0.1, value=0.0, label="Edge Enhancement", visible=False)719 720 with gr.Row():721 red_balance = gr.Slider(minimum=-1.0, maximum=1.0, step=0.1, value=0.0, label="Red Balance")722 green_balance = gr.Slider(minimum=-1.0, maximum=1.0, step=0.1, value=0.0, label="Green Balance")723 blue_balance = gr.Slider(minimum=-1.0, maximum=1.0, step=0.1, value=0.0, label="Blue Balance")724 725 726 with gr.Row():727 brightness = gr.Slider(minimum=0.1, maximum=2.0, step=0.1, value=1.0, label="Brightness")728 contrast = gr.Slider(minimum=0.1, maximum=2.0, step=0.1, value=1.0, label="Contrast")729 saturation = gr.Slider(minimum=0.1, maximum=2.0, step=0.1, value=1.0, label="Saturation")730 with gr.Row():731 invert_button = gr.Button("Invert Image", size="sm")732 733 with gr.Row():734 edited_image = gr.Image(label="Edited QR Code", show_download_button=True, show_fullscreen_button=True, visible=False)735 scan_button = gr.Button("Verify QR Code Works", size="sm", visible=False)736 scan_result = gr.Textbox(label="Validation Result of QR Code", interactive=False, visible=False)737 738 used_seed = gr.Number(label="Seed Used", interactive=False)739 740 gr.Markdown(741 """742 ### ๐ Analyzing Your Creation743 - Is the QR code scannable? Check with your phone camera to see if it can scan it.744 - If not scannable, use the Brightness, Contrast, and Saturation sliders to optimize the QR code for scanning.745 - Does the art style match your prompt? If not, try adjusting the 'Prompt Adherence'.746 - Want more artistic flair? Increase the 'Artistic Freedom'.747 - Need a clearer QR code? Raise the 'QR Code Visibility'.748 """749 )750 751 def scan_and_display(image):752 if image is None:753 return "No image to scan"754 755 scanned_text = scan_qr_code(image)756 if scanned_text:757 return f"Scanned successfully: {scanned_text}"758 else:759 return "Failed to scan QR code. Try adjusting the settings for better visibility."760 761 def invert_displayed_image(image):762 if image is None:763 return None764 return invert_image(image)765 766 scan_button.click(767 scan_and_display,768 inputs=[result_image],769 outputs=[scan_result]770 )771 772 invert_button.click(773 invert_displayed_image,774 inputs=[result_image],775 outputs=[result_image]776 )777 778 invert_init_image_button.click(779 invert_init_image_display,780 inputs=[init_image],781 outputs=[init_image]782 )783 784 brightness.change(785 adjust_image,786 inputs=[result_image, brightness, contrast, saturation],787 outputs=[result_image]788 )789 contrast.change(790 adjust_image,791 inputs=[result_image, brightness, contrast, saturation],792 outputs=[result_image]793 )794 saturation.change(795 adjust_image,796 inputs=[result_image, brightness, contrast, saturation],797 outputs=[result_image]798 )799 800 # Add logic to show/hide the reference_image_strength slider801 def update_reference_image_strength_visibility(init_image, use_qr_code_as_init_image):802 return gr.update(visible=init_image is not None and not use_qr_code_as_init_image)803 804 init_image.change(805 update_reference_image_strength_visibility,806 inputs=[init_image, use_qr_code_as_init_image],807 outputs=[reference_image_strength]808 )809 810 use_qr_code_as_init_image.change(811 update_reference_image_strength_visibility,812 inputs=[init_image, use_qr_code_as_init_image],813 outputs=[reference_image_strength]814 )815 816 run_btn.click(817 fn=inference,818 inputs=[819 qr_code_content,820 prompt,821 negative_prompt,822 guidance_scale,823 qr_conditioning_scale,824 num_inference_steps,825 seed,826 image_resolution,827 scheduler,828 eta,829 low_threshold,830 high_threshold,831 guess_mode,832 disable_safety_check,833 ],834 outputs=[result_image, used_seed],835 concurrency_limit=20836 )837 838 # Define login button click behavior839 login_button.click(840 login,841 inputs=[username, password],842 outputs=[app_container, login_message, login_button, login_message]843 )844 845 # Define password textbox submit behavior846 password.submit(847 login,848 inputs=[username, password],849 outputs=[app_container, login_message, login_button, login_message]850 )851 852# Load models on launch853#load_models_on_launch()854 855blocks.queue(max_size=20)856blocks.launch(share=False, show_api=False)