mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-05-26 08:57:26 +08:00
Correct PIL contract in ImageBlend channel-cap rationale
PIL.Image.fromarray accepts 2-channel (LA mode) arrays as well, not just 1/3/4-channel. Reword the inline comments and test docstrings to say 'rejects > 4-channel arrays', which is the actual constraint driving the cap. Also drop a too-narrow 'mode in (L, RGB, RGBA)' assertion in test_save_compatible_output_passes_through_pil so a future 2-channel result would not be flagged as a failure.
This commit is contained in:
parent
ae88cd1966
commit
7c0c70b608
@ -37,8 +37,8 @@ class Blend(io.ComfyNode):
|
|||||||
def execute(cls, image1: torch.Tensor, image2: torch.Tensor, blend_factor: float, blend_mode: str) -> io.NodeOutput:
|
def execute(cls, image1: torch.Tensor, image2: torch.Tensor, blend_factor: float, blend_mode: str) -> io.NodeOutput:
|
||||||
image2 = image2.to(image1.device)
|
image2 = image2.to(image1.device)
|
||||||
# Reconcile mismatched channel counts. Downstream nodes (SaveImage,
|
# Reconcile mismatched channel counts. Downstream nodes (SaveImage,
|
||||||
# PreviewImage) ultimately call PIL.Image.fromarray which only
|
# PreviewImage) ultimately call PIL.Image.fromarray, which rejects
|
||||||
# supports 1/3/4-channel arrays, so we cap the output at 4 channels
|
# arrays with more than 4 channels, so we cap the output at 4
|
||||||
# (RGBA): any image with > 4 channels is truncated, and any image
|
# (RGBA): any image with > 4 channels is truncated, and any image
|
||||||
# with fewer channels than the (capped) target is padded with 1.0s
|
# with fewer channels than the (capped) target is padded with 1.0s
|
||||||
# so the extra slot behaves like an opaque alpha channel.
|
# so the extra slot behaves like an opaque alpha channel.
|
||||||
|
|||||||
@ -54,9 +54,9 @@ class TestImageBlend:
|
|||||||
non-singleton dimension 3'.
|
non-singleton dimension 3'.
|
||||||
|
|
||||||
The output is capped at 4 channels (RGBA) because downstream
|
The output is capped at 4 channels (RGBA) because downstream
|
||||||
SaveImage/PreviewImage rely on PIL.Image.fromarray, which only
|
SaveImage/PreviewImage rely on PIL.Image.fromarray, which rejects
|
||||||
supports 1/3/4-channel arrays. Without this cap, the failure would
|
arrays with more than 4 channels. Without this cap, the failure
|
||||||
just shift from blend-time to save-time.
|
would just shift from blend-time to save-time.
|
||||||
"""
|
"""
|
||||||
image1 = self.create_test_image(channels=3)
|
image1 = self.create_test_image(channels=3)
|
||||||
image2 = self.create_test_image(channels=5)
|
image2 = self.create_test_image(channels=5)
|
||||||
@ -65,8 +65,8 @@ class TestImageBlend:
|
|||||||
|
|
||||||
def test_output_capped_at_four_channels(self):
|
def test_output_capped_at_four_channels(self):
|
||||||
"""Both inputs having > 4 channels should still produce a 4-channel
|
"""Both inputs having > 4 channels should still produce a 4-channel
|
||||||
output, since SaveImage/PreviewImage cannot serialize anything
|
output. PIL.Image.fromarray (used by SaveImage/PreviewImage)
|
||||||
wider than RGBA via PIL.Image.fromarray."""
|
rejects arrays with more than 4 channels."""
|
||||||
image1 = self.create_test_image(channels=6)
|
image1 = self.create_test_image(channels=6)
|
||||||
image2 = self.create_test_image(channels=5)
|
image2 = self.create_test_image(channels=5)
|
||||||
result = Blend.execute(image1, image2, 0.5, "normal")
|
result = Blend.execute(image1, image2, 0.5, "normal")
|
||||||
@ -82,12 +82,11 @@ class TestImageBlend:
|
|||||||
image1 = self.create_test_image(channels=3)
|
image1 = self.create_test_image(channels=3)
|
||||||
image2 = self.create_test_image(channels=5)
|
image2 = self.create_test_image(channels=5)
|
||||||
result = Blend.execute(image1, image2, 0.5, "normal")
|
result = Blend.execute(image1, image2, 0.5, "normal")
|
||||||
# Mirror SaveImage's exact conversion (nodes.py:1662)
|
# Mirror SaveImage's exact conversion (nodes.py:1662). PIL accepts
|
||||||
|
# 1/2/3/4-channel arrays (L/LA/RGB/RGBA); a >4-channel output would
|
||||||
|
# raise "TypeError: Cannot handle this data type" here.
|
||||||
arr = np.clip(255.0 * result[0][0].cpu().numpy(), 0, 255).astype(np.uint8)
|
arr = np.clip(255.0 * result[0][0].cpu().numpy(), 0, 255).astype(np.uint8)
|
||||||
img = Image.fromarray(arr)
|
Image.fromarray(arr)
|
||||||
assert img.mode in ("L", "RGB", "RGBA"), (
|
|
||||||
f"Output mode {img.mode!r} cannot be saved by SaveImage"
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_different_size_and_channels(self):
|
def test_different_size_and_channels(self):
|
||||||
"""Different spatial size AND different channel counts should both be reconciled."""
|
"""Different spatial size AND different channel counts should both be reconciled."""
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user