Files

140 lines
5.6 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import json
import base64
from PIL import Image, ImageOps, ImageChops
from io import BytesIO
import requests
import numpy as np
class SceneGenerator:
@staticmethod
def INPUT_TYPES():
return {
"required": {
"json_img": ("STRING", {"multiline": True}),
}
}
RETURN_TYPES = ("STRING", "STRING")
FUNCTION = "process"
def __init__(self):
pass
def process(self, json_img):
try:
if not json_img:
raise ValueError("JSON input must not be empty")
# Parse the JSON string
try:
json_data = json.loads(json_img)
except json.JSONDecodeError as e:
raise ValueError(f"Invalid JSON format: {str(e)}")
if "json_img" not in json_data:
raise ValueError("Invalid JSON input: missing 'json_img' key")
def sort_key(item):
return item['config'].get('z', float('-inf'))
data = json_data["json_img"]["json"]
original_width = json_data["json_img"]["stage"]["width"]
original_height = json_data["json_img"]["stage"]["height"]
scale_factor = 1
main_image = Image.new('RGBA', (original_width, original_height), (255, 255, 255, 255))
product_image = Image.new('RGBA', (original_width, original_height), (255, 255, 255, 0))
product_mask = Image.new('L', (original_width, original_height), 0) # Alpha channel for the product
sorted_data = sorted(data, key=sort_key)
for item in sorted_data:
config = item['config']
if config["width"] == 0 or config["height"] == 0 or config["scale"]["x"] == 0 or config["scale"]["y"] == 0:
continue
# Ölçeklendirme
config["x"] *= scale_factor
config["y"] *= scale_factor
config["width"] *= scale_factor
config["height"] *= scale_factor
# Görüntüyü URL'den indirme ve yükleme
image_url = config["src"]
response = requests.get(image_url)
image = Image.open(BytesIO(response.content))
image = self.apply_flip(image, config["flip"])
if image.mode != 'RGBA':
image = image.convert('RGBA')
# Ayarlama ve döndürme
new_width = int(image.width * config["scale"]["x"])
new_height = int(image.height * config["scale"]["y"])
image_resized = image.resize((new_width, new_height), Image.LANCZOS)
center_x, center_y = new_width / 2, new_height / 2
image_rotated = image_resized.rotate(-config["rotation"], center=(center_x, center_y), expand=True)
# Döndürme sonrası yeni konum hesaplamaları
rotated_width, rotated_height = image_rotated.size
rotated_center_x, rotated_center_y = rotated_width / 2, rotated_height / 2
new_x = config["x"] + center_x - rotated_center_x
new_y = config["y"] + center_y - rotated_center_y
# Koordinatları merkezleme
paste_x = int(config["x"])
paste_y = int(config["y"])
if config["p_type"] == 'product':
product_image.paste(image_rotated, (int(new_x), int(new_y)), image_rotated)
main_image.paste(image_rotated, (int(new_x), int(new_y)), image_rotated)
# Product maskesine ekleme
mask_to_add = Image.new('L', (rotated_width, rotated_height), 255)
product_mask.paste(mask_to_add, (int(new_x), int(new_y)))
else:
main_image.paste(image_rotated, (int(new_x), int(new_y)), image_rotated)
# Prop'un product maskesindeki etkisini kaldırma
mask_to_remove = image_rotated.split()[3] # Alpha channel
mask_to_remove_resized = mask_to_remove.resize((rotated_width, rotated_height), Image.LANCZOS)
mask_to_remove_position = Image.new('L', (original_width, original_height), 0)
mask_to_remove_position.paste(mask_to_remove_resized, (int(new_x), int(new_y)))
product_mask = ImageChops.subtract(product_mask, mask_to_remove_position)
# Apply the final product mask to the product image
product_image = self.apply_transparency_mask(product_image, product_mask)
# Convert images to base64
product_image_base64 = self.image_to_base64(product_image)
main_image_base64 = self.image_to_base64(main_image)
return (product_image_base64, main_image_base64)
except Exception as e:
raise ValueError(f"An error occurred: {str(e)}")
def apply_flip(self, image, flip):
flip_x, flip_y = json.loads(flip)
if flip_x == -1:
image = ImageOps.mirror(image)
if flip_y == -1:
image = ImageOps.flip(image)
return image
def image_to_base64(self, image):
buffered = BytesIO()
image.save(buffered, format="PNG")
img_str = base64.b64encode(buffered.getvalue()).decode("utf-8")
return img_str
def apply_transparency_mask(self, image, mask):
if image.mode != 'RGBA':
image = image.convert('RGBA')
mask = mask.resize(image.size, Image.LANCZOS)
alpha = image.split()[3]
alpha = ImageChops.multiply(alpha, mask)
image.putalpha(alpha)
return image