Removed all V1 nodes, added missing docs, fixed imports
This commit is contained in:
+8
-26
@@ -1,31 +1,13 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
# import glob
|
||||
# import re
|
||||
|
||||
from .node_mappings import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS, NODES_COUNT, RESET, BRIGHT_GREEN, BRIGHT_CYAN, CYAN, YELLOW
|
||||
|
||||
|
||||
# def count_tt_classes():
|
||||
# total = 0
|
||||
# for path in sorted(glob.glob("nodes_*.py")):
|
||||
# count = sum(1 for line in open(path) if re.match(r"^class TT_", line))
|
||||
# total += count
|
||||
#
|
||||
# return total
|
||||
# (c) TenserTensor <tenser.tensor@proton.me> || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from .comfy_extension import TenserTensorExtension
|
||||
|
||||
WEB_DIRECTORY = "./web"
|
||||
|
||||
__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS', 'WEB_DIRECTORY']
|
||||
|
||||
print()
|
||||
SEP = f"{CYAN}{'=' * 60}{RESET}"
|
||||
print(SEP)
|
||||
print(f"{YELLOW}TenserTensor ComfyUI Nodes Pack (v1.7.8): {BRIGHT_GREEN}{NODES_COUNT} Nodes Loaded{RESET}")
|
||||
print(SEP)
|
||||
print(f"{BRIGHT_CYAN}[V] Repository: https://github.com/tenser-tensor/ComfyUI-TenserTensor{RESET}")
|
||||
print(f"{BRIGHT_CYAN}[V] ComfyUI Registry: https://registry.comfy.org/publishers/tenser-tensor{RESET}")
|
||||
print(f"{BRIGHT_CYAN}[V] Please check README file: https://github.com/tenser-tensor/ComfyUI-TenserTensor/blob/main/README.md{RESET}")
|
||||
print(SEP)
|
||||
print()
|
||||
# ==============================================================================
|
||||
# V3 entrypoint — registers context nodes with ComfyUI
|
||||
# ==============================================================================
|
||||
|
||||
async def comfy_entrypoint() -> TenserTensorExtension:
|
||||
return TenserTensorExtension()
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
# (c) TenserTensor <tenser.tensor@proton.me> || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from typing import override
|
||||
|
||||
from comfy_api.latest import ComfyExtension, io
|
||||
|
||||
from .nodes_context import NODES as NODES_CONTEXT
|
||||
from .nodes_controlnet import NODES as NODES_CONTROLNET
|
||||
from .nodes_detector import NODES as NODES_DETECTOR
|
||||
from .nodes_image import NODES as NODES_IMAGE
|
||||
from .nodes_latent import NODES as NODES_LATENT
|
||||
from .nodes_loaders import NODES as NODES_LOADERS
|
||||
from .nodes_postproduction import NODES as NODES_POSTPRODUCTION
|
||||
from .nodes_sampling import NODES as NODES_SAMPLING
|
||||
from .nodes_text_encoder import NODES as NODES_TEXT_ENCODER
|
||||
from .nodes_workflow import NODES as NODES_WORKFLOW
|
||||
|
||||
|
||||
class TenserTensorExtension(ComfyExtension):
|
||||
@override
|
||||
async def get_node_list(self) -> list[type[io.ComfyNode]]:
|
||||
return [
|
||||
*NODES_CONTEXT,
|
||||
*NODES_CONTROLNET,
|
||||
*NODES_DETECTOR,
|
||||
*NODES_IMAGE,
|
||||
*NODES_LATENT,
|
||||
*NODES_LOADERS,
|
||||
*NODES_POSTPRODUCTION,
|
||||
*NODES_SAMPLING,
|
||||
*NODES_TEXT_ENCODER,
|
||||
*NODES_WORKFLOW,
|
||||
]
|
||||
@@ -1,389 +0,0 @@
|
||||
# (c) TenserTensor <tenser.tensor@proton.me> || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
RESET = "\033[0m"
|
||||
BOLD = "\033[1m"
|
||||
RED = "\033[31m"
|
||||
GREEN = "\033[32m"
|
||||
YELLOW = "\033[33m"
|
||||
BLUE = "\033[34m"
|
||||
CYAN = "\033[36m"
|
||||
WHITE = "\033[37m"
|
||||
BRIGHT_GREEN = "\033[92m"
|
||||
BRIGHT_CYAN = "\033[96m"
|
||||
|
||||
import inspect
|
||||
import sys
|
||||
|
||||
try:
|
||||
from .nodes_context import *
|
||||
from .nodes.context.base_context import TT_BaseContext
|
||||
from .nodes.context.context import TT_Context
|
||||
from .nodes.context.context_passthrough import TT_ContextPassthrough
|
||||
from .nodes.context.context_set_guider import TT_ContextSetGuider
|
||||
from .nodes.context.context_set_image import TT_ContextSetImage
|
||||
from .nodes.context.context_set_latent import TT_ContextSetLatent
|
||||
from .nodes.context.even_larger_context import TT_EvenLargerContext
|
||||
from .nodes.context.large_context_flux import TT_LargeContextFlux
|
||||
from .nodes.context.large_context_sdxl import TT_LargeContextSdxl
|
||||
except ImportError:
|
||||
print(f"{YELLOW}TenserTensor: {RED}ERROR: Context nodes unavailable{RESET}")
|
||||
|
||||
try:
|
||||
from .nodes_detector import *
|
||||
except ImportError:
|
||||
print(f"{YELLOW}TenserTensor: {RED}ERROR: Detector nodes unavailable{RESET}")
|
||||
|
||||
try:
|
||||
from .nodes.image.image_preview_save import TT_ImagePreviewSave
|
||||
from .nodes.image.image_preview_upscale_save import TT_ImagePreviewUpscaleSave
|
||||
from .nodes.image.guider_image_reference import TT_GuiderImageReference
|
||||
from .nodes_image import *
|
||||
except ImportError:
|
||||
print(f"{YELLOW}TenserTensor: {RED}ERROR: Image nodes unavailable{RESET}")
|
||||
|
||||
try:
|
||||
from .nodes_controlnet import *
|
||||
except ImportError:
|
||||
print(f"{YELLOW}TenserTensor: {RED}ERROR: ControlNet nodes unavailable{RESET}")
|
||||
|
||||
try:
|
||||
from .nodes.latent.latent_factory import TT_LatentFactory
|
||||
from .nodes_latent import *
|
||||
except ImportError:
|
||||
print(f"{YELLOW}TenserTensor: {RED}ERROR: Latent nodes unavailable{RESET}")
|
||||
|
||||
try:
|
||||
from .nodes.loaders.flux_models_loader import TT_FluxModelsLoader
|
||||
from .nodes.loaders.flux_models_loader_advanced import TT_FluxModelsLoaderAdvanced
|
||||
from .nodes.loaders.gguf_models_loader import TT_Flux2GgufModelsLoader
|
||||
from .nodes.loaders.gguf_models_loader_advanced import TT_Flux2GgufModelsLoaderAdvanced
|
||||
from .nodes.loaders.sdxl_models_loader import TT_SdxlModelsLoader
|
||||
from .nodes.loaders.sdxl_models_loader_advanced import TT_SdxlModelsLoaderAdvanced
|
||||
from .nodes_loaders import *
|
||||
except ImportError:
|
||||
print(f"{YELLOW}TenserTensor: {RED}ERROR: Loader nodes unavailable{RESET}")
|
||||
|
||||
try:
|
||||
from .nodes.postproduction.add_film_grain import TT_AddFilmGrain
|
||||
from .nodes.postproduction.apply_lut import TT_ApplyLut
|
||||
from .nodes.postproduction.image_enhancer import TT_ImageEnhancer
|
||||
from .nodes.postproduction.postproduction import TT_Postproduction
|
||||
from .nodes.postproduction.postproduction_advanced import TT_PostproductionAdvanced
|
||||
from .nodes.postproduction.quick_image_upscaler import TT_QuickImageUpscaler
|
||||
from .nodes_postproduction import *
|
||||
except ImportError:
|
||||
print(f"{YELLOW}TenserTensor: {RED}ERROR: Postproduction nodes unavailable{RESET}")
|
||||
|
||||
try:
|
||||
from .nodes.sampling.ksampler import TT_KSampler
|
||||
from .nodes.sampling.ksampler_advanced import TT_KSamplerAdvanced
|
||||
from .nodes.sampling.ksampler_context import TT_KSamplerContext
|
||||
from .nodes.sampling.ksampler_two_stage import TT_KSamplerTwoStage
|
||||
from .nodes.sampling.ksampler_guided import TT_KSamplerGuided
|
||||
from .nodes_sampling import *
|
||||
except ImportError:
|
||||
print("f{YELLOW}TenserTensor: {RED}ERROR: Sampler nodes unavailable{RESET}")
|
||||
|
||||
try:
|
||||
from .nodes.text_encoders.clip_text_encode_flux import TT_ClipTextEncodeFlux
|
||||
from .nodes.text_encoders.clip_text_encode_flux_context import TT_ClipTextEncodeFluxContext
|
||||
from .nodes.text_encoders.clip_text_encode_sdxl import TT_ClipTextEncodeSdxl
|
||||
from .nodes.text_encoders.clip_text_encode_sdxl_context import TT_ClipTextEncodeSdxlContext
|
||||
from .nodes.text_encoders.clip_text_encode_flux2 import TT_ClipTextEncodeFlux2
|
||||
from .nodes.text_encoders.clip_text_encode_flux2_context import TT_ClipTextEncodeFlux2Context
|
||||
from .nodes_text_encoder import *
|
||||
except ImportError:
|
||||
print(f"{YELLOW}TenserTensor: {RED}ERROR: Text Encoder nodes unavailable{RESET}")
|
||||
|
||||
try:
|
||||
from .nodes.vae.vae_decode_context import TT_VaeDecodeContext
|
||||
from .nodes.vae.vae_decode_tiled import TT_VaeDecodeTiled
|
||||
from .nodes.vae.vae_encode_context import TT_VaeEncodeContext
|
||||
from .nodes.vae.vae_encode_tiled import TT_VaeEncodeTiled
|
||||
from .nodes_vae import *
|
||||
except ImportError:
|
||||
print(f"{YELLOW}TenserTensor: {RED}ERROR: VAE nodes unavailable{RESET}")
|
||||
|
||||
try:
|
||||
before = set(dir())
|
||||
from .nodes.workflow.flux_workflow_settings import TT_FluxWorkflowSettings
|
||||
from .nodes.workflow.flux_workflow_settings_advanced import TT_FluxWorkflowSettingsAdvanced
|
||||
from .nodes.workflow.sdxl_workflow_settings import TT_SdxlWorkflowSettings
|
||||
from .nodes.workflow.sdxl_workflow_settings_advanced import TT_SdxlWorkflowSettingsAdvanced
|
||||
from .nodes.workflow.flux2_workflow_settings import TT_Flux2WorkflowSettings
|
||||
from .nodes.workflow.flux2_workflow_settings_advanced import TT_Flux2WorkflowSettingsAdvanced
|
||||
from .nodes_workflow import *
|
||||
except ImportError:
|
||||
print(f"{YELLOW}TenserTensor: {RED}ERROR: Workflow nodes unavailable{RESET}")
|
||||
|
||||
ADDED = {
|
||||
name
|
||||
for name, obj
|
||||
in inspect.getmembers(sys.modules[__name__], inspect.isclass)
|
||||
if name.startswith("TT_")
|
||||
}
|
||||
NODES_COUNT = len(ADDED)
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
# Context Deprecated
|
||||
"TT_BaseContext": TT_BaseContext,
|
||||
"TT_Context": TT_Context,
|
||||
"TT_LargeContextFlux": TT_LargeContextFlux,
|
||||
"TT_LargeContextSdxl": TT_LargeContextSdxl,
|
||||
"TT_EvenLargerContext": TT_EvenLargerContext,
|
||||
"TT_ContextSetImage": TT_ContextSetImage,
|
||||
"TT_ContextSetLatent": TT_ContextSetLatent,
|
||||
"TT_ContextSetGuider": TT_ContextSetGuider,
|
||||
"TT_ContextPassthrough": TT_ContextPassthrough,
|
||||
# Context V3 Nodes
|
||||
"TT_BaseContextNode": TT_BaseContextNode,
|
||||
"TT_BaseContextFlux2Node": TT_BaseContextFlux2Node,
|
||||
"TT_ContextPassthroughNode": TT_ContextPassthroughNode,
|
||||
"TT_ContextNode": TT_ContextNode,
|
||||
"TT_ContextFlux2Node": TT_ContextFlux2Node,
|
||||
"TT_ContextSetGuiderNode": TT_ContextSetGuiderNode,
|
||||
"TT_ContextSetImageNode": TT_ContextSetImageNode,
|
||||
"TT_ContextSetLatentNode": TT_ContextSetLatentNode,
|
||||
"TT_ContextExtractEncoderFlux2Node": TT_ContextExtractEncoderFlux2Node,
|
||||
"TT_ContextExtractGuidedSamplerFlux2Node": TT_ContextExtractGuidedSamplerFlux2Node,
|
||||
"TT_ContextExtractVaeNode": TT_ContextExtractVaeNode,
|
||||
"TT_ContextExtractImageNode": TT_ContextExtractImageNode,
|
||||
# ControlNet V3 Nodes
|
||||
"TT_Flux2ApplyControlNetNode": TT_Flux2ApplyControlNetNode,
|
||||
"TT_Flux2ApplyControlNetAdvancedNode": TT_Flux2ApplyControlNetAdvancedNode,
|
||||
# Detector V3 Nodes
|
||||
"TT_CannyEdgeDetectorNode": TT_CannyEdgeDetectorNode,
|
||||
# Image
|
||||
"TT_ImagePreviewSave": TT_ImagePreviewSave,
|
||||
"TT_ImagePreviewUpscaleSave": TT_ImagePreviewUpscaleSave,
|
||||
"TT_GuiderImageReference": TT_GuiderImageReference,
|
||||
# Image V3 Nodes
|
||||
"TT_ImageLoaderResizerNode": TT_ImageLoaderResizerNode,
|
||||
"TT_ImagePreviewSaveNode": TT_ImagePreviewSaveNode,
|
||||
"TT_ImagePreviewUpscaleSaveNode": TT_ImagePreviewUpscaleSaveNode,
|
||||
"TT_GuiderImageReferenceNode": TT_GuiderImageReferenceNode,
|
||||
# Latent
|
||||
"TT_LatentFactory": TT_LatentFactory,
|
||||
# Latent V3 Nodes
|
||||
"TT_LatentFactoryNode": TT_LatentFactoryNode,
|
||||
"TT_LatentFactoryByModelNode": TT_LatentFactoryByModelNode,
|
||||
"TT_LatentMultiTransformNode": TT_LatentMultiTransformNode,
|
||||
"TT_LatentMultiTransformOnPixelSpaceNode": TT_LatentMultiTransformOnPixelSpaceNode,
|
||||
# Loaders
|
||||
"TT_SdxlModelsLoader": TT_SdxlModelsLoader,
|
||||
"TT_SdxlModelsLoaderAdvanced": TT_SdxlModelsLoaderAdvanced,
|
||||
"TT_Flux2GgufModelsLoader": TT_Flux2GgufModelsLoader,
|
||||
"TT_Flux2GgufModelsLoaderAdvanced": TT_Flux2GgufModelsLoaderAdvanced,
|
||||
"TT_FluxModelsLoader": TT_FluxModelsLoader,
|
||||
"TT_FluxModelsLoaderAdvanced": TT_FluxModelsLoaderAdvanced,
|
||||
# Loaders V3 Nodes
|
||||
"TT_SdxlModelsLoaderNode": TT_SdxlModelsLoaderNode,
|
||||
"TT_SdxlModelsLoaderAdvancedNode": TT_SdxlModelsLoaderAdvancedNode,
|
||||
"TT_FluxModelsLoaderNode": TT_FluxModelsLoaderNode,
|
||||
"TT_FluxModelsLoaderAdvancedNode": TT_FluxModelsLoaderAdvancedNode,
|
||||
"TT_Flux2GgufModelsLoaderNode": TT_Flux2GgufModelsLoaderNode,
|
||||
"TT_Flux2GgufModelsLoaderAdvancedNode": TT_Flux2GgufModelsLoaderAdvancedNode,
|
||||
"TT_Sd35GgufModelsLoaderNode": TT_Sd35GgufModelsLoaderNode,
|
||||
"TT_Sd35GgufModelsLoaderAdvancedNode": TT_Sd35GgufModelsLoaderAdvancedNode,
|
||||
# Postproduction
|
||||
"TT_ApplyLut": TT_ApplyLut,
|
||||
"TT_AddFilmGrain": TT_AddFilmGrain,
|
||||
"TT_QuickImageUpscaler": TT_QuickImageUpscaler,
|
||||
"TT_ImageEnhancer": TT_ImageEnhancer,
|
||||
"TT_Postproduction": TT_Postproduction,
|
||||
"TT_PostproductionAdvanced": TT_PostproductionAdvanced,
|
||||
# Postproduction V3 Nodes
|
||||
"TT_AddFilmGrainNode": TT_AddFilmGrainNode,
|
||||
"TT_ApplyLutNode": TT_ApplyLutNode,
|
||||
"TT_ImageEnhancerNode": TT_ImageEnhancerNode,
|
||||
"TT_QuickImageUpscalerNode": TT_QuickImageUpscalerNode,
|
||||
"TT_PostproductionNode": TT_PostproductionNode,
|
||||
"TT_PostproductionAdvancedNode": TT_PostproductionAdvancedNode,
|
||||
# Samplers
|
||||
"TT_KSampler": TT_KSampler,
|
||||
"TT_KSamplerAdvanced": TT_KSamplerAdvanced,
|
||||
"TT_KSamplerContext": TT_KSamplerContext,
|
||||
"TT_KSamplerTwoStage": TT_KSamplerTwoStage,
|
||||
"TT_KSamplerGuided": TT_KSamplerGuided,
|
||||
# Samplers V3 Nodes
|
||||
"TT_KSamplerNode": TT_KSamplerNode,
|
||||
"TT_KSamplerAdvancedNode": TT_KSamplerAdvancedNode,
|
||||
"TT_KSamplerContextNode": TT_KSamplerContextNode,
|
||||
"TT_KSamplerTwoStageNode": TT_KSamplerTwoStageNode,
|
||||
"TT_GuidedKSamplerNode": TT_GuidedKSamplerNode,
|
||||
"TT_GuidedUpscaleKSamplerNode": TT_GuidedUpscaleKSamplerNode,
|
||||
# Text Encoder
|
||||
"TT_ClipTextEncodeFlux": TT_ClipTextEncodeFlux,
|
||||
"TT_ClipTextEncodeFluxContext": TT_ClipTextEncodeFluxContext,
|
||||
"TT_ClipTextEncodeSdxl": TT_ClipTextEncodeSdxl,
|
||||
"TT_ClipTextEncodeSdxlContext": TT_ClipTextEncodeSdxlContext,
|
||||
"TT_ClipTextEncodeFlux2": TT_ClipTextEncodeFlux2,
|
||||
"TT_ClipTextEncodeFlux2Context": TT_ClipTextEncodeFlux2Context,
|
||||
# Text Encoder V3 Nodes
|
||||
"TT_SdxlClipTextEncoderNode": TT_SdxlClipTextEncoderNode,
|
||||
"TT_SdxlClipTextEncoderContextNode": TT_SdxlClipTextEncoderContextNode,
|
||||
"TT_Flux1ClipTextEncoderNode": TT_Flux1ClipTextEncoderNode,
|
||||
"TT_Flux1ClipTextEncoderContextNode": TT_Flux1ClipTextEncoderContextNode,
|
||||
"TT_Flux2TextEncoderNode": TT_Flux2TextEncoderNode,
|
||||
"TT_Flux2TextEncoderContextNode": TT_Flux2TextEncoderContextNode,
|
||||
"TT_Sd35TextEncoderNode": TT_Sd35TextEncoderNode,
|
||||
"TT_Sd35TextEncoderContextNode": TT_Sd35TextEncoderContextNode,
|
||||
# VAE
|
||||
"TT_VaeDecodeContext": TT_VaeDecodeContext,
|
||||
"TT_VaeDecodeTiled": TT_VaeDecodeTiled,
|
||||
"TT_VaeEncodeContext": TT_VaeEncodeContext,
|
||||
"TT_VaeEncodeTiled": TT_VaeEncodeTiled,
|
||||
# VAE V3 Nodes
|
||||
"TT_VaeDecodeTiledNode": TT_VaeDecodeTiledNode,
|
||||
"TT_VaeDecodeContextNode": TT_VaeDecodeContextNode,
|
||||
"TT_VaeEncodeTiledNode": TT_VaeEncodeTiledNode,
|
||||
"TT_VaeEncodeContextNode": TT_VaeEncodeContextNode,
|
||||
# Workflow
|
||||
"TT_FluxWorkflowSettings": TT_FluxWorkflowSettings,
|
||||
"TT_FluxWorkflowSettingsAdvanced": TT_FluxWorkflowSettingsAdvanced,
|
||||
"TT_SdxlWorkflowSettings": TT_SdxlWorkflowSettings,
|
||||
"TT_SdxlWorkflowSettingsAdvanced": TT_SdxlWorkflowSettingsAdvanced,
|
||||
"TT_Flux2WorkflowSettings": TT_Flux2WorkflowSettings,
|
||||
"TT_Flux2WorkflowSettingsAdvanced": TT_Flux2WorkflowSettingsAdvanced,
|
||||
# Workflow V3 Nodes
|
||||
"TT_SdxlWorkflowSettingsNode": TT_SdxlWorkflowSettingsNode,
|
||||
"TT_SdxlWorkflowSettingsAdvancedNode": TT_SdxlWorkflowSettingsAdvancedNode,
|
||||
"TT_FluxWorkflowSettingsNode": TT_FluxWorkflowSettingsNode,
|
||||
"TT_FluxWorkflowSettingsAdvancedNode": TT_FluxWorkflowSettingsAdvancedNode,
|
||||
"TT_Flux2WorkflowSettingsNode": TT_Flux2WorkflowSettingsNode,
|
||||
"TT_Flux2WorkflowSettingsAdvancedNode": TT_Flux2WorkflowSettingsAdvancedNode,
|
||||
"TT_Sd35GgufWorkflowSettingsNode": TT_Sd35GgufWorkflowSettingsNode,
|
||||
"TT_Sd35GgufWorkflowSettingsAdvancedNode": TT_Sd35GgufWorkflowSettingsAdvancedNode,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
# Context Deprecated
|
||||
"TT_BaseContext": "TT Base Context (Deprecated)",
|
||||
"TT_Context": "TT Context (Deprecated)",
|
||||
"TT_LargeContextFlux": "TT FLUX Large Context (Deprecated)",
|
||||
"TT_LargeContextSdxl": "TT SDXL Large Context (Deprecated)",
|
||||
"TT_EvenLargerContext": "TT Even Larger Context (Deprecated)",
|
||||
"TT_ContextSetImage": "TT Context Set Image (Deprecated)",
|
||||
"TT_ContextSetLatent": "TT Context Set Latent (Deprecated)",
|
||||
"TT_ContextSetGuider": "TT Context Set Guider (Deprecated)",
|
||||
"TT_ContextPassthrough": "TT Context Passthrough (Deprecated)",
|
||||
# Context V3 Nodes
|
||||
"TT_BaseContextNode": "TT Base Context",
|
||||
"TT_BaseContextFlux2Node": "TT FLUX2 Base Context",
|
||||
"TT_ContextPassthroughNode": "TT Context Passthrough",
|
||||
"TT_ContextNode": "TT Context",
|
||||
"TT_ContextFlux2Node": "TT FLUX2 Context",
|
||||
"TT_ContextSetGuiderNode": "TT Context Set Guider",
|
||||
"TT_ContextSetImageNode": "TT Context Set Image",
|
||||
"TT_ContextSetLatentNode": "TT Context Set Latent",
|
||||
"TT_ContextExtractEncoderFlux2Node": "TT Context Extract Encoder FLUX2",
|
||||
"TT_ContextExtractGuidedSamplerFlux2Node": "TT Context Extract Guided Sampler Flux2",
|
||||
"TT_ContextExtractVaeNode": "TT Context Extract VAE Flux2",
|
||||
"TT_ContextExtractImageNode": "TT Context Extract Image Flux2",
|
||||
# ControlNet V3 Nodes
|
||||
"TT_Flux2ApplyControlNetNode": "TT Flux2 Apply ControlNet",
|
||||
"TT_Flux2ApplyControlNetAdvancedNode": "TT FLUX2 Apply ControlNet (Advanced)",
|
||||
# Detector V3 Nodes
|
||||
"TT_CannyEdgeDetectorNode": "TT_Canny Edge Detector",
|
||||
# Image
|
||||
"TT_ImagePreviewSave": "TT Image Preview / Save (Deprecated)",
|
||||
"TT_ImagePreviewUpscaleSave": "TT Image Preview / Upscale / Save (Deprecated)",
|
||||
"TT_GuiderImageReference": "TT Guider Image Reference (Deprecated)",
|
||||
# Image V3 Nodes
|
||||
"TT_ImageLoaderResizerNode": "TT Image Loader / Resizer",
|
||||
"TT_ImagePreviewSaveNode": "TT Image Preview / Save",
|
||||
"TT_ImagePreviewUpscaleSaveNode": "TT Image Preview / Upscale / Save",
|
||||
"TT_GuiderImageReferenceNode": "TT Guider Image Reference",
|
||||
# Latent
|
||||
"TT_LatentFactory": "TT Latent Factory (Deprecated)",
|
||||
# Latent V3 Nodes
|
||||
"TT_LatentFactoryNode": "TT Latent Factory",
|
||||
"TT_LatentFactoryByModelNode": "TT Latent Factory (By Model)",
|
||||
"TT_LatentMultiTransformNode": "TT Latent Multi Transform",
|
||||
"TT_LatentMultiTransformOnPixelSpaceNode": "TT Latent MultiTransform (On Pixel Space)",
|
||||
# Loaders
|
||||
"TT_SdxlModelsLoader": "TT SDXL Models Loader",
|
||||
"TT_SdxlModelsLoaderAdvanced": "TT SDXL Models Loader (Advanced)",
|
||||
"TT_Flux2GgufModelsLoader": "TT FLUX2 GGUF Models Loader",
|
||||
"TT_Flux2GgufModelsLoaderAdvanced": "TT FLUX2 GGUF Models Loader (Advanced)",
|
||||
"TT_FluxModelsLoader": "TT FLUX Models Loader",
|
||||
"TT_FluxModelsLoaderAdvanced": "TT FLUX Models Loader (Advanced)",
|
||||
# Loaders V3 Nodes
|
||||
"TT_SdxlModelsLoaderNode": "TT SDXL Models Loader",
|
||||
"TT_SdxlModelsLoaderAdvancedNode": "TT SDXL Models Loader (Advanced)",
|
||||
"TT_FluxModelsLoaderNode": "TT FLUX Models Loader",
|
||||
"TT_FluxModelsLoaderAdvancedNode": "TT FLUX Models Loader (Advanced)",
|
||||
"TT_Flux2GgufModelsLoaderNode": "TT FLUX2 GGUF Models Loader",
|
||||
"TT_Flux2GgufModelsLoaderAdvancedNode": "TT FLUX2 GGUF Models Loader (Advanced)",
|
||||
"TT_Sd35GgufModelsLoaderNode": "TT SD3.5 GGUF Models Loader",
|
||||
"TT_Sd35GgufModelsLoaderAdvancedNode": "TT SD3.5 GGUF Models Loader (Advanced)",
|
||||
# Postproduction
|
||||
"TT_ApplyLut": "TT Apply LUT",
|
||||
"TT_AddFilmGrain": "TT Add Film Grain",
|
||||
"TT_QuickImageUpscaler": "TT Quick Image Upscaler",
|
||||
"TT_ImageEnhancer": "TT Image Enhancer",
|
||||
"TT_Postproduction": "TT Postproduction",
|
||||
"TT_PostproductionAdvanced": "TT Postproduction (Advanced)",
|
||||
# Postproduction V3 Nodes
|
||||
"TT_AddFilmGrainNode": "TT Add Film Grain",
|
||||
"TT_ApplyLutNode": "TT Apply LUT",
|
||||
"TT_ImageEnhancerNode": "TT Image Enhancer",
|
||||
"TT_QuickImageUpscalerNode": "TT Quick Image Upscaler",
|
||||
"TT_PostproductionNode": "TT Postproduction",
|
||||
"TT_PostproductionAdvancedNode": "TT Postproduction (Advanced)",
|
||||
# Samplers
|
||||
"TT_KSampler": "TT KSampler",
|
||||
"TT_KSamplerAdvanced": "TT KSampler (Advanced)",
|
||||
"TT_KSamplerContext": "TT KSampler (Context)",
|
||||
"TT_KSamplerTwoStage": "TT KSampler (Two Stages)",
|
||||
"TT_KSamplerGuided": "TT KSampler (Guided)",
|
||||
# Samplers V3 Nodes
|
||||
"TT_KSamplerNode": "TT KSampler",
|
||||
"TT_KSamplerAdvancedNode": "TT KSampler (Advanced)",
|
||||
"TT_KSamplerContextNode": "TT KSampler (Context)",
|
||||
"TT_KSamplerTwoStageNode": "TT KSampler (Two Stage)",
|
||||
"TT_GuidedKSamplerNode": "TT Guided KSampler",
|
||||
"TT_GuidedUpscaleKSamplerNode": "TT Guided Upscale KSampler",
|
||||
# Text Encoder
|
||||
"TT_ClipTextEncodeFlux": "TT CLIP Text Encode FLUX",
|
||||
"TT_ClipTextEncodeFluxContext": "TT CLIP Text Encode FLUX (Context)",
|
||||
"TT_ClipTextEncodeSdxl": "TT CLIP Text Encode SDXL",
|
||||
"TT_ClipTextEncodeSdxlContext": "TT CLIP Text Encode SDXL (Context)",
|
||||
"TT_ClipTextEncodeFlux2": "TT CLIP Text Encode FLUX2",
|
||||
"TT_ClipTextEncodeFlux2Context": "TT CLIP Text Encode FLUX2 (Context)",
|
||||
# Text Encoder V3 Nodes
|
||||
"TT_SdxlClipTextEncoderNode": "TT SDXL CLIP Text Encoder",
|
||||
"TT_SdxlClipTextEncoderContextNode": "TT SDXL CLIP Text Encoder (Context)",
|
||||
"TT_Flux1ClipTextEncoderNode": "TT FLUX1 CLIP Text Encoder",
|
||||
"TT_Flux1ClipTextEncoderContextNode": "TT FLUX1 CLIP Text Encoder (Context)",
|
||||
"TT_Flux2TextEncoderNode": "TT FLUX2 Text Encoder",
|
||||
"TT_Flux2TextEncoderContextNode": "TT FLUX2 Text Encoder (Context)",
|
||||
"TT_Sd35TextEncoderNode": "TT SD3.5 Text Encoder",
|
||||
"TT_Sd35TextEncoderContextNode": "TT SD3.5 Text Encoder (Context)",
|
||||
# VAE
|
||||
"TT_VaeDecodeContext": "TT VAE Decode (Context)",
|
||||
"TT_VaeDecodeTiled": "TT VAE Decode (Tiled)",
|
||||
"TT_VaeEncodeContext": "TT Vae Encode (Context)",
|
||||
"TT_VaeEncodeTiled": "TT Vae Encode (Tiled)",
|
||||
# VAE V3 Nodes
|
||||
"TT_VaeDecodeTiledNode": "TT Vae Decode (Tiled)",
|
||||
"TT_VaeDecodeContextNode": "TT Vae Decode (Context)",
|
||||
"TT_VaeEncodeTiledNode": "TT Vae Encode (Tiled)",
|
||||
"TT_VaeEncodeContextNode": "TT Vae Encode (Context)",
|
||||
# Workflow
|
||||
"TT_FluxWorkflowSettings": "TT FLUX Workflow Settings",
|
||||
"TT_FluxWorkflowSettingsAdvanced": "TT FLUX Workflow Settings (Advanced)",
|
||||
"TT_SdxlWorkflowSettings": "TT SDXL Workflow Settings",
|
||||
"TT_SdxlWorkflowSettingsAdvanced": "TT SDXL Workflow Settings (Advanced)",
|
||||
"TT_Flux2WorkflowSettings": "TT FLUX2 Workflow Settings (Deprecated)",
|
||||
"TT_Flux2WorkflowSettingsAdvanced": "TT FLUX2 Workflow Settings (Deprecated/Advanced)",
|
||||
# Workflow V3 Nodes
|
||||
"TT_SdxlWorkflowSettingsNode": "TT SDXL Workflow Settings",
|
||||
"TT_SdxlWorkflowSettingsAdvancedNode": "TT SDXL Workflow Settings (Advanced)",
|
||||
"TT_FluxWorkflowSettingsNode": "TT FLUX Workflow Settings",
|
||||
"TT_FluxWorkflowSettingsAdvancedNode": "TT FLUX Workflow Settings (Advanced)",
|
||||
"TT_Flux2WorkflowSettingsNode": "TT FLUX2 Workflow Settings",
|
||||
"TT_Flux2WorkflowSettingsAdvancedNode": "TT FLUX2 Workflow Settings (Advanced)",
|
||||
"TT_Sd35WorkflowSettingsNode": "TT SD3.5 Workflow Settings",
|
||||
"TT_Sd35WorkflowSettingsAdvancedNode": "TT SD3.5 Workflow Settings (Advanced)",
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from .context_helpers import create_context_schema
|
||||
|
||||
|
||||
class TT_BaseContext:
|
||||
INPUT_TYPES_DICT, RETURN_TYPES, RETURN_NAMES = create_context_schema("base")
|
||||
FUNCTION = "process_context"
|
||||
CATEGORY = "TenserTensor/Deprecated/Context"
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return cls.INPUT_TYPES_DICT
|
||||
|
||||
def process_context(self, workflow_config, model, clip, vae, latent):
|
||||
context = {
|
||||
"workflow_config": workflow_config,
|
||||
"model": model,
|
||||
"clip": clip,
|
||||
"vae": vae,
|
||||
"latent": latent,
|
||||
}
|
||||
|
||||
return (context,)
|
||||
@@ -1,18 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from .context_helpers import (build_return_tuple, create_context_schema, init_context)
|
||||
|
||||
|
||||
class TT_Context:
|
||||
INPUT_TYPES_DICT, RETURN_TYPES, RETURN_NAMES = create_context_schema("standard")
|
||||
FUNCTION = "process_context"
|
||||
CATEGORY = "TenserTensor/Deprecated/Context"
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return cls.INPUT_TYPES_DICT
|
||||
|
||||
def process_context(self, context=None, **kwargs):
|
||||
args = init_context(context, **kwargs)
|
||||
|
||||
return build_return_tuple("standard", args)
|
||||
@@ -1,334 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
import comfy.samplers as S
|
||||
|
||||
CONTEXT_FIELDS = [
|
||||
# input_name, return_name, field_type
|
||||
("context", "CONTEXT", "TT_CONTEXT",),
|
||||
("model", "MODEL", "MODEL",),
|
||||
("clip", "CLIP", "CLIP",),
|
||||
("vae", "VAE", "VAE",),
|
||||
("latent", "LATENT", "LATENT",),
|
||||
("positive", "POSITIVE", "CONDITIONING"),
|
||||
("negative", "NEGATIVE", "CONDITIONING"),
|
||||
("image", "IMAGE", "IMAGE"),
|
||||
("mask", "MASK", "MASK"),
|
||||
("guider", "GUIDER", "GUIDER"),
|
||||
("control_net", "CONTROL_NET", "CONTROL_NET"),
|
||||
("workflow_config", "WORKFLOW_CONFIG", "TT_WORKFLOW_CONFIG",),
|
||||
("seed", "SEED", "INT"),
|
||||
("steps", "STEPS", "INT"),
|
||||
("cfg", "CFG", "FLOAT"),
|
||||
("sampler_name", "SAMPLER_NAME", S.KSampler.SAMPLERS),
|
||||
("sampler", "SAMPLER", "SAMPLER"),
|
||||
("scheduler", "SCHEDULER", S.KSampler.SCHEDULERS),
|
||||
("guidance", "GUIDANCE", "FLOAT"),
|
||||
("prompt", "PROMPT", "STRING"),
|
||||
("lora_triggers", "LORA_TRIGGERS", "STRING"),
|
||||
("clip_l_positive", "CLIP_L_POSITIVE", "STRING"),
|
||||
("clip_g_positive", "CLIP_L_POSITIVE", "STRING"),
|
||||
("t5xxl_positive", "T5XXL_POSITIVE", "STRING"),
|
||||
("clip_l_negative", "CLIP_L_NEGATIVE", "STRING"),
|
||||
("clip_g_negative", "CLIP_L_NEGATIVE", "STRING"),
|
||||
("t5xxl_negative", "T5XXL_NEGATIVE", "STRING"),
|
||||
("ascore_positive", "ASCORE_POSITIVE", "FLOAT"),
|
||||
("ascore_negative", "ASCORE_NEGATIVE", "FLOAT"),
|
||||
("width", "WIDTH", "INT"),
|
||||
("height", "HEIGHT", "INT"),
|
||||
("target_width", "TARGET_WIDTH", "INT"),
|
||||
("target_height", "TARGET_HEIGHT", "INT"),
|
||||
]
|
||||
|
||||
CONTEXTS = {
|
||||
"base": {
|
||||
"required": (
|
||||
"model",
|
||||
"clip",
|
||||
"vae",
|
||||
"latent",
|
||||
),
|
||||
"optional": (
|
||||
"workflow_config",
|
||||
),
|
||||
"return": (
|
||||
"context",
|
||||
)
|
||||
},
|
||||
"standard": {
|
||||
"optional": (
|
||||
"context",
|
||||
"workflow_config",
|
||||
"model",
|
||||
"clip",
|
||||
"vae",
|
||||
"positive",
|
||||
"negative",
|
||||
"latent",
|
||||
"image",
|
||||
"seed",
|
||||
"steps",
|
||||
"cfg",
|
||||
"sampler_name",
|
||||
"scheduler",
|
||||
)
|
||||
},
|
||||
"big_flux": {
|
||||
"optional": (
|
||||
"context",
|
||||
"workflow_config",
|
||||
"model",
|
||||
"clip",
|
||||
"vae",
|
||||
"positive",
|
||||
"negative",
|
||||
"latent",
|
||||
"image",
|
||||
"seed",
|
||||
"steps",
|
||||
"cfg",
|
||||
"sampler_name",
|
||||
"scheduler",
|
||||
"guidance",
|
||||
"clip_l_positive",
|
||||
"t5xxl_positive",
|
||||
"clip_l_negative",
|
||||
"t5xxl_negative",
|
||||
"width",
|
||||
"height",
|
||||
)
|
||||
},
|
||||
"big_flux2": {
|
||||
"optional": (
|
||||
"context",
|
||||
"workflow_config",
|
||||
"model",
|
||||
"clip",
|
||||
"vae",
|
||||
"latent",
|
||||
"image",
|
||||
"seed",
|
||||
"steps",
|
||||
"cfg",
|
||||
"sampler_name",
|
||||
"sampler",
|
||||
"scheduler",
|
||||
"guidance",
|
||||
"prompt",
|
||||
"lora_triggers",
|
||||
"width",
|
||||
"height",
|
||||
)
|
||||
},
|
||||
"big_sdxl": {
|
||||
"optional": (
|
||||
"context",
|
||||
"workflow_config",
|
||||
"model",
|
||||
"clip",
|
||||
"vae",
|
||||
"positive",
|
||||
"negative",
|
||||
"latent",
|
||||
"image",
|
||||
"seed",
|
||||
"steps",
|
||||
"cfg",
|
||||
"sampler_name",
|
||||
"scheduler",
|
||||
"guidance",
|
||||
"clip_l_positive",
|
||||
"clip_g_positive",
|
||||
"clip_l_negative",
|
||||
"clip_g_negative",
|
||||
"ascore_positive",
|
||||
"ascore_negative",
|
||||
"width",
|
||||
"height",
|
||||
"target_width",
|
||||
"target_height",
|
||||
)
|
||||
},
|
||||
"huge": {
|
||||
"optional": tuple(f[0] for f in CONTEXT_FIELDS)
|
||||
},
|
||||
"passthrough": {
|
||||
"required": (
|
||||
"context",
|
||||
)
|
||||
},
|
||||
"set_image": {
|
||||
"required": (
|
||||
"context",
|
||||
"image",
|
||||
),
|
||||
"return": (
|
||||
"context",
|
||||
)
|
||||
},
|
||||
"set_latent": {
|
||||
"required": (
|
||||
"context",
|
||||
"latent",
|
||||
),
|
||||
"return": (
|
||||
"context",
|
||||
)
|
||||
},
|
||||
"set_guider": {
|
||||
"required": (
|
||||
"context",
|
||||
"guider",
|
||||
),
|
||||
"return": (
|
||||
"context",
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
FORCE_INPUT_TYPES = {
|
||||
"INT",
|
||||
"FLOAT",
|
||||
"STRING",
|
||||
"BOOLEAN",
|
||||
}
|
||||
|
||||
WORKFOW_SETTINGS_KEYS = [
|
||||
"seed",
|
||||
"steps",
|
||||
"cfg",
|
||||
"sampler_name",
|
||||
"sampler",
|
||||
"scheduler",
|
||||
"pos_a_score",
|
||||
"clip_l_positive",
|
||||
"clip_g_positive",
|
||||
"t5xxl_positive",
|
||||
"neg_a_score",
|
||||
"clip_l_negative",
|
||||
"clip_g_negative",
|
||||
"t5xxl_negative",
|
||||
"guidance",
|
||||
"ascore_positive",
|
||||
"ascore_negative",
|
||||
"width",
|
||||
"height",
|
||||
"target_width",
|
||||
"target_height",
|
||||
]
|
||||
|
||||
|
||||
def _get_field_map():
|
||||
return {field[0]: (field[1], field[2]) for field in CONTEXT_FIELDS}
|
||||
|
||||
|
||||
def _get_input_types(field_map, fields):
|
||||
retval = {}
|
||||
for field_name in fields:
|
||||
field_type = field_map[field_name][1]
|
||||
|
||||
if isinstance(field_type, (list, tuple)) or field_type in FORCE_INPUT_TYPES:
|
||||
retval[field_name] = (field_type, {"forceInput": True})
|
||||
else:
|
||||
retval[field_name] = (field_type,)
|
||||
|
||||
return retval
|
||||
|
||||
|
||||
def _get_input_schema(context_name):
|
||||
context_def = CONTEXTS[context_name]
|
||||
field_map = _get_field_map()
|
||||
|
||||
input_types = {
|
||||
"required": _get_input_types(field_map, context_def.get("required", ())),
|
||||
"optional": _get_input_types(field_map, context_def.get("optional", ()))
|
||||
}
|
||||
|
||||
return input_types
|
||||
|
||||
|
||||
def _get_return_fields(context_name):
|
||||
context_def = CONTEXTS[context_name]
|
||||
|
||||
if "return" in context_def:
|
||||
return context_def.get("return", ())
|
||||
else:
|
||||
return context_def.get("required", ()) + context_def.get("optional", ())
|
||||
|
||||
|
||||
def _get_return_schema(context_name):
|
||||
field_map = _get_field_map()
|
||||
return_fields = _get_return_fields(context_name)
|
||||
|
||||
return_types = tuple(field_map[field][1] for field in return_fields)
|
||||
return_names = tuple(field_map[field][0] for field in return_fields)
|
||||
|
||||
return return_types, return_names
|
||||
|
||||
|
||||
def create_context_schema(context_name):
|
||||
input_types = _get_input_schema(context_name)
|
||||
return_types, return_names = _get_return_schema(context_name)
|
||||
|
||||
return input_types, return_types, return_names
|
||||
|
||||
|
||||
def init_context(context, **kwargs):
|
||||
field_map = _get_field_map()
|
||||
retval = {}
|
||||
|
||||
workflow_config = kwargs.get("workflow_config", None)
|
||||
|
||||
if workflow_config is None and context and "workflow_config" in context:
|
||||
workflow_config = context["workflow_config"]
|
||||
|
||||
if workflow_config:
|
||||
for key in WORKFOW_SETTINGS_KEYS:
|
||||
if key in workflow_config:
|
||||
retval[key] = workflow_config[key]
|
||||
|
||||
for idx in field_map:
|
||||
if idx == "context":
|
||||
continue
|
||||
|
||||
if idx in WORKFOW_SETTINGS_KEYS and idx in retval:
|
||||
val = kwargs.get(idx, None)
|
||||
if val is not None:
|
||||
retval[idx] = val
|
||||
continue
|
||||
|
||||
val = kwargs[idx] if idx in kwargs else None
|
||||
if val is not None:
|
||||
retval[idx] = val
|
||||
elif context and idx in context:
|
||||
retval[idx] = context[idx]
|
||||
else:
|
||||
retval[idx] = None
|
||||
|
||||
if any(k in retval for k in WORKFOW_SETTINGS_KEYS):
|
||||
retval["workflow_config"] = {
|
||||
"seed": retval.get("seed"),
|
||||
"steps": retval.get("steps"),
|
||||
"cfg": retval.get("cfg"),
|
||||
"sampler_name": retval.get("sampler_name"),
|
||||
"scheduler": retval.get("scheduler"),
|
||||
"clip_l_positive": retval.get("clip_l_positive"),
|
||||
"clip_g_positive": retval.get("clip_g_positive"),
|
||||
"t5xxl_positive": retval.get("t5xxl_positive"),
|
||||
"clip_l_negative": retval.get("clip_l_negative"),
|
||||
"clip_g_negative": retval.get("clip_g_negative"),
|
||||
"t5xxl_negative": retval.get("t5xxl_negative"),
|
||||
"guidance": retval.get("guidance"),
|
||||
"ascore_positive": retval.get("ascore_positive"),
|
||||
"ascore_negative": retval.get("ascore_negative"),
|
||||
"target_width": retval.get("target_width"),
|
||||
"target_height": retval.get("target_height"),
|
||||
}
|
||||
else:
|
||||
retval["workflow_config"] = workflow_config
|
||||
|
||||
return retval
|
||||
|
||||
|
||||
def build_return_tuple(context_name, args):
|
||||
context_fields = _get_return_fields(context_name)
|
||||
return tuple([args] + [args.get(field) for field in context_fields if field != "context"])
|
||||
@@ -1,18 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from .context_helpers import (build_return_tuple, create_context_schema, init_context)
|
||||
|
||||
|
||||
class TT_ContextPassthrough:
|
||||
INPUT_TYPES_DICT, RETURN_TYPES, RETURN_NAMES = create_context_schema("passthrough")
|
||||
FUNCTION = "process_context"
|
||||
CATEGORY = "TenserTensor/Deprecated/Context"
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return cls.INPUT_TYPES_DICT
|
||||
|
||||
def process_context(self, context=None, **kwargs):
|
||||
args = init_context(context, **kwargs)
|
||||
|
||||
return build_return_tuple("passthrough", args)
|
||||
@@ -1,18 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from .context_helpers import create_context_schema
|
||||
|
||||
|
||||
class TT_ContextSetGuider:
|
||||
INPUT_TYPES_DICT, RETURN_TYPES, RETURN_NAMES = create_context_schema("set_guider")
|
||||
FUNCTION = "process_context"
|
||||
CATEGORY = "TenserTensor/Deprecated/Context"
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return cls.INPUT_TYPES_DICT
|
||||
|
||||
def process_context(self, context, guider):
|
||||
context["guider"] = guider
|
||||
|
||||
return (context,)
|
||||
@@ -1,18 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from .context_helpers import create_context_schema
|
||||
|
||||
|
||||
class TT_ContextSetImage:
|
||||
INPUT_TYPES_DICT, RETURN_TYPES, RETURN_NAMES = create_context_schema("set_image")
|
||||
FUNCTION = "process_context"
|
||||
CATEGORY = "TenserTensor/Deprecated/Context"
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return cls.INPUT_TYPES_DICT
|
||||
|
||||
def process_context(self, context, image):
|
||||
context["image"] = image
|
||||
|
||||
return (context,)
|
||||
@@ -1,18 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from .context_helpers import create_context_schema
|
||||
|
||||
|
||||
class TT_ContextSetLatent:
|
||||
INPUT_TYPES_DICT, RETURN_TYPES, RETURN_NAMES = create_context_schema("set_latent")
|
||||
FUNCTION = "process_context"
|
||||
CATEGORY = "TenserTensor/Deprecated/Context"
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return cls.INPUT_TYPES_DICT
|
||||
|
||||
def process_context(self, context, latent):
|
||||
context["latent"] = latent
|
||||
|
||||
return (context,)
|
||||
@@ -1,18 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from .context_helpers import (build_return_tuple, create_context_schema, init_context)
|
||||
|
||||
|
||||
class TT_EvenLargerContext:
|
||||
INPUT_TYPES_DICT, RETURN_TYPES, RETURN_NAMES = create_context_schema("huge")
|
||||
FUNCTION = "process_context"
|
||||
CATEGORY = "TenserTensor/Deprecated/Context"
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return cls.INPUT_TYPES_DICT
|
||||
|
||||
def process_context(self, context=None, **kwargs):
|
||||
args = init_context(context, **kwargs)
|
||||
|
||||
return build_return_tuple("huge", args)
|
||||
@@ -1,18 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from .context_helpers import (build_return_tuple, create_context_schema, init_context)
|
||||
|
||||
|
||||
class TT_LargeContextFlux:
|
||||
INPUT_TYPES_DICT, RETURN_TYPES, RETURN_NAMES = create_context_schema("big_flux")
|
||||
FUNCTION = "process_context"
|
||||
CATEGORY = "TenserTensor/Deprecated/Context"
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return cls.INPUT_TYPES_DICT
|
||||
|
||||
def process_context(self, context=None, **kwargs):
|
||||
args = init_context(context, **kwargs)
|
||||
|
||||
return build_return_tuple("big_flux", args)
|
||||
@@ -1,18 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from .context_helpers import (build_return_tuple, create_context_schema, init_context)
|
||||
|
||||
|
||||
class TT_LargeContextSdxl:
|
||||
INPUT_TYPES_DICT, RETURN_TYPES, RETURN_NAMES = create_context_schema("big_sdxl")
|
||||
FUNCTION = "process_context"
|
||||
CATEGORY = "TenserTensor/Deprecated/Context"
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return cls.INPUT_TYPES_DICT
|
||||
|
||||
def process_context(self, context=None, **kwargs):
|
||||
args = init_context(context, **kwargs)
|
||||
|
||||
return build_return_tuple("big_sdxl", args)
|
||||
@@ -1,58 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
import os
|
||||
|
||||
import folder_paths as FP
|
||||
from node_helpers import conditioning_set_values
|
||||
|
||||
from ..image.image_helpers import load_image, resize_image_to_megapixels
|
||||
from ...lib.common import CommonTypes
|
||||
|
||||
UPSCALE_METHODS = ["nearest-exact", "bilinear", "area", "bicubic", "lanczos"]
|
||||
TILE_SIZE, OVERLAP = 512, 64
|
||||
|
||||
|
||||
class TT_GuiderImageReference():
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
input_dir = FP.get_input_directory()
|
||||
files = FP.filter_files_content_types(
|
||||
[f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))], ["image"]
|
||||
)
|
||||
|
||||
return {
|
||||
"required": {
|
||||
"vae": ("VAE",),
|
||||
"guider": ("GUIDER",),
|
||||
"megapixels": (CommonTypes.MEGAPIXELS,),
|
||||
"upscale_method": (UPSCALE_METHODS, {"default": "bicubic", "advanced": True}),
|
||||
"dimension_step": ("INT", {"default": 1, "min": 1, "max": 10000, "advanced": True}),
|
||||
"image": (sorted(files), {"image_upload": True}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("VAE", "GUIDER",)
|
||||
RETURN_NAMES = ("VAE", "GUIDER",)
|
||||
FUNCTION = "update_latent"
|
||||
CATEGORY = "TenserTensor/Deprecated/Image"
|
||||
|
||||
def update_latent(self, vae, guider, megapixels, upscale_method, dimension_step, image):
|
||||
timage, _ = load_image(image)
|
||||
scaled = resize_image_to_megapixels(timage, upscale_method, megapixels, dimension_step)
|
||||
|
||||
samples = vae.encode_tiled(
|
||||
scaled,
|
||||
tile_x=TILE_SIZE,
|
||||
tile_y=TILE_SIZE,
|
||||
overlap=OVERLAP
|
||||
)
|
||||
|
||||
conditioning = guider.get_conds()
|
||||
|
||||
if conditioning is not None:
|
||||
conditioning = conditioning_set_values(conditioning, {"reference_latents": [samples]}, append=True)
|
||||
guider.set_conds(conditioning)
|
||||
else:
|
||||
raise ValueError("ERROR: Guider has no conditioning")
|
||||
|
||||
return (vae, guider,)
|
||||
@@ -1,197 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
import fnmatch
|
||||
import math
|
||||
import os
|
||||
import random
|
||||
import string as S
|
||||
from datetime import datetime
|
||||
|
||||
import folder_paths as FP
|
||||
import numpy
|
||||
import numpy as NP
|
||||
import torch
|
||||
from PIL import Image, ImageOps, ImageSequence
|
||||
from comfy import model_management as MM
|
||||
from comfy import utils as U
|
||||
from node_helpers import pillow
|
||||
|
||||
FORMAT_EXT = {
|
||||
"PNG": ".png",
|
||||
"JPEG": ".jpg",
|
||||
"WEBP": ".webp",
|
||||
}
|
||||
|
||||
|
||||
class InvalidSavePathError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def _build_filename(save_path, filename_mask):
|
||||
count = sum(1 for f in os.scandir(save_path) if fnmatch.fnmatch(f.name, filename_mask)) + 1
|
||||
|
||||
return filename_mask.replace("*", f"{count:05}")
|
||||
|
||||
|
||||
def _build_save_path(output_path, subfolder, filename_prefix, filename_format, image_format):
|
||||
save_path = os.path.join(output_path, subfolder)
|
||||
if os.path.commonpath((output_path, os.path.abspath(save_path))) != output_path:
|
||||
raise InvalidSavePathError("Saving image outside the output folder is not allowed.")
|
||||
|
||||
os.makedirs(save_path, exist_ok=True)
|
||||
|
||||
ext = FORMAT_EXT[image_format]
|
||||
|
||||
filename = ""
|
||||
match filename_format:
|
||||
case "name-###":
|
||||
filename = _build_filename(save_path, f"{filename_prefix}-*{ext}")
|
||||
case "date-name-###":
|
||||
date = datetime.now().strftime("%Y-%m-%d")
|
||||
filename = _build_filename(save_path, f"{date}-{filename_prefix}-*{ext}")
|
||||
case "name-datetime":
|
||||
timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
|
||||
filename = f"{filename_prefix}-{timestamp}{ext}"
|
||||
case _:
|
||||
filename = f"{filename_prefix}{ext}"
|
||||
|
||||
return save_path, filename
|
||||
|
||||
|
||||
def _store_image(
|
||||
images,
|
||||
filename_prefix,
|
||||
output_path,
|
||||
subfolder,
|
||||
filename_format,
|
||||
image_format,
|
||||
quality,
|
||||
compress_level
|
||||
):
|
||||
retval = list()
|
||||
for image in images:
|
||||
img_np = 255. * image.cpu().numpy()
|
||||
timage = Image.fromarray(NP.clip(img_np, 0, 255).astype(NP.uint8))
|
||||
save_path, filename = _build_save_path(
|
||||
output_path, subfolder, filename_prefix, filename_format, image_format
|
||||
)
|
||||
params = {"compress_level": compress_level} if image_format == "PNG" else {"quality": quality}
|
||||
timage.save(os.path.join(save_path, filename), format=image_format, **params)
|
||||
|
||||
retval.append({
|
||||
"filename": filename,
|
||||
"subfolder": subfolder,
|
||||
"type": "temp" if filename_prefix.startswith("tmp") else "output"
|
||||
})
|
||||
|
||||
return retval
|
||||
|
||||
|
||||
def store(
|
||||
image,
|
||||
filename_prefix,
|
||||
filename_format,
|
||||
subfolder,
|
||||
image_format,
|
||||
image_quality,
|
||||
compress_level
|
||||
):
|
||||
output_folder = FP.get_output_directory()
|
||||
|
||||
return _store_image(
|
||||
images=image,
|
||||
filename_prefix=filename_prefix,
|
||||
output_path=output_folder,
|
||||
subfolder=subfolder,
|
||||
filename_format=filename_format,
|
||||
image_format=image_format,
|
||||
quality=image_quality,
|
||||
compress_level=compress_level
|
||||
)
|
||||
|
||||
|
||||
def preview(image, filename_prefix):
|
||||
temp_dir = FP.get_temp_directory()
|
||||
rand = "".join(random.choices(S.ascii_lowercase, k=5))
|
||||
prefix = f"tmp-{filename_prefix}-{rand}"
|
||||
|
||||
return _store_image(
|
||||
images=image,
|
||||
filename_prefix=prefix,
|
||||
output_path=temp_dir,
|
||||
)
|
||||
|
||||
|
||||
def load_image(image_filename, device=None):
|
||||
tdevice = MM.get_torch_device() if device == None else torch.device("cpu")
|
||||
|
||||
image_path = FP.get_annotated_filepath(image_filename)
|
||||
pil_image = pillow(Image.open, image_path)
|
||||
|
||||
images, masks = [], []
|
||||
width, height = None, None
|
||||
|
||||
for frame in ImageSequence.Iterator(pil_image):
|
||||
pil_frame = pillow(ImageOps.exif_transpose, frame)
|
||||
|
||||
if pil_frame.mode == "I":
|
||||
pil_frame = pil_frame.point(lambda i: i * (1 / 255))
|
||||
|
||||
if len(images) == 0:
|
||||
width, height = pil_frame.size
|
||||
|
||||
if pil_frame.size != (width, height,):
|
||||
continue
|
||||
|
||||
alpha = numpy.zeros((height, width,), dtype=numpy.float32)
|
||||
if 'A' in pil_frame.getbands():
|
||||
alpha = numpy.array(pil_frame.getchannel('A'), dtype=numpy.float32) / 255.0
|
||||
elif pil_frame.mode == 'P' and 'transparency' in pil_frame.info:
|
||||
alpha = numpy.array(pil_frame.convert('RGBA').getchannel('A'), dtype=numpy.float32) / 255.0
|
||||
|
||||
tmask = torch.from_numpy(1.0 - alpha).to(tdevice)
|
||||
|
||||
rgb_frame = pil_frame.convert("RGB")
|
||||
np_image = numpy.array(rgb_frame, dtype=numpy.float32) / 255.0
|
||||
timage = torch.from_numpy(np_image)[None].to(tdevice)
|
||||
|
||||
images.append(timage)
|
||||
masks.append(tmask)
|
||||
|
||||
if pil_image.format == "MPO":
|
||||
break
|
||||
|
||||
if len(images) == 0:
|
||||
raise ValueError(f"ERROR: No frames found in {image_path}")
|
||||
|
||||
oimage = torch.cat(images, dim=0) if len(images) > 1 else images[0]
|
||||
omask = torch.cat(masks, dim=0) if len(masks) > 1 else masks[0]
|
||||
|
||||
return oimage, omask
|
||||
|
||||
|
||||
def _align_to_step(size, scale_factor, dimension_step):
|
||||
return round(size * scale_factor / dimension_step) * dimension_step
|
||||
|
||||
|
||||
# crop = "center" / "disabled"
|
||||
def resize_image(timage, to_width, to_height, upscale_method, dimension_step=1, crop="disabled"):
|
||||
samples = timage.movedim(-1, 1)
|
||||
orig_height, orig_width = samples.shape[2:]
|
||||
scale_factor = max(to_width / orig_width, to_height / orig_height)
|
||||
to_width = _align_to_step(orig_width, scale_factor, dimension_step)
|
||||
to_height = _align_to_step(orig_height, scale_factor, dimension_step)
|
||||
|
||||
return U.common_upscale(samples, int(to_width), int(to_height), upscale_method, crop).movedim(1, -1)
|
||||
|
||||
|
||||
def resize_image_to_megapixels(timage, upscale_method, megapixels, dimension_step=1):
|
||||
mp_value = float(megapixels.split()[0])
|
||||
total_pixels = int(mp_value * 1_000_000)
|
||||
samples = timage.movedim(-1, 1)
|
||||
orig_height, orig_width = samples.shape[2:]
|
||||
scale_factor = math.sqrt(total_pixels / (orig_width * orig_height))
|
||||
to_width = _align_to_step(orig_width, scale_factor, dimension_step)
|
||||
to_height = _align_to_step(orig_height, scale_factor, dimension_step)
|
||||
|
||||
return U.common_upscale(samples, int(to_width), int(to_height), upscale_method, "disabled").movedim(1, -1)
|
||||
@@ -1,55 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from .image_helpers import store, preview
|
||||
|
||||
|
||||
class TT_ImagePreviewSave():
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
FILENAME_FORMATS = ["name-###", "date-name-###", "name-datetime"]
|
||||
IMAGE_FORMATS = ["PNG", "JPEG", "WEBP"]
|
||||
|
||||
return {
|
||||
"required": {
|
||||
"image": ("IMAGE",),
|
||||
"save_image": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}),
|
||||
"filename_prefix": ("STRING", {"default": "tenser-tensor"}),
|
||||
"filename_format": (FILENAME_FORMATS, {"default": "name-###", "advanced": True}),
|
||||
"subfolder": ("STRING", {"default": "", "advanced": True}),
|
||||
"image_format": (IMAGE_FORMATS, {"default": "PNG", "advanced": True}),
|
||||
"image_quality": ("INT", {"default": 100, "min": 0, "max": 100, "advanced": True}),
|
||||
"compression_level": ("INT", {"default": 9, "min": 0, "max": 9, "advanced": True}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ()
|
||||
RETURN_NAMES = ()
|
||||
OUTPUT_NODE = True
|
||||
FUNCTION = "preview_save_image"
|
||||
CATEGORY = "TenserTensor/Deprecated/Image"
|
||||
|
||||
def preview_save_image(
|
||||
self,
|
||||
image,
|
||||
save_image,
|
||||
filename_prefix,
|
||||
filename_format,
|
||||
subfolder,
|
||||
image_format,
|
||||
image_quality,
|
||||
compression_level
|
||||
):
|
||||
if save_image:
|
||||
retval = store(
|
||||
image,
|
||||
filename_prefix,
|
||||
filename_format,
|
||||
subfolder,
|
||||
image_format,
|
||||
image_quality,
|
||||
compression_level
|
||||
)
|
||||
else:
|
||||
retval = preview(image, filename_prefix)
|
||||
|
||||
return {"ui": {"images": retval}}
|
||||
@@ -1,71 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
import folder_paths as FP
|
||||
|
||||
from .image_helpers import store, preview
|
||||
from ..postproduction.postproduction_helpers import upscale_image as upscale
|
||||
|
||||
|
||||
class TT_ImagePreviewUpscaleSave():
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
FILENAME_FORMATS = ["name-###", "date-name-###", "name-datetime"]
|
||||
IMAGE_FORMATS = ["PNG", "JPEG", "WEBP"]
|
||||
DEVICES = ["default", "cpu"]
|
||||
UPSCALE_MODELS = FP.get_filename_list("upscale_models")
|
||||
|
||||
return {
|
||||
"required": {
|
||||
"image": ("IMAGE",),
|
||||
"save_image": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}),
|
||||
"filename_prefix": ("STRING", {"default": "tenser-tensor"}),
|
||||
"filename_format": (FILENAME_FORMATS, {"advanced": True, "default": "name-###"}),
|
||||
"subfolder": ("STRING", {"default": "", "advanced": True}),
|
||||
"image_format": (IMAGE_FORMATS, {"advanced": True, "default": "PNG"}),
|
||||
"image_quality": ("INT", {"default": 100, "min": 0, "max": 100, "advanced": True}),
|
||||
"compression_level": ("INT", {"default": 9, "min": 0, "max": 9, "advanced": True}),
|
||||
"upscale_image": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}),
|
||||
"upscaler_device": (DEVICES, {"advanced": True}),
|
||||
"upscale_model_name": (UPSCALE_MODELS, {"advanced": True}),
|
||||
"tile": ("INT", {"default": 512, "min": 256, "max": 4096, "step": 64, "advanced": True}),
|
||||
"overlap": ("INT", {"default": 64, "min": 0, "max": 256, "step": 8, "advanced": True}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ()
|
||||
RETURN_NAMES = ()
|
||||
OUTPUT_NODE = True
|
||||
FUNCTION = "preview_upscale_save_image"
|
||||
CATEGORY = "TenserTensor/Deprecated/Image"
|
||||
|
||||
def preview_upscale_save_image(self, **kwargs):
|
||||
image = kwargs.get("image")
|
||||
timage = image.clone()
|
||||
|
||||
upscale_image = kwargs.get("upscale_image")
|
||||
if upscale_image:
|
||||
timage = upscale(
|
||||
timage=timage,
|
||||
device=kwargs.get("upscaler_device"),
|
||||
upscale_model_name=kwargs.get("upscale_model_name"),
|
||||
tile=kwargs.get("tile"),
|
||||
overlap=kwargs.get("overlap")
|
||||
)
|
||||
|
||||
save_image = kwargs.get("save_image")
|
||||
if save_image:
|
||||
timage = store(
|
||||
image=timage,
|
||||
filename_prefix=kwargs.get("filename_prefix"),
|
||||
subfolder=kwargs.get("subfolder"),
|
||||
filename_format=kwargs.get("filename_format"),
|
||||
image_format=kwargs.get("image_format"),
|
||||
image_quality=kwargs.get("image_quality"),
|
||||
compress_level=kwargs.get("compression_level"),
|
||||
)
|
||||
else:
|
||||
timage = preview(
|
||||
image=timage,
|
||||
filename_prefix=kwargs.get("filename_prefix"),
|
||||
)
|
||||
|
||||
return {"ui": {"images": timage}}
|
||||
@@ -1,34 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from .latent_helpers import create_empty_latent
|
||||
from ...lib.common import CommonTypes
|
||||
|
||||
ASPECT_RATIOS = ["1:1", "4:3", "3:2", "16:9", "21:9"]
|
||||
ORIENTATIONS = ["landscape", "portrait"]
|
||||
MODEL_TYPES = ["FLUX1.D", "FLUX2.D", "SDXL"]
|
||||
CLIP_MULTIPLIERS = ["1x", "2x", "4x"]
|
||||
|
||||
|
||||
class TT_LatentFactory:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff},),
|
||||
"noise_seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff},),
|
||||
"aspect_ratio": (ASPECT_RATIOS,),
|
||||
"megapixels": (CommonTypes.MEGAPIXELS,),
|
||||
"orientation": (ORIENTATIONS,),
|
||||
"model_type": (MODEL_TYPES,),
|
||||
"batch_size": ("INT", {"default": 1, "min": 1, "max": 64, "advanced": True},),
|
||||
"clip_multiplier": (CLIP_MULTIPLIERS, {"advanced": True},)
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("LATENT", "NOISE", "INT", "INT", CommonTypes.MEGAPIXELS, "INT", "INT", "INT", "INT")
|
||||
RETURN_NAMES = ("LATENT", "RANDOM_NOISE", "SEED", "NOISE_SEED", "MEGAPIXELS", "WIDTH", "HEIGHT", "TARGET_WIDTH", "TARGET_HEIGHT")
|
||||
FUNCTION = "create_latent"
|
||||
CATEGORY = "TenserTensor/Deprecated/Latent"
|
||||
|
||||
def create_latent(self, **kwargs):
|
||||
return create_empty_latent(**kwargs)
|
||||
@@ -1,89 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
import math
|
||||
|
||||
import torch
|
||||
|
||||
import comfy.sample as S
|
||||
|
||||
|
||||
class RandomNoise:
|
||||
def __init__(self, seed):
|
||||
self.seed = seed
|
||||
|
||||
def generate_noise(self, input_latent):
|
||||
latent_image = input_latent["samples"]
|
||||
batch_idx = input_latent["batch_index"] if "batch_index" in input_latent else None
|
||||
return S.prepare_noise(latent_image, self.seed, batch_idx)
|
||||
|
||||
|
||||
LATENT_DIMENSION_STEP = 64
|
||||
|
||||
|
||||
def _calculate_dimensions(total_pixels, ratio_w, ratio_h):
|
||||
height = math.sqrt(total_pixels * ratio_h / ratio_w)
|
||||
width = height * ratio_w / ratio_h
|
||||
width = int(width)
|
||||
height = int(height)
|
||||
width = round(width / LATENT_DIMENSION_STEP) * LATENT_DIMENSION_STEP
|
||||
height = round(height / LATENT_DIMENSION_STEP) * LATENT_DIMENSION_STEP
|
||||
|
||||
return width, height
|
||||
|
||||
|
||||
def create_empty_latent(seed, noise_seed, aspect_ratio, megapixels, orientation, model_type, batch_size, clip_multiplier):
|
||||
mp_value = float(megapixels.split()[0])
|
||||
total_pixels = int(mp_value * 1_000_000)
|
||||
|
||||
ratio_parts = aspect_ratio.split(':')
|
||||
ratio_w = int(ratio_parts[0])
|
||||
ratio_h = int(ratio_parts[1])
|
||||
|
||||
if orientation == "portrait":
|
||||
ratio_w, ratio_h = ratio_h, ratio_w
|
||||
|
||||
width, height = _calculate_dimensions(total_pixels, ratio_w, ratio_h)
|
||||
|
||||
multiplier = int(clip_multiplier.replace('x', ''))
|
||||
clip_width = width * multiplier
|
||||
clip_height = height * multiplier
|
||||
|
||||
match model_type:
|
||||
case "FLUX1.D":
|
||||
scale_factor, channels = 8, 16
|
||||
case "FLUX2.D":
|
||||
scale_factor, channels = 16, 128
|
||||
case "SDXL":
|
||||
scale_factor, channels = 8, 4
|
||||
|
||||
latent_width = width // scale_factor
|
||||
latent_height = height // scale_factor
|
||||
|
||||
generator = torch.Generator().manual_seed(seed)
|
||||
latent = torch.randn(
|
||||
batch_size,
|
||||
channels,
|
||||
latent_height,
|
||||
latent_width,
|
||||
generator=generator
|
||||
)
|
||||
|
||||
latent_dict = {"samples": latent}
|
||||
noise = RandomNoise(noise_seed)
|
||||
|
||||
return (latent_dict, noise, seed, noise_seed, megapixels, width, height, clip_width, clip_height,)
|
||||
|
||||
|
||||
def vae_encode(latent, image, vae):
|
||||
tile_width, tile_height, overlap = 512, 512, 64
|
||||
|
||||
samples = vae.encode_tiled(
|
||||
image,
|
||||
tile_x=tile_width,
|
||||
tile_y=tile_height,
|
||||
overlap=overlap
|
||||
)
|
||||
|
||||
latent["samples"] = samples
|
||||
|
||||
return (latent,)
|
||||
@@ -1,39 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from folder_paths import get_filename_list
|
||||
|
||||
from nodes import VAELoader
|
||||
from .loader_helpers import load_unet, load_flux_clip, load_vae
|
||||
|
||||
|
||||
class TT_FluxModelsLoader():
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"unet_name": (get_filename_list("diffusion_models"),),
|
||||
"clip_l": (get_filename_list("text_encoders"),),
|
||||
"t5xxl": (get_filename_list("text_encoders"),),
|
||||
"clip_device": (["default", "cpu"], {"advanced": True}),
|
||||
"vae_name": (VAELoader.vae_list(VAELoader),)
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("MODEL", "CLIP", "VAE",)
|
||||
RETURN_NAMES = ("MODEL", "CLIP", "VAE",)
|
||||
FUNCTION = "load_models"
|
||||
CATEGORY = "TenserTensor/Deprecated/Loaders/FLUX"
|
||||
|
||||
def load_models(
|
||||
self,
|
||||
unet_name,
|
||||
clip_l,
|
||||
t5xxl,
|
||||
clip_device,
|
||||
vae_name
|
||||
):
|
||||
model = load_unet(unet_name)
|
||||
clip = load_flux_clip(clip_l, t5xxl, clip_device)
|
||||
vae = load_vae(vae_name, "cpu", "bfloat16")
|
||||
|
||||
return (model, clip, vae,)
|
||||
@@ -1,90 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from folder_paths import get_filename_list
|
||||
|
||||
from nodes import VAELoader, MAX_RESOLUTION
|
||||
from .loader_helpers import load_unet, patch_flux_sampling, load_flux_clip, apply_lora, load_vae
|
||||
|
||||
|
||||
class TT_FluxModelsLoaderAdvanced():
|
||||
def __init__(self):
|
||||
self.loaded_lora_1 = None
|
||||
self.loaded_lora_2 = None
|
||||
self.loaded_lora_3 = None
|
||||
self.loaded_lora_4 = None
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
UNET_DTYPES = ["default", "fp8_e4m3fn", "fp8_e4m3fn_fast", "fp8_e5m2"]
|
||||
DEVICES = ["default", "cpu"]
|
||||
VAE_DTYPES = ["bfloat16", "float16", "float32"]
|
||||
|
||||
return {
|
||||
"required": {
|
||||
"unet_name": (get_filename_list("diffusion_models"),),
|
||||
"unet_dtype": (UNET_DTYPES, {"advanced": True}),
|
||||
"apply_sampling": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}),
|
||||
"base_sampling_shift": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 100.0, "step": 0.01}),
|
||||
"max_sampling_shift": ("FLOAT", {"default": 1.15, "min": 0.0, "max": 100.0, "step": 0.01}),
|
||||
"sampling_width": ("INT", {"default": 1024, "min": 16, "max": MAX_RESOLUTION, "step": 8}),
|
||||
"sampling_height": ("INT", {"default": 1024, "min": 16, "max": MAX_RESOLUTION, "step": 8}),
|
||||
"clip_l": (get_filename_list("text_encoders"),),
|
||||
"t5xxl": (get_filename_list("text_encoders"),),
|
||||
"clip_device": (["default", "cpu"], {"advanced": True}),
|
||||
"lora_name_1": (["None"] + get_filename_list("loras"),),
|
||||
"strength_1": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1}),
|
||||
"lora_name_2": (["None"] + get_filename_list("loras"),),
|
||||
"strength_2": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1}),
|
||||
"lora_name_3": (["None"] + get_filename_list("loras"),),
|
||||
"strength_3": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1}),
|
||||
"lora_name_4": (["None"] + get_filename_list("loras"),),
|
||||
"strength_4": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1}),
|
||||
"vae_name": (VAELoader.vae_list(VAELoader),),
|
||||
"vae_device": (DEVICES, {"advanced": True}),
|
||||
"vae_dtype": (VAE_DTYPES, {"advanced": True}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("MODEL", "CLIP", "VAE",)
|
||||
RETURN_NAMES = ("MODEL", "CLIP", "VAE",)
|
||||
FUNCTION = "load_models"
|
||||
CATEGORY = "TenserTensor/Deprecated/Loaders/FLUX"
|
||||
|
||||
def load_models(self, **kwargs):
|
||||
unet_name = kwargs.get("unet_name")
|
||||
apply_sampling = kwargs.get("apply_sampling")
|
||||
unet_dtype = kwargs.get("unet_dtype")
|
||||
model = load_unet(unet_name, unet_dtype)
|
||||
|
||||
if apply_sampling:
|
||||
args = {
|
||||
"model": model,
|
||||
"base_sampling_shift": kwargs.get("base_sampling_shift"),
|
||||
"max_sampling_shift": kwargs.get("max_sampling_shift"),
|
||||
"sampling_width": kwargs.get("sampling_width"),
|
||||
"sampling_height": kwargs.get("sampling_height"),
|
||||
}
|
||||
model = patch_flux_sampling(**args)
|
||||
|
||||
clip = load_flux_clip(
|
||||
clip_l=kwargs.get("clip_l"),
|
||||
t5xxl=kwargs.get("t5xxl"),
|
||||
device=kwargs.get("clip_device"),
|
||||
)
|
||||
|
||||
loras = [
|
||||
(kwargs.get("lora_name_1"), kwargs.get("strength_1"), 'loaded_lora_1'),
|
||||
(kwargs.get("lora_name_2"), kwargs.get("strength_2"), 'loaded_lora_2'),
|
||||
(kwargs.get("lora_name_3"), kwargs.get("strength_3"), 'loaded_lora_3'),
|
||||
(kwargs.get("lora_name_4"), kwargs.get("strength_4"), 'loaded_lora_4'),
|
||||
]
|
||||
|
||||
for name, strength, attr in loras:
|
||||
if name != "None" and strength != 0:
|
||||
cached = getattr(self, attr)
|
||||
model, clip, lora = apply_lora(cached, model, clip, name, strength)
|
||||
setattr(self, attr, lora)
|
||||
|
||||
vae = load_vae(kwargs.get("vae_name"), kwargs.get("vae_device"), kwargs.get("vae_dtype"))
|
||||
|
||||
return (model, clip, vae,)
|
||||
@@ -1,170 +0,0 @@
|
||||
# Contains slightly modified code by City96
|
||||
# (c) City96 || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
# Modified by TenserTensor
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
import collections as C
|
||||
import inspect as I
|
||||
import logging as LOG
|
||||
|
||||
import folder_paths as FP
|
||||
import torch
|
||||
from comfy import float as FL, lora as L, model_management as MM, model_patcher as MP, sd as SD, utils as U
|
||||
|
||||
from ...gguf.dequant import is_quantized, is_torch_compatible
|
||||
from ...gguf.loader import gguf_sd_loader, gguf_clip_loader
|
||||
from ...gguf.ops import GGMLOps, move_patch_to_device
|
||||
|
||||
WeightBackup = C.namedtuple('WeightBackup', ['weight', 'inplace_update'])
|
||||
|
||||
|
||||
class GGUFModelPatcher(MP.ModelPatcher):
|
||||
patch_on_device = False
|
||||
|
||||
def patch_weight_to_device(self, key, device_to=None, inplace_update=False):
|
||||
if key not in self.patches:
|
||||
return
|
||||
|
||||
weight = U.get_attr(self.model, key)
|
||||
|
||||
patches = self.patches[key]
|
||||
if is_quantized(weight):
|
||||
out_weight = weight.to(device_to)
|
||||
patches = move_patch_to_device(patches, self.load_device if self.patch_on_device else self.offload_device)
|
||||
# TODO: do we ever have legitimate duplicate patches? (i.e. patch on top of patched weight)
|
||||
out_weight.patches = [(patches, key)]
|
||||
else:
|
||||
inplace_update = self.weight_inplace_update or inplace_update
|
||||
if key not in self.backup:
|
||||
self.backup[key] = WeightBackup(
|
||||
weight.to(device=self.offload_device, copy=inplace_update), inplace_update
|
||||
)
|
||||
|
||||
if device_to is not None:
|
||||
temp_weight = MM.cast_to_device(weight, device_to, torch.float32, copy=True)
|
||||
else:
|
||||
temp_weight = weight.to(torch.float32, copy=True)
|
||||
|
||||
out_weight = L.calculate_weight(patches, temp_weight, key)
|
||||
out_weight = FL.stochastic_rounding(out_weight, weight.dtype)
|
||||
|
||||
if inplace_update:
|
||||
U.copy_to_param(self.model, key, out_weight)
|
||||
else:
|
||||
U.set_attr_param(self.model, key, out_weight)
|
||||
|
||||
def unpatch_model(self, device_to=None, unpatch_weights=True):
|
||||
if unpatch_weights:
|
||||
for p in self.model.parameters():
|
||||
if is_torch_compatible(p):
|
||||
continue
|
||||
patches = getattr(p, "patches", [])
|
||||
if len(patches) > 0:
|
||||
p.patches = []
|
||||
# TODO: Find another way to not unload after patches
|
||||
return super().unpatch_model(device_to=device_to, unpatch_weights=unpatch_weights)
|
||||
|
||||
|
||||
def update_folder_names_and_paths(key, targets=[]):
|
||||
base = FP.folder_names_and_paths.get(key, ([], {}))
|
||||
base = base[0] if isinstance(base[0], (list, set, tuple)) else []
|
||||
|
||||
target = next((x for x in targets if x in FP.folder_names_and_paths), targets[0])
|
||||
orig, _ = FP.folder_names_and_paths.get(target, ([], {}))
|
||||
FP.folder_names_and_paths[key] = (orig or base, {".gguf"})
|
||||
if base and base != orig:
|
||||
LOG.warning(f"Unknown file list already present on key {key}: {base}")
|
||||
|
||||
|
||||
def _get_dtype(dtype):
|
||||
match dtype:
|
||||
case None | "default":
|
||||
return None
|
||||
case "target":
|
||||
return dtype
|
||||
case _:
|
||||
return getattr(torch, dtype)
|
||||
|
||||
|
||||
def load_unet(unet_name, dequant_dtype=None, patch_dtype=None, patch_on_device=None):
|
||||
ops = GGMLOps()
|
||||
|
||||
ops.Linear.dequant_dtype = _get_dtype(dequant_dtype)
|
||||
ops.Linear.patch_dtype = _get_dtype(patch_dtype)
|
||||
|
||||
unet_path = FP.get_full_path("unet", unet_name)
|
||||
sd, extra = gguf_sd_loader(unet_path)
|
||||
|
||||
kwargs = {}
|
||||
valid_params = I.signature(SD.load_diffusion_model_state_dict).parameters
|
||||
if "metadata" in valid_params:
|
||||
kwargs["metadata"] = extra.get("metadata", {})
|
||||
|
||||
model = SD.load_diffusion_model_state_dict(
|
||||
sd, model_options={"custom_operations": ops}, **kwargs,
|
||||
)
|
||||
|
||||
if model is None:
|
||||
raise RuntimeError("ERROR: Could not detect model type of: {}".format(unet_path))
|
||||
|
||||
model = GGUFModelPatcher.clone(model)
|
||||
model.patch_on_device = patch_on_device
|
||||
|
||||
return model
|
||||
|
||||
|
||||
def get_filename_list():
|
||||
files = []
|
||||
files += FP.get_filename_list("clip")
|
||||
files += FP.get_filename_list("clip_gguf")
|
||||
return sorted(files)
|
||||
|
||||
|
||||
def _load_data(ckpt_paths):
|
||||
clip_data = []
|
||||
for p in ckpt_paths:
|
||||
if p.endswith(".gguf"):
|
||||
sd = gguf_clip_loader(p)
|
||||
else:
|
||||
sd = U.load_torch_file(p, safe_load=True)
|
||||
# NOTE: Scaled FP8 would require different custom ops, but only one can be active
|
||||
if "scaled_fp8" in sd:
|
||||
raise NotImplementedError(
|
||||
f"Mixing scaled FP8 with GGUF is not supported! Use regular CLIP loader or switch model(s)\n({p})")
|
||||
clip_data.append(sd)
|
||||
|
||||
return clip_data
|
||||
|
||||
|
||||
def _load_patcher(clip_type, clip_data):
|
||||
clip = SD.load_text_encoder_state_dicts(
|
||||
clip_type=clip_type,
|
||||
state_dicts=clip_data,
|
||||
model_options={
|
||||
"custom_operations": GGMLOps,
|
||||
"initial_device": MM.text_encoder_offload_device()
|
||||
},
|
||||
embedding_directory=FP.get_folder_paths("embeddings"),
|
||||
)
|
||||
clip.patcher = GGUFModelPatcher.clone(clip.patcher)
|
||||
|
||||
return clip
|
||||
|
||||
|
||||
def load_clip(clip_name, type="flux2"):
|
||||
clip_path = FP.get_full_path("clip", clip_name)
|
||||
clip_type = getattr(SD.CLIPType, type.upper(), SD.CLIPType.FLUX2)
|
||||
|
||||
return _load_patcher(clip_type, _load_data([clip_path]))
|
||||
|
||||
|
||||
def apply_bypass_lora_for_models(loaded_lora, model, clip, lora_name, strength):
|
||||
if loaded_lora == None:
|
||||
lora_path = FP.get_full_path_or_raise("loras", lora_name)
|
||||
lora = U.load_torch_file(lora_path, safe_load=True)
|
||||
else:
|
||||
lora = loaded_lora
|
||||
|
||||
patched_model, patched_clip = SD.load_bypass_lora_for_models(model, clip, lora, strength, strength)
|
||||
|
||||
return (patched_model, patched_clip, lora,)
|
||||
@@ -1,41 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
import folder_paths as FP
|
||||
|
||||
from nodes import VAELoader as VL
|
||||
from .gguf_loader_helpers import update_folder_names_and_paths, load_unet, load_clip
|
||||
from .loader_helpers import load_vae
|
||||
|
||||
update_folder_names_and_paths("unet_gguf", ["diffusion_models", "unet"])
|
||||
update_folder_names_and_paths("clip_gguf", ["text_encoders", "clip"])
|
||||
|
||||
|
||||
class TT_Flux2GgufModelsLoader():
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
UNET_NAMES = [x for x in FP.get_filename_list("unet_gguf")]
|
||||
CLIP_NAMES = [x for x in FP.get_filename_list("clip_gguf")]
|
||||
VAE_NAMES = [x for x in VL.vae_list(VL)]
|
||||
|
||||
return {
|
||||
"required": {
|
||||
"unet_name": (UNET_NAMES,),
|
||||
"clip_name": (CLIP_NAMES,),
|
||||
"vae_name": (VAE_NAMES,)
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("MODEL", "CLIP", "VAE",)
|
||||
RETURN_NAMES = ("MODEL", "CLIP", "VAE",)
|
||||
FUNCTION = "load_models"
|
||||
CATEGORY = "TenserTensor/Deprecated/Loaders/FLUX2 GGUF"
|
||||
|
||||
VAE_DEVICE = "cpu"
|
||||
VAE_DTYPE = "bfloat16"
|
||||
|
||||
def load_models(self, unet_name, clip_name, vae_name):
|
||||
model = load_unet(unet_name)
|
||||
clip = load_clip(clip_name)
|
||||
vae = load_vae(vae_name, self.VAE_DEVICE, self.VAE_DTYPE)
|
||||
|
||||
return (model, clip, vae,)
|
||||
@@ -1,96 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
import folder_paths as FP
|
||||
|
||||
from nodes import VAELoader as VL, MAX_RESOLUTION
|
||||
from .gguf_loader_helpers import update_folder_names_and_paths, load_unet, load_clip, apply_bypass_lora_for_models
|
||||
from .loader_helpers import load_vae, patch_flux_sampling
|
||||
|
||||
update_folder_names_and_paths("unet_gguf", ["diffusion_models", "unet"])
|
||||
update_folder_names_and_paths("clip_gguf", ["text_encoders", "clip"])
|
||||
|
||||
|
||||
class TT_Flux2GgufModelsLoaderAdvanced():
|
||||
def __init__(self):
|
||||
self.loaded_lora_1 = None
|
||||
self.loaded_lora_2 = None
|
||||
self.loaded_lora_3 = None
|
||||
self.loaded_lora_4 = None
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
UNET_NAMES = [x for x in FP.get_filename_list("unet_gguf")]
|
||||
CLIP_NAMES = [x for x in FP.get_filename_list("clip_gguf")]
|
||||
LORAS = [x for x in FP.get_filename_list("loras")]
|
||||
VAE_NAMES = [x for x in VL.vae_list(VL)]
|
||||
DTYPES = ["default", "target", "float32", "float16", "bfloat16"]
|
||||
DEVICES = ["default", "cpu"]
|
||||
VAE_DTYPES = ["bfloat16", "float16", "float32"]
|
||||
|
||||
return {
|
||||
"required": {
|
||||
"unet_name": (UNET_NAMES,),
|
||||
"dequant_dtype": (DTYPES, {"default": "bfloat16", "advanced": True},),
|
||||
"patch_dtype": (DTYPES, {"default": "bfloat16", "advanced": True},),
|
||||
"apply_sampling": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"},),
|
||||
"base_sampling_shift": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 100.0, "step": 0.01, "advanced": True},),
|
||||
"max_sampling_shift": ("FLOAT", {"default": 1.15, "min": 0.0, "max": 100.0, "step": 0.01, "advanced": True},),
|
||||
"sampling_width": ("INT", {"default": 1024, "min": 16, "max": MAX_RESOLUTION, "step": 8, "advanced": True},),
|
||||
"sampling_height": ("INT", {"default": 1024, "min": 16, "max": MAX_RESOLUTION, "step": 8, "advanced": True},),
|
||||
"lora_name_1": (["None"] + LORAS, {"advanced": True},),
|
||||
"strength_1": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1, "advanced": True},),
|
||||
"lora_name_2": (["None"] + LORAS, {"advanced": True},),
|
||||
"strength_2": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1, "advanced": True},),
|
||||
"lora_name_3": (["None"] + LORAS, {"advanced": True},),
|
||||
"strength_3": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1, "advanced": True},),
|
||||
"lora_name_4": (["None"] + LORAS, {"advanced": True},),
|
||||
"strength_4": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1, "advanced": True},),
|
||||
"clip_name": (CLIP_NAMES,),
|
||||
"vae_name": (VAE_NAMES,),
|
||||
"vae_device": (DEVICES, {"advanced": True},),
|
||||
"vae_dtype": (VAE_DTYPES, {"advanced": True},),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("MODEL", "CLIP", "VAE",)
|
||||
RETURN_NAMES = ("MODEL", "CLIP", "VAE",)
|
||||
FUNCTION = "load_models"
|
||||
CATEGORY = "TenserTensor/Deprecated/Loaders/FLUX2 GGUF"
|
||||
|
||||
def load_models(self, **kwargs):
|
||||
model = load_unet(
|
||||
kwargs.get("unet_name"),
|
||||
kwargs.get("dequant_dtype"),
|
||||
kwargs.get("patch_dtype"),
|
||||
kwargs.get("patch_on_device")
|
||||
)
|
||||
|
||||
apply_sampling = kwargs.get("apply_sampling")
|
||||
if apply_sampling:
|
||||
args = {
|
||||
"model": model,
|
||||
"base_sampling_shift": kwargs.get("base_sampling_shift"),
|
||||
"max_sampling_shift": kwargs.get("max_sampling_shift"),
|
||||
"sampling_width": kwargs.get("sampling_width"),
|
||||
"sampling_height": kwargs.get("sampling_height"),
|
||||
}
|
||||
model = patch_flux_sampling(**args)
|
||||
|
||||
clip = load_clip(kwargs.get("clip_name"))
|
||||
|
||||
loras = [
|
||||
(kwargs.get("lora_name_1"), kwargs.get("strength_1"), 'loaded_lora_1'),
|
||||
(kwargs.get("lora_name_2"), kwargs.get("strength_2"), 'loaded_lora_2'),
|
||||
(kwargs.get("lora_name_3"), kwargs.get("strength_3"), 'loaded_lora_3'),
|
||||
(kwargs.get("lora_name_4"), kwargs.get("strength_4"), 'loaded_lora_4'),
|
||||
]
|
||||
|
||||
for name, strength, attr in loras:
|
||||
if name != "None" and strength != 0:
|
||||
cached = getattr(self, attr)
|
||||
model, clip, lora = apply_bypass_lora_for_models(cached, model, clip, name, strength)
|
||||
setattr(self, attr, lora)
|
||||
|
||||
vae = load_vae(kwargs.get("vae_name"), kwargs.get("vae_device"), kwargs.get("vae_dtype"))
|
||||
|
||||
return (model, clip, vae,)
|
||||
@@ -1,140 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
import os
|
||||
|
||||
import folder_paths as FP
|
||||
from comfy import model_management as MM, model_sampling as MS, sd as SD, utils as U
|
||||
from torch import bfloat16, float16, float32, float8_e4m3fn, float8_e5m2, device, tensor
|
||||
|
||||
from nodes import VAELoader as VL
|
||||
|
||||
VIDEO_TAES = ["taehv", "lighttaew2_2", "lighttaew2_1", "lighttaehy1_5"]
|
||||
IMAGE_TAES = ["taesd", "taesdxl", "taesd3", "taef1"]
|
||||
|
||||
|
||||
def load_checkpoint(ckpt_name):
|
||||
ckpt_path = FP.get_full_path_or_raise("checkpoints", ckpt_name)
|
||||
return SD.load_checkpoint_guess_config(
|
||||
ckpt_path, output_vae=False, output_clip=False,
|
||||
embedding_directory=FP.get_folder_paths("embeddings")
|
||||
)
|
||||
|
||||
|
||||
def load_unet(unet_name, unet_dtype="default"):
|
||||
unet_path = FP.get_full_path_or_raise("diffusion_models", unet_name)
|
||||
|
||||
model_options = {}
|
||||
match unet_dtype:
|
||||
case "fp8_e4m3fn":
|
||||
model_options["dtype"] = float8_e4m3fn
|
||||
case "fp8_e4m3fn_fast":
|
||||
model_options["dtype"] = float8_e4m3fn
|
||||
model_options["fp8_optimizations"] = True
|
||||
case "fp8_e5m2":
|
||||
model_options["dtype"] = float8_e5m2
|
||||
case _:
|
||||
pass
|
||||
|
||||
return SD.load_diffusion_model(
|
||||
unet_path,
|
||||
model_options=model_options
|
||||
)
|
||||
|
||||
|
||||
TORCH_DEVICE_CPU = "cpu"
|
||||
|
||||
|
||||
def _load_clip(clip_type, clip_paths, torch_device=TORCH_DEVICE_CPU):
|
||||
model_options = {}
|
||||
if torch_device == TORCH_DEVICE_CPU:
|
||||
model_options["load_device"] = model_options["offload_device"] = device(TORCH_DEVICE_CPU)
|
||||
|
||||
return SD.load_clip(
|
||||
ckpt_paths=clip_paths,
|
||||
embedding_directory=FP.get_folder_paths("embeddings"),
|
||||
clip_type=clip_type,
|
||||
model_options=model_options
|
||||
)
|
||||
|
||||
|
||||
def load_sdxl_clip(clip_l, clip_g, device):
|
||||
clip_type = getattr(SD.CLIPType, "SDXL", SD.CLIPType.STABLE_DIFFUSION)
|
||||
clip_l_path = FP.get_full_path_or_raise("text_encoders", clip_l)
|
||||
clip_g_path = FP.get_full_path_or_raise("text_encoders", clip_g)
|
||||
clip_paths = [clip_l_path, clip_g_path]
|
||||
|
||||
return _load_clip(clip_type, clip_paths, device)
|
||||
|
||||
|
||||
def load_flux_clip(clip_l, t5xxl, device):
|
||||
clip_type = SD.CLIPType.FLUX
|
||||
clip_l_path = FP.get_full_path_or_raise("text_encoders", clip_l)
|
||||
t5xxl_path = FP.get_full_path_or_raise("text_encoders", t5xxl)
|
||||
clip_paths = [clip_l_path, t5xxl_path]
|
||||
|
||||
return _load_clip(clip_type, clip_paths, device)
|
||||
|
||||
|
||||
def apply_lora(loaded_lora, model, clip, lora_name, strength):
|
||||
if loaded_lora == None:
|
||||
lora_path = FP.get_full_path_or_raise("loras", lora_name)
|
||||
lora = U.load_torch_file(lora_path, safe_load=True)
|
||||
else:
|
||||
lora = loaded_lora
|
||||
|
||||
patched_model, patched_clip = SD.load_lora_for_models(model, clip, lora, strength, strength)
|
||||
|
||||
return (patched_model, patched_clip, lora)
|
||||
|
||||
|
||||
def load_vae(vae_name, vae_device="default", vae_dtype="bfloat16"):
|
||||
dtype = {"bfloat16": bfloat16, "float16": float16, "float32": float32}[vae_dtype]
|
||||
|
||||
torch_device = None
|
||||
if vae_device == "default":
|
||||
torch_device = MM.get_torch_device()
|
||||
elif vae_device == TORCH_DEVICE_CPU:
|
||||
torch_device = device(TORCH_DEVICE_CPU)
|
||||
|
||||
metadata = None
|
||||
if vae_name == "pixel_space":
|
||||
sd = {}
|
||||
sd["pixel_space_vae"] = tensor(1.0)
|
||||
|
||||
elif vae_name in IMAGE_TAES:
|
||||
sd = VL.load_taesd(vae_name)
|
||||
|
||||
else:
|
||||
if os.path.splitext(vae_name)[0] in VIDEO_TAES:
|
||||
vae_path = FP.get_full_path_or_raise("vae_approx", vae_name)
|
||||
else:
|
||||
vae_path = FP.get_full_path_or_raise("vae", vae_name)
|
||||
sd, metadata = U.load_torch_file(vae_path, return_metadata=True)
|
||||
|
||||
vae = SD.VAE(sd=sd, device=torch_device, dtype=dtype, metadata=metadata)
|
||||
vae.throw_exception_if_invalid()
|
||||
|
||||
return vae
|
||||
|
||||
|
||||
MIN_SAMPLING_RES = 256
|
||||
MAX_SAMPLING_RES = 4096
|
||||
|
||||
|
||||
class ModelSamplingFluxAdvanced(MS.ModelSamplingFlux, MS.CONST):
|
||||
pass
|
||||
|
||||
|
||||
def patch_flux_sampling(model, base_sampling_shift, max_sampling_shift, sampling_width, sampling_height):
|
||||
tmodel = model.clone()
|
||||
|
||||
slope = (max_sampling_shift - base_sampling_shift) / (MAX_SAMPLING_RES - MIN_SAMPLING_RES)
|
||||
intercept = base_sampling_shift - slope * MIN_SAMPLING_RES
|
||||
current_res = (sampling_width * sampling_height / (8 * 8 * 2 * 2))
|
||||
shift = current_res * slope + intercept
|
||||
|
||||
model_sampling = ModelSamplingFluxAdvanced(model.model.model_config)
|
||||
model_sampling.set_parameters(shift=shift)
|
||||
tmodel.add_object_patch("model_sampling", model_sampling)
|
||||
|
||||
return tmodel
|
||||
@@ -1,43 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
import folder_paths
|
||||
|
||||
from nodes import VAELoader
|
||||
from .loader_helpers import load_checkpoint, load_sdxl_clip, load_vae
|
||||
|
||||
|
||||
class TT_SdxlModelsLoader:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"primary_ckpt": (folder_paths.get_filename_list("checkpoints"),),
|
||||
"secondary_ckpt": (["None"] + folder_paths.get_filename_list("checkpoints"),),
|
||||
"primary_weight": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"clip_l": (folder_paths.get_filename_list("text_encoders"),),
|
||||
"clip_g": (folder_paths.get_filename_list("text_encoders"),),
|
||||
"clip_device": (["default", "cpu"], {"advanced": True}),
|
||||
"vae_name": (VAELoader.vae_list(VAELoader),)
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("MODEL", "CLIP", "VAE",)
|
||||
RETURN_NAMES = ("MODEL", "CLIP", "VAE",)
|
||||
FUNCTION = "load_models"
|
||||
CATEGORY = "TenserTensor/Deprecated/Loaders/SDXL"
|
||||
|
||||
def load_models(self, primary_ckpt, secondary_ckpt, primary_weight, clip_l, clip_g, clip_device, vae_name):
|
||||
model = load_checkpoint(primary_ckpt)[0]
|
||||
|
||||
if secondary_ckpt != "None":
|
||||
secondary_model = load_checkpoint(secondary_ckpt)[0]
|
||||
model = model.clone()
|
||||
key_patches = secondary_model.get_key_patches("diffusion_model.")
|
||||
for key in key_patches:
|
||||
model.add_patches({key: key_patches[key]}, 1.0 - primary_weight, primary_weight)
|
||||
|
||||
clip = load_sdxl_clip(clip_l, clip_g, clip_device)
|
||||
|
||||
vae = load_vae(vae_name, "cpu", "bfloat16")
|
||||
|
||||
return (model, clip, vae,)
|
||||
@@ -1,78 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
import folder_paths
|
||||
|
||||
from nodes import VAELoader
|
||||
from .loader_helpers import load_checkpoint, load_sdxl_clip, apply_lora, load_vae
|
||||
|
||||
|
||||
class TT_SdxlModelsLoaderAdvanced:
|
||||
def __init__(self):
|
||||
self.loaded_lora_1 = None
|
||||
self.loaded_lora_2 = None
|
||||
self.loaded_lora_3 = None
|
||||
self.loaded_lora_4 = None
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
DEVICES = ["default", "cpu"]
|
||||
DTYPES = ["bfloat16", "float16", "float32"]
|
||||
|
||||
return {
|
||||
"required": {
|
||||
"primary_ckpt": (folder_paths.get_filename_list("checkpoints"),),
|
||||
"secondary_ckpt": (["None"] + folder_paths.get_filename_list("checkpoints"),),
|
||||
"primary_weight": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"clip_l": (folder_paths.get_filename_list("text_encoders"),),
|
||||
"clip_g": (folder_paths.get_filename_list("text_encoders"),),
|
||||
"clip_device": (DEVICES, {"advanced": True}),
|
||||
"lora_name_1": (["None"] + folder_paths.get_filename_list("loras"),),
|
||||
"strength_1": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1}),
|
||||
"lora_name_2": (["None"] + folder_paths.get_filename_list("loras"),),
|
||||
"strength_2": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1}),
|
||||
"lora_name_3": (["None"] + folder_paths.get_filename_list("loras"),),
|
||||
"strength_3": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1}),
|
||||
"lora_name_4": (["None"] + folder_paths.get_filename_list("loras"),),
|
||||
"strength_4": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.1}),
|
||||
"vae_name": (VAELoader.vae_list(VAELoader),),
|
||||
"vae_device": (DEVICES, {"advanced": True}),
|
||||
"vae_dtype": (DTYPES, {"advanced": True}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("MODEL", "CLIP", "VAE",)
|
||||
RETURN_NAMES = ("MODEL", "CLIP", "VAE",)
|
||||
FUNCTION = "load_models"
|
||||
CATEGORY = "TenserTensor/Deprecated/Loaders/SDXL"
|
||||
|
||||
def load_models(self, primary_ckpt, secondary_ckpt, primary_weight, clip_l, clip_g, clip_device,
|
||||
lora_name_1, strength_1, lora_name_2, strength_2, lora_name_3, strength_3, lora_name_4, strength_4,
|
||||
vae_name, vae_device, vae_dtype):
|
||||
|
||||
model = load_checkpoint(primary_ckpt)[0]
|
||||
|
||||
if secondary_ckpt != "None":
|
||||
secondary_model = load_checkpoint(secondary_ckpt)[0]
|
||||
model = model.clone()
|
||||
key_patches = secondary_model.get_key_patches("diffusion_model.")
|
||||
for key in key_patches:
|
||||
model.add_patches({key: key_patches[key]}, 1.0 - primary_weight, primary_weight)
|
||||
|
||||
clip = load_sdxl_clip(clip_l, clip_g, clip_device)
|
||||
|
||||
loras = [
|
||||
(lora_name_1, strength_1, 'loaded_lora_1'),
|
||||
(lora_name_2, strength_2, 'loaded_lora_2'),
|
||||
(lora_name_3, strength_3, 'loaded_lora_3'),
|
||||
(lora_name_4, strength_4, 'loaded_lora_4'),
|
||||
]
|
||||
|
||||
for name, strength, attr in loras:
|
||||
if name != "None" and strength != 0:
|
||||
cached = getattr(self, attr)
|
||||
model, clip, lora = apply_lora(cached, model, clip, name, strength)
|
||||
setattr(self, attr, lora)
|
||||
|
||||
vae = load_vae(vae_name, vae_device, vae_dtype)
|
||||
|
||||
return (model, clip, vae,)
|
||||
@@ -1,39 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from .postproduction_helpers import apply_film_grain
|
||||
|
||||
|
||||
class TT_AddFilmGrain():
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
UPSCALE_MODES = ["bilinear", "bicubic", "lanczos", "nearest", "area"]
|
||||
|
||||
return {
|
||||
"required": {
|
||||
"image": ("IMAGE",),
|
||||
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
||||
"scale": ("FLOAT", {"default": 0.25, "min": 0.25, "max": 2.0, "step": 0.05}),
|
||||
"strength": ("FLOAT", {"default": 0.15, "min": 0.0, "max": 10.0, "step": 0.01}),
|
||||
"saturation": ("FLOAT", {"default": 0.2, "min": 0.0, "max": 2.0, "step": 0.01}),
|
||||
"toe": ("FLOAT", {"default": 0.0, "min": -0.2, "max": 0.5, "step": 0.001}),
|
||||
"upscale_mode": (UPSCALE_MODES, {"advanced": True}),
|
||||
"antialias": ("BOOLEAN", {"default": False, "label_on": "Enabled", "label_off": "Disabled"}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
RETURN_NAMES = ("IMAGE",)
|
||||
FUNCTION = "apply_film_grain"
|
||||
CATEGORY = "TenserTensor/Deprecated/Postproduction"
|
||||
|
||||
def apply_film_grain(self, **kwargs):
|
||||
return (apply_film_grain(
|
||||
image=kwargs.get("image").clone(),
|
||||
seed=kwargs.get("seed"),
|
||||
scale=kwargs.get("scale"),
|
||||
strength=kwargs.get("strength"),
|
||||
saturation=kwargs.get("saturation"),
|
||||
toe=kwargs.get("toe"),
|
||||
mode=kwargs.get("upscale_mode"),
|
||||
antialias=kwargs.get("antialias"),
|
||||
),)
|
||||
@@ -1,37 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from .postproduction_helpers import get_lut_files_list, color_correction
|
||||
|
||||
|
||||
class TT_ApplyLut:
|
||||
LUT_DIR = None
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
cls.LUT_DIR, LUT_FILES = get_lut_files_list()
|
||||
COLORSPACES = ["linear", "logarithmic"]
|
||||
|
||||
return {
|
||||
"required": {
|
||||
"image": ("IMAGE",),
|
||||
"lut_file": (LUT_FILES, {"advanced": True}),
|
||||
"strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"colorspace": (COLORSPACES, {"advanced": True}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
RETURN_NAMES = ("IMAGE",)
|
||||
FUNCTION = "apply_lut"
|
||||
CATEGORY = "TenserTensor/Deprecated/Postproduction"
|
||||
|
||||
def apply_lut(self, image, lut_file, strength, colorspace):
|
||||
return (
|
||||
color_correction(
|
||||
image.clone(),
|
||||
TT_ApplyLut.LUT_DIR,
|
||||
lut_file,
|
||||
strength,
|
||||
colorspace
|
||||
),
|
||||
)
|
||||
@@ -1,57 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from .postproduction_helpers import enhance_image
|
||||
|
||||
|
||||
class TT_ImageEnhancer():
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"image": ("IMAGE",),
|
||||
"brightness_factor": ("FLOAT", {"default": 0.0, "min": -1.0, "max": 1.0, "step": 0.01}),
|
||||
"contrast_factor": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 5.0, "step": 0.01}),
|
||||
"gamma_factor": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 3.0, "step": 0.01}),
|
||||
"gamma_gain": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 3.0, "step": 0.01}),
|
||||
"hue_factor": ("FLOAT", {"default": 0.0, "min": -3.14, "max": 3.14, "step": 0.01}),
|
||||
"saturation_factor": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 3.0, "step": 0.01}),
|
||||
"sharpness_factor": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 3.0, "step": 0.01}),
|
||||
"posterize_bits": ("INT", {"default": 8, "min": 0, "max": 8}),
|
||||
"solarize_thresholds": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
RETURN_NAMES = ("IMAGE",)
|
||||
FUNCTION = "enhance_image"
|
||||
CATEGORY = "TenserTensor/Deprecated/Postproduction"
|
||||
|
||||
def enhance_image(
|
||||
self,
|
||||
image,
|
||||
brightness_factor,
|
||||
contrast_factor,
|
||||
gamma_factor,
|
||||
gamma_gain,
|
||||
hue_factor,
|
||||
saturation_factor,
|
||||
sharpness_factor,
|
||||
posterize_bits,
|
||||
solarize_thresholds
|
||||
):
|
||||
timage = image.clone()
|
||||
|
||||
timage = enhance_image(
|
||||
timage,
|
||||
brightness_factor,
|
||||
contrast_factor,
|
||||
gamma_factor,
|
||||
gamma_gain,
|
||||
hue_factor,
|
||||
saturation_factor,
|
||||
sharpness_factor,
|
||||
posterize_bits,
|
||||
solarize_thresholds
|
||||
)
|
||||
|
||||
return (timage,)
|
||||
@@ -1,86 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from folder_paths import get_filename_list
|
||||
|
||||
from .postproduction_helpers import get_lut_files_list, color_correction, apply_film_grain, upscale_image
|
||||
|
||||
|
||||
class TT_Postproduction():
|
||||
LUT_DIR = None
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
cls.LUT_DIR, LUT_FILES = get_lut_files_list()
|
||||
COLORSPACES = ["linear", "logarithmic"]
|
||||
UPSCALE_MODES = ["bilinear", "bicubic", "lanczos", "nearest", "area"]
|
||||
UPSCALE_MODELS = get_filename_list("upscale_models")
|
||||
DEVICES = ["default", "cpu"]
|
||||
|
||||
return {
|
||||
"required": {
|
||||
"image": ("IMAGE",),
|
||||
"apply_lut": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}),
|
||||
"lut_file": (LUT_FILES, {"advanced": True}),
|
||||
"lut_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"lut_colorspace": (COLORSPACES, {"advanced": True}),
|
||||
"add_film_grain": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}),
|
||||
"grain_seed": (
|
||||
"INT",
|
||||
{"default": 0, "min": 0, "max": 0xffffffffffffffff, "control_after_generate": True}
|
||||
),
|
||||
"grain_scale": ("FLOAT", {"default": 0.25, "min": 0.25, "max": 2.0, "step": 0.05}),
|
||||
"grain_strength": ("FLOAT", {"default": 0.2, "min": 0.0, "max": 10.0, "step": 0.01}),
|
||||
"grain_saturation": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 2.0, "step": 0.01}),
|
||||
"grain_toe": ("FLOAT", {"default": 0.05, "min": -0.2, "max": 0.5, "step": 0.01}),
|
||||
"grain_upscale_mode": (UPSCALE_MODES, {"advanced": True}),
|
||||
"grain_antialias": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}),
|
||||
"image_upscaler": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}),
|
||||
"upscaler_device": (DEVICES, {"advanced": True}),
|
||||
"upscale_model_name": (UPSCALE_MODELS, {"advanced": True}),
|
||||
"upscaler_tile": ("INT", {"default": 512, "min": 256, "max": 4096, "step": 64}),
|
||||
"upscaler_overlap": ("INT", {"default": 64, "min": 0, "max": 256, "step": 8}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
RETURN_NAMES = ("IMAGE",)
|
||||
FUNCTION = "apply_postprocessing"
|
||||
CATEGORY = "TenserTensor/Deprecated/Postproduction"
|
||||
|
||||
def apply_postprocessing(self, **kwargs):
|
||||
image = kwargs.get("image").clone()
|
||||
|
||||
apply_lut = kwargs.get("apply_lut")
|
||||
if apply_lut:
|
||||
image = color_correction(
|
||||
image=image,
|
||||
lut_dir=TT_Postproduction.LUT_DIR,
|
||||
lut_file=kwargs.get("lut_file"),
|
||||
strength=kwargs.get("lut_strength"),
|
||||
colorspace=kwargs.get("lut_colorspace")
|
||||
)
|
||||
|
||||
add_film_grain = kwargs.get("add_film_grain")
|
||||
if add_film_grain:
|
||||
image = apply_film_grain(
|
||||
image=image,
|
||||
seed=kwargs.get("grain_seed"),
|
||||
scale=kwargs.get("grain_scale"),
|
||||
strength=kwargs.get("grain_strength"),
|
||||
saturation=kwargs.get("grain_saturation"),
|
||||
toe=kwargs.get("grain_toe"),
|
||||
mode=kwargs.get("grain_upscale_mode"),
|
||||
antialias=kwargs.get("grain_antialias")
|
||||
)
|
||||
|
||||
image_upscaler = kwargs.get("image_upscaler")
|
||||
if image_upscaler:
|
||||
image = upscale_image(
|
||||
timage=image,
|
||||
device=kwargs.get("upscaler_device"),
|
||||
upscale_model_name=kwargs.get("upscale_model_name"),
|
||||
tile=kwargs.get("upscaler_tile"),
|
||||
overlap=kwargs.get("upscaler_overlap"),
|
||||
)
|
||||
|
||||
return (image,)
|
||||
@@ -1,111 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from folder_paths import get_filename_list
|
||||
|
||||
from .postproduction_helpers import get_lut_files_list, color_correction, apply_film_grain, upscale_image, enhance_image
|
||||
|
||||
|
||||
class TT_PostproductionAdvanced():
|
||||
LUT_DIR = None
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
cls.LUT_DIR, LUT_FILES = get_lut_files_list()
|
||||
COLORSPACES = ["linear", "logarithmic"]
|
||||
UPSCALE_MODES = ["bilinear", "bicubic", "lanczos", "nearest", "area"]
|
||||
UPSCALE_MODELS = get_filename_list("upscale_models")
|
||||
DEVICES = ["default", "cpu"]
|
||||
|
||||
return {
|
||||
"required": {
|
||||
"image": ("IMAGE",),
|
||||
"image_enhancer": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}),
|
||||
"brightness_factor": ("FLOAT", {"default": 0.0, "min": -1.0, "max": 1.0, "step": 0.01}),
|
||||
"contrast_factor": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 5.0, "step": 0.01}),
|
||||
"gamma_factor": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 3.0, "step": 0.01}),
|
||||
"gamma_gain": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 3.0, "step": 0.01}),
|
||||
"hue_factor": ("FLOAT", {"default": 0.0, "min": -3.14, "max": 3.14, "step": 0.01}),
|
||||
"saturation_factor": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 3.0, "step": 0.01}),
|
||||
"sharpness_factor": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 3.0, "step": 0.01}),
|
||||
"posterize_bits": ("INT", {"default": 8, "min": 0, "max": 8}),
|
||||
"solarize_thresholds": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"apply_lut": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}),
|
||||
"lut_file": (LUT_FILES, {"advanced": True}),
|
||||
"lut_strength": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"lut_colorspace": (COLORSPACES, {"advanced": True}),
|
||||
"add_film_grain": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}),
|
||||
"grain_seed": (
|
||||
"INT",
|
||||
{"default": 0, "min": 0, "max": 0xffffffffffffffff, "control_after_generate": True}
|
||||
),
|
||||
"grain_scale": ("FLOAT", {"default": 0.25, "min": 0.25, "max": 2.0, "step": 0.05}),
|
||||
"grain_strength": ("FLOAT", {"default": 0.2, "min": 0.0, "max": 10.0, "step": 0.01}),
|
||||
"grain_saturation": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 2.0, "step": 0.01}),
|
||||
"grain_toe": ("FLOAT", {"default": 0.05, "min": -0.2, "max": 0.5, "step": 0.01}),
|
||||
"grain_upscale_mode": (UPSCALE_MODES, {"advanced": True}),
|
||||
"grain_antialias": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}),
|
||||
"image_upscaler": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}),
|
||||
"upscaler_device": (DEVICES, {"advanced": True}),
|
||||
"upscale_model_name": (UPSCALE_MODELS, {"advanced": True}),
|
||||
"upscaler_tile": ("INT", {"default": 512, "min": 256, "max": 4096, "step": 64}),
|
||||
"upscaler_overlap": ("INT", {"default": 64, "min": 0, "max": 256, "step": 8}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
RETURN_NAMES = ("IMAGE",)
|
||||
FUNCTION = "apply_postprocessing"
|
||||
CATEGORY = "TenserTensor/Deprecated/Postproduction"
|
||||
|
||||
def apply_postprocessing(self, **kwargs):
|
||||
image = kwargs.get("image").clone()
|
||||
|
||||
image_enhancer = kwargs.get("image_enhancer")
|
||||
if image_enhancer:
|
||||
image = enhance_image(
|
||||
timage=image,
|
||||
brightness_factor=kwargs.get("brightness_factor"),
|
||||
contrast_factor=kwargs.get("contrast_factor"),
|
||||
gamma_factor=kwargs.get("gamma_factor"),
|
||||
gamma_gain=kwargs.get("gamma_gain"),
|
||||
hue_factor=kwargs.get("hue_factor"),
|
||||
saturation_factor=kwargs.get("saturation_factor"),
|
||||
sharpness_factor=kwargs.get("sharpness_factor"),
|
||||
posterize_bits=kwargs.get("posterize_bits"),
|
||||
solarize_thresholds=kwargs.get("solarize_thresholds")
|
||||
)
|
||||
|
||||
apply_lut = kwargs.get("apply_lut")
|
||||
if apply_lut:
|
||||
image = color_correction(
|
||||
image=image,
|
||||
lut_dir=TT_PostproductionAdvanced.LUT_DIR,
|
||||
lut_file=kwargs.get("lut_file"),
|
||||
strength=kwargs.get("lut_strength"),
|
||||
colorspace=kwargs.get("lut_colorspace")
|
||||
)
|
||||
|
||||
add_film_grain = kwargs.get("add_film_grain")
|
||||
if add_film_grain:
|
||||
image = apply_film_grain(
|
||||
image=image,
|
||||
seed=kwargs.get("grain_seed"),
|
||||
scale=kwargs.get("grain_scale"),
|
||||
strength=kwargs.get("grain_strength"),
|
||||
saturation=kwargs.get("grain_saturation"),
|
||||
toe=kwargs.get("grain_toe"),
|
||||
mode=kwargs.get("grain_upscale_mode"),
|
||||
antialias=kwargs.get("grain_antialias")
|
||||
)
|
||||
|
||||
image_upscaler = kwargs.get("image_upscaler")
|
||||
if image_upscaler:
|
||||
image = upscale_image(
|
||||
timage=image,
|
||||
device=kwargs.get("upscaler_device"),
|
||||
upscale_model_name=kwargs.get("upscale_model_name"),
|
||||
tile=kwargs.get("upscaler_tile"),
|
||||
overlap=kwargs.get("upscaler_overlap"),
|
||||
)
|
||||
|
||||
return (image,)
|
||||
@@ -1,236 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import colour
|
||||
import comfy.utils as U
|
||||
import kornia
|
||||
import torch
|
||||
import torch.nn.functional as F
|
||||
from comfy import model_management
|
||||
from folder_paths import get_folder_paths, get_filename_list, get_full_path_or_raise
|
||||
from spandrel import ModelLoader, ImageModelDescriptor
|
||||
|
||||
|
||||
def get_lut_files_list():
|
||||
base = get_folder_paths("custom_nodes")[0]
|
||||
lut_dir = Path(base) / "ComfyUI-TenserTensor" / "lut"
|
||||
|
||||
if not lut_dir.is_dir():
|
||||
raise FileNotFoundError(f"lut dir not found: {lut_dir}")
|
||||
|
||||
files = [file.name for file in lut_dir.glob("*.cube")]
|
||||
|
||||
return lut_dir, sorted(files)
|
||||
|
||||
|
||||
def color_correction(image, lut_dir, lut_file, strength, colorspace):
|
||||
is_log = colorspace == "logarithmic"
|
||||
device, dtype = image.device, image.dtype
|
||||
image = image.detach().cpu().numpy()
|
||||
retval = image.copy()
|
||||
if is_log:
|
||||
retval **= 1 / 2.2
|
||||
retval = colour.read_LUT(str(lut_dir / lut_file)).apply(retval)
|
||||
if is_log:
|
||||
retval **= 2.2
|
||||
if strength < 1.0:
|
||||
retval = strength * retval + (1 - strength) * image
|
||||
|
||||
return torch.from_numpy(retval).to(device, dtype)
|
||||
|
||||
|
||||
def apply_film_grain(image, seed, scale, strength, saturation, toe, mode, antialias):
|
||||
batch, height, width, channels = image.shape
|
||||
image = image.detach()
|
||||
if seed is not None:
|
||||
torch.manual_seed(seed)
|
||||
grain = torch.rand(batch, int(height // scale), int(width // scale), 3)
|
||||
ycbcr = kornia.color.rgb_to_ycbcr(grain.movedim(-1, 1)).movedim(1, -1)
|
||||
|
||||
for idx, ksize in enumerate([3, 15, 11]):
|
||||
sigma = (ksize / 3.0,) * 2
|
||||
kernel_size = (ksize,) * 2
|
||||
channel = ycbcr[..., idx:idx + 1].movedim(-1, 1)
|
||||
ycbcr[..., idx] = kornia.filters.gaussian_blur2d(
|
||||
channel,
|
||||
kernel_size=kernel_size,
|
||||
sigma=sigma,
|
||||
border_type='reflect'
|
||||
).movedim(1, -1).squeeze(-1)
|
||||
|
||||
grain = (kornia.color.ycbcr_to_rgb(ycbcr.movedim(-1, 1)).movedim(1, -1) - 0.5) * strength
|
||||
grain[..., 0] *= 2
|
||||
grain[..., 2] *= 3
|
||||
grain += 1
|
||||
|
||||
mono = grain[..., 1:2].expand(-1, -1, -1, 3)
|
||||
grain = grain * saturation + mono * (1 - saturation)
|
||||
|
||||
grain = F.interpolate(
|
||||
grain.movedim(-1, 1),
|
||||
size=(height, width),
|
||||
mode=mode,
|
||||
antialias=antialias if mode in ['bilinear', 'bicubic'] else False
|
||||
).movedim(1, -1)
|
||||
|
||||
base = image[..., :3]
|
||||
shadow_lift = 1 - toe
|
||||
image[..., :3] = torch.clip(
|
||||
(1 - (1 - base) * grain) * shadow_lift + toe,
|
||||
0.0, 1.0
|
||||
)
|
||||
|
||||
return image
|
||||
|
||||
|
||||
def _load_upscale_model(upscale_model_name):
|
||||
model_path = get_full_path_or_raise("upscale_models", upscale_model_name)
|
||||
|
||||
try:
|
||||
state_dict = U.load_torch_file(model_path, safe_load=True)
|
||||
except Exception as e:
|
||||
raise RuntimeError(f"Failed to load model file {model_path}: {e}")
|
||||
|
||||
state_dict = U.state_dict_prefix_replace(state_dict, {"module.": ""})
|
||||
upscale_model = ModelLoader().load_from_state_dict(state_dict).eval()
|
||||
|
||||
if not isinstance(upscale_model, ImageModelDescriptor):
|
||||
raise TypeError(f"Expected ImageModelDescriptor, got {type(upscale_model).__name__}")
|
||||
|
||||
return upscale_model
|
||||
|
||||
|
||||
def upscale_image(timage, device, upscale_model_name, tile, overlap):
|
||||
upscale_device = model_management.get_torch_device() if device == "default" else torch.device("cpu")
|
||||
upscale_model = _load_upscale_model(upscale_model_name)
|
||||
|
||||
iimage = timage.movedim(-1, 1).to(upscale_device)
|
||||
batch, channels, height, width = iimage.shape
|
||||
|
||||
BUFFER_FACTOR = 384.0
|
||||
|
||||
model_mem = model_management.module_size(upscale_model.model)
|
||||
tile_mem = (tile * tile * 3) * iimage.element_size() * max(upscale_model.scale, 1) * BUFFER_FACTOR
|
||||
total_mem = model_mem + tile_mem + iimage.nelement() * iimage.element_size()
|
||||
model_management.free_memory(total_mem, upscale_device)
|
||||
upscale_model.to(upscale_device)
|
||||
|
||||
try:
|
||||
while True:
|
||||
try:
|
||||
steps = batch * U.get_tiled_scale_steps(
|
||||
width,
|
||||
height,
|
||||
tile_x=tile,
|
||||
tile_y=tile,
|
||||
overlap=overlap
|
||||
)
|
||||
pbar = U.ProgressBar(steps)
|
||||
simage = U.tiled_scale(
|
||||
iimage,
|
||||
upscale_model,
|
||||
tile_x=tile,
|
||||
tile_y=tile,
|
||||
overlap=overlap,
|
||||
upscale_amount=upscale_model.scale,
|
||||
pbar=pbar
|
||||
)
|
||||
break
|
||||
except model_management.OOM_EXCEPTION as e:
|
||||
pbar = None
|
||||
tile //= 2
|
||||
if tile < 128:
|
||||
raise e
|
||||
finally:
|
||||
if upscale_device.type != "cpu":
|
||||
upscale_model.to("cpu")
|
||||
|
||||
return torch.clamp(simage.movedim(1, -1), min=0.0, max=1.0)
|
||||
|
||||
|
||||
def adjust_brightness(image, factor, clip_output=True):
|
||||
timage = image.movedim(-1, 1)
|
||||
|
||||
return kornia.enhance.adjust_brightness(timage, factor, clip_output).movedim(1, -1)
|
||||
|
||||
|
||||
def adjust_contrast(image, factor, clip_output=True):
|
||||
timage = image.movedim(-1, 1)
|
||||
|
||||
return kornia.enhance.adjust_contrast(timage, factor, clip_output).movedim(1, -1)
|
||||
|
||||
|
||||
def adjust_gamma(image, gamma, gain=1.0):
|
||||
timage = image.movedim(-1, 1)
|
||||
|
||||
return kornia.enhance.adjust_gamma(timage, gamma, gain).movedim(1, -1)
|
||||
|
||||
|
||||
def adjust_hue(image, factor):
|
||||
timage = image.movedim(-1, 1)
|
||||
|
||||
return kornia.enhance.adjust_hue(timage, factor).movedim(1, -1)
|
||||
|
||||
|
||||
def adjust_saturation(image, factor):
|
||||
timage = image.movedim(-1, 1)
|
||||
|
||||
return kornia.enhance.adjust_saturation(timage, factor).movedim(1, -1)
|
||||
|
||||
|
||||
def sharpness(image, factor):
|
||||
timage = image.movedim(-1, 1)
|
||||
|
||||
return kornia.enhance.sharpness(timage, factor).movedim(1, -1)
|
||||
|
||||
|
||||
def posterize(image, bits):
|
||||
timage = image.movedim(-1, 1)
|
||||
|
||||
return kornia.enhance.posterize(timage, bits).movedim(1, -1)
|
||||
|
||||
|
||||
def solarize(image, thresholds=0.5, additions=None):
|
||||
timage = image.movedim(-1, 1)
|
||||
|
||||
return kornia.enhance.solarize(timage, thresholds, additions).movedim(1, -1)
|
||||
|
||||
|
||||
def enhance_image(
|
||||
timage,
|
||||
brightness_factor,
|
||||
contrast_factor,
|
||||
gamma_factor,
|
||||
gamma_gain,
|
||||
hue_factor,
|
||||
saturation_factor,
|
||||
sharpness_factor,
|
||||
posterize_bits,
|
||||
solarize_thresholds
|
||||
):
|
||||
if brightness_factor != 0.0:
|
||||
timage = adjust_brightness(timage, brightness_factor)
|
||||
|
||||
if contrast_factor != 1.0:
|
||||
timage = adjust_contrast(timage, contrast_factor)
|
||||
|
||||
if gamma_factor != 1.0:
|
||||
timage = adjust_gamma(timage, gamma_factor, gamma_gain)
|
||||
|
||||
if hue_factor != 0.0:
|
||||
timage = adjust_hue(timage, hue_factor)
|
||||
|
||||
if saturation_factor != 1.0:
|
||||
timage = adjust_saturation(timage, saturation_factor)
|
||||
|
||||
if sharpness_factor != 0.0:
|
||||
timage = sharpness(timage, sharpness_factor)
|
||||
|
||||
if posterize_bits != 8:
|
||||
timage = posterize(timage, posterize_bits)
|
||||
|
||||
if solarize_thresholds != 1.0:
|
||||
timage = solarize(timage, solarize_thresholds)
|
||||
|
||||
return timage
|
||||
@@ -1,38 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from folder_paths import get_filename_list
|
||||
|
||||
from .postproduction_helpers import upscale_image
|
||||
|
||||
|
||||
class TT_QuickImageUpscaler():
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
DEVICES = ["default", "cpu"]
|
||||
UPSCALE_MODELS = get_filename_list("upscale_models")
|
||||
|
||||
return {
|
||||
"required": {
|
||||
"image": ("IMAGE",),
|
||||
"device": (DEVICES, {"advanced": True}),
|
||||
"upscale_model_name": (UPSCALE_MODELS, {"advanced": True}),
|
||||
"tile": ("INT", {"default": 512, "min": 256, "max": 4096, "step": 64}),
|
||||
"overlap": ("INT", {"default": 64, "min": 0, "max": 256, "step": 8}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
RETURN_NAMES = ("IMAGE",)
|
||||
FUNCTION = "upscale_image"
|
||||
CATEGORY = "TenserTensor/Deprecated/Postproduction"
|
||||
|
||||
def upscale_image(self, image, device, upscale_model_name, tile, overlap):
|
||||
timage = image.clone()
|
||||
|
||||
return (upscale_image(
|
||||
timage=timage,
|
||||
device=device,
|
||||
upscale_model_name=upscale_model_name,
|
||||
tile=tile,
|
||||
overlap=overlap,
|
||||
),)
|
||||
@@ -1,31 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
import comfy.samplers
|
||||
|
||||
from .ksampler_helpers import sample_latents
|
||||
|
||||
|
||||
class TT_KSampler():
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"model": ("MODEL",),
|
||||
"positive": ("CONDITIONING",),
|
||||
"negative": ("CONDITIONING",),
|
||||
"latent": ("LATENT",),
|
||||
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
||||
"steps": ("INT", {"default": 25, "min": 1, "max": 10000}),
|
||||
"cfg": ("FLOAT", {"default": 1.5, "min": 0.0, "max": 100.0, "step": 0.1}),
|
||||
"sampler_name": (comfy.samplers.KSampler.SAMPLERS,),
|
||||
"scheduler": (comfy.samplers.KSampler.SCHEDULERS,),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("LATENT",)
|
||||
RETURN_NAMES = ("SAMPLES",)
|
||||
FUNCTION = "execute_sampling"
|
||||
CATEGORY = "TenserTensor/Deprecated/Sampling"
|
||||
|
||||
def execute_sampling(self, **kwargs):
|
||||
return (sample_latents(**kwargs),)
|
||||
@@ -1,36 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
import comfy.samplers
|
||||
|
||||
from .ksampler_helpers import sample_latents
|
||||
|
||||
|
||||
class TT_KSamplerAdvanced():
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"model": ("MODEL",),
|
||||
"positive": ("CONDITIONING",),
|
||||
"negative": ("CONDITIONING",),
|
||||
"latent": ("LATENT",),
|
||||
"add_noise": ("BOOLEAN", {"default": True, "label_on": "Enabled", "label_off": "Disabled"}),
|
||||
"full_denoise": ("BOOLEAN", {"default": False, "label_on": "Enabled", "label_off": "Disabled"}),
|
||||
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
||||
"steps": ("INT", {"default": 25, "min": 1, "max": 10000}),
|
||||
"start_step": ("INT", {"default": 0, "min": 0, "max": 10000}),
|
||||
"last_step": ("INT", {"default": 10000, "min": 0, "max": 10000}),
|
||||
"cfg": ("FLOAT", {"default": 1.5, "min": 0.0, "max": 100.0, "step": 0.1}),
|
||||
"sampler_name": (comfy.samplers.KSampler.SAMPLERS,),
|
||||
"scheduler": (comfy.samplers.KSampler.SCHEDULERS,),
|
||||
"denoise": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("LATENT",)
|
||||
RETURN_NAMES = ("SAMPLES",)
|
||||
FUNCTION = "execute_sampling"
|
||||
CATEGORY = "TenserTensor/Deprecated/Sampling"
|
||||
|
||||
def execute_sampling(self, **kwargs):
|
||||
return (sample_latents(**kwargs),)
|
||||
@@ -1,47 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from .ksampler_helpers import sample_latents
|
||||
|
||||
|
||||
class TT_KSamplerContext():
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"context": ("TT_CONTEXT",)
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("TT_CONTEXT", "LATENT",)
|
||||
RETURN_NAMES = ("CONTEXT", "SAMPLES",)
|
||||
FUNCTION = "execute_sampling"
|
||||
CATEGORY = "TenserTensor/Deprecated/Sampling"
|
||||
|
||||
def execute_sampling(self, context):
|
||||
model = context.get("model", None)
|
||||
latent = context.get("latent", None)
|
||||
config = context.get("workflow_config", None)
|
||||
|
||||
if model is None:
|
||||
raise ValueError("Model is required for sampling")
|
||||
if latent is None:
|
||||
raise ValueError("Latent image is required for sampling")
|
||||
if config is None:
|
||||
raise ValueError("Workflow Config is required for sampling")
|
||||
|
||||
args = {
|
||||
"model": model,
|
||||
"positive": context.get("positive", None),
|
||||
"negative": context.get("negative", None),
|
||||
"latent": latent,
|
||||
"seed": config.get("seed", 0),
|
||||
"steps": config.get("steps", 0),
|
||||
"cfg": config.get("cfg", 0),
|
||||
"sampler_name": config.get("sampler_name", None),
|
||||
"scheduler": config.get("scheduler", None),
|
||||
}
|
||||
|
||||
samples = sample_latents(**args)
|
||||
context["latent"] = samples
|
||||
|
||||
return (context, samples)
|
||||
@@ -1,25 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from .ksampler_helpers import guided_sample_latents
|
||||
|
||||
|
||||
class TT_KSamplerGuided:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"latent": ("LATENT",),
|
||||
"guider": ("GUIDER",),
|
||||
"sigmas": ("SIGMAS",),
|
||||
"sampler": ("SAMPLER",),
|
||||
"random_noise": ("NOISE",),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("LATENT",)
|
||||
RETURN_NAMES = ("SAMPLES",)
|
||||
FUNCTION = "execute_sampling"
|
||||
CATEGORY = "TenserTensor/Deprecated/Sampling"
|
||||
|
||||
def execute_sampling(self, latent, guider, sigmas, sampler, random_noise):
|
||||
return (guided_sample_latents(latent, guider, sigmas, sampler, random_noise),)
|
||||
@@ -1,95 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
import comfy
|
||||
import latent_preview as LP
|
||||
import torch
|
||||
from comfy import sample as S, utils as U, model_management as MM, nested_tensor as NT
|
||||
|
||||
|
||||
def sample_latents(**kwargs):
|
||||
model = kwargs.get("model", None)
|
||||
latent = kwargs.get("latent", None)
|
||||
|
||||
if model is None:
|
||||
raise ValueError("Model is required for sampling")
|
||||
if latent is None:
|
||||
raise ValueError("Latent image is required for sampling")
|
||||
|
||||
steps = kwargs.get("steps", 0)
|
||||
seed = kwargs.get("seed", 0)
|
||||
|
||||
latent_img = comfy.sample.fix_empty_latent_channels(model, latent["samples"])
|
||||
|
||||
add_noise = kwargs.get("add_noise", True)
|
||||
if add_noise:
|
||||
bat_idx = latent.get("batch_index", None)
|
||||
noise = comfy.sample.prepare_noise(latent_img, seed, bat_idx)
|
||||
else:
|
||||
noise = torch.zeros(latent_img.size(), dtype=latent_img.dtype, layout=latent_img.layout, device="cpu")
|
||||
|
||||
callback = LP.prepare_callback(model, steps)
|
||||
|
||||
args = {
|
||||
"model": model,
|
||||
"noise": noise,
|
||||
"steps": steps,
|
||||
"cfg": kwargs.get("cfg", 0),
|
||||
"sampler_name": kwargs.get("sampler_name", None),
|
||||
"scheduler": kwargs.get("scheduler", None),
|
||||
"positive": kwargs.get("positive", None),
|
||||
"negative": kwargs.get("negative", None),
|
||||
"latent_image": latent_img,
|
||||
"denoise": kwargs.get("denoise", 1.0),
|
||||
"disable_noise": not add_noise,
|
||||
"start_step": kwargs.get("start_step", 0),
|
||||
"last_step": kwargs.get("last_step", 10000),
|
||||
"force_full_denoise": kwargs.get("full_denoise", True),
|
||||
"noise_mask": latent.get("noise_mask", None),
|
||||
"disable_pbar": not comfy.utils.PROGRESS_BAR_ENABLED,
|
||||
"callback": callback,
|
||||
"seed": seed,
|
||||
}
|
||||
|
||||
samples = comfy.sample.sample(**args)
|
||||
|
||||
retval = latent.copy()
|
||||
retval["samples"] = samples
|
||||
|
||||
return retval
|
||||
|
||||
|
||||
def guided_sample_latents(latent, guider, sigmas, sampler, random_noise):
|
||||
model_patcher = guider.model_patcher
|
||||
latent_dict = latent.copy()
|
||||
latent_tensor = S.fix_empty_latent_channels(model_patcher, latent_dict["samples"], latent.get("downscale_ratio_spacial", None))
|
||||
latent_dict["samples"] = latent_tensor
|
||||
|
||||
noise_mask = latent.get("noise_mask", None)
|
||||
|
||||
interim_buffer = {}
|
||||
callback = LP.prepare_callback(model_patcher, sigmas.shape[-1] - 1, interim_buffer)
|
||||
disable_pbar = not U.PROGRESS_BAR_ENABLED
|
||||
|
||||
print(f"latent: {latent}")
|
||||
print(f"sampler: {sampler}")
|
||||
print(f"sigmas: {sigmas}")
|
||||
print(f"random_noise: {random_noise}")
|
||||
print(f"GUIDER: {guider}")
|
||||
|
||||
|
||||
samples = guider.sample(
|
||||
random_noise.generate_noise(latent),
|
||||
latent_tensor,
|
||||
sampler,
|
||||
sigmas,
|
||||
denoise_mask=noise_mask,
|
||||
callback=callback,
|
||||
disable_pbar=disable_pbar,
|
||||
seed=random_noise.seed
|
||||
).to(MM.intermediate_device())
|
||||
|
||||
retval = latent_dict.copy()
|
||||
retval.pop("downscale_ratio_spacial", None)
|
||||
retval["samples"] = samples
|
||||
|
||||
return retval
|
||||
@@ -1,65 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
import comfy.samplers
|
||||
|
||||
from .ksampler_helpers import sample_latents
|
||||
|
||||
|
||||
class TT_KSamplerTwoStage():
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"model": ("MODEL",),
|
||||
"positive": ("CONDITIONING",),
|
||||
"negative": ("CONDITIONING",),
|
||||
"latent": ("LATENT",),
|
||||
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
||||
"cfg": ("FLOAT", {"default": 1.5, "min": 0.0, "max": 100.0, "step": 0.1}),
|
||||
"draft_steps": ("INT", {"default": 25, "min": 1, "max": 10000}),
|
||||
"refiner_steps": ("INT", {"default": 25, "min": 1, "max": 10000}),
|
||||
"draft_sampler_name": (comfy.samplers.KSampler.SAMPLERS,),
|
||||
"draft_scheduler": (comfy.samplers.KSampler.SCHEDULERS,),
|
||||
"refiner_sampler_name": (comfy.samplers.KSampler.SAMPLERS,),
|
||||
"refiner_scheduler": (comfy.samplers.KSampler.SCHEDULERS,),
|
||||
"draft_denoise": ("FLOAT", {"default": 0.7, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"refiner_denoise": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("LATENT",)
|
||||
RETURN_NAMES = ("SAMPLES",)
|
||||
FUNCTION = "execute_sampling"
|
||||
CATEGORY = "TenserTensor/Deprecated/Sampling"
|
||||
|
||||
def execute_sampling(self, **kwargs):
|
||||
draft_steps = kwargs["draft_steps"]
|
||||
refiner_steps = kwargs["refiner_steps"]
|
||||
|
||||
args = {
|
||||
"model": kwargs["model"],
|
||||
"positive": kwargs["positive"],
|
||||
"negative": kwargs["negative"],
|
||||
"latent": kwargs["latent"],
|
||||
"seed": kwargs["seed"],
|
||||
"steps": draft_steps,
|
||||
"start_step": 0,
|
||||
"cfg": kwargs["cfg"],
|
||||
"sampler_name": kwargs["draft_sampler_name"],
|
||||
"scheduler": kwargs["draft_scheduler"],
|
||||
"add_noise": True,
|
||||
"full_denoise": False,
|
||||
"denoise": kwargs["refiner_denoise"],
|
||||
}
|
||||
|
||||
samples = sample_latents(**args)
|
||||
|
||||
args["latent"] = samples
|
||||
args["steps"] = draft_steps + refiner_steps
|
||||
args["start_step"] = draft_steps
|
||||
args["denoise"] = kwargs["draft_denoise"]
|
||||
args["sampler_name"] = kwargs["refiner_sampler_name"]
|
||||
args["scheduler"] = kwargs["refiner_scheduler"]
|
||||
args["full_denoise"] = True
|
||||
|
||||
return (sample_latents(**args),)
|
||||
@@ -1,26 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from .encoder_helpers import encode_prompts_flux
|
||||
|
||||
|
||||
class TT_ClipTextEncodeFlux():
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"clip": ("CLIP",),
|
||||
"clip_l_positive": ("STRING", {"multiline": True, "placeholder": "CLIP_L Positive", "dynamicPrompts": True}),
|
||||
"t5xxl_positive": ("STRING", {"multiline": True, "placeholder": "T5XXL Positive", "dynamicPrompts": True}),
|
||||
"clip_l_negative": ("STRING", {"multiline": True, "placeholder": "CLIP_L Negative", "dynamicPrompts": True}),
|
||||
"t5xxl_negative": ("STRING", {"multiline": True, "placeholder": "CLIP_L Negative", "dynamicPrompts": True}),
|
||||
"guidance": ("FLOAT", {"default": 3.5, "min": 1.0, "max": 10.0, "step": 0.1})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONDITIONING", "CONDITIONING",)
|
||||
RETURN_NAMES = ("POSITIVE", "NEGATIVE",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "TenserTensor/Deprecated/Text Encoders/FLUX"
|
||||
|
||||
def execute(self, **kwargs):
|
||||
return encode_prompts_flux(**kwargs)
|
||||
@@ -1,25 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from .encoder_helpers import encode_prompts_flux2
|
||||
|
||||
|
||||
class TT_ClipTextEncodeFlux2():
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"model": ("MODEL",),
|
||||
"clip": ("CLIP",),
|
||||
"prompt": ("STRING", {"multiline": True, "placeholder": "Prompt", "dynamicPrompts": True}),
|
||||
"lora_triggers": ("STRING", {"multiline": True, "placeholder": "LoRA Triggers", "dynamicPrompts": True}),
|
||||
"guidance": ("FLOAT", {"default": 3.5, "min": 1.0, "max": 10.0, "step": 0.1})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("GUIDER",)
|
||||
RETURN_NAMES = ("GUIDER",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "TenserTensor/Deprecated/Text Encoders/FLUX2"
|
||||
|
||||
def execute(self, model, clip, prompt, lora_triggers, guidance):
|
||||
return encode_prompts_flux2(model, clip, prompt, lora_triggers, guidance)
|
||||
@@ -1,41 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from .encoder_helpers import encode_prompts_flux2
|
||||
|
||||
|
||||
class TT_ClipTextEncodeFlux2Context():
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"context": ("TT_CONTEXT",)
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("TT_CONTEXT", "GUIDER",)
|
||||
RETURN_NAMES = ("CONTEXT", "GUIDER",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "TenserTensor/Deprecated/Text Encoders/FLUX2"
|
||||
|
||||
def execute(self, context):
|
||||
model = context.get("model", None)
|
||||
clip = context.get("clip", None)
|
||||
config = context.get("workflow_config", None)
|
||||
|
||||
if model is None:
|
||||
raise ValueError("Model is required for text encoder")
|
||||
if clip is None:
|
||||
raise ValueError("CLIP is required for text encoder")
|
||||
if config is None:
|
||||
raise ValueError("Workflow Config is required for text encoder")
|
||||
|
||||
guider = encode_prompts_flux2(
|
||||
model,
|
||||
clip,
|
||||
config.get("prompt", None),
|
||||
config.get("lora_triggers", None),
|
||||
config.get("guidance", None),
|
||||
)
|
||||
context["guider"] = guider
|
||||
|
||||
return (context, guider,)
|
||||
@@ -1,36 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from .encoder_helpers import encode_prompts_flux
|
||||
|
||||
|
||||
class TT_ClipTextEncodeFluxContext():
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"context": ("TT_CONTEXT",)
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("TT_CONTEXT", "CONDITIONING", "CONDITIONING",)
|
||||
RETURN_NAMES = ("CONTEXT", "POSITIVE", "NEGATIVE",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "TenserTensor/Deprecated/Text Encoders/FLUX"
|
||||
|
||||
def execute(self, context):
|
||||
clip = context["clip"]
|
||||
config = context["workflow_config"]
|
||||
|
||||
positive, negative = encode_prompts_flux(
|
||||
clip,
|
||||
config["clip_l_positive"],
|
||||
config["t5xxl_positive"],
|
||||
config["clip_l_negative"],
|
||||
config["t5xxl_negative"],
|
||||
config["guidance"],
|
||||
)
|
||||
|
||||
context["positive"] = positive
|
||||
context["negative"] = negative
|
||||
|
||||
return (context, positive, negative,)
|
||||
@@ -1,32 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from nodes import MAX_RESOLUTION
|
||||
from .encoder_helpers import encode_prompts_sdxl
|
||||
|
||||
|
||||
class TT_ClipTextEncodeSdxl():
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"clip": ("CLIP",),
|
||||
"clip_l_positive": ("STRING", {"multiline": True, "placeholder": "CLIP_L Positive", "dynamicPrompts": True}),
|
||||
"clip_g_positive": ("STRING", {"multiline": True, "placeholder": "CLIP_G Positive", "dynamicPrompts": True}),
|
||||
"clip_l_negative": ("STRING", {"multiline": True, "placeholder": "CLIP_L Negative", "dynamicPrompts": True}),
|
||||
"clip_g_negative": ("STRING", {"multiline": True, "placeholder": "CLIP_G Negative", "dynamicPrompts": True}),
|
||||
"ascore_positive": ("FLOAT", {"default": 9.0, "min": 0.0, "max": 1000.0, "step": 0.1}),
|
||||
"ascore_negative": ("FLOAT", {"default": 6.0, "min": 0.0, "max": 1000.0, "step": 0.1}),
|
||||
"width": ("INT", {"default": 512, "min": 0.0, "max": MAX_RESOLUTION}),
|
||||
"height": ("INT", {"default": 512, "min": 0.0, "max": MAX_RESOLUTION}),
|
||||
"target_width": ("INT", {"default": 512, "min": 0.0, "max": MAX_RESOLUTION}),
|
||||
"target_height": ("INT", {"default": 512, "min": 0.0, "max": MAX_RESOLUTION}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("CONDITIONING", "CONDITIONING",)
|
||||
RETURN_NAMES = ("POSITIVE", "NEGATIVE",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "TenserTensor/Deprecated/Text Encoders/SDXL"
|
||||
|
||||
def execute(self, **kwargs):
|
||||
return encode_prompts_sdxl(**kwargs)
|
||||
@@ -1,41 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from .encoder_helpers import encode_prompts_sdxl
|
||||
|
||||
|
||||
class TT_ClipTextEncodeSdxlContext():
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"context": ("TT_CONTEXT",)
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("TT_CONTEXT", "CONDITIONING", "CONDITIONING",)
|
||||
RETURN_NAMES = ("CONTEXT", "POSITIVE", "NEGATIVE",)
|
||||
FUNCTION = "execute"
|
||||
CATEGORY = "TenserTensor/Deprecated/Text Encoders/SDXL"
|
||||
|
||||
def execute(self, context):
|
||||
clip = context["clip"]
|
||||
config = context["workflow_config"]
|
||||
|
||||
positive, negative = encode_prompts_sdxl(
|
||||
clip,
|
||||
config["clip_l_positive"],
|
||||
config["clip_g_positive"],
|
||||
config["clip_l_negative"],
|
||||
config["clip_g_negative"],
|
||||
config["ascore_positive"],
|
||||
config["ascore_negative"],
|
||||
config["width"],
|
||||
config["height"],
|
||||
config["target_width"],
|
||||
config["target_height"],
|
||||
)
|
||||
|
||||
context["positive"] = positive
|
||||
context["negative"] = negative
|
||||
|
||||
return (context, positive, negative,)
|
||||
@@ -1,72 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
import comfy.samplers as S
|
||||
|
||||
from ...lib.common import BasicGuider
|
||||
|
||||
|
||||
class Guider_Basic(S.CFGGuider):
|
||||
def set_conds(self, positive):
|
||||
self.inner_set_conds({"positive": positive})
|
||||
|
||||
|
||||
def encode_prompts_sdxl(clip, clip_l_positive, clip_g_positive, clip_l_negative, clip_g_negative,
|
||||
ascore_positive, ascore_negative, width, height, target_width, target_height):
|
||||
if clip is None:
|
||||
raise ValueError("ERROR: CLIP is required for text encoder")
|
||||
|
||||
positive_tokens = clip.tokenize(clip_g_positive)
|
||||
positive_tokens["l"] = clip.tokenize(clip_l_positive)["l"]
|
||||
negative_tokens = clip.tokenize(clip_g_negative)
|
||||
negative_tokens["l"] = clip.tokenize(clip_l_negative)["l"]
|
||||
|
||||
return (
|
||||
clip.encode_from_tokens_scheduled(
|
||||
positive_tokens,
|
||||
add_dict={
|
||||
"aesthetic_score": ascore_positive,
|
||||
"width": width,
|
||||
"height": height,
|
||||
"target_width": target_width,
|
||||
"target_height": target_height,
|
||||
}
|
||||
),
|
||||
clip.encode_from_tokens_scheduled(
|
||||
negative_tokens,
|
||||
add_dict={
|
||||
"aesthetic_score": ascore_negative,
|
||||
"width": width,
|
||||
"height": height,
|
||||
"target_width": target_width,
|
||||
"target_height": target_height,
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def encode_prompts_flux(clip, clip_l_positive, t5xxl_positive, clip_l_negative, t5xxl_negative, guidance):
|
||||
if clip is None:
|
||||
raise ValueError("ERROR: CLIP is required for text encoder")
|
||||
|
||||
positive_tokens = clip.tokenize(clip_l_positive)
|
||||
positive_tokens["t5xxl"] = clip.tokenize(t5xxl_positive)["t5xxl"]
|
||||
negative_tokens = clip.tokenize(clip_l_negative)
|
||||
negative_tokens["t5xxl"] = clip.tokenize(t5xxl_negative)["t5xxl"]
|
||||
|
||||
return (
|
||||
clip.encode_from_tokens_scheduled(positive_tokens, add_dict={"guidance": guidance, }),
|
||||
clip.encode_from_tokens_scheduled(negative_tokens, add_dict={"guidance": guidance, })
|
||||
)
|
||||
|
||||
|
||||
def encode_prompts_flux2(model, clip, prompt, lora_triggers, guidance):
|
||||
if clip is None:
|
||||
raise ValueError("ERROR: CLIP is required for text encoder")
|
||||
|
||||
full_prompt = f"{lora_triggers}, {prompt}" if lora_triggers.strip() else prompt
|
||||
tokens = clip.tokenize(full_prompt)
|
||||
conditioning = clip.encode_from_tokens_scheduled(tokens, add_dict={"guidance": guidance, })
|
||||
guider = BasicGuider(model)
|
||||
guider.set_conds(conditioning)
|
||||
|
||||
return (guider,)
|
||||
@@ -1,31 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
from .vae_helpers import vae_decode
|
||||
|
||||
|
||||
class TT_VaeDecodeContext:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"context": ("TT_CONTEXT",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("TT_CONTEXT", "IMAGE",)
|
||||
RETURN_NAMES = ("CONTEXT", "IMAGE",)
|
||||
FUNCTION = "vae_decode"
|
||||
CATEGORY = "TenserTensor/Deprecated/VAE"
|
||||
|
||||
def vae_decode(self, context):
|
||||
vae = context["vae"]
|
||||
latent = context["latent"]
|
||||
|
||||
if vae is None:
|
||||
raise ValueError("ERROR: VAE is required for decode")
|
||||
if latent is None:
|
||||
raise ValueError("ERROR: Latent image is required for decode")
|
||||
|
||||
images = vae_decode(latent, vae)
|
||||
context["image"] = images
|
||||
|
||||
return (context, images,)
|
||||
@@ -1,27 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
|
||||
from .vae_helpers import vae_decode
|
||||
|
||||
|
||||
class TT_VaeDecodeTiled:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"vae": ("VAE",),
|
||||
"latent": ("LATENT",),
|
||||
"tile_width": ("INT", {"default": 512, "min": 64, "max": 4096, "step": 64}),
|
||||
"tile_height": ("INT", {"default": 512, "min": 64, "max": 4096, "step": 64}),
|
||||
"overlap": ("INT", {"default": 64, "min": 0, "max": 4096, "step": 32}),
|
||||
"circular": ("BOOLEAN", {"default": False, "label_on": "Enabled", "label_off": "Disabled"}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
RETURN_NAMES = ("IMAGE",)
|
||||
FUNCTION = "vae_decode"
|
||||
CATEGORY = "TenserTensor/Deprecated/VAE"
|
||||
|
||||
def vae_decode(self, latent, vae, tile_width, tile_height, overlap, circular):
|
||||
return (vae_decode(latent, vae, tile_width, tile_height, overlap, circular),)
|
||||
@@ -1,32 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from .vae_helpers import vae_encode
|
||||
|
||||
|
||||
class TT_VaeEncodeContext:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"context": ("TT_CONTEXT",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("TT_CONTEXT", "LATENT",)
|
||||
RETURN_NAMES = ("CONTEXT", "LATENT",)
|
||||
FUNCTION = "vae_encode"
|
||||
CATEGORY = "TenserTensor/Deprecated/VAE"
|
||||
|
||||
def vae_encode(self, context):
|
||||
vae = context["vae"]
|
||||
image = context["image"]
|
||||
|
||||
if vae is None:
|
||||
raise ValueError("VAE is required for encode")
|
||||
if image is None:
|
||||
raise ValueError("Pixel image is required for encode")
|
||||
|
||||
samples = vae_encode(image, vae)
|
||||
context["latent"] = samples
|
||||
|
||||
return (context, samples,)
|
||||
@@ -1,25 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from .vae_helpers import vae_encode
|
||||
|
||||
|
||||
class TT_VaeEncodeTiled:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"vae": ("VAE",),
|
||||
"image": ("IMAGE",),
|
||||
"tile_width": ("INT", {"default": 512, "min": 64, "max": 4096, "step": 64}),
|
||||
"tile_height": ("INT", {"default": 512, "min": 64, "max": 4096, "step": 64}),
|
||||
"overlap": ("INT", {"default": 64, "min": 0, "max": 4096, "step": 32}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("LATENT",)
|
||||
RETURN_NAMES = ("LATENT",)
|
||||
FUNCTION = "vae_encode"
|
||||
CATEGORY = "TenserTensor/Deprecated/VAE"
|
||||
|
||||
def vae_encode(self, image, vae, tile_width, tile_height, overlap):
|
||||
return (vae_encode(image, vae, tile_width, tile_height, overlap),)
|
||||
@@ -1,38 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
import torch
|
||||
|
||||
|
||||
def vae_encode(image, vae, tile_width=512, tile_height=512, overlap=64):
|
||||
samples = vae.encode_tiled(
|
||||
image,
|
||||
tile_x=tile_width,
|
||||
tile_y=tile_height,
|
||||
overlap=overlap
|
||||
)
|
||||
latent_dict = {"samples": samples}
|
||||
|
||||
return latent_dict
|
||||
|
||||
|
||||
def vae_decode(latent, vae, tile_width=512, tile_height=512, overlap=64, circular=False):
|
||||
samples = latent["samples"]
|
||||
if samples.is_nested:
|
||||
samples = samples.unbind()[0]
|
||||
|
||||
if circular == True:
|
||||
for layer in [layer for layer in vae.first_stage_model.modules() if isinstance(layer, torch.nn.Conv2d)]:
|
||||
layer.padding_mode = "circular"
|
||||
|
||||
compression = vae.spacial_compression_decode()
|
||||
images = vae.decode_tiled(
|
||||
samples,
|
||||
tile_x=tile_width // compression,
|
||||
tile_y=tile_height // compression,
|
||||
overlap=overlap // compression
|
||||
)
|
||||
|
||||
if len(images.shape) == 5:
|
||||
images = images.reshape(-1, images.shape[-3], images.shape[-2], images.shape[-1])
|
||||
|
||||
return images
|
||||
@@ -1,67 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
import comfy.samplers as S
|
||||
|
||||
from nodes import MAX_RESOLUTION
|
||||
from .workflow_settings_helpers import get_schedule
|
||||
|
||||
|
||||
class TT_Flux2WorkflowSettings:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
||||
"steps": ("INT", {"default": 25, "min": 1, "max": 10000}),
|
||||
"cfg": ("FLOAT", {"default": 3.0, "min": 0.0, "max": 100.0, "step": 0.1}),
|
||||
"sampler_name": (S.KSampler.SAMPLERS,),
|
||||
"width": ("INT", {"default": 1024, "min": 16, "max": MAX_RESOLUTION, "step": 8}),
|
||||
"height": ("INT", {"default": 1024, "min": 16, "max": MAX_RESOLUTION, "step": 8}),
|
||||
"guidance": ("FLOAT", {"default": 3.5, "min": 1.0, "max": 10.0, "step": 0.1})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (
|
||||
"TT_WORKFLOW_CONFIG",
|
||||
"INT",
|
||||
"INT",
|
||||
"FLOAT",
|
||||
"SAMPLER",
|
||||
S.KSampler.SAMPLERS,
|
||||
"SIGMAS",
|
||||
"INT",
|
||||
"INT",
|
||||
"FLOAT"
|
||||
)
|
||||
RETURN_NAMES = (
|
||||
"WORKFLOW_CONFIG",
|
||||
"SEED",
|
||||
"STEPS",
|
||||
"CFG",
|
||||
"SAMPLER",
|
||||
"SAMPLER_NAME",
|
||||
"SCHEDULER",
|
||||
"WIDTH",
|
||||
"HEIGHT",
|
||||
"GUIDANCE"
|
||||
)
|
||||
FUNCTION = "get_settings"
|
||||
CATEGORY = "TenserTensor/Deprecated/Workflow/FLUX2"
|
||||
|
||||
def get_settings(self, seed, steps, cfg, sampler_name, width, height, guidance):
|
||||
scheduler = get_schedule(steps, width, height)
|
||||
sampler = S.sampler_object(sampler_name)
|
||||
|
||||
workflow_config = {
|
||||
"seed": seed,
|
||||
"steps": steps,
|
||||
"cfg": cfg,
|
||||
"sampler": sampler,
|
||||
"sampler_name": sampler_name,
|
||||
"scheduler": scheduler,
|
||||
"width": width,
|
||||
"height": height,
|
||||
"guidance": guidance
|
||||
}
|
||||
|
||||
return (workflow_config, seed, steps, cfg, sampler, sampler_name, scheduler, width, height, guidance)
|
||||
@@ -1,75 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
import comfy.samplers as S
|
||||
|
||||
from nodes import MAX_RESOLUTION
|
||||
from .workflow_settings_helpers import get_schedule
|
||||
|
||||
|
||||
class TT_Flux2WorkflowSettingsAdvanced:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
||||
"steps": ("INT", {"default": 25, "min": 1, "max": 10000}),
|
||||
"cfg": ("FLOAT", {"default": 3.0, "min": 0.0, "max": 100.0, "step": 0.1}),
|
||||
"sampler_name": (S.KSampler.SAMPLERS,),
|
||||
"width": ("INT", {"default": 1024, "min": 16, "max": MAX_RESOLUTION, "step": 8}),
|
||||
"height": ("INT", {"default": 1024, "min": 16, "max": MAX_RESOLUTION, "step": 8}),
|
||||
"prompt": ("STRING", {"multiline": True, "placeholder": "Prompt", "dynamicPrompts": True}),
|
||||
"lora_triggers": ("STRING", {"multiline": True, "placeholder": "LoRA Triggers", "dynamicPrompts": True}),
|
||||
"guidance": ("FLOAT", {"default": 3.5, "min": 1.0, "max": 10.0, "step": 0.1})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (
|
||||
"TT_WORKFLOW_CONFIG",
|
||||
"INT",
|
||||
"INT",
|
||||
"FLOAT",
|
||||
S.KSampler.SAMPLERS,
|
||||
"SAMPLER",
|
||||
"SIGMAS",
|
||||
"INT",
|
||||
"INT",
|
||||
"STRING",
|
||||
"STRING",
|
||||
"FLOAT"
|
||||
)
|
||||
RETURN_NAMES = (
|
||||
"WORKFLOW_CONFIG",
|
||||
"SEED",
|
||||
"STEPS",
|
||||
"CFG",
|
||||
"SAMPLER_NAME",
|
||||
"SAMPLER",
|
||||
"SCHEDULER",
|
||||
"WIDTH",
|
||||
"HEIGHT",
|
||||
"PROMPT",
|
||||
"LORA_TRIGGERS",
|
||||
"GUIDANCE"
|
||||
)
|
||||
FUNCTION = "get_settings"
|
||||
CATEGORY = "TenserTensor/Deprecated/Workflow/FLUX2"
|
||||
|
||||
def get_settings(self, seed, steps, cfg, sampler_name, width, height, prompt, lora_triggers, guidance):
|
||||
scheduler = get_schedule(steps, width, height)
|
||||
sampler = S.sampler_object(sampler_name)
|
||||
|
||||
workflow_config = {
|
||||
"seed": seed,
|
||||
"steps": steps,
|
||||
"cfg": cfg,
|
||||
"sampler": sampler,
|
||||
"sampler_name": sampler_name,
|
||||
"scheduler": scheduler,
|
||||
"width": width,
|
||||
"height": height,
|
||||
"prompt": prompt,
|
||||
"lora_triggers": lora_triggers,
|
||||
"guidance": guidance
|
||||
}
|
||||
|
||||
return (workflow_config, seed, steps, cfg, sampler_name, sampler, scheduler, width, height, prompt, lora_triggers, guidance)
|
||||
@@ -1,51 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
import comfy.samplers as S
|
||||
|
||||
|
||||
class TT_FluxWorkflowSettings:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
||||
"steps": ("INT", {"default": 25, "min": 1, "max": 10000}),
|
||||
"cfg": ("FLOAT", {"default": 1.5, "min": 0.0, "max": 100.0, "step": 0.1}),
|
||||
"sampler_name": (S.KSampler.SAMPLERS,),
|
||||
"scheduler": (S.KSampler.SCHEDULERS,),
|
||||
"guidance": ("FLOAT", {"default": 3.5, "min": 1.0, "max": 10.0, "step": 0.1})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (
|
||||
"TT_WORKFLOW_CONFIG",
|
||||
"INT",
|
||||
"INT",
|
||||
"FLOAT",
|
||||
S.KSampler.SAMPLERS,
|
||||
S.KSampler.SCHEDULERS,
|
||||
"FLOAT"
|
||||
)
|
||||
RETURN_NAMES = (
|
||||
"WORKFLOW_CONFIG",
|
||||
"SEED",
|
||||
"STEPS",
|
||||
"CFG",
|
||||
"SAMPLER_NAME",
|
||||
"SCHEDULER",
|
||||
"GUIDANCE"
|
||||
)
|
||||
FUNCTION = "get_settings"
|
||||
CATEGORY = "TenserTensor/Deprecated/Workflow/FLUX"
|
||||
|
||||
def get_settings(self, seed, steps, cfg, sampler_name, scheduler, guidance, ):
|
||||
workflow_config = {
|
||||
"seed": seed,
|
||||
"steps": steps,
|
||||
"cfg": cfg,
|
||||
"sampler_name": sampler_name,
|
||||
"scheduler": scheduler,
|
||||
"guidance": guidance
|
||||
}
|
||||
|
||||
return (workflow_config, seed, steps, cfg, sampler_name, scheduler, guidance)
|
||||
@@ -1,68 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
import comfy.samplers as S
|
||||
|
||||
|
||||
class TT_FluxWorkflowSettingsAdvanced:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
||||
"steps": ("INT", {"default": 25, "min": 1, "max": 10000}),
|
||||
"cfg": ("FLOAT", {"default": 1.5, "min": 0.0, "max": 100.0, "step": 0.1}),
|
||||
"sampler_name": (S.KSampler.SAMPLERS,),
|
||||
"scheduler": (S.KSampler.SCHEDULERS,),
|
||||
"clip_l_positive": ("STRING", {"multiline": True, "placeholder": "CLIP_L Positive", "dynamicPrompts": True}),
|
||||
"t5xxl_positive": ("STRING", {"multiline": True, "placeholder": "T5XXL Positive", "dynamicPrompts": True}),
|
||||
"clip_l_negative": ("STRING", {"multiline": True, "placeholder": "CLIP_L Negative", "dynamicPrompts": True}),
|
||||
"t5xxl_negative": ("STRING", {"multiline": True, "placeholder": "CLIP_L Negative", "dynamicPrompts": True}),
|
||||
"guidance": ("FLOAT", {"default": 3.5, "min": 1.0, "max": 10.0, "step": 0.1})
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (
|
||||
"TT_WORKFLOW_CONFIG",
|
||||
"INT",
|
||||
"INT",
|
||||
"FLOAT",
|
||||
S.KSampler.SAMPLERS,
|
||||
S.KSampler.SCHEDULERS,
|
||||
"STRING",
|
||||
"STRING",
|
||||
"STRING",
|
||||
"STRING",
|
||||
"FLOAT",
|
||||
)
|
||||
RETURN_NAMES = (
|
||||
"WORKFLOW_CONFIG",
|
||||
"SEED",
|
||||
"STEPS",
|
||||
"CFG",
|
||||
"SAMPLER_NAME",
|
||||
"SCHEDULER",
|
||||
"CLIP_L_POSITIVE",
|
||||
"T5XXL_POSITIVE",
|
||||
"CLIP_L_NEGATIVE",
|
||||
"T5XXL_NEGATIVE",
|
||||
"GUIDANCE",
|
||||
)
|
||||
FUNCTION = "get_settings"
|
||||
CATEGORY = "TenserTensor/Deprecated/Workflow/FLUX"
|
||||
|
||||
def get_settings(self, seed, steps, cfg, sampler_name, scheduler, guidance, clip_l_positive, t5xxl_positive, clip_l_negative, t5xxl_negative):
|
||||
workflow_config = {
|
||||
"seed": seed,
|
||||
"steps": steps,
|
||||
"cfg": cfg,
|
||||
"sampler_name": sampler_name,
|
||||
"scheduler": scheduler,
|
||||
"clip_l_positive": clip_l_positive,
|
||||
"t5xxl_positive": t5xxl_positive,
|
||||
"clip_l_negative": clip_l_negative,
|
||||
"t5xxl_negative": t5xxl_negative,
|
||||
"guidance": guidance
|
||||
}
|
||||
|
||||
return (workflow_config, seed, steps, cfg, sampler_name, scheduler, guidance, clip_l_positive, t5xxl_positive, clip_l_negative,
|
||||
t5xxl_negative)
|
||||
@@ -1,49 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
import comfy.samplers as S
|
||||
|
||||
|
||||
class TT_SdxlWorkflowSettings:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
||||
"steps": ("INT", {"default": 30, "min": 1, "max": 10000}),
|
||||
"cfg": ("FLOAT", {"default": 7.0, "min": 0.0, "max": 100.0, "step": 0.1}),
|
||||
"sampler_name": (S.KSampler.SAMPLERS,),
|
||||
"scheduler": (S.KSampler.SCHEDULERS,),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (
|
||||
"TT_WORKFLOW_CONFIG",
|
||||
"INT",
|
||||
"INT",
|
||||
"FLOAT",
|
||||
S.KSampler.SAMPLERS,
|
||||
S.KSampler.SCHEDULERS,
|
||||
)
|
||||
|
||||
RETURN_NAMES = (
|
||||
"WORKFLOW_CONFIG",
|
||||
"SEED",
|
||||
"STEPS",
|
||||
"CFG",
|
||||
"SAMPLER_NAME",
|
||||
"SCHEDULER",
|
||||
)
|
||||
|
||||
FUNCTION = "get_settings"
|
||||
CATEGORY = "TenserTensor/Deprecated/Workflow/SDXL"
|
||||
|
||||
def get_settings(self, seed, steps, cfg, sampler_name, scheduler):
|
||||
workflow_config = {
|
||||
"seed": seed,
|
||||
"steps": steps,
|
||||
"cfg": cfg,
|
||||
"sampler_name": sampler_name,
|
||||
"scheduler": scheduler,
|
||||
}
|
||||
|
||||
return (workflow_config, seed, steps, cfg, sampler_name, scheduler)
|
||||
@@ -1,92 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
import comfy.samplers as S
|
||||
|
||||
from nodes import MAX_RESOLUTION
|
||||
|
||||
|
||||
class TT_SdxlWorkflowSettingsAdvanced:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
||||
"steps": ("INT", {"default": 30, "min": 1, "max": 10000}),
|
||||
"cfg": ("FLOAT", {"default": 7.0, "min": 0.0, "max": 100.0, "step": 0.1}),
|
||||
"sampler_name": (S.KSampler.SAMPLERS,),
|
||||
"scheduler": (S.KSampler.SCHEDULERS,),
|
||||
"clip_l_positive": ("STRING", {"multiline": True, "placeholder": "CLIP_L Positive", "dynamicPrompts": True}),
|
||||
"clip_g_positive": ("STRING", {"multiline": True, "placeholder": "CLIP_G Positive", "dynamicPrompts": True}),
|
||||
"clip_l_negative": ("STRING", {"multiline": True, "placeholder": "CLIP_L Negative", "dynamicPrompts": True}),
|
||||
"clip_g_negative": ("STRING", {"multiline": True, "placeholder": "CLIP_G Negative", "dynamicPrompts": True}),
|
||||
"ascore_positive": ("FLOAT", {"default": 9.0, "min": 0.0, "max": 1000.0, "step": 0.1}),
|
||||
"ascore_negative": ("FLOAT", {"default": 6.0, "min": 0.0, "max": 1000.0, "step": 0.1}),
|
||||
"width": ("INT", {"default": 512, "min": 0.0, "max": MAX_RESOLUTION}),
|
||||
"height": ("INT", {"default": 512, "min": 0.0, "max": MAX_RESOLUTION}),
|
||||
"target_width": ("INT", {"default": 512, "min": 0.0, "max": MAX_RESOLUTION}),
|
||||
"target_height": ("INT", {"default": 512, "min": 0.0, "max": MAX_RESOLUTION}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = (
|
||||
"TT_WORKFLOW_CONFIG",
|
||||
"INT",
|
||||
"INT",
|
||||
"FLOAT",
|
||||
S.KSampler.SAMPLERS,
|
||||
S.KSampler.SCHEDULERS,
|
||||
"STRING",
|
||||
"STRING",
|
||||
"STRING",
|
||||
"STRING",
|
||||
"FLOAT",
|
||||
"FLOAT",
|
||||
"INT",
|
||||
"INT",
|
||||
"INT",
|
||||
"INT",
|
||||
)
|
||||
RETURN_NAMES = (
|
||||
"WORKFLOW_CONFIG",
|
||||
"SEED",
|
||||
"STEPS",
|
||||
"CFG",
|
||||
"SAMPLER_NAME",
|
||||
"SCHEDULER",
|
||||
"CLIP_L_POSITIVE",
|
||||
"CLIP_G_POSITIVE",
|
||||
"CLIP_L_NEGATIVE",
|
||||
"CLIP_G_NEGATIVE",
|
||||
"ASCORE_POSITIVE",
|
||||
"ASCORE_NEGATIVE",
|
||||
"WIDTH",
|
||||
"HEIGHT",
|
||||
"TARGET_WIDTH",
|
||||
"TARGET_HEIGHT",
|
||||
)
|
||||
FUNCTION = "get_settings"
|
||||
CATEGORY = "TenserTensor/Deprecated/Workflow/SDXL"
|
||||
|
||||
def get_settings(self, seed, steps, cfg, sampler_name, scheduler, clip_l_positive, clip_g_positive, clip_l_negative,
|
||||
clip_g_negative, ascore_positive, ascore_negative, width, height, target_width, target_height):
|
||||
workflow_config = {
|
||||
"seed": seed,
|
||||
"steps": steps,
|
||||
"cfg": cfg,
|
||||
"sampler_name": sampler_name,
|
||||
"scheduler": scheduler,
|
||||
"clip_l_positive": clip_l_positive,
|
||||
"clip_g_positive": clip_g_positive,
|
||||
"clip_l_negative": clip_l_negative,
|
||||
"clip_g_negative": clip_g_negative,
|
||||
"ascore_positive": ascore_positive,
|
||||
"ascore_negative": ascore_negative,
|
||||
"width": width,
|
||||
"height": height,
|
||||
"target_width": target_width,
|
||||
"target_height": target_height,
|
||||
}
|
||||
|
||||
return (workflow_config, seed, steps, cfg, sampler_name, scheduler, clip_l_positive, clip_g_positive,
|
||||
clip_l_negative,
|
||||
clip_g_negative, ascore_positive, ascore_negative, width, height, target_width, target_height)
|
||||
@@ -1,36 +0,0 @@
|
||||
# (c) TenserTensor || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
import math
|
||||
|
||||
import torch
|
||||
|
||||
|
||||
def _compute_empirical_mu(image_seq_len, num_steps):
|
||||
a1, b1 = 8.73809524e-05, 1.89833333
|
||||
a2, b2 = 0.00016927, 0.45666666
|
||||
|
||||
if image_seq_len > 4300:
|
||||
mu = a2 * image_seq_len + b2
|
||||
return float(mu)
|
||||
|
||||
m_200 = a2 * image_seq_len + b2
|
||||
m_10 = a1 * image_seq_len + b1
|
||||
|
||||
a = (m_200 - m_10) / 190.0
|
||||
b = m_200 - 200.0 * a
|
||||
mu = a * num_steps + b
|
||||
|
||||
return float(mu)
|
||||
|
||||
|
||||
def _generalized_time_snr_shift(t, mu, sigma):
|
||||
return math.exp(mu) / (math.exp(mu) + (1 / t - 1) ** sigma)
|
||||
|
||||
|
||||
def get_schedule(num_steps, width, height):
|
||||
image_seq_len = (width * height / (16 * 16))
|
||||
mu = _compute_empirical_mu(image_seq_len, num_steps)
|
||||
timesteps = torch.linspace(1, 0, num_steps + 1)
|
||||
timesteps = _generalized_time_snr_shift(timesteps, mu, 1.0)
|
||||
|
||||
return timesteps
|
||||
+14
-43
@@ -3,12 +3,10 @@
|
||||
import dataclasses
|
||||
import re
|
||||
from dataclasses import dataclass
|
||||
from typing import override
|
||||
|
||||
import torch
|
||||
|
||||
from comfy.clip_vision import Output
|
||||
from comfy_api.latest import IO, ComfyExtension, Input
|
||||
|
||||
from .nodes_workflow import TTWorkflowSettings, WorkflowSettings
|
||||
|
||||
CATEGORY = "TenserTensor/Context"
|
||||
@@ -315,44 +313,17 @@ class TT_ContextExtractImageNode(ContextNode):
|
||||
# V3 entrypoint — registers context nodes with ComfyUI
|
||||
# ==============================================================================
|
||||
|
||||
class ContextNodesExtension(ComfyExtension):
|
||||
@override
|
||||
async def get_node_list(self) -> list[type[IO.ComfyNode]]:
|
||||
return [
|
||||
TT_BaseContextNode,
|
||||
TT_BaseContextFlux2Node,
|
||||
TT_ContextPassthroughNode,
|
||||
TT_ContextNode,
|
||||
TT_ContextFlux2Node,
|
||||
TT_ContextSetGuiderNode,
|
||||
TT_ContextSetImageNode,
|
||||
TT_ContextSetLatentNode,
|
||||
TT_ContextExtractEncoderFlux2Node,
|
||||
TT_ContextExtractGuidedSamplerFlux2Node,
|
||||
TT_ContextExtractVaeNode,
|
||||
TT_ContextExtractImageNode,
|
||||
]
|
||||
|
||||
|
||||
async def comfy_entrypoint() -> ContextNodesExtension:
|
||||
return ContextNodesExtension()
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
# Re-exports for backward compatibility
|
||||
# ==============================================================================
|
||||
|
||||
__all__ = [
|
||||
"TT_BaseContextNode",
|
||||
"TT_BaseContextFlux2Node",
|
||||
"TT_ContextPassthroughNode",
|
||||
"TT_ContextNode",
|
||||
"TT_ContextFlux2Node",
|
||||
"TT_ContextSetGuiderNode",
|
||||
"TT_ContextSetImageNode",
|
||||
"TT_ContextSetLatentNode",
|
||||
"TT_ContextExtractEncoderFlux2Node",
|
||||
"TT_ContextExtractGuidedSamplerFlux2Node",
|
||||
"TT_ContextExtractVaeNode",
|
||||
"TT_ContextExtractImageNode",
|
||||
NODES = [
|
||||
TT_BaseContextNode,
|
||||
TT_BaseContextFlux2Node,
|
||||
TT_ContextPassthroughNode,
|
||||
TT_ContextNode,
|
||||
TT_ContextFlux2Node,
|
||||
TT_ContextSetGuiderNode,
|
||||
TT_ContextSetImageNode,
|
||||
TT_ContextSetLatentNode,
|
||||
TT_ContextExtractEncoderFlux2Node,
|
||||
TT_ContextExtractGuidedSamplerFlux2Node,
|
||||
TT_ContextExtractVaeNode,
|
||||
TT_ContextExtractImageNode,
|
||||
]
|
||||
|
||||
+4
-22
@@ -1,10 +1,9 @@
|
||||
# (c) TenserTensor <tenser.tensor@proton.me> || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from typing import override
|
||||
|
||||
import folder_paths
|
||||
from comfy import controlnet
|
||||
from comfy_api.latest import io, ui, ComfyExtension
|
||||
|
||||
from .nodes_image import SingleCondCFGGuider, get_image_files, load_image
|
||||
|
||||
CATEGORY = "TenserTensor/ControlNet"
|
||||
@@ -170,24 +169,7 @@ class TT_Flux2ApplyControlNetAdvancedNode(io.ComfyNode):
|
||||
# V3 entrypoint — registers context nodes with ComfyUI
|
||||
# ==============================================================================
|
||||
|
||||
class ControlNetNodesExtension(ComfyExtension):
|
||||
@override
|
||||
async def get_node_list(self) -> list[type[io.ComfyNode]]:
|
||||
return [
|
||||
TT_Flux2ApplyControlNetNode,
|
||||
TT_Flux2ApplyControlNetAdvancedNode,
|
||||
]
|
||||
|
||||
|
||||
async def comfy_entrypoint() -> ControlNetNodesExtension:
|
||||
return ControlNetNodesExtension()
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
# Re-exports for backward compatibility
|
||||
# ==============================================================================
|
||||
|
||||
__all__ = [
|
||||
"TT_Flux2ApplyControlNetNode",
|
||||
"TT_Flux2ApplyControlNetAdvancedNode",
|
||||
NODES = [
|
||||
TT_Flux2ApplyControlNetNode,
|
||||
TT_Flux2ApplyControlNetAdvancedNode,
|
||||
]
|
||||
|
||||
+4
-22
@@ -1,12 +1,10 @@
|
||||
# (c) TenserTensor <tenser.tensor@proton.me> || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
|
||||
from typing import override
|
||||
|
||||
from kornia.filters import canny
|
||||
|
||||
from comfy import model_management
|
||||
from comfy_api.latest import io, ui, ComfyExtension
|
||||
from kornia.filters import canny
|
||||
|
||||
from .nodes_image import get_image_files, load_image
|
||||
|
||||
CATEGORY = "TenserTensor/Detector"
|
||||
@@ -51,22 +49,6 @@ class TT_CannyEdgeDetectorNode(io.ComfyNode):
|
||||
# V3 entrypoint — registers context nodes with ComfyUI
|
||||
# ==============================================================================
|
||||
|
||||
class DetectorNodesExtension(ComfyExtension):
|
||||
@override
|
||||
async def get_node_list(self) -> list[type[io.ComfyNode]]:
|
||||
return [
|
||||
TT_CannyEdgeDetectorNode,
|
||||
]
|
||||
|
||||
|
||||
async def comfy_entrypoint() -> DetectorNodesExtension:
|
||||
return DetectorNodesExtension()
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
# Re-exports for backward compatibility
|
||||
# ==============================================================================
|
||||
|
||||
__all__ = [
|
||||
"TT_CannyEdgeDetectorNode",
|
||||
NODES = [
|
||||
TT_CannyEdgeDetectorNode,
|
||||
]
|
||||
|
||||
+9
-28
@@ -5,17 +5,17 @@ import math
|
||||
import os
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import override, Any
|
||||
from typing import Any
|
||||
|
||||
import folder_paths
|
||||
import numpy
|
||||
import torch
|
||||
from PIL import Image, ImageOps, ImageSequence
|
||||
from spandrel import ModelLoader, ImageModelDescriptor
|
||||
|
||||
import folder_paths
|
||||
from comfy import model_management, utils
|
||||
from comfy_api.latest import ComfyExtension, io, ui
|
||||
from node_helpers import conditioning_set_values, pillow
|
||||
from spandrel import ModelLoader, ImageModelDescriptor
|
||||
|
||||
from .nodes_text_encoder import SingleCondCFGGuider
|
||||
from .nodes_vae import vae_encode
|
||||
|
||||
@@ -478,28 +478,9 @@ class TT_GuiderImageReferenceNode(io.ComfyNode):
|
||||
# V3 entrypoint — registers context nodes with ComfyUI
|
||||
# ==============================================================================
|
||||
|
||||
class ImageNodesExtension(ComfyExtension):
|
||||
@override
|
||||
async def get_node_list(self) -> list[type[io.ComfyNode]]:
|
||||
return [
|
||||
TT_ImageLoaderResizerNode,
|
||||
TT_ImagePreviewSaveNode,
|
||||
TT_ImagePreviewUpscaleSaveNode,
|
||||
TT_GuiderImageReferenceNode,
|
||||
]
|
||||
|
||||
|
||||
async def comfy_entrypoint() -> ImageNodesExtension:
|
||||
return ImageNodesExtension()
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
# Re-exports for backward compatibility
|
||||
# ==============================================================================
|
||||
|
||||
__all__ = [
|
||||
"TT_ImageLoaderResizerNode",
|
||||
"TT_ImagePreviewSaveNode",
|
||||
"TT_ImagePreviewUpscaleSaveNode",
|
||||
"TT_GuiderImageReferenceNode",
|
||||
NODES = [
|
||||
TT_ImageLoaderResizerNode,
|
||||
TT_ImagePreviewSaveNode,
|
||||
TT_ImagePreviewUpscaleSaveNode,
|
||||
TT_GuiderImageReferenceNode,
|
||||
]
|
||||
|
||||
+7
-26
@@ -1,13 +1,13 @@
|
||||
# (c) TenserTensor <tenser.tensor@proton.me> || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
import math
|
||||
from typing import Any, override
|
||||
from typing import Any
|
||||
|
||||
import torch
|
||||
|
||||
from comfy import sample, utils
|
||||
from comfy.latent_formats import SDXL, Flux, Flux2, SD3
|
||||
from comfy_api.latest import io, ComfyExtension
|
||||
|
||||
from .nodes_image import MEGAPIXELS, resize_image, rotate_image, flip_image
|
||||
from .nodes_vae import vae_decode, vae_encode
|
||||
|
||||
@@ -323,28 +323,9 @@ class TT_LatentMultiTransformOnPixelSpaceNode(io.ComfyNode):
|
||||
# V3 entrypoint — registers context nodes with ComfyUI
|
||||
# ==============================================================================
|
||||
|
||||
class LatentNodesExtension(ComfyExtension):
|
||||
@override
|
||||
async def get_node_list(self) -> list[type[io.ComfyNode]]:
|
||||
return [
|
||||
TT_LatentFactoryNode,
|
||||
TT_LatentFactoryByModelNode,
|
||||
TT_LatentMultiTransformNode,
|
||||
TT_LatentMultiTransformOnPixelSpaceNode,
|
||||
]
|
||||
|
||||
|
||||
async def comfy_entrypoint() -> LatentNodesExtension:
|
||||
return LatentNodesExtension()
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
# Re-exports for backward compatibility
|
||||
# ==============================================================================
|
||||
|
||||
__all__ = [
|
||||
"TT_LatentFactoryNode",
|
||||
"TT_LatentFactoryByModelNode",
|
||||
"TT_LatentMultiTransformNode",
|
||||
"TT_LatentMultiTransformOnPixelSpaceNode",
|
||||
NODES = [
|
||||
TT_LatentFactoryNode,
|
||||
TT_LatentFactoryByModelNode,
|
||||
TT_LatentMultiTransformNode,
|
||||
TT_LatentMultiTransformOnPixelSpaceNode,
|
||||
]
|
||||
|
||||
+12
-36
@@ -8,14 +8,13 @@
|
||||
import collections
|
||||
import inspect
|
||||
import os
|
||||
from typing import override
|
||||
|
||||
import torch
|
||||
from torch import bfloat16, float16, float32, float8_e4m3fn, float8_e5m2, device, tensor
|
||||
|
||||
import folder_paths
|
||||
import torch
|
||||
from comfy import sd, model_management, utils, model_sampling, model_patcher, lora, float
|
||||
from comfy_api.latest import io, ComfyExtension
|
||||
from torch import bfloat16, float16, float32, float8_e4m3fn, float8_e5m2, device, tensor
|
||||
|
||||
from nodes import VAELoader, MAX_RESOLUTION
|
||||
from .gguf.dequant import is_quantized, is_torch_compatible
|
||||
from .gguf.loader import gguf_sd_loader, gguf_clip_loader
|
||||
@@ -775,36 +774,13 @@ class TT_Sd35GgufModelsLoaderAdvancedNode(io.ComfyNode):
|
||||
# V3 entrypoint — registers context nodes with ComfyUI
|
||||
# ==============================================================================
|
||||
|
||||
class LoaderNodesExtension(ComfyExtension):
|
||||
@override
|
||||
async def get_node_list(self) -> list[type[io.ComfyNode]]:
|
||||
return [
|
||||
TT_SdxlModelsLoaderNode,
|
||||
TT_SdxlModelsLoaderAdvancedNode,
|
||||
TT_FluxModelsLoaderNode,
|
||||
TT_FluxModelsLoaderAdvancedNode,
|
||||
TT_Flux2GgufModelsLoaderNode,
|
||||
TT_Flux2GgufModelsLoaderAdvancedNode,
|
||||
TT_Sd35GgufModelsLoaderNode,
|
||||
TT_Sd35GgufModelsLoaderAdvancedNode,
|
||||
]
|
||||
|
||||
|
||||
async def comfy_entrypoint() -> LoaderNodesExtension:
|
||||
return LoaderNodesExtension()
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
# Re-exports for backward compatibility
|
||||
# ==============================================================================
|
||||
|
||||
__all__ = [
|
||||
"TT_SdxlModelsLoaderNode",
|
||||
"TT_SdxlModelsLoaderAdvancedNode",
|
||||
"TT_FluxModelsLoaderNode",
|
||||
"TT_FluxModelsLoaderAdvancedNode",
|
||||
"TT_Flux2GgufModelsLoaderNode",
|
||||
"TT_Flux2GgufModelsLoaderAdvancedNode",
|
||||
"TT_Sd35GgufModelsLoaderNode",
|
||||
"TT_Sd35GgufModelsLoaderAdvancedNode",
|
||||
NODES = [
|
||||
TT_SdxlModelsLoaderNode,
|
||||
TT_SdxlModelsLoaderAdvancedNode,
|
||||
TT_FluxModelsLoaderNode,
|
||||
TT_FluxModelsLoaderAdvancedNode,
|
||||
TT_Flux2GgufModelsLoaderNode,
|
||||
TT_Flux2GgufModelsLoaderAdvancedNode,
|
||||
TT_Sd35GgufModelsLoaderNode,
|
||||
TT_Sd35GgufModelsLoaderAdvancedNode,
|
||||
]
|
||||
|
||||
+9
-31
@@ -1,15 +1,14 @@
|
||||
# (c) TenserTensor <tenser.tensor@proton.me> || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from pathlib import Path
|
||||
from typing import override
|
||||
|
||||
import colour
|
||||
import folder_paths
|
||||
import kornia
|
||||
import torch
|
||||
from comfy_api.latest import ComfyExtension, io
|
||||
from torch.nn import functional
|
||||
|
||||
import folder_paths
|
||||
from comfy_api.latest import ComfyExtension, io
|
||||
from .nodes_image import DEVICES, RESIZE_METHODS, get_upscale_models, upscale
|
||||
|
||||
CATEGORY = "TenserTensor/Postproduction"
|
||||
@@ -460,32 +459,11 @@ class TT_PostproductionAdvancedNode(io.ComfyNode):
|
||||
# V3 entrypoint — registers context nodes with ComfyUI
|
||||
# ==============================================================================
|
||||
|
||||
class PostproductionNodesExtension(ComfyExtension):
|
||||
@override
|
||||
async def get_node_list(self) -> list[type[io.ComfyNode]]:
|
||||
return [
|
||||
TT_AddFilmGrainNode,
|
||||
TT_ApplyLutNode,
|
||||
TT_ImageEnhancerNode,
|
||||
TT_QuickImageUpscalerNode,
|
||||
TT_PostproductionNode,
|
||||
TT_PostproductionAdvancedNode,
|
||||
]
|
||||
|
||||
|
||||
async def comfy_entrypoint() -> PostproductionNodesExtension:
|
||||
return PostproductionNodesExtension()
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
# Re-exports for backward compatibility
|
||||
# ==============================================================================
|
||||
|
||||
__all__ = [
|
||||
"TT_AddFilmGrainNode",
|
||||
'TT_ApplyLutNode',
|
||||
'TT_ImageEnhancerNode',
|
||||
'TT_QuickImageUpscalerNode',
|
||||
'TT_PostproductionNode',
|
||||
'TT_PostproductionAdvancedNode',
|
||||
NODES = [
|
||||
TT_AddFilmGrainNode,
|
||||
TT_ApplyLutNode,
|
||||
TT_ImageEnhancerNode,
|
||||
TT_QuickImageUpscalerNode,
|
||||
TT_PostproductionNode,
|
||||
TT_PostproductionAdvancedNode,
|
||||
]
|
||||
|
||||
+9
-32
@@ -1,12 +1,10 @@
|
||||
# (c) TenserTensor <tenser.tensor@proton.me> || Apache-2.0 (apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
from typing import override
|
||||
|
||||
import torch
|
||||
|
||||
import latent_preview
|
||||
import torch
|
||||
from comfy import sample, model_management, samplers
|
||||
from comfy_api.latest import ComfyExtension, io
|
||||
|
||||
from .nodes_context import Context
|
||||
from .nodes_latent import SCALE_FACTORS, SCALE_METHODS, scale_latent
|
||||
from .nodes_text_encoder import SingleCondCFGGuider
|
||||
@@ -368,32 +366,11 @@ class TT_GuidedUpscaleKSamplerNode(io.ComfyNode):
|
||||
# V3 entrypoint — registers context nodes with ComfyUI
|
||||
# ==============================================================================
|
||||
|
||||
class SamplingNodesExtension(ComfyExtension):
|
||||
@override
|
||||
async def get_node_list(self) -> list[type[io.ComfyNode]]:
|
||||
return [
|
||||
TT_KSamplerNode,
|
||||
TT_KSamplerAdvancedNode,
|
||||
TT_KSamplerContextNode,
|
||||
TT_KSamplerTwoStageNode,
|
||||
TT_GuidedKSamplerNode,
|
||||
TT_GuidedUpscaleKSamplerNode,
|
||||
]
|
||||
|
||||
|
||||
async def comfy_entrypoint() -> SamplingNodesExtension:
|
||||
return SamplingNodesExtension()
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
# Re-exports for backward compatibility
|
||||
# ==============================================================================
|
||||
|
||||
__all__ = [
|
||||
"TT_KSamplerNode",
|
||||
"TT_KSamplerAdvancedNode",
|
||||
"TT_KSamplerContextNode",
|
||||
"TT_KSamplerTwoStageNode",
|
||||
"TT_GuidedKSamplerNode",
|
||||
"TT_GuidedUpscaleKSamplerNode",
|
||||
NODES = [
|
||||
TT_KSamplerNode,
|
||||
TT_KSamplerAdvancedNode,
|
||||
TT_KSamplerContextNode,
|
||||
TT_KSamplerTwoStageNode,
|
||||
TT_GuidedKSamplerNode,
|
||||
TT_GuidedUpscaleKSamplerNode,
|
||||
]
|
||||
|
||||
+10
-32
@@ -4,6 +4,7 @@ from typing import override
|
||||
|
||||
from comfy import samplers
|
||||
from comfy_api.latest import io, ComfyExtension
|
||||
|
||||
from nodes import MAX_RESOLUTION
|
||||
from .nodes_context import Context
|
||||
|
||||
@@ -413,36 +414,13 @@ class TT_Sd35TextEncoderContextNode(io.ComfyNode):
|
||||
# V3 entrypoint — registers context nodes with ComfyUI
|
||||
# ==============================================================================
|
||||
|
||||
class TextEncodeNodesExtension(ComfyExtension):
|
||||
@override
|
||||
async def get_node_list(self) -> list[type[io.ComfyNode]]:
|
||||
return [
|
||||
TT_SdxlClipTextEncoderNode,
|
||||
TT_SdxlClipTextEncoderContextNode,
|
||||
TT_Flux1ClipTextEncoderNode,
|
||||
TT_Flux1ClipTextEncoderContextNode,
|
||||
TT_Flux2TextEncoderNode,
|
||||
TT_Flux2TextEncoderContextNode,
|
||||
TT_Sd35TextEncoderNode,
|
||||
TT_Sd35TextEncoderContextNode,
|
||||
]
|
||||
|
||||
|
||||
async def comfy_entrypoint() -> TextEncodeNodesExtension:
|
||||
return TextEncodeNodesExtension()
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
# Re-exports for backward compatibility
|
||||
# ==============================================================================
|
||||
|
||||
__all__ = [
|
||||
"TT_SdxlClipTextEncoderNode",
|
||||
"TT_SdxlClipTextEncoderContextNode",
|
||||
"TT_Flux1ClipTextEncoderNode",
|
||||
"TT_Flux1ClipTextEncoderContextNode",
|
||||
"TT_Flux2TextEncoderNode",
|
||||
"TT_Flux2TextEncoderContextNode",
|
||||
"TT_Sd35TextEncoderNode",
|
||||
"TT_Sd35TextEncoderContextNode",
|
||||
NODES = [
|
||||
TT_SdxlClipTextEncoderNode,
|
||||
TT_SdxlClipTextEncoderContextNode,
|
||||
TT_Flux1ClipTextEncoderNode,
|
||||
TT_Flux1ClipTextEncoderContextNode,
|
||||
TT_Flux2TextEncoderNode,
|
||||
TT_Flux2TextEncoderContextNode,
|
||||
TT_Sd35TextEncoderNode,
|
||||
TT_Sd35TextEncoderContextNode,
|
||||
]
|
||||
|
||||
@@ -159,6 +159,11 @@ class TT_VaeEncodeContextNode(io.ComfyNode):
|
||||
# V3 entrypoint — registers context nodes with ComfyUI
|
||||
# ==============================================================================
|
||||
|
||||
NODES=[]
|
||||
|
||||
|
||||
|
||||
|
||||
class VaeNodesExtension(ComfyExtension):
|
||||
@override
|
||||
async def get_node_list(self) -> list[type[io.ComfyNode]]:
|
||||
|
||||
+9
-34
@@ -3,10 +3,8 @@
|
||||
import dataclasses
|
||||
import math
|
||||
from dataclasses import dataclass
|
||||
from typing import override
|
||||
|
||||
import torch
|
||||
|
||||
from comfy.samplers import KSampler, sampler_object, Sampler
|
||||
from comfy_api.latest import io, ComfyExtension
|
||||
from nodes import MAX_RESOLUTION
|
||||
@@ -560,36 +558,13 @@ class TT_Sd35GgufWorkflowSettingsAdvancedNode(io.ComfyNode):
|
||||
# V3 entrypoint — registers context nodes with ComfyUI
|
||||
# ==============================================================================
|
||||
|
||||
class WorkflowNodesExtension(ComfyExtension):
|
||||
@override
|
||||
async def get_node_list(self) -> list[type[io.ComfyNode]]:
|
||||
return [
|
||||
TT_SdxlWorkflowSettingsNode,
|
||||
TT_SdxlWorkflowSettingsAdvancedNode,
|
||||
TT_FluxWorkflowSettingsNode,
|
||||
TT_FluxWorkflowSettingsAdvancedNode,
|
||||
TT_Flux2WorkflowSettingsNode,
|
||||
TT_Flux2WorkflowSettingsAdvancedNode,
|
||||
TT_Sd35GgufWorkflowSettingsNode,
|
||||
TT_Sd35GgufWorkflowSettingsAdvancedNode,
|
||||
]
|
||||
|
||||
|
||||
async def comfy_entrypoint() -> WorkflowNodesExtension:
|
||||
return WorkflowNodesExtension()
|
||||
|
||||
|
||||
# ==============================================================================
|
||||
# Re-exports for backward compatibility
|
||||
# ==============================================================================
|
||||
|
||||
__all__ = [
|
||||
"TT_SdxlWorkflowSettingsNode",
|
||||
"TT_SdxlWorkflowSettingsAdvancedNode",
|
||||
"TT_FluxWorkflowSettingsNode",
|
||||
"TT_FluxWorkflowSettingsAdvancedNode",
|
||||
"TT_Flux2WorkflowSettingsNode",
|
||||
"TT_Flux2WorkflowSettingsAdvancedNode",
|
||||
"TT_Sd35GgufWorkflowSettingsNode",
|
||||
"TT_Sd35GgufWorkflowSettingsAdvancedNode",
|
||||
NODES = [
|
||||
TT_SdxlWorkflowSettingsNode,
|
||||
TT_SdxlWorkflowSettingsAdvancedNode,
|
||||
TT_FluxWorkflowSettingsNode,
|
||||
TT_FluxWorkflowSettingsAdvancedNode,
|
||||
TT_Flux2WorkflowSettingsNode,
|
||||
TT_Flux2WorkflowSettingsAdvancedNode,
|
||||
TT_Sd35GgufWorkflowSettingsNode,
|
||||
TT_Sd35GgufWorkflowSettingsAdvancedNode,
|
||||
]
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
## TT Add Film Grain *TT_AddFilmGrain*
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Add procedural film grain texture to images for a cinematic look.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|----------------|---------|----------|---------------------------------------------------------------------------------|
|
||||
| `image` | IMAGE | Yes | Input image to add grain to |
|
||||
| `seed` | INT | Yes | Random seed for grain pattern (0 to 2^64-1, default: 0) |
|
||||
| `scale` | FLOAT | Yes | Scale of grain texture (0.25-2.0, default: 0.25) |
|
||||
| `strength` | FLOAT | Yes | Intensity of grain effect (0.0-10.0, default: 0.15) |
|
||||
| `saturation` | FLOAT | Yes | Color saturation of grain (0.0-2.0, default: 0.2) |
|
||||
| `toe` | FLOAT | Yes | Toe adjustment for grain distribution (-0.2 to 0.5, default: 0.0) |
|
||||
| `upscale_mode` | STRING | Yes | Interpolation mode for grain (bilinear/bicubic/lanczos/nearest/area) - advanced |
|
||||
| `antialias` | BOOLEAN | Yes | Enable antialiasing for grain (default: False) |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|-------|-------------------------------|
|
||||
| `IMAGE` | IMAGE | Image with applied film grain |
|
||||
|
||||
### Usage
|
||||
|
||||
Add realistic film grain texture to images for a cinematic aesthetic. Adjust scale for grain size, strength for
|
||||
intensity, and saturation for color. The toe parameter controls the distribution curve of grain in shadows/highlights.
|
||||
Use different seeds for varied grain patterns.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -1,30 +0,0 @@
|
||||
## TT Apply LUT *TT_ApplyLut*
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Apply color grading LUT (Look-Up Table) to images for professional color correction.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|--------------|----------|----------|----------------------------------------------------------------|
|
||||
| `image` | IMAGE | Yes | Input image to apply LUT to |
|
||||
| `lut_file` | LUT_FILE | Yes | LUT file to apply (from LUT directory) - advanced |
|
||||
| `strength` | FLOAT | Yes | Blend strength of LUT effect (0.0-1.0, default: 1.0) |
|
||||
| `colorspace` | STRING | Yes | Colorspace for LUT application (linear/logarithmic) - advanced |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|-------|--------------------------------------|
|
||||
| `IMAGE` | IMAGE | Image with applied LUT color grading |
|
||||
|
||||
### Usage
|
||||
|
||||
Apply professional color grading using LUT files. Place your .cube LUT files in the designated LUT directory. Adjust
|
||||
strength to blend between original and graded image (1.0 = full LUT, 0.0 = original). Choose colorspace based on your
|
||||
LUT file's intended working space.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -1,32 +0,0 @@
|
||||
## TT Base Context *TT_BaseContext*
|
||||
|
||||
⚠️ Deprecated: This node will be removed in a future major release. Please migrate to the new context nodes.
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Creates a foundational context object by combining essential workflow components.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-------------------|--------------------|----------|---------------------------------|
|
||||
| `model` | MODEL | Yes | The diffusion model (UNet/DiT) |
|
||||
| `clip` | CLIP | Yes | CLIP text encoder |
|
||||
| `vae` | VAE | Yes | VAE for encoding/decoding |
|
||||
| `latent` | LATENT | Yes | Latent image tensor |
|
||||
| `workflow_config` | TT_WORKFLOW_CONFIG | No | Workflow configuration settings |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------------|--------------------------------------------|
|
||||
| `CONTEXT` | TT_CONTEXT | Dictionary containing all input components |
|
||||
|
||||
### Usage
|
||||
|
||||
Use this node to package your core workflow components into a single context object that can be passed through your
|
||||
workflow and modified by other context nodes.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -1,32 +0,0 @@
|
||||
## TT CLIP Text Encode FLUX *TT_ClipTextEncodeFlux*
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Flux text encoder with separate CLIP-L and T5-XXL prompt inputs.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-------------------|--------|----------|--------------------------------------------------|
|
||||
| `clip` | CLIP | Yes | CLIP text encoder (dual CLIP-L + T5-XXL) |
|
||||
| `clip_l_positive` | STRING | Yes | CLIP-L positive prompt (multiline) |
|
||||
| `t5xxl_positive` | STRING | Yes | T5-XXL positive prompt (multiline) |
|
||||
| `clip_l_negative` | STRING | Yes | CLIP-L negative prompt (multiline) |
|
||||
| `t5xxl_negative` | STRING | Yes | T5-XXL negative prompt (multiline) |
|
||||
| `guidance` | FLOAT | Yes | Guidance scale for Flux (1.0-10.0, default: 3.5) |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|------------|--------------|------------------------------------------|
|
||||
| `POSITIVE` | CONDITIONING | Positive conditioning from both encoders |
|
||||
| `NEGATIVE` | CONDITIONING | Negative conditioning from both encoders |
|
||||
|
||||
### Usage
|
||||
|
||||
Encode text prompts for Flux with fine-grained control over CLIP-L and T5-XXL inputs separately. Useful when you want
|
||||
different prompts for each encoder or need precise control over the conditioning process.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -1,31 +0,0 @@
|
||||
## TT Clip Text Encode Flux2 *TT_ClipTextEncodeFlux2*
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Text prompt encoder for FLUX2 models with LoRA trigger word support and built-in guidance configuration.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------------|--------|----------|--------------------------------------------------------------|
|
||||
| `model` | MODEL | Yes | Diffusion model |
|
||||
| `clip` | CLIP | Yes | CLIP model for text encoding |
|
||||
| `prompt` | STRING | Yes | Main generation prompt (multiline, supports dynamic prompts) |
|
||||
| `lora_triggers` | STRING | Yes | LoRA trigger words (multiline, supports dynamic prompts) |
|
||||
| `guidance` | FLOAT | Yes | Guidance scale for generation (1.0–10.0, default: 3.5) |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|--------|----------------------------------------------------|
|
||||
| `GUIDER` | GUIDER | Configured guider with encoded prompt and guidance |
|
||||
|
||||
### Usage
|
||||
|
||||
Encodes text prompts specifically for FLUX2 models. Enter your main prompt in `prompt` and any LoRA-specific trigger
|
||||
words separately in `lora_triggers` — the node combines them internally. Adjust `guidance` to control how strongly
|
||||
the model follows the prompt (3.5 is a good starting point for FLUX2).
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -1,29 +0,0 @@
|
||||
## TT Clip Text Encode Flux2 (Context) *TT_ClipTextEncodeFlux2Context*
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Context-based text prompt encoder for FLUX2 models. Extracts model, CLIP, and prompt configuration directly from a TT_CONTEXT object.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------------|----------|---------------------------------------------------------------------------------------|
|
||||
| `context` | TT_CONTEXT | Yes | Context object containing `model`, `clip`, and `workflow_config` with prompt settings |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------------|----------------------------------------------------|
|
||||
| `CONTEXT` | TT_CONTEXT | Updated context with `guider` written back into it |
|
||||
| `GUIDER` | GUIDER | Configured guider with encoded prompt and guidance |
|
||||
|
||||
### Usage
|
||||
|
||||
Context-aware version of the FLUX2 text encoder. Instead of individual inputs, it reads `model`, `clip`, and
|
||||
`workflow_config` (containing `prompt`, `lora_triggers`, and `guidance`) from the passed `context`. The resulting
|
||||
guider is both returned as an output and stored back into the context under the `guider` key. Raises an error if
|
||||
any of the required fields are missing from the context.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -1,34 +0,0 @@
|
||||
## TT CLIP Text Encode FLUX (Context) *TT_ClipTextEncodeFluxContext*
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Context-based Flux text encoder that extracts prompts from workflow config.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------------|----------|------------------------------------------------------------------|
|
||||
| `context` | TT_CONTEXT | Yes | Context containing CLIP encoder and workflow config with prompts |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|------------|--------------|-----------------------------------------------------------|
|
||||
| `CONTEXT` | TT_CONTEXT | Updated context with positive/negative conditioning added |
|
||||
| `POSITIVE` | CONDITIONING | Positive conditioning from both encoders |
|
||||
| `NEGATIVE` | CONDITIONING | Negative conditioning from both encoders |
|
||||
|
||||
### Usage
|
||||
|
||||
Simplified encoder for context-based workflows. Automatically extracts CLIP-L and T5-XXL prompts plus guidance from
|
||||
workflow_config:
|
||||
|
||||
- `clip_l_positive`, `t5xxl_positive` for positive prompts
|
||||
- `clip_l_negative`, `t5xxl_negative` for negative prompts
|
||||
- `guidance` for Flux guidance scale
|
||||
|
||||
Updates context with the generated conditioning and also returns them separately for convenient access.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -1,37 +0,0 @@
|
||||
## TT CLIP Text Encode SDXL *TT_ClipTextEncodeSdxl*
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
SDXL text encoder with separate CLIP-L and CLIP-G prompt inputs and conditioning parameters.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-------------------|--------|----------|---------------------------------------------------------|
|
||||
| `clip` | CLIP | Yes | CLIP text encoder (dual CLIP-L + CLIP-G) |
|
||||
| `clip_l_positive` | STRING | Yes | CLIP-L positive prompt (multiline) |
|
||||
| `clip_g_positive` | STRING | Yes | CLIP-G positive prompt (multiline) |
|
||||
| `clip_l_negative` | STRING | Yes | CLIP-L negative prompt (multiline) |
|
||||
| `clip_g_negative` | STRING | Yes | CLIP-G negative prompt (multiline) |
|
||||
| `ascore_positive` | FLOAT | Yes | Aesthetic score for positive (0.0-1000.0, default: 9.0) |
|
||||
| `ascore_negative` | FLOAT | Yes | Aesthetic score for negative (0.0-1000.0, default: 6.0) |
|
||||
| `width` | INT | Yes | Image width for conditioning (default: 512) |
|
||||
| `height` | INT | Yes | Image height for conditioning (default: 512) |
|
||||
| `target_width` | INT | Yes | Target width for conditioning (default: 512) |
|
||||
| `target_height` | INT | Yes | Target height for conditioning (default: 512) |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|------------|--------------|-----------------------------------------------------------|
|
||||
| `POSITIVE` | CONDITIONING | Positive conditioning with aesthetic score and dimensions |
|
||||
| `NEGATIVE` | CONDITIONING | Negative conditioning with aesthetic score and dimensions |
|
||||
|
||||
### Usage
|
||||
|
||||
Encode text prompts for SDXL with separate control over CLIP-L and CLIP-G inputs, aesthetic scores, and target
|
||||
dimensions. The aesthetic scores and dimensions are embedded into the conditioning to guide the generation process.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -1,35 +0,0 @@
|
||||
## TT CLIP Text Encode SDXL (Context) *TT_ClipTextEncodeSdxlContext*
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Context-based SDXL text encoder that extracts prompts and parameters from workflow config.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------------|----------|---------------------------------------------------------------------------------|
|
||||
| `context` | TT_CONTEXT | Yes | Context containing CLIP encoder and workflow config with prompts and parameters |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|------------|--------------|-----------------------------------------------------------|
|
||||
| `CONTEXT` | TT_CONTEXT | Updated context with positive/negative conditioning added |
|
||||
| `POSITIVE` | CONDITIONING | Positive conditioning with aesthetic score and dimensions |
|
||||
| `NEGATIVE` | CONDITIONING | Negative conditioning with aesthetic score and dimensions |
|
||||
|
||||
### Usage
|
||||
|
||||
Simplified encoder for context-based SDXL workflows. Automatically extracts all encoding parameters from
|
||||
workflow_config:
|
||||
|
||||
- `clip_l_positive`, `clip_g_positive` for positive prompts
|
||||
- `clip_l_negative`, `clip_g_negative` for negative prompts
|
||||
- `ascore_positive`, `ascore_negative` for aesthetic scores
|
||||
- `width`, `height`, `target_width`, `target_height` for dimensions
|
||||
|
||||
Updates context with the generated conditioning and also returns them separately for convenient access.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -1,55 +0,0 @@
|
||||
## TT Context *TT_Context*
|
||||
|
||||
⚠️ Deprecated: This node will be removed in a future major release. Please migrate to the new context nodes.
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Standard context node that can create a new context or modify an existing one.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-------------------|--------------------|----------|-----------------------------------------------------------|
|
||||
| `context` | TT_CONTEXT | No | Existing context to modify (if not provided, creates new) |
|
||||
| `workflow_config` | TT_WORKFLOW_CONFIG | No | Workflow configuration settings |
|
||||
| `model` | MODEL | No | The diffusion model (UNet/DiT) |
|
||||
| `clip` | CLIP | No | CLIP text encoder |
|
||||
| `vae` | VAE | No | VAE for encoding/decoding |
|
||||
| `positive` | CONDITIONING | No | Positive conditioning |
|
||||
| `negative` | CONDITIONING | No | Negative conditioning |
|
||||
| `latent` | LATENT | No | Latent image tensor |
|
||||
| `image` | IMAGE | No | Image tensor |
|
||||
| `seed` | INT | No | Random seed |
|
||||
| `steps` | INT | No | Sampling steps |
|
||||
| `cfg` | FLOAT | No | Classifier-free guidance scale |
|
||||
| `sampler_name` | COMBO | No | Sampler name |
|
||||
| `scheduler` | COMBO | No | Scheduler name |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-------------------|--------------------|-----------------------------|
|
||||
| `CONTEXT` | TT_CONTEXT | Created or modified context |
|
||||
| `WORKFLOW_CONFIG` | TT_WORKFLOW_CONFIG | Workflow configuration |
|
||||
| `MODEL` | MODEL | Diffusion model |
|
||||
| `CLIP` | CLIP | Text encoder |
|
||||
| `VAE` | VAE | VAE |
|
||||
| `POSITIVE` | CONDITIONING | Positive conditioning |
|
||||
| `NEGATIVE` | CONDITIONING | Negative conditioning |
|
||||
| `LATENT` | LATENT | Latent tensor |
|
||||
| `IMAGE` | IMAGE | Image tensor |
|
||||
| `SEED` | INT | Random seed |
|
||||
| `STEPS` | INT | Sampling steps |
|
||||
| `CFG` | FLOAT | CFG scale |
|
||||
| `SAMPLER_NAME` | COMBO | Sampler name |
|
||||
| `SCHEDULER` | COMBO | Scheduler name |
|
||||
|
||||
### Usage
|
||||
|
||||
Use this node to create a new context from scratch or modify specific parameters in an existing context. All parameters
|
||||
are optional - provide only what you need to set or change.
|
||||
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -1,32 +0,0 @@
|
||||
## TT Context Extract Encoder FLUX2 *TT_ContextExtractEncoderFlux2*
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Extracts model, clip, prompt, LoRA triggers, and guidance from the context for direct connection to a FLUX2
|
||||
text encoder node.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------------|----------|----------------|
|
||||
| `context` | TT_CONTEXT | Yes | Context object |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------------|------------|---------------------------------|
|
||||
| `CONTEXT` | TT_CONTEXT | Passthrough context object |
|
||||
| `MODEL` | MODEL | Diffusion model |
|
||||
| `CLIP` | CLIP | CLIP text encoder |
|
||||
| `PROMPT` | STRING | Main generation prompt |
|
||||
| `LORA_TRIGGERS` | STRING | LoRA trigger words |
|
||||
| `GUIDANCE` | FLOAT | Guidance scale for text encoder |
|
||||
|
||||
### Usage
|
||||
|
||||
Use this node to extract encoding parameters from the context and connect them directly to a FLUX2 text
|
||||
encoder node without manually routing each wire.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -0,0 +1,30 @@
|
||||
## TT Context Extract Encoder (FLUX2) *TT_ContextExtractEncoderFlux2Node*
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Extracts model, CLIP, and encoding parameters from a context object for use with a FLUX2 text encoder node.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------------|----------|----------------------------------------------|
|
||||
| `context` | TT_CONTEXT | Yes | Context object from an upstream context node |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------------|------------|---------------------|
|
||||
| `CONTEXT` | TT_CONTEXT | Context passthrough |
|
||||
| `MODEL` | MODEL | Diffusion model |
|
||||
| `CLIP` | CLIP | CLIP text encoder |
|
||||
| `PROMPT` | STRING | Text prompt |
|
||||
| `LORA_TRIGGERS` | STRING | LoRA trigger words |
|
||||
| `GUIDANCE` | FLOAT | Guidance scale |
|
||||
|
||||
### Usage
|
||||
|
||||
Connect `CONTEXT` from a FLUX2 context node. Connect outputs to a FLUX2 text encoder node.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -0,0 +1,30 @@
|
||||
## TT Context Extract Guided Sampler (FLUX2) *TT_ContextExtractGuidedSamplerFlux2Node*
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Extracts latent, guider, sigmas, sampler, and noise from a context object for use with a FLUX2 guided sampler node.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------------|----------|----------------------------------------------|
|
||||
| `context` | TT_CONTEXT | Yes | Context object from an upstream context node |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-------------|------------|-------------------------------------|
|
||||
| `CONTEXT` | TT_CONTEXT | Context passthrough |
|
||||
| `LATENT` | LATENT | Latent tensor |
|
||||
| `GUIDER` | GUIDER | Configured guider with conditioning |
|
||||
| `SIGMAS` | SIGMAS | Noise schedule |
|
||||
| `SAMPLER` | SAMPLER | Sampler algorithm |
|
||||
| `RND_NOISE` | NOISE | Noise generator with seed |
|
||||
|
||||
### Usage
|
||||
|
||||
Connect `CONTEXT` from a FLUX2 context node. Connect outputs directly to a guided sampler node.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
+31
-32
@@ -2,47 +2,46 @@
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
General-purpose context node for FLUX and SDXL workflows. Accepts any combination of pipeline fields and
|
||||
merges them into the context object. All fields are optional.
|
||||
General-purpose context node for FLUX and SDXL workflows. Merges or updates fields in an existing context object. All fields are optional.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-------------------|--------------------|----------|-------------------------------|
|
||||
| `context` | TT_CONTEXT | No | Existing context to update |
|
||||
| `workflow_config` | TT_WORKFLOW_CONFIG | No | Workflow configuration object |
|
||||
| `model` | MODEL | No | Diffusion model |
|
||||
| `clip` | CLIP | No | CLIP text encoder |
|
||||
| `vae` | VAE | No | VAE encoder/decoder |
|
||||
| `latent` | LATENT | No | Latent image tensor |
|
||||
| `positive` | CONDITIONING | No | Positive conditioning |
|
||||
| `negative` | CONDITIONING | No | Negative conditioning |
|
||||
| `image` | IMAGE | No | Pixel-space image |
|
||||
| `seed` | INT | No | Generation seed |
|
||||
| `steps` | INT | No | Number of sampling steps |
|
||||
| `cfg` | FLOAT | No | CFG scale |
|
||||
| Parameter | Type | Required | Description |
|
||||
|-------------------|--------------------|----------|-----------------------------------|
|
||||
| `context` | TT_CONTEXT | No | Existing context object to update |
|
||||
| `workflow_config` | TT_WORKFLOW_CONFIG | No | Workflow configuration object |
|
||||
| `model` | MODEL | No | Diffusion model |
|
||||
| `clip` | CLIP | No | CLIP text encoder |
|
||||
| `vae` | VAE | No | VAE encoder/decoder |
|
||||
| `latent` | LATENT | No | Latent tensor |
|
||||
| `positive` | CONDITIONING | No | Positive conditioning |
|
||||
| `negative` | CONDITIONING | No | Negative conditioning |
|
||||
| `image` | IMAGE | No | Image tensor |
|
||||
| `seed` | INT | No | Sampling seed |
|
||||
| `steps` | INT | No | Number of denoising steps |
|
||||
| `cfg` | FLOAT | No | Classifier-free guidance scale |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-------------------|--------------------|--------------------------|
|
||||
| `CONTEXT` | TT_CONTEXT | Updated context object |
|
||||
| `WORKFLOW_CONFIG` | TT_WORKFLOW_CONFIG | Workflow configuration |
|
||||
| `MODEL` | MODEL | Diffusion model |
|
||||
| `CLIP` | CLIP | CLIP text encoder |
|
||||
| `VAE` | VAE | VAE encoder/decoder |
|
||||
| `LATENT` | LATENT | Latent image tensor |
|
||||
| `POSITIVE` | CONDITIONING | Positive conditioning |
|
||||
| `NEGATIVE` | CONDITIONING | Negative conditioning |
|
||||
| `IMAGE` | IMAGE | Pixel-space image |
|
||||
| `SEED` | INT | Generation seed |
|
||||
| `STEPS` | INT | Number of sampling steps |
|
||||
| `CFG` | FLOAT | CFG scale |
|
||||
| Parameter | Type | Description |
|
||||
|-------------------|--------------------|-----------------------------------|
|
||||
| `CONTEXT` | TT_CONTEXT | Updated context object |
|
||||
| `WORKFLOW_CONFIG` | TT_WORKFLOW_CONFIG | Workflow config passthrough |
|
||||
| `MODEL` | MODEL | Model passthrough |
|
||||
| `CLIP` | CLIP | CLIP passthrough |
|
||||
| `VAE` | VAE | VAE passthrough |
|
||||
| `LATENT` | LATENT | Latent passthrough |
|
||||
| `POSITIVE` | CONDITIONING | Positive conditioning passthrough |
|
||||
| `NEGATIVE` | CONDITIONING | Negative conditioning passthrough |
|
||||
| `IMAGE` | IMAGE | Image passthrough |
|
||||
| `SEED` | INT | Seed passthrough |
|
||||
| `STEPS` | INT | Steps passthrough |
|
||||
| `CFG` | FLOAT | CFG passthrough |
|
||||
|
||||
### Usage
|
||||
|
||||
Use this node to create or update a context object with any combination of pipeline fields. If `context` is
|
||||
connected, existing fields are updated with the provided values. If not connected, a new context is created.
|
||||
Use to update or extend an existing context object mid-pipeline. Connect `context` from an upstream context node and override only the fields you
|
||||
need.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
## TT Context Passthrough *TT_ContextPassthrough*
|
||||
|
||||
⚠️ Deprecated: This node will be removed in a future major release. Please migrate to the new context nodes.
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Pass-through node that forwards context while allowing optional parameter modifications.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------------|----------|-------------------------------|
|
||||
| `context` | TT_CONTEXT | Yes | Input context to pass through |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------------|---------------------------------------------|
|
||||
| `CONTEXT` | TT_CONTEXT | Context with optionally modified parameters |
|
||||
|
||||
### Usage
|
||||
|
||||
Use this node to pass context through your workflow while optionally modifying specific parameters without changing the
|
||||
rest of the context.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -1,29 +0,0 @@
|
||||
## TT Context Set Guider *TT_ContextSetGuider*
|
||||
|
||||
⚠️ Deprecated: This node will be removed in a future major release. Please migrate to the new context nodes.
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Writes a GUIDER object into the TT_CONTEXT, making it available for downstream context-aware nodes.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------------|----------|--------------------------------|
|
||||
| `context` | TT_CONTEXT | Yes | Context object to update |
|
||||
| `guider` | GUIDER | Yes | Guider to store in the context |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------------|-----------------------------------------------|
|
||||
| `CONTEXT` | TT_CONTEXT | Updated context with `guider` written into it |
|
||||
|
||||
### Usage
|
||||
|
||||
Sets the `guider` field inside a TT_CONTEXT object. Use this node when you have a guider produced outside the
|
||||
context pipeline and need to inject it back in for use by subsequent context-aware nodes.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -1,28 +0,0 @@
|
||||
## TT Context Set Image *TT_ContextSetImage*
|
||||
|
||||
⚠️ Deprecated: This node will be removed in a future major release. Please migrate to the new context nodes.
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Adds or updates image in context object.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------------|----------|---------------------------|
|
||||
| `context` | TT_CONTEXT | Yes | Context to update |
|
||||
| `image` | IMAGE | Yes | Image to store in context |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------------|------------------------|
|
||||
| `CONTEXT` | TT_CONTEXT | Updated context object |
|
||||
|
||||
### Usage
|
||||
|
||||
Stores pixel-space image in context for use by downstream nodes. Overwrites existing image if present.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -1,28 +0,0 @@
|
||||
## TT Context Set Image *TT_ContextSetImage*
|
||||
|
||||
⚠️ Deprecated: This node will be removed in a future major release. Please migrate to the new context nodes.
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Adds or updates latent image in context object.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------|------------|----------|----------------------------------|
|
||||
| `context` | TT_CONTEXT | Yes | Context to update |
|
||||
| `latent` | LATENT | Yes | Latent image to store in context |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|------------|------------------------|
|
||||
| `CONTEXT` | TT_CONTEXT | Updated context object |
|
||||
|
||||
### Usage
|
||||
|
||||
Stores latent representation in context for use by downstream nodes. Overwrites existing latent if present.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -1,84 +0,0 @@
|
||||
## TT Even Larger Context *TT_EvenLargerContext*
|
||||
|
||||
⚠️ Deprecated: This node will be removed in a future major release. Please migrate to the new context nodes.
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Maximum capacity context node supporting all workflow parameters including ControlNet and masking.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-------------------|--------------------|----------|-----------------------------------------------------------|
|
||||
| `context` | TT_CONTEXT | No | Existing context to modify (if not provided, creates new) |
|
||||
| `workflow_config` | TT_WORKFLOW_CONFIG | No | Workflow configuration settings |
|
||||
| `model` | MODEL | No | The diffusion model (UNet/DiT) |
|
||||
| `clip` | CLIP | No | CLIP text encoder |
|
||||
| `vae` | VAE | No | VAE for encoding/decoding |
|
||||
| `positive` | CONDITIONING | No | Positive conditioning |
|
||||
| `negative` | CONDITIONING | No | Negative conditioning |
|
||||
| `latent` | LATENT | No | Latent image tensor |
|
||||
| `image` | IMAGE | No | Image tensor |
|
||||
| `mask` | MASK | No | Image mask |
|
||||
| `control_net` | CONTROL_NET | No | ControlNet model |
|
||||
| `seed` | INT | No | Random seed |
|
||||
| `steps` | INT | No | Sampling steps |
|
||||
| `cfg` | FLOAT | No | Classifier-free guidance scale |
|
||||
| `sampler_name` | COMBO | No | Sampler name |
|
||||
| `scheduler` | COMBO | No | Scheduler name |
|
||||
| `guidance` | FLOAT | No | Guidance value |
|
||||
| `clip_l_positive` | STRING | No | CLIP-L positive prompt |
|
||||
| `clip_g_positive` | STRING | No | CLIP-G positive prompt |
|
||||
| `t5xxl_positive` | STRING | No | T5-XXL positive prompt |
|
||||
| `clip_l_negative` | STRING | No | CLIP-L negative prompt |
|
||||
| `clip_g_negative` | STRING | No | CLIP-G negative prompt |
|
||||
| `t5xxl_negative` | STRING | No | T5-XXL negative prompt |
|
||||
| `ascore_positive` | FLOAT | No | Aesthetic score for positive |
|
||||
| `ascore_negative` | FLOAT | No | Aesthetic score for negative |
|
||||
| `width` | INT | No | Image width |
|
||||
| `height` | INT | No | Image height |
|
||||
| `target_width` | INT | No | Target width for conditioning |
|
||||
| `target_height` | INT | No | Target height for conditioning |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-------------------|--------------------|-----------------------------|
|
||||
| `CONTEXT` | TT_CONTEXT | Created or modified context |
|
||||
| `WORKFLOW_CONFIG` | TT_WORKFLOW_CONFIG | Workflow configuration |
|
||||
| `MODEL` | MODEL | Diffusion model |
|
||||
| `CLIP` | CLIP | Text encoder |
|
||||
| `VAE` | VAE | VAE |
|
||||
| `POSITIVE` | CONDITIONING | Positive conditioning |
|
||||
| `NEGATIVE` | CONDITIONING | Negative conditioning |
|
||||
| `LATENT` | LATENT | Latent tensor |
|
||||
| `IMAGE` | IMAGE | Image tensor |
|
||||
| `MASK` | MASK | Image mask |
|
||||
| `CONTROL_NET` | CONTROL_NET | ControlNet |
|
||||
| `SEED` | INT | Random seed |
|
||||
| `STEPS` | INT | Sampling steps |
|
||||
| `CFG` | FLOAT | CFG scale |
|
||||
| `SAMPLER_NAME` | COMBO | Sampler name |
|
||||
| `SCHEDULER` | COMBO | Scheduler name |
|
||||
| `GUIDANCE` | FLOAT | Guidance value |
|
||||
| `CLIP_L_POSITIVE` | STRING | CLIP-L positive |
|
||||
| `CLIP_G_POSITIVE` | STRING | CLIP-G positive |
|
||||
| `T5XXL_POSITIVE` | STRING | T5-XXL positive |
|
||||
| `CLIP_L_NEGATIVE` | STRING | CLIP-L negative |
|
||||
| `CLIP_G_NEGATIVE` | STRING | CLIP-G negative |
|
||||
| `T5XXL_NEGATIVE` | STRING | T5-XXL negative |
|
||||
| `ASCORE_POSITIVE` | FLOAT | Aesthetic score positive |
|
||||
| `ASCORE_NEGATIVE` | FLOAT | Aesthetic score negative |
|
||||
| `WIDTH` | INT | Width |
|
||||
| `HEIGHT` | INT | Height |
|
||||
| `TARGET_WIDTH` | INT | Target width |
|
||||
| `TARGET_HEIGHT` | INT | Target height |
|
||||
|
||||
### Usage
|
||||
|
||||
Use this node when you need comprehensive control over all workflow parameters including ControlNet and masking.
|
||||
Supports both SDXL (CLIP-L/G) and Flux (T5-XXL) conditioning simultaneously.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -0,0 +1,36 @@
|
||||
## TT FLUX2 Apply ControlNet (Advanced) *TT_Flux2ApplyControlNetAdvancedNode*
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Extended version of TT FLUX2 Apply ControlNet with built-in image picker and reference image preview. Supports both connected image input and file
|
||||
browser selection.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------------------|------------|----------|-----------------------------------------------------------------------------------------------|
|
||||
| `guider` | GUIDER | Yes | Configured guider from a FLUX2 context or workflow settings node |
|
||||
| `control_net_opt` | CONTROLNET | No | Preloaded ControlNet object. If provided, `control_net` combo is ignored |
|
||||
| `reference_image_opt` | IMAGE | No | Connected reference image. If provided, `reference_image` file picker is ignored |
|
||||
| `vae_opt` | VAE | No | Optional VAE for image preprocessing |
|
||||
| `control_net` | COMBO | Yes | ControlNet model file from `models/controlnet` |
|
||||
| `strength` | FLOAT | No | ControlNet influence strength. Default: `1.0`, range: `0.0` to `10.0`. Set to `0.0` to bypass |
|
||||
| `start_percent` | FLOAT | No | Step percentage at which ControlNet starts. Default: `0.0` |
|
||||
| `end_percent` | FLOAT | No | Step percentage at which ControlNet ends. Default: `100.0` |
|
||||
| `reference_image` | COMBO | No | Reference image file picker with upload support |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|--------|--------------------------------|
|
||||
| `GUIDER` | GUIDER | Guider with ControlNet applied |
|
||||
|
||||
### Usage
|
||||
|
||||
Connect `GUIDER` from a FLUX2 workflow settings or context node. Use `reference_image_opt` to pass an image from another node, or use the built-in
|
||||
file picker to load from disk. Reference image is displayed as a preview after execution. Set `strength=0.0` to bypass ControlNet without
|
||||
disconnecting the node.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -0,0 +1,33 @@
|
||||
## TT FLUX2 Apply ControlNet *TT_Flux2ApplyControlNetNode*
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Applies a ControlNet to a FLUX2 guider using a reference image. Supports preloaded ControlNet objects and optional VAE for image preprocessing.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-------------------|------------|----------|-----------------------------------------------------------------------------------------------|
|
||||
| `guider` | GUIDER | Yes | Configured guider from a FLUX2 context or workflow settings node |
|
||||
| `reference_image` | IMAGE | Yes | Reference image for ControlNet conditioning |
|
||||
| `control_net_opt` | CONTROLNET | No | Preloaded ControlNet object. If provided, `control_net` combo is ignored |
|
||||
| `vae_opt` | VAE | No | Optional VAE for image preprocessing |
|
||||
| `control_net` | COMBO | Yes | ControlNet model file from `models/controlnet` |
|
||||
| `strength` | FLOAT | No | ControlNet influence strength. Default: `1.0`, range: `0.0` to `10.0`. Set to `0.0` to bypass |
|
||||
| `start_percent` | FLOAT | No | Step percentage at which ControlNet starts. Default: `0.0` |
|
||||
| `end_percent` | FLOAT | No | Step percentage at which ControlNet ends. Default: `100.0` |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|--------|--------------------------------|
|
||||
| `GUIDER` | GUIDER | Guider with ControlNet applied |
|
||||
|
||||
### Usage
|
||||
|
||||
Connect `GUIDER` from a FLUX2 workflow settings or context node. Connect output `GUIDER` to a guided sampler node. Set `strength=0.0` to bypass
|
||||
ControlNet without disconnecting the node.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -1,30 +0,0 @@
|
||||
## TT FLUX2 GGUF Models Loader *TT_GgufModelsLoader*
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Load GGUF-quantized diffusion model (UNet), CLIP text encoder, and VAE in a single node.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-------------|--------|----------|------------------------------------|
|
||||
| `unet_name` | STRING | Yes | GGUF UNet/diffusion model filename |
|
||||
| `clip_name` | STRING | Yes | GGUF CLIP text encoder filename |
|
||||
| `vae_name` | STRING | Yes | VAE model filename |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|-------|------------------------|
|
||||
| `MODEL` | MODEL | Loaded diffusion model |
|
||||
| `CLIP` | CLIP | Loaded text encoder |
|
||||
| `VAE` | VAE | Loaded VAE decoder |
|
||||
|
||||
### Usage
|
||||
|
||||
All-in-one loader for GGUF-quantized FLUX2 models. Place your `.gguf` diffusion model files in the `diffusion_models` or `unet` directory, CLIP files in
|
||||
`text_encoders` or `clip` directory. VAE can be any standard ComfyUI-compatible VAE file.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -1,42 +0,0 @@
|
||||
## TT FLUX2 GGUF Models Loader (Advanced) *TT_GgufModelsLoaderAdvanced*
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
All-in-one loader for GGUF-quantized models with extended control over quantization, sampling, and LoRA support.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Advanced | Description |
|
||||
|-----------------------|---------|----------|----------|------------------------------------------------------------------------|
|
||||
| `unet_name` | STRING | Yes | | GGUF UNet/diffusion model filename |
|
||||
| `dequant_dtype` | STRING | Yes | Yes | Data type for dequantization (default/target/float32/float16/bfloat16) |
|
||||
| `patch_dtype` | STRING | Yes | Yes | Data type for weight patching |
|
||||
| `apply_sampling` | BOOLEAN | Yes | | Enable/disable flux sampling shift patch |
|
||||
| `base_sampling_shift` | FLOAT | Yes | Yes | Base shift value for flux sampling (default: 0.5) |
|
||||
| `max_sampling_shift` | FLOAT | Yes | Yes | Maximum shift value for flux sampling (default: 1.15) |
|
||||
| `sampling_width` | INT | Yes | Yes | Reference width for sampling shift calculation |
|
||||
| `sampling_height` | INT | Yes | Yes | Reference height for sampling shift calculation |
|
||||
| `lora_name_1..4` | STRING | Yes | Yes | LoRA filename (None to skip) |
|
||||
| `strength_1..4` | FLOAT | Yes | Yes | LoRA blend strength (-10.0 to 10.0, default: 1.0) |
|
||||
| `clip_name` | STRING | Yes | | GGUF CLIP text encoder filename |
|
||||
| `vae_name` | STRING | Yes | | VAE model filename |
|
||||
| `vae_device` | STRING | Yes | Yes | Device for VAE (default/cpu) |
|
||||
| `vae_dtype` | STRING | Yes | Yes | Data type for VAE (bfloat16/float16/float32) |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|-------|------------------------|
|
||||
| `MODEL` | MODEL | Loaded diffusion model |
|
||||
| `CLIP` | CLIP | Loaded text encoder |
|
||||
| `VAE` | VAE | Loaded VAE decoder |
|
||||
|
||||
### Usage
|
||||
|
||||
Extended version of FLUX2 GGUF Models Loader. Supports up to 4 LoRAs loaded simultaneously. Enable `apply_sampling` to apply flux sampling shift patch —
|
||||
useful for improving quality at non-standard resolutions. Advanced parameters are hidden by default and can be revealed via the node's show/hide
|
||||
controls.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -1,46 +0,0 @@
|
||||
## TT Flux2 Workflow Settings *TT_Flux2WorkflowSettings*
|
||||
|
||||
⚠️ Deprecated: This node will be removed in a future major release. Please migrate to the new context nodes.
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Central workflow configuration node for FLUX2 pipelines. Consolidates all sampling parameters into a single
|
||||
TT_WORKFLOW_CONFIG object while also exposing each value as an individual output.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|----------------|--------|----------|---------------------------------------------------------------------------|
|
||||
| `seed` | INT | Yes | Generation seed (0 – 18446744073709551615, default: 0) |
|
||||
| `steps` | INT | Yes | Number of sampling steps (1–10000, default: 25) |
|
||||
| `cfg` | FLOAT | Yes | CFG scale (0.0–100.0, default: 1.5) |
|
||||
| `sampler_name` | STRING | Yes | Sampler algorithm (KSampler sampler list) |
|
||||
| `width` | INT | Yes | Output image width in pixels (16–MAX_RESOLUTION, step: 8, default: 1024) |
|
||||
| `height` | INT | Yes | Output image height in pixels (16–MAX_RESOLUTION, step: 8, default: 1024) |
|
||||
| `guidance` | FLOAT | Yes | Guidance scale for text encoder (1.0–10.0, default: 3.5) |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-------------------|--------------------|------------------------------------------------------|
|
||||
| `WORKFLOW_CONFIG` | TT_WORKFLOW_CONFIG | Full configuration object with all settings bundled |
|
||||
| `SEED` | INT | Generation seed |
|
||||
| `STEPS` | INT | Number of sampling steps |
|
||||
| `CFG` | FLOAT | CFG scale |
|
||||
| `SAMPLER` | SAMPLER | Instantiated sampler object |
|
||||
| `SAMPLER_NAME` | STRING | Name of the selected sampler |
|
||||
| `SCHEDULER` | SIGMAS | Computed sigma schedule based on seed and resolution |
|
||||
| `WIDTH` | INT | Output image width |
|
||||
| `HEIGHT` | INT | Output image height |
|
||||
| `GUIDANCE` | FLOAT | Guidance scale |
|
||||
|
||||
### Usage
|
||||
|
||||
Use this node as the single source of truth for FLUX2 workflow parameters. The `WORKFLOW_CONFIG` output is
|
||||
designed for context-aware nodes that consume a TT_WORKFLOW_CONFIG directly. Individual outputs are available
|
||||
for connecting to standard ComfyUI nodes. The sigma schedule (`SCHEDULER`) is computed automatically from
|
||||
the seed and resolution via `get_schedule`.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -1,49 +0,0 @@
|
||||
## TT Flux2 Workflow Settings (Advanced) *TT_Flux2WorkflowSettingsAdvanced*
|
||||
|
||||
⚠️ Deprecated: This node will be removed in a future major release. Please migrate to the new context nodes.
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Extended workflow configuration node for FLUX2 pipelines. Includes all parameters from the base version plus
|
||||
built-in prompt and LoRA trigger fields, bundling everything into a single TT_WORKFLOW_CONFIG object.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------------|--------|----------|---------------------------------------------------------------------------|
|
||||
| `seed` | INT | Yes | Generation seed (0 – 18446744073709551615, default: 0) |
|
||||
| `steps` | INT | Yes | Number of sampling steps (1–10000, default: 25) |
|
||||
| `cfg` | FLOAT | Yes | CFG scale (0.0–100.0, default: 1.5) |
|
||||
| `sampler_name` | STRING | Yes | Sampler algorithm (KSampler sampler list) |
|
||||
| `width` | INT | Yes | Output image width in pixels (16–MAX_RESOLUTION, step: 8, default: 1024) |
|
||||
| `height` | INT | Yes | Output image height in pixels (16–MAX_RESOLUTION, step: 8, default: 1024) |
|
||||
| `prompt` | STRING | Yes | Main generation prompt (multiline, supports dynamic prompts) |
|
||||
| `lora_triggers` | STRING | Yes | LoRA trigger words (multiline, supports dynamic prompts) |
|
||||
| `guidance` | FLOAT | Yes | Guidance scale for text encoder (1.0–10.0, default: 3.5) |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-------------------|--------------------|------------------------------------------------------|
|
||||
| `WORKFLOW_CONFIG` | TT_WORKFLOW_CONFIG | Full configuration object with all settings bundled |
|
||||
| `SEED` | INT | Generation seed |
|
||||
| `STEPS` | INT | Number of sampling steps |
|
||||
| `CFG` | FLOAT | CFG scale |
|
||||
| `SAMPLER` | SAMPLER | Instantiated sampler object |
|
||||
| `SAMPLER_NAME` | STRING | Name of the selected sampler |
|
||||
| `SCHEDULER` | SIGMAS | Computed sigma schedule based on seed and resolution |
|
||||
| `WIDTH` | INT | Output image width |
|
||||
| `HEIGHT` | INT | Output image height |
|
||||
| `PROMPT` | STRING | Main generation prompt |
|
||||
| `GUIDANCE` | FLOAT | Guidance scale |
|
||||
|
||||
### Usage
|
||||
|
||||
Advanced version of TT Flux2 Workflow Settings with `prompt` and `lora_triggers` fields included directly in the
|
||||
node. Both are stored in the `WORKFLOW_CONFIG` output alongside all other sampling parameters, making this node
|
||||
sufficient as the sole configuration source for full context-driven FLUX2 pipelines. Individual outputs remain
|
||||
available for connecting to standard ComfyUI nodes.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -1,32 +0,0 @@
|
||||
## TT FLUX Models Loader *TT_FluxModelsLoader*
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
All-in-one model loader for Flux workflows.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|---------------|------------|----------|-------------------------------------------------|
|
||||
| `ckpt_name` | CHECKPOINT | Yes | Flux checkpoint to load |
|
||||
| `clip_l` | STRING | Yes | CLIP-L text encoder model |
|
||||
| `t5xxl` | STRING | Yes | T5-XXL text encoder model |
|
||||
| `clip_device` | STRING | Yes | Device for CLIP ("default" or "cpu") - advanced |
|
||||
| `vae_name` | VAE | Yes | VAE model to load |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|-------|------------------------------------------|
|
||||
| `MODEL` | MODEL | Loaded Flux model |
|
||||
| `CLIP` | CLIP | Combined CLIP-L and T5-XXL text encoders |
|
||||
| `VAE` | VAE | Loaded VAE |
|
||||
|
||||
### Usage
|
||||
|
||||
Load all Flux model components in one place. Combines CLIP-L and T5-XXL encoders into a dual CLIP for Flux's text
|
||||
conditioning system.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -1,49 +0,0 @@
|
||||
## TT FLUX Models Loader (Advanced) *TT_FluxModelsLoaderAdvanced*
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Extended all-in-one model loader for Flux with sampling patches, LoRA support, and advanced settings.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|-----------------------|------------|----------|------------------------------------------------------------------------------------|
|
||||
| `unet_name` | CHECKPOINT | Yes | Flux checkpoint to load |
|
||||
| `unet_dtype` | STRING | Yes | U-Net data type: "default", "fp8_e4m3fn", "fp8_e4m3fn_fast", "fp8_e5m2" - advanced |
|
||||
| `apply_sampling` | BOOLEAN | Yes | Apply sampling shift patch (default: True) |
|
||||
| `base_sampling_shift` | FLOAT | Yes | Base sampling shift value (0.0-100.0, default: 0.5) |
|
||||
| `max_sampling_shift` | FLOAT | Yes | Maximum sampling shift (0.0-100.0, default: 1.15) |
|
||||
| `sampling_width` | INT | Yes | Width for sampling shift calculation (16-MAX_RESOLUTION, step: 8, default: 1024) |
|
||||
| `sampling_height` | INT | Yes | Height for sampling shift calculation (16-MAX_RESOLUTION, step: 8, default: 1024) |
|
||||
| `clip_l` | STRING | Yes | CLIP-L text encoder model |
|
||||
| `t5xxl` | STRING | Yes | T5-XXL text encoder model |
|
||||
| `clip_device` | STRING | Yes | Device for CLIP ("default" or "cpu") - advanced |
|
||||
| `lora_name_1` | LORA | Yes | First LoRA to apply (select "None" to skip) |
|
||||
| `strength_1` | FLOAT | Yes | Strength for first LoRA (-10.0 to 10.0, default: 1.0) |
|
||||
| `lora_name_2` | LORA | Yes | Second LoRA to apply (select "None" to skip) |
|
||||
| `strength_2` | FLOAT | Yes | Strength for second LoRA (-10.0 to 10.0, default: 1.0) |
|
||||
| `lora_name_3` | LORA | Yes | Third LoRA to apply (select "None" to skip) |
|
||||
| `strength_3` | FLOAT | Yes | Strength for third LoRA (-10.0 to 10.0, default: 1.0) |
|
||||
| `lora_name_4` | LORA | Yes | Fourth LoRA to apply (select "None" to skip) |
|
||||
| `strength_4` | FLOAT | Yes | Strength for fourth LoRA (-10.0 to 10.0, default: 1.0) |
|
||||
| `vae_name` | VAE | Yes | VAE model to load |
|
||||
| `vae_device` | STRING | Yes | Device for VAE ("default" or "cpu") - advanced |
|
||||
| `vae_dtype` | STRING | Yes | Data type for VAE ("bfloat16", "float16", "float32") - advanced |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|-------|-------------------------------------------------------------|
|
||||
| `MODEL` | MODEL | Loaded Flux model with applied patches and LoRAs |
|
||||
| `CLIP` | CLIP | Combined CLIP-L and T5-XXL text encoders with applied LoRAs |
|
||||
| `VAE` | VAE | Loaded VAE |
|
||||
|
||||
### Usage
|
||||
|
||||
Extended Flux loader with optional sampling shift patching for improved high-resolution generation, support for up to 4
|
||||
LoRAs, and advanced VAE configuration. The sampling shift patch adjusts noise scheduling based on image dimensions.
|
||||
LoRAs are cached for efficiency.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -1,37 +0,0 @@
|
||||
# TT FLUX Workflow Settings *TT_FluxWorkflowSettings*
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Node for configuring Flux workflow generation parameters.
|
||||
|
||||
## Inputs
|
||||
|
||||
| Parameter | Type | Default | Range | Description |
|
||||
|----------------|-------|---------|-------------|--------------------------------------|
|
||||
| `seed` | INT | 0 | 0 - 2^64-1 | Seed for reproducible results |
|
||||
| `steps` | INT | 25 | 1 - 10000 | Number of sampling steps |
|
||||
| `cfg` | FLOAT | 1.5 | 0.0 - 100.0 | CFG scale (classifier-free guidance) |
|
||||
| `sampler_name` | COMBO | - | - | Sampler name from available list |
|
||||
| `scheduler` | COMBO | - | - | Scheduler type |
|
||||
| `guidance` | FLOAT | 3.5 | 1.0 - 10.0 | Guidance strength for Flux |
|
||||
|
||||
## Outputs
|
||||
|
||||
| Output | Type | Description |
|
||||
|-------------------|--------------------|------------------------------|
|
||||
| `WORKFLOW_CONFIG` | TT_WORKFLOW_CONFIG | Dictionary with all settings |
|
||||
| `SEED` | INT | Seed value |
|
||||
| `STEPS` | INT | Number of steps |
|
||||
| `CFG` | FLOAT | CFG scale |
|
||||
| `SAMPLER_NAME` | COMBO | Sampler name |
|
||||
| `SCHEDULER` | COMBO | Scheduler |
|
||||
| `GUIDANCE` | FLOAT | Guidance value |
|
||||
|
||||
## Purpose
|
||||
|
||||
Centralized control of generation settings for Flux models. Allows you to set all main parameters in one place and pass
|
||||
them through the workflow both as a single config object and as individual values.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -1,45 +0,0 @@
|
||||
# TT FLUX Workflow Settings (Advanced) *TT_FluxWorkflowSettingsAdvanced*
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Advanced node for configuring Flux workflow generation parameters with separate CLIP-L and T5XXL prompts.
|
||||
|
||||
## Inputs
|
||||
|
||||
| Parameter | Type | Default | Range | Description |
|
||||
|-------------------|--------|---------|-------------|--------------------------------------|
|
||||
| `seed` | INT | 0 | 0 - 2^64-1 | Seed for reproducible results |
|
||||
| `steps` | INT | 25 | 1 - 10000 | Number of sampling steps |
|
||||
| `cfg` | FLOAT | 1.5 | 0.0 - 100.0 | CFG scale (classifier-free guidance) |
|
||||
| `sampler_name` | COMBO | - | - | Sampler name from available list |
|
||||
| `scheduler` | COMBO | - | - | Scheduler type |
|
||||
| `clip_l_positive` | STRING | - | - | Positive prompt for CLIP-L encoder |
|
||||
| `t5xxl_positive` | STRING | - | - | Positive prompt for T5XXL encoder |
|
||||
| `clip_l_negative` | STRING | - | - | Negative prompt for CLIP-L encoder |
|
||||
| `t5xxl_negative` | STRING | - | - | Negative prompt for T5XXL encoder |
|
||||
| `guidance` | FLOAT | 3.5 | 1.0 - 10.0 | Guidance strength for Flux |
|
||||
|
||||
## Outputs
|
||||
|
||||
| Output | Type | Description |
|
||||
|-------------------|--------------------|------------------------------|
|
||||
| `WORKFLOW_CONFIG` | TT_WORKFLOW_CONFIG | Dictionary with all settings |
|
||||
| `SEED` | INT | Seed value |
|
||||
| `STEPS` | INT | Number of steps |
|
||||
| `CFG` | FLOAT | CFG scale |
|
||||
| `SAMPLER_NAME` | COMBO | Sampler name |
|
||||
| `SCHEDULER` | COMBO | Scheduler |
|
||||
| `CLIP_L_POSITIVE` | STRING | CLIP-L positive prompt |
|
||||
| `T5XXL_POSITIVE` | STRING | T5XXL positive prompt |
|
||||
| `CLIP_L_NEGATIVE` | STRING | CLIP-L negative prompt |
|
||||
| `T5XXL_NEGATIVE` | STRING | T5XXL negative prompt |
|
||||
| `GUIDANCE` | FLOAT | Guidance value |
|
||||
|
||||
## Purpose
|
||||
|
||||
Extended version of Flux workflow settings with dual-encoder prompt control. Allows separate configuration of CLIP-L and
|
||||
T5XXL text encoders for precise control over the generation process. Supports dynamic prompts and multiline text input.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
@@ -1,32 +0,0 @@
|
||||
## TT Guided KSampler (With Preview) *TT_GuidedKSamplerWithPreviewNode*
|
||||
|
||||
*This description was generated with AI assistance. If you spot any errors, please create an issue on GitHub.*
|
||||
|
||||
Runs guided diffusion sampling with optional step-by-step latent preview in the ComfyUI interface. Identical to TT Guided KSampler with an added
|
||||
preview toggle.
|
||||
|
||||
### Inputs
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|------------------|---------|----------|--------------------------------------------|
|
||||
| `latent` | LATENT | Yes | Input latent tensor |
|
||||
| `guider` | GUIDER | Yes | Configured Guider with conditioning |
|
||||
| `sigmas` | SIGMAS | Yes | Noise schedule |
|
||||
| `sampler` | SAMPLER | Yes | Sampler algorithm |
|
||||
| `random_noise` | NOISE | Yes | Noise generator with seed |
|
||||
| `preview_latent` | BOOLEAN | Yes | Show intermediate previews during sampling |
|
||||
|
||||
### Outputs
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|-----------|--------|-----------------------|
|
||||
| `SAMPLES` | LATENT | Sampled latent tensor |
|
||||
|
||||
### Usage
|
||||
|
||||
Enable `preview_latent` to display latent previews at each sampling step in the node interface. Note: ComfyUI launches with previews disabled by
|
||||
default — this node overrides that setting automatically.
|
||||
|
||||
---
|
||||
|
||||
[View on GitHub](https://github.com/tenser-tensor/ComfyUI-TenserTensor)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user