saliacoel commited on
Commit
403bc1d
·
verified ·
1 Parent(s): c127a51

Upload canvas_crop.py

Browse files
Files changed (1) hide show
  1. canvas_crop.py +95 -0
canvas_crop.py ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+
3
+ class Canvas_Crop:
4
+ """
5
+ Reduce the canvas of an image by cropping pixels from each side.
6
+
7
+ Inputs
8
+ ------
9
+ image : IMAGE
10
+ Torch tensor [B, H, W, C], C=3 (RGB) or C=4 (RGBA), values in [0, 1].
11
+ If RGB is provided, it will be converted to RGBA by appending an opaque alpha channel.
12
+
13
+ left, right, up, down : INT
14
+ Number of pixels to remove from the corresponding side.
15
+
16
+ Output
17
+ ------
18
+ image : IMAGE
19
+ Torch tensor [B, H - (up+down), W - (left+right), 4] (RGBA).
20
+ """
21
+
22
+ @classmethod
23
+ def INPUT_TYPES(s):
24
+ return {
25
+ "required": {
26
+ "image": ("IMAGE",),
27
+ "left": ("INT", {"default": 0, "min": 0, "max": 16384, "step": 1}),
28
+ "right": ("INT", {"default": 0, "min": 0, "max": 16384, "step": 1}),
29
+ "up": ("INT", {"default": 0, "min": 0, "max": 16384, "step": 1}),
30
+ "down": ("INT", {"default": 0, "min": 0, "max": 16384, "step": 1}),
31
+ }
32
+ }
33
+
34
+ RETURN_TYPES = ("IMAGE",)
35
+ RETURN_NAMES = ("image",)
36
+ FUNCTION = "crop"
37
+ CATEGORY = "image/canvas"
38
+
39
+ def _ensure_rgba(self, img: torch.Tensor) -> torch.Tensor:
40
+ # Expect [B, H, W, C]
41
+ if img.dim() != 4:
42
+ raise ValueError(f"Expected image tensor [B, H, W, C], got shape {tuple(img.shape)}")
43
+
44
+ c = img.shape[-1]
45
+ if c == 4:
46
+ return img
47
+ elif c == 3:
48
+ # Add opaque alpha if only RGB provided
49
+ alpha = torch.ones((*img.shape[:-1], 1), dtype=img.dtype, device=img.device)
50
+ return torch.cat([img, alpha], dim=-1)
51
+ elif c > 4:
52
+ # If extra channels exist, keep the first 4 (RGBA)
53
+ return img[..., :4]
54
+ else:
55
+ raise ValueError("Expected RGB or RGBA image with 3 or 4 channels.")
56
+
57
+ def crop(self, image: torch.Tensor, left: int, right: int, up: int, down: int):
58
+ rgba = self._ensure_rgba(image) # [B, H, W, 4]
59
+ b, h, w, _ = rgba.shape
60
+
61
+ # Sanitize
62
+ left = max(0, int(left))
63
+ right = max(0, int(right))
64
+ up = max(0, int(up))
65
+ down = max(0, int(down))
66
+
67
+ # Validate that the requested crop is possible
68
+ if left + right >= w:
69
+ raise ValueError(
70
+ f"Crop too wide: left({left}) + right({right}) >= image width({w})."
71
+ )
72
+ if up + down >= h:
73
+ raise ValueError(
74
+ f"Crop too tall: up({up}) + down({down}) >= image height({h})."
75
+ )
76
+
77
+ # Compute crop window
78
+ y0 = up
79
+ y1 = h - down
80
+ x0 = left
81
+ x1 = w - right
82
+
83
+ # Perform crop
84
+ out = rgba[:, y0:y1, x0:x1, :]
85
+ return (out,)
86
+
87
+
88
+ # Required mappings for ComfyUI to discover the node
89
+ NODE_CLASS_MAPPINGS = {
90
+ "Canvas_Crop": Canvas_Crop
91
+ }
92
+
93
+ NODE_DISPLAY_NAME_MAPPINGS = {
94
+ "Canvas_Crop": "Canvas_Crop (Salia)",
95
+ }