Core (nodes/core/): alpha, masks, batch consolidation, blend, transform matrix, bbox, parameters, validation engines shared across nodes, each with unit tests. Fix an unconditional RGB clamp to [0,1] that silently destroyed HDR/negative values in Merge, Transform, Color Correct, Comp, CornerPin, Distort, Spherize, Crop Stitch, and the shared masked-compositing helpers. Alpha stays clamped everywhere; RGB no longer does. Fix Grain applying `amount` twice in overlay/soft_light modes (quadratic instead of linear falloff). Add STMap mode to Distort (absolute UV remap vs relative displacement). Add bbox output/input wiring between Crop and Crop Stitch. Add edge_grow and edge_color_match to Crop Stitch. Add despill to Keyer. Add shuffle mode to Channel (R/G/B/A routed from any source). Add size/luma_response to Grain. Add grid mode to Constant. Add frame/layer accumulation limits to Preview and Draw, plus a font-path containment fix and supersampling in Text. Make Frame Range and Append recognize a real ComfyUI VIDEO input (not only this pack's internal media wrapper), preserving true fps/audio instead of silently dropping them, and add a native VIDEO output alongside the existing IMAGE output on both. Add node_replacements.py (empty registry, wired into the extension lifecycle) for future schema migrations. Add a CI matrix pinning the verified requires-comfyui floor, and .comfyignore for Registry packaging.
76 lines
2.1 KiB
Python
76 lines
2.1 KiB
Python
from __future__ import annotations
|
|
|
|
import math
|
|
|
|
import torch
|
|
|
|
from nodes.core.transform import build_2d_transform, mat_rotate, transform_points
|
|
|
|
DEVICE = torch.device("cpu")
|
|
DTYPE = torch.float32
|
|
|
|
|
|
def _transform(**kwargs) -> torch.Tensor:
|
|
return build_2d_transform(device=DEVICE, dtype=DTYPE, **kwargs)
|
|
|
|
|
|
def test_identity_leaves_points_unchanged():
|
|
matrix = _transform()
|
|
points = torch.tensor([[0.0, 0.0], [10.0, 5.0]])
|
|
|
|
out = transform_points(matrix, points)
|
|
|
|
assert torch.allclose(out, points, atol=1e-6)
|
|
|
|
|
|
def test_pure_translation():
|
|
matrix = _transform(tx=5.0, ty=-3.0)
|
|
points = torch.tensor([[0.0, 0.0], [1.0, 1.0]])
|
|
|
|
out = transform_points(matrix, points)
|
|
|
|
assert torch.allclose(out, torch.tensor([[5.0, -3.0], [6.0, -2.0]]), atol=1e-6)
|
|
|
|
|
|
def test_non_uniform_scale():
|
|
matrix = _transform(sx=2.0, sy=0.5)
|
|
points = torch.tensor([[10.0, 10.0]])
|
|
|
|
out = transform_points(matrix, points)
|
|
|
|
assert torch.allclose(out, torch.tensor([[20.0, 5.0]]), atol=1e-6)
|
|
|
|
|
|
def test_90_degree_rotation_about_origin():
|
|
matrix = mat_rotate(90.0, device=DEVICE, dtype=DTYPE)
|
|
points = torch.tensor([[1.0, 0.0]])
|
|
|
|
out = transform_points(matrix, points)
|
|
|
|
assert torch.allclose(out, torch.tensor([[0.0, 1.0]]), atol=1e-5)
|
|
|
|
|
|
def test_rotation_about_pivot_keeps_pivot_fixed():
|
|
matrix = _transform(rotation=45.0, pivot_x=50.0, pivot_y=50.0)
|
|
pivot = torch.tensor([[50.0, 50.0]])
|
|
|
|
out = transform_points(matrix, pivot)
|
|
|
|
assert torch.allclose(out, pivot, atol=1e-4)
|
|
|
|
|
|
def test_expanded_bbox_of_rotated_square():
|
|
# A 100x100 square rotated 45 degrees about its center should expand to
|
|
# roughly its diagonal (100*sqrt(2)) on each axis.
|
|
matrix = _transform(rotation=45.0, pivot_x=50.0, pivot_y=50.0)
|
|
corners = torch.tensor([[0.0, 0.0], [100.0, 0.0], [100.0, 100.0], [0.0, 100.0]])
|
|
|
|
warped = transform_points(matrix, corners)
|
|
|
|
span_x = warped[:, 0].max() - warped[:, 0].min()
|
|
span_y = warped[:, 1].max() - warped[:, 1].min()
|
|
|
|
expected = 100.0 * math.sqrt(2.0)
|
|
assert abs(float(span_x) - expected) < 1e-3
|
|
assert abs(float(span_y) - expected) < 1e-3
|