Team Ai
Apppublic

Underground-Digital/Code-Cooker

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
app.py856 linesDownload Raw Back to root
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)