Files
2025-04-02 16:21:08 +08:00

113 lines
4.3 KiB
Python

import requests
from PIL import Image
from io import BytesIO
import torch
import numpy as np
from . import TA_SettingsManger
class TAUploadImageNode:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"image": ("IMAGE",),
},
}
RETURN_TYPES = ("STRING",)
CATEGORY = "TensorArt"
FUNCTION = "process"
def process(self, image: torch.Tensor):
settings = TA_SettingsManger.instance.load_settings()
if not settings:
raise Exception("settings cannot be empty")
if settings["baseUrl"] == "":
raise Exception("baseUrl cannot be empty")
if settings["apiKey"] == "":
raise Exception("apiKey cannot be empty")
if not isinstance(image, torch.Tensor):
raise TypeError("image must be a torch.Tensor")
image_np = image.detach().cpu().numpy()
if image_np.ndim == 4:
# 处理批量维度,例如 [B, C, H, W]
print("Detected 4D tensor. Assuming shape [B, C, H, W]. Taking the first image in the batch.")
image_np = image_np[0]
print(f"Image shape after removing batch dimension: {image_np.shape}")
if image_np.ndim == 3:
if image_np.shape[0] in [1, 3, 4]: # [C, H, W]
image_np = np.transpose(image_np, (1, 2, 0)) # 转换为 [H, W, C]
print(f"Transposed image shape to [H, W, C]: {image_np.shape}")
elif image_np.shape[2] in [1, 3, 4]: # [H, W, C]
print(f"Image already in [H, W, C] format: {image_np.shape}")
else:
raise ValueError(f"Unsupported number of channels: {image_np.shape[2]}")
elif image_np.ndim == 2:
image_np = np.expand_dims(image_np, axis=-1) # 转换为 [H, W, 1]
print(f"Expanded grayscale image to [H, W, 1]: {image_np.shape}")
else:
raise ValueError(f"Unsupported image shape: {image_np.shape}")
# 确定图像模式
if image_np.shape[2] == 1:
mode = "L" # 灰度图像
image_pil = Image.fromarray((image_np.squeeze(-1) * 255).astype(np.uint8), mode)
print("Converted to PIL Image with mode 'L'")
elif image_np.shape[2] == 3:
mode = "RGB" # RGB 图像
image_pil = Image.fromarray((image_np * 255).astype(np.uint8), mode)
print("Converted to PIL Image with mode 'RGB'")
elif image_np.shape[2] == 4:
mode = "RGBA" # RGBA 图像
image_pil = Image.fromarray((image_np * 255).astype(np.uint8), mode)
print("Converted to PIL Image with mode 'RGBA'")
else:
raise ValueError(f"Unsupported number of channels: {image_np.shape[2]}")
# 将 PIL 图像保存到 BytesIO 缓冲区
buffer = BytesIO()
image_pil.save(buffer, format='PNG') # 可以根据需要选择 'JPEG' 或其他格式
# 先获取缓冲区大小
buffer_size = buffer.tell()
# 然后重置指针到开头
buffer.seek(0)
print("Saved PIL Image to BytesIO buffer.")
# 打印图像大小,以 MB 为单位
buffer_size_mb = buffer_size / (1024 * 1024)
print(f"Image size: {buffer_size_mb:.2f} MB")
put_info = self.get_put_info(settings)
print(f"Received PUT data {put_info}")
self.upload_image(buffer, put_info)
print("Uploaded image successfully.")
return (put_info["resourceId"], )
def get_put_info(self, settings):
data = {}
response = requests.post(f"{settings["baseUrl"]}/v1/resource/image", json=data, headers={
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': "Bearer " + settings["apiKey"]
})
if response.status_code != 200:
raise Exception(f"Failed to get PUT URL: {response.text}")
return response.json()
def upload_image(self, buffer, put_info):
headers = put_info["headers"]
response = requests.put(put_info["putUrl"], data=buffer, headers=headers)
if response.status_code != 200:
raise Exception(f"Failed to upload image: {response.text}")