New ColorMatchingNode (Color Matching Ops): image + reference inputs, one output. Methods LAB/RGB/Histogram (LAB default) and a target selector (All/Lightness/Color) that keeps only the matched Oklab lightness or color. Statistics-only, so inputs may be any size. Live in-node preview. Filter Ops: add Laplacian Sharpen (4-/8-neighbor kernel) and Unsharp Masking (Gaussian amount/radius/threshold), with matching JS live previews, widget visibility, and tooltips. Layer Blending: rename to Layer Blending Ops, drop the unused preview_ref output, and make the live preview match the backend exactly (resize fg to bg size, default opacity 255, per-mode clamp parity) - fixes big mismatches e.g. Linear Dodge (Add) at high opacity. Rename Color Matching node display to Color Matching Ops. Raise color-match preview resolution to 1024 to tighten preview-vs-output stats. Previews: use widget.last_y to stop the preview box overlapping the last widget (all nodes, incl. Channel Ops); hide the preview box until a preview exists; auto-size the node to a sensible preview area on first preview; keep fresh Filter Ops compact instead of huge with empty space. README: add per-node preview GIFs (channel_ops/Layer_blend/filter_ops/ color_match) and document the new node/effects; drop the old preview.gif reference.
50 lines
1.6 KiB
Python
50 lines
1.6 KiB
Python
import os
|
|
from typing import Dict, Any
|
|
from .channel_ops import ChannelOpsNode
|
|
from .layer_blending import LayerBlendingNode
|
|
from .image_effects import ImageEffectsNode
|
|
from .color_matching import ColorMatchingNode
|
|
|
|
# Expose web extension directory so ComfyUI serves JS files from ./web
|
|
WEB_DIRECTORY = "./web"
|
|
|
|
NODE_CLASS_MAPPINGS: Dict[str, Any] = {
|
|
"ChannelOpsNode": ChannelOpsNode,
|
|
"LayerBlendingNode": LayerBlendingNode,
|
|
"ImageEffectsNode": ImageEffectsNode,
|
|
"ColorMatchingNode": ColorMatchingNode,
|
|
}
|
|
|
|
NODE_DISPLAY_NAME_MAPPINGS: Dict[str, str] = {
|
|
"ChannelOpsNode": "Channel Ops (live-preview)",
|
|
"LayerBlendingNode": "Layer Blending Ops (live-preview)",
|
|
"ImageEffectsNode": "Filter Ops (live-preview)",
|
|
"ColorMatchingNode": "Color Matching Ops (live-preview)",
|
|
}
|
|
|
|
__all__ = [
|
|
"NODE_CLASS_MAPPINGS",
|
|
"NODE_DISPLAY_NAME_MAPPINGS",
|
|
"WEB_DIRECTORY",
|
|
]
|
|
|
|
# Cleanup: remove all preview images in our web folder at startup
|
|
def _cleanup_web_folder():
|
|
try:
|
|
this_dir = os.path.dirname(os.path.abspath(__file__))
|
|
web_dir = os.path.join(this_dir, "web")
|
|
if not os.path.isdir(web_dir):
|
|
return
|
|
for name in os.listdir(web_dir):
|
|
# Only delete image files to avoid removing JS or other assets
|
|
if name.lower().endswith((".png", ".jpg", ".jpeg")):
|
|
try:
|
|
os.remove(os.path.join(web_dir, name))
|
|
except Exception:
|
|
pass
|
|
except Exception:
|
|
# Silent by design; preview cleanup is best-effort
|
|
pass
|
|
|
|
_cleanup_web_folder()
|