import json import io import random import gradio as gr from PIL import Image from generate import * from typing import Dict, Any from processImage import process_and_encode_image def display_image(image_bytes): if isinstance(image_bytes, str): # If we received a string (error message), return it to be displayed return None, gr.update(visible=True, value=image_bytes) elif image_bytes: # If we received image bytes, process and display the image return Image.open(io.BytesIO(image_bytes)), gr.update(visible=False) else: # Handle None case return None, gr.update(visible=False) def process_optional_params(**kwargs) -> Dict[str, Any]: return {k: v for k, v in kwargs.items() if v is not None} def process_images(primary=None, secondary=None, validate=True) -> Dict[str, str]: if validate and primary is None: raise ValueError("Primary image is required.") result = {} if primary: result["image"] = process_and_encode_image(primary) if secondary: result["maskImage"] = process_and_encode_image(secondary) return result def create_image_generation_config(height=1024, width=1024, quality="standard", cfg_scale=8.0, seed=0): return { "numberOfImages": 1, "height": height, "width": width, "quality": quality, "cfgScale": cfg_scale, "seed": seed } def build_request(task_type, params, height=1024, width=1024, quality="standard", cfg_scale=8.0, seed=0): param_dict = {"TEXT_IMAGE": "textToImageParams", "INPAINTING": "inPaintingParams", "OUTPAINTING":"outPaintingParams","IMAGE_VARIATION":"imageVariationParams", "COLOR_GUIDED_GENERATION":"colorGuidedGenerationParams","BACKGROUND_REMOVAL":"backgroundRemovalParams"} return json.dumps({ "taskType": task_type, param_dict[task_type]: params, "imageGenerationConfig": create_image_generation_config( height=height, width=width, quality=quality, cfg_scale=cfg_scale, seed=seed ) }) def check_return(result): if not isinstance(result, bytes): return None, gr.update(visible=True, value=result) return Image.open(io.BytesIO(result)), gr.update(visible=False) def text_to_image(prompt, negative_text=None, height=1024, width=1024, quality="standard", cfg_scale=8.0, seed=0): text_to_image_params = {"text": prompt, **({"negativeText": negative_text} if negative_text not in [None, ""] else {}) } body = build_request("TEXT_IMAGE", text_to_image_params, height, width, quality, cfg_scale, seed) result = generate_image(body) return check_return(result) def inpainting(image, mask_prompt=None, mask_image=None, text=None, negative_text=None, height=1024, width=1024, quality="standard", cfg_scale=8.0, seed=0): images = process_images(primary=image, secondary=None) for value in images.values(): if len(value) < 200: return None, gr.update(visible=True, value=value) # Prepare the inPaintingParams dictionary if mask_prompt and mask_image: raise ValueError("You must specify either maskPrompt or maskImage, but not both.") if not mask_prompt and not mask_image: raise ValueError("You must specify either maskPrompt or maskImage.") # Prepare the inPaintingParams dictionary with the appropriate mask parameter in_painting_params = { **images, # Unpacks image and maskImage if present **({"maskPrompt": mask_prompt} if mask_prompt not in [None, ""] else {}), **({"text": text} if text not in [None, ""] else {}), **({"negativeText": negative_text} if negative_text not in [None, ""] else {}) } body = build_request("INPAINTING", in_painting_params, height, width, quality, cfg_scale, seed) result = generate_image(body) return check_return(result) def outpainting(image, mask_prompt=None, mask_image=None, text=None, negative_text=None, outpainting_mode="DEFAULT", height=1024, width=1024, quality="standard", cfg_scale=8.0, seed=0): images = process_images(primary=image, secondary=None) for value in images.values(): if len(value) < 200: return None, gr.update(visible=True, value=value) if mask_prompt and mask_image: raise ValueError("You must specify either maskPrompt or maskImage, but not both.") if not mask_prompt and not mask_image: raise ValueError("You must specify either maskPrompt or maskImage.") # Prepare the outPaintingParams dictionary out_painting_params = { **images, # Unpacks image and maskImage if present **process_optional_params( **({"maskPrompt": mask_prompt} if mask_prompt not in [None, ""] else {}), **({"text": text} if text not in [None, ""] else {}), **({"negativeText": negative_text} if negative_text not in [None, ""] else {}) ) } body = build_request("OUTPAINTING", out_painting_params, height, width, quality, cfg_scale, seed) result = generate_image(body) return check_return(result) def image_variation(images, text=None, negative_text=None, similarity_strength=0.5, height=1024, width=1024, quality="standard", cfg_scale=8.0, seed=0): encoded_images = [] for image_path in images: with open(image_path, "rb") as image_file: value = process_and_encode_image(image_file) if len(value) < 200: return None, gr.update(visible=True, value=value) encoded_images.append(value) # Prepare the imageVariationParams dictionary image_variation_params = { "images": encoded_images, **({"text": text} if text not in [None, ""] else {}), **({"negativeText": negative_text} if negative_text not in [None, ""] else {}) } body = build_request("IMAGE_VARIATION", image_variation_params, height, width, quality, cfg_scale, seed) result = generate_image(body) return check_return(result) def image_conditioning(condition_image, text, negative_text=None, control_mode="CANNY_EDGE", control_strength=0.7, height=1024, width=1024, quality="standard", cfg_scale=8.0, seed=0): condition_image_encoded = process_images(primary=condition_image) for value in condition_image_encoded.values(): if len(value) < 200: return None, gr.update(visible=True, value=value) # Prepare the textToImageParams dictionary text_to_image_params = { "text": text, "controlMode": control_mode, "controlStrength": control_strength, "conditionImage": condition_image_encoded.get('image'), **({"negativeText": negative_text} if negative_text not in [None, ""] else {}) } body = build_request("TEXT_IMAGE", text_to_image_params, height, width, quality, cfg_scale, seed) result = generate_image(body) return check_return(result) def color_guided_content(text=None, reference_image=None, negative_text=None, colors=None, height=1024, width=1024, quality="standard", cfg_scale=8.0, seed=0): reference_image_str = None if reference_image is not None and not isinstance(reference_image, type(None)): reference_image_encoded = process_images(primary=reference_image) for value in reference_image_encoded.values(): if len(value) < 200: return None, gr.update(visible=True, value=value) reference_image_str = reference_image_encoded.get('image') if not colors: colors = "#FF5733,#33FF57,#3357FF,#FF33A1,#33FFF5,#FF8C33,#8C33FF,#33FF8C,#FF3333,#33A1FF" color_guided_generation_params = { "text": text, "colors": colors.split(','), **({"referenceImage": reference_image_str} if reference_image_str is not None else {}), **({"negativeText": negative_text} if negative_text not in [None, ""] else {}) } body = build_request("COLOR_GUIDED_GENERATION", color_guided_generation_params, height, width, quality, cfg_scale, seed) result = generate_image(body) return check_return(result) def background_removal(image): input_image = process_images(primary=image) for value in input_image.values(): if len(value) < 200: return None, gr.update(visible=True, value=value) body = json.dumps({ "taskType": "BACKGROUND_REMOVAL", "backgroundRemovalParams": { "image": input_image.get('image') } }) result = generate_image(body) return check_return(result) def generate_nova_prompt(): with open('seeds.json', 'r') as file: data = json.load(file) if 'seeds' not in data or not isinstance(data['seeds'], list): raise ValueError("The JSON file must contain a 'seeds' key with a list of strings.") random_string = random.choice(data['seeds']) prompt = f""" Generate a creative image prompt that builds upon this concept: "{random_string}" Requirements: - Create a new, expanded prompt without mentioning or repeating the original concept - Focus on vivid visual details and artistic elements - Keep the prompt under 1000 characters - Do not include any meta-instructions or seed references - Return only the new prompt text Response Format: [Just the new prompt text, nothing else] """ messages = [ {"role": "user", "content": [{"text": prompt}]} ] return generate_prompt(messages)