mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-04-14 04:22:31 +08:00
Range Editor
This commit is contained in:
parent
de67bb0870
commit
4d721bff59
@ -1252,6 +1252,41 @@ class Curve(ComfyTypeIO):
|
|||||||
return super().as_dict()
|
return super().as_dict()
|
||||||
|
|
||||||
|
|
||||||
|
@comfytype(io_type="RANGE")
|
||||||
|
class Range(ComfyTypeIO):
|
||||||
|
Type = dict # {"min": float, "max": float, "midpoint"?: float}
|
||||||
|
|
||||||
|
class Input(WidgetInput):
|
||||||
|
def __init__(self, id: str, display_name: str=None, optional=False, tooltip: str=None,
|
||||||
|
socketless: bool=True, default: dict=None,
|
||||||
|
display: str=None,
|
||||||
|
gradient_stops: list=None,
|
||||||
|
show_midpoint: bool=None,
|
||||||
|
midpoint_scale: str=None,
|
||||||
|
value_min: float=None,
|
||||||
|
value_max: float=None,
|
||||||
|
advanced: bool=None):
|
||||||
|
super().__init__(id, display_name, optional, tooltip, None, default, socketless, None, None, None, None, advanced)
|
||||||
|
if default is None:
|
||||||
|
self.default = {"min": 0.0, "max": 1.0}
|
||||||
|
self.display = display
|
||||||
|
self.gradient_stops = gradient_stops
|
||||||
|
self.show_midpoint = show_midpoint
|
||||||
|
self.midpoint_scale = midpoint_scale
|
||||||
|
self.value_min = value_min
|
||||||
|
self.value_max = value_max
|
||||||
|
|
||||||
|
def as_dict(self):
|
||||||
|
return super().as_dict() | prune_dict({
|
||||||
|
"display": self.display,
|
||||||
|
"gradient_stops": self.gradient_stops,
|
||||||
|
"show_midpoint": self.show_midpoint,
|
||||||
|
"midpoint_scale": self.midpoint_scale,
|
||||||
|
"value_min": self.value_min,
|
||||||
|
"value_max": self.value_max,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
@comfytype(io_type="COLOR_CURVES")
|
@comfytype(io_type="COLOR_CURVES")
|
||||||
class ColorCurves(ComfyTypeIO):
|
class ColorCurves(ComfyTypeIO):
|
||||||
class ColorCurvesDict(TypedDict):
|
class ColorCurvesDict(TypedDict):
|
||||||
|
|||||||
122
nodes.py
122
nodes.py
@ -2057,6 +2057,122 @@ class TestCurveWidget:
|
|||||||
return {"ui": {"text": [result]}, "result": (result,)}
|
return {"ui": {"text": [result]}, "result": (result,)}
|
||||||
|
|
||||||
|
|
||||||
|
class TestRangePlain:
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(s):
|
||||||
|
return {
|
||||||
|
"required": {
|
||||||
|
"range": ("RANGE", {"default": {"min": 0.0, "max": 1.0}}),
|
||||||
|
"range_midpoint": ("RANGE", {
|
||||||
|
"default": {"min": 0.2, "max": 0.8, "midpoint": 0.5},
|
||||||
|
"show_midpoint": True,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN_TYPES = ("STRING",)
|
||||||
|
FUNCTION = "execute"
|
||||||
|
OUTPUT_NODE = True
|
||||||
|
CATEGORY = "testing"
|
||||||
|
|
||||||
|
def execute(self, **kwargs):
|
||||||
|
import json
|
||||||
|
result = json.dumps(kwargs, indent=2)
|
||||||
|
return {"ui": {"text": [result]}, "result": (result,)}
|
||||||
|
|
||||||
|
|
||||||
|
class TestRangeGradient:
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(s):
|
||||||
|
return {
|
||||||
|
"required": {
|
||||||
|
"range": ("RANGE", {
|
||||||
|
"default": {"min": 0.0, "max": 1.0},
|
||||||
|
"display": "gradient",
|
||||||
|
"gradient_stops": [
|
||||||
|
{"offset": 0.0, "color": [0, 0, 0]},
|
||||||
|
{"offset": 1.0, "color": [255, 255, 255]}
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
"range_midpoint": ("RANGE", {
|
||||||
|
"default": {"min": 0.0, "max": 1.0, "midpoint": 0.5},
|
||||||
|
"display": "gradient",
|
||||||
|
"gradient_stops": [
|
||||||
|
{"offset": 0.0, "color": [0, 0, 0]},
|
||||||
|
{"offset": 1.0, "color": [255, 255, 255]}
|
||||||
|
],
|
||||||
|
"show_midpoint": True,
|
||||||
|
"midpoint_scale": "gamma",
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN_TYPES = ("STRING",)
|
||||||
|
FUNCTION = "execute"
|
||||||
|
OUTPUT_NODE = True
|
||||||
|
CATEGORY = "testing"
|
||||||
|
|
||||||
|
def execute(self, **kwargs):
|
||||||
|
import json
|
||||||
|
result = json.dumps(kwargs, indent=2)
|
||||||
|
return {"ui": {"text": [result]}, "result": (result,)}
|
||||||
|
|
||||||
|
|
||||||
|
class TestRangeHistogram:
|
||||||
|
RANGE_OPTS = {
|
||||||
|
"display": "histogram",
|
||||||
|
"show_midpoint": True,
|
||||||
|
"midpoint_scale": "gamma",
|
||||||
|
"value_min": 0,
|
||||||
|
"value_max": 255,
|
||||||
|
}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(s):
|
||||||
|
default = {"min": 0, "max": 255, "midpoint": 0.5}
|
||||||
|
return {
|
||||||
|
"required": {
|
||||||
|
"image": ("IMAGE",),
|
||||||
|
"rgb": ("RANGE", {"default": {**default}, **s.RANGE_OPTS}),
|
||||||
|
"red": ("RANGE", {"default": {**default}, **s.RANGE_OPTS}),
|
||||||
|
"green": ("RANGE", {"default": {**default}, **s.RANGE_OPTS}),
|
||||||
|
"blue": ("RANGE", {"default": {**default}, **s.RANGE_OPTS}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RETURN_TYPES = ("STRING",)
|
||||||
|
FUNCTION = "execute"
|
||||||
|
OUTPUT_NODE = True
|
||||||
|
CATEGORY = "testing"
|
||||||
|
|
||||||
|
def execute(self, image, rgb, red, green, blue):
|
||||||
|
import json
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
img = image[0].cpu().numpy() # (H, W, C)
|
||||||
|
|
||||||
|
# Per-channel histograms
|
||||||
|
hist_r, _ = np.histogram(img[:, :, 0].flatten(), bins=256, range=(0.0, 1.0))
|
||||||
|
hist_g, _ = np.histogram(img[:, :, 1].flatten(), bins=256, range=(0.0, 1.0))
|
||||||
|
hist_b, _ = np.histogram(img[:, :, 2].flatten(), bins=256, range=(0.0, 1.0))
|
||||||
|
|
||||||
|
# Luminance histogram (BT.709)
|
||||||
|
luminance = 0.2126 * img[:, :, 0] + 0.7152 * img[:, :, 1] + 0.0722 * img[:, :, 2]
|
||||||
|
hist_rgb, _ = np.histogram(luminance.flatten(), bins=256, range=(0.0, 1.0))
|
||||||
|
|
||||||
|
result = json.dumps({"rgb": rgb, "red": red, "green": green, "blue": blue}, indent=2)
|
||||||
|
return {
|
||||||
|
"ui": {
|
||||||
|
"text": [result],
|
||||||
|
"range_histogram_rgb": hist_rgb.astype(np.uint32).tolist(),
|
||||||
|
"range_histogram_red": hist_r.astype(np.uint32).tolist(),
|
||||||
|
"range_histogram_green": hist_g.astype(np.uint32).tolist(),
|
||||||
|
"range_histogram_blue": hist_b.astype(np.uint32).tolist(),
|
||||||
|
},
|
||||||
|
"result": (result,)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {
|
NODE_CLASS_MAPPINGS = {
|
||||||
"KSampler": KSampler,
|
"KSampler": KSampler,
|
||||||
"CheckpointLoaderSimple": CheckpointLoaderSimple,
|
"CheckpointLoaderSimple": CheckpointLoaderSimple,
|
||||||
@ -2126,6 +2242,9 @@ NODE_CLASS_MAPPINGS = {
|
|||||||
"ConditioningSetTimestepRange": ConditioningSetTimestepRange,
|
"ConditioningSetTimestepRange": ConditioningSetTimestepRange,
|
||||||
"LoraLoaderModelOnly": LoraLoaderModelOnly,
|
"LoraLoaderModelOnly": LoraLoaderModelOnly,
|
||||||
"TestCurveWidget": TestCurveWidget,
|
"TestCurveWidget": TestCurveWidget,
|
||||||
|
"TestRangePlain": TestRangePlain,
|
||||||
|
"TestRangeGradient": TestRangeGradient,
|
||||||
|
"TestRangeHistogram": TestRangeHistogram,
|
||||||
}
|
}
|
||||||
|
|
||||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||||
@ -2195,6 +2314,9 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
|||||||
"VAEDecodeTiled": "VAE Decode (Tiled)",
|
"VAEDecodeTiled": "VAE Decode (Tiled)",
|
||||||
"VAEEncodeTiled": "VAE Encode (Tiled)",
|
"VAEEncodeTiled": "VAE Encode (Tiled)",
|
||||||
"TestCurveWidget": "Test Curve Widget",
|
"TestCurveWidget": "Test Curve Widget",
|
||||||
|
"TestRangePlain": "Test Range (Plain)",
|
||||||
|
"TestRangeGradient": "Test Range (Gradient)",
|
||||||
|
"TestRangeHistogram": "Test Range (Histogram)",
|
||||||
}
|
}
|
||||||
|
|
||||||
EXTENSION_WEB_DIRS = {}
|
EXTENSION_WEB_DIRS = {}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user