Add Qwen Image Edit Single MXD node
Introduces the QwenImageEditSingleMXD node for single-image editing with prompt and optional image input, supporting reference latents and VAE encoding. Updates node mappings and display names accordingly. Bumps project version to 1.5.1.
This commit is contained in:
@@ -3,6 +3,7 @@ import torch, math, comfy, os, folder_paths, node_helpers, comfy.model_managemen
|
||||
from comfy.comfy_types import IO, ComfyNodeABC, InputTypeDict
|
||||
import numpy as np
|
||||
from PIL import Image, ImageOps, ImageSequence
|
||||
from comfy_api.latest import io
|
||||
|
||||
########################################################################################################################
|
||||
# Flux Empty Latent Image (SD3-compatible)
|
||||
@@ -425,6 +426,65 @@ class PromptWithGuidance(ComfyNodeABC):
|
||||
conditioning = clip.encode_from_tokens_scheduled(tokens)
|
||||
conditioning = node_helpers.conditioning_set_values(conditioning, {"guidance": guidance})
|
||||
return (conditioning,)
|
||||
|
||||
########################################################################################################################
|
||||
# Qwen Image Edit Single MXD
|
||||
class QwenImageEditSingleMXD(io.ComfyNode):
|
||||
@classmethod
|
||||
def define_schema(cls):
|
||||
return io.Schema(
|
||||
node_id="QwenImageEditSingleMXD",
|
||||
display_name="Qwen Image Edit Prompt Single MXD",
|
||||
category="MXD/conditioning",
|
||||
description="Encode a prompt and optional image for Qwen single-image editing.",
|
||||
inputs=[
|
||||
io.Clip.Input("clip"),
|
||||
io.String.Input("prompt", multiline=True, dynamic_prompts=True),
|
||||
io.Vae.Input("vae", optional=True),
|
||||
io.Image.Input("image", optional=True),
|
||||
],
|
||||
outputs=[
|
||||
io.Conditioning.Output(),
|
||||
],
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def execute(cls, clip, prompt, vae=None, image=None) -> io.NodeOutput:
|
||||
ref_latents = []
|
||||
images_vl = []
|
||||
llama_template = "<|im_start|>system\nDescribe the key features of the input image (color, shape, size, texture, objects, background), then explain how the user's text instruction should alter or modify the image. Generate a new image that meets the user's requirements while maintaining consistency with the original input where appropriate.<|im_end|>\n<|im_start|>user\n{}<|im_end|>\n<|im_start|>assistant\n"
|
||||
image_prompt = ""
|
||||
|
||||
if image is not None:
|
||||
samples = image.movedim(-1, 1)
|
||||
total = int(384 * 384)
|
||||
|
||||
scale_by = math.sqrt(total / (samples.shape[3] * samples.shape[2]))
|
||||
width = round(samples.shape[3] * scale_by)
|
||||
height = round(samples.shape[2] * scale_by)
|
||||
|
||||
s = comfy.utils.common_upscale(samples, width, height, "area", "disabled")
|
||||
images_vl.append(s.movedim(1, -1))
|
||||
if vae is not None:
|
||||
total = int(1024 * 1024)
|
||||
scale_by = math.sqrt(total / (samples.shape[3] * samples.shape[2]))
|
||||
width = round(samples.shape[3] * scale_by / 8.0) * 8
|
||||
height = round(samples.shape[2] * scale_by / 8.0) * 8
|
||||
|
||||
s = comfy.utils.common_upscale(samples, width, height, "area", "disabled")
|
||||
ref_latents.append(vae.encode(s.movedim(1, -1)[:, :, :, :3]))
|
||||
|
||||
image_prompt += "Picture 1: <|vision_start|><|image_pad|><|vision_end|>"
|
||||
|
||||
tokens = clip.tokenize(image_prompt + prompt, images=images_vl, llama_template=llama_template)
|
||||
conditioning = clip.encode_from_tokens_scheduled(tokens)
|
||||
if len(ref_latents) > 0:
|
||||
conditioning = node_helpers.conditioning_set_values(
|
||||
conditioning,
|
||||
{"reference_latents": ref_latents},
|
||||
append=True,
|
||||
)
|
||||
return io.NodeOutput(conditioning)
|
||||
|
||||
########################################################################################################################
|
||||
class FluxResolutionMatcher:
|
||||
@@ -1080,6 +1140,7 @@ NODE_CLASS_MAPPINGS = {
|
||||
"Image Scale To Total Pixels (SDXL Safe)": SDXLImageScaleToTotalPixelsSafe,
|
||||
"Flux Image Scale To Total Pixels (Flux Safe)": FluxImageScaleToTotalPixelsSafe,
|
||||
"Prompt With Guidance (Flux)": PromptWithGuidance,
|
||||
"QwenImageEditSingleMXD": QwenImageEditSingleMXD,
|
||||
"FluxResolutionMatcher": FluxResolutionMatcher,
|
||||
"SDXLResolutionMatcher": SDXLResolutionMatcher,
|
||||
"LatentHalfMasks": LatentHalfMasks,
|
||||
@@ -1099,6 +1160,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"Image Scale To Total Pixels (SDXL Safe)": "Scale SDXL Image MXD",
|
||||
"Flux Image Scale To Total Pixels (Flux Safe)": "Scale Flux Image MXD",
|
||||
"Prompt With Guidance (Flux)": "Prompt with Flux Guidance MXD",
|
||||
"QwenImageEditSingleMXD": "Qwen Image Edit Prompt Single MXD",
|
||||
"FluxResolutionMatcher": "Flux Resolution Matcher MXD",
|
||||
"SDXLResolutionMatcher": "SDXL Resolution Matcher MXD",
|
||||
"LatentHalfMasks": "Latent to L/R Masks MXD",
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "maxedout"
|
||||
description = "Custom ComfyUI nodes used in Maxed Out workflows (SDXL, Flux, Wan 2.2, etc.)"
|
||||
version = "1.5.0"
|
||||
version = "1.5.1"
|
||||
license = {file = "LICENSE"}
|
||||
# classifiers = [
|
||||
# # For OS-independent nodes (works on all operating systems)
|
||||
|
||||
Reference in New Issue
Block a user