Files
2026-03-18 16:54:40 -07:00

165 lines
5.2 KiB
Python

# "Design-focused node suite for ComfyUI."
# Copyright 2026 Augment Studio
# Paid Node, credit values may change.
# Augmentstudio.app
import io
import json
import os
import requests
import time
import folder_paths
import numpy as np
import torch
from PIL import Image
NODE_ID = "logo_upscale"
API_URL = "https://augmentstudio.app/api"
UPLOAD_DIR = folder_paths.get_input_directory()
class AugmentLogoUpscale:
@classmethod
def INPUT_TYPES(cls):
files = sorted([
f for f in os.listdir(UPLOAD_DIR)
if f.lower().endswith((".png", ".jpg", ".jpeg", ".webp"))
])
return {
"required": {
"api_key": ("STRING", {"default": ""}),
"scale": (["2x"], {"default": "2x"}),
},
"optional": {
"image": ("IMAGE",),
"image_file": (files, {"image_upload": True}),
"trigger": ("TRIGGER",),
},
}
RETURN_TYPES = ("IMAGE", "AUGMENT_JSON", "TRIGGER")
RETURN_NAMES = ("image", "json_result", "trigger")
FUNCTION = "execute"
CATEGORY = "Augment/Enhance"
OUTPUT_NODE = True
@classmethod
def IS_CHANGED(cls, **kwargs):
return time.time()
@classmethod
def VALIDATE_INPUTS(cls, **kwargs):
return True
def execute(self, api_key, scale="2x", image=None, image_file=None, trigger=None):
api_url = API_URL.rstrip("/")
auth = {"Authorization": f"Bearer {api_key}"}
scale_factor = int(scale.replace("x", ""))
if image is not None:
img_np = (image[0].cpu().numpy() * 255).astype(np.uint8)
pil_img = Image.fromarray(img_np, "RGB")
buf = io.BytesIO()
pil_img.save(buf, format="PNG")
img_bytes = buf.getvalue()
source_name = "image_input.png"
mime = "image/png"
elif image_file:
path = os.path.join(UPLOAD_DIR, image_file)
with open(path, "rb") as f:
img_bytes = f.read()
source_name = image_file
ext = os.path.splitext(image_file)[1].lower()
mime_types = {".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".webp": "image/webp"}
mime = mime_types.get(ext, "image/png")
else:
raise RuntimeError("No image provided — connect an image input or select a file")
print(f"[Augment API] Submitting image for {scale} upscale: {source_name} ({len(img_bytes)} bytes)")
try:
r = requests.post(
f"{api_url}/process",
files={"image": (source_name, img_bytes, mime)},
data={"node_id": NODE_ID, "scale": scale_factor},
headers=auth,
timeout=30,
)
except requests.exceptions.RequestException as e:
print(f"[Augment API] Submit failed: {e}")
raise
if r.status_code != 200:
raise RuntimeError(f"Submit error {r.status_code}: {r.text[:500]}")
request_id = r.json().get("request_id")
if not request_id:
raise RuntimeError(f"No request_id: {r.text[:500]}")
print(f"[Augment API] Job submitted: {request_id}")
max_wait = 120
elapsed = 0
job_status = "unknown"
while elapsed < max_wait:
time.sleep(1)
elapsed += 1
try:
status_r = requests.get(
f"{api_url}/job/{request_id}/status",
headers=auth, timeout=10,
)
job_status = status_r.json().get("status", "unknown")
except Exception as e:
print(f"[Augment API] Poll error: {e}")
continue
if job_status == "done":
break
elif job_status == "error":
raise RuntimeError(f"Job failed: {status_r.json().get('error')}")
if job_status != "done":
raise RuntimeError(f"Timed out after {max_wait}s")
img_r = requests.get(
f"{api_url}/job/{request_id}/image",
headers=auth, timeout=60,
)
if img_r.status_code != 200:
raise RuntimeError(f"Image fetch error: {img_r.status_code}")
img = Image.open(io.BytesIO(img_r.content)).convert("RGB")
arr = np.array(img).astype(np.float32) / 255.0
image_tensor = torch.from_numpy(arr).unsqueeze(0)
json_result = json.dumps({
"node": "LogoUpscale",
"scale": scale,
"width": img.size[0],
"height": img.size[1],
"source": source_name,
}, indent=2)
temp_dir = folder_paths.get_temp_directory()
os.makedirs(temp_dir, exist_ok=True)
preview_file = f"augment_upscale_{time.time_ns()}.png"
img.save(os.path.join(temp_dir, preview_file))
print(f"[Augment API] Done! {img.size[0]}x{img.size[1]} ({scale} upscale)")
return {
"ui": {"images": [{"filename": preview_file, "subfolder": "", "type": "temp"}]},
"result": (image_tensor, json_result, "done"),
}
NODE_CLASS_MAPPINGS = {
"AugmentLogoUpscale": AugmentLogoUpscale,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"AugmentLogoUpscale": "Logo Upscale",
}