Spaces:
Running
Running
import json | |
import io | |
import random | |
import gradio as gr | |
from PIL import Image | |
from generate import * | |
import numpy as np | |
from typing import Dict, Any | |
from processImage import process_and_encode_image | |
def rgba_to_hex(rgba): | |
r, g, b, _ = [int(float(x)) for x in rgba[5:-1].split(',')] | |
return f"#{r:02X}{g:02X}{b:02X}" | |
def add_color_to_list(current_colors, new_color): | |
new_color_hex = rgba_to_hex(new_color) | |
color_list = current_colors.split(',') | |
if new_color_hex not in color_list and len(color_list) < 10: | |
color_list.append(new_color_hex) | |
return ','.join(filter(None, color_list)) | |
def create_padded_image(image, padding_percent=100): | |
image = image['background'] | |
if image.mode != 'RGBA': | |
image = image.convert('RGBA') | |
width, height = image.size | |
new_width = int(width * (1 + padding_percent/100)) | |
new_height = int(height * (1 + padding_percent/100)) | |
padded = Image.new('RGBA', (new_width, new_height), (0, 0, 0, 0)) | |
x_offset = (new_width - width) // 2 | |
y_offset = (new_height - height) // 2 | |
padded.paste(image, (x_offset, y_offset)) | |
return padded | |
def process_composite_to_mask(original_image, composite_image, transparent=False): | |
original_array = np.array(original_image.convert('RGBA')) | |
if transparent: | |
black_background = Image.new('RGBA', original_image.size, (0, 0, 0, 255)) | |
black_background.paste(original_image, (0, 0), original_image) | |
return black_background | |
if composite_image is None: | |
mask = np.full(original_array.shape[:2], 0, dtype=np.uint8) | |
transparent_areas = original_array[:, :, 3] == 0 | |
mask[transparent_areas] = 255 | |
else: | |
composite_array = np.array(composite_image.convert('RGBA')) | |
difference = np.any(original_array != composite_array, axis=2) | |
mask = np.full(original_array.shape[:2], 255, dtype=np.uint8) | |
mask[difference] = 0 | |
return Image.fromarray(mask, mode='L') | |
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": { | |
"numberOfImages": 1, | |
"height": height, | |
"width": width, | |
"quality": quality, | |
"cfgScale": 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(value=None,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(mask_image, mask_prompt=None, text=None, negative_text=None, height=1024, width=1024, quality="standard", cfg_scale=8.0, seed=0): | |
image = process_and_encode_image(mask_image['background']) | |
if len(image) < 200: | |
return None, gr.update(visible=True, value=image) | |
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.") | |
if mask_image and 'composite' in mask_image: | |
mask = process_composite_to_mask(mask_image['background'], mask_image['composite']) | |
mask_image = process_and_encode_image(mask) | |
in_painting_params = { | |
"image": image, | |
**({"maskImage": mask_image} if mask_image not in [None, ""] else {}), | |
**({"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(mask_image, mask_prompt=None, text=None, negative_text=None, outpainting_mode="DEFAULT", height=1024, width=1024, quality="standard", cfg_scale=8.0, seed=0): | |
image = process_and_encode_image(mask_image['background']) | |
if len(image) < 200: | |
print(image) | |
return None, gr.update(visible=True, value=image) | |
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.") | |
if mask_image and 'composite' in mask_image: | |
mask = process_composite_to_mask(mask_image['background'], None) | |
image = process_composite_to_mask(mask_image['background'], None, True) | |
image.save("image.png") | |
image = process_and_encode_image(image) | |
mask.save("mask.png") | |
mask_image = process_and_encode_image(mask) | |
out_painting_params = { | |
"image": image, | |
"outPaintingMode": outpainting_mode, ## Malformed JSON Error | |
**({"maskImage": mask_image} if mask_image not in [None, ""] else {}), | |
**({"maskPrompt": mask_prompt} if mask_prompt not in [None, ""] else {}), | |
**({"text": text} if text not in [None, ""] else {"text": " "}), | |
**({"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) | |
image_variation_params = { | |
"images": encoded_images, | |
**({"similarityStrength": similarity_strength} if similarity_strength 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("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_and_encode_image(condition_image) | |
if len(condition_image_encoded) < 200: | |
return None, gr.update(visible=True, value=condition_image_encoded) | |
text_to_image_params = { | |
"text": text, | |
"controlMode": control_mode, | |
"controlStrength": control_strength, | |
"conditionImage": condition_image_encoded, | |
**({"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_and_encode_image(reference_image) | |
if len(reference_image_encoded) < 200: | |
return None, gr.update(visible=True, value=reference_image_encoded) | |
if not colors: | |
colors = "#FF5733,#33FF57,#3357FF,#FF33A1,#33FFF5,#FF8C33,#8C33FF,#33FF8C,#FF3333,#33A1FF" | |
color_guided_generation_params = { | |
"text": text, | |
"colors": [color.strip() for color in colors.split(',')], | |
**({"referenceImage": reference_image_encoded} 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_and_encode_image(image) | |
if len(input_image) < 200: | |
return None, gr.update(visible=True, value=input_image) | |
body = json.dumps({ | |
"taskType": "BACKGROUND_REMOVAL", | |
"backgroundRemovalParams": { | |
"image": input_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) | |