πΎ Transform & Rotate Pro
Straighten, scale and park anything on a ComfyUI canvas β mask rides along
- image
- mask
- image
- mask
- mask_bw
You know the drill: you cut a subject out, then spend ten minutes chaining rotate, resize and paste nodes together to set it down on a scene, and the mask you carefully kept loses sync halfway through. Transform & Rotate Pro (node class MP_ImageTransform, from the MachinePainting Nodes pack) collapses that into one node: rotate, scale and reposition an image inside a definable canvas, with an optional mask that rides the exact same transform and cuts the image out over a background you pick. It's a late addition - v2.2.0, alongside the rotation block added to Remove Background Pro - and both share the same underlying math, so cut with Remove Background Pro, park the result here, composite.
This is squarely the deterministic post-processing layer, not a generative pass - nothing runs a model, and nothing rewrites your pixels' content; it's the affine-transform equivalent of Photoshop's move tool. The use case is compositing: generated texture onto a product mockup, a character into a scene, any "one more element needs to sit at an angle on this canvas" job that would otherwise be three nodes and a prayer.
How it works
The canvas_width / canvas_height inputs (0 = match the incoming image, step of 8, up to 8192) define the frame your image lives in. The source is first fitted inside that canvas preserving aspect ratio, and only then is zoom applied - so zoom 0 always shows the whole image, whatever canvas size you chose. The zoom slider is exponential and centred on 0: -100 = 0.25x, -50 = 0.5x, 0 = 1.0x, +50 = 2x, +100 = 4x. Exponential means dragging left shrinks exactly as much as dragging right grows.
Under the hood it's a single OpenCV affine matrix built once and applied to everything: cv2.warpAffine with Lanczos resampling for the image and bilinear for the mask (bilinear avoids the ringing halos Lanczos leaves on hard mask edges). Rotation is free, or "fixed" to snap to the nearest 45Β° increment - handy when you actually want exactly 45Β°, not 46.3Β°. The angle slider reads clockwise-positive to the right. The XY offsets are a percentage of the canvas rather than raw pixels, so they keep meaning the same thing if you change canvas or source size later. Heads-up for Photoshop refugees: positive Y moves the image up, the opposite sign to PS's transform - deliberate, so both sliders read the same way, and it'll fight your muscle memory for about a minute.
The clever bit is the mask. Pass one in and it's warped with the identical matrix, so it stays pixel-registered to the image, then multiplied by a coverage mask so it can never claim area outside the rotated image. Whatever the mask leaves out is filled with your background (transparent, black, or white). No mask supplied? The transformed image's own extent becomes the mask.
The inputs that matter
- image - required, the thing you're moving.
- mask - optional; rides the transform and decides what stays visible.
- canvas_width / canvas_height - 0 matches the incoming image; set both to build a bigger frame.
- background - transparent / black / white fill for what the mask cuts away.
- rotation_method, rotation_angle, zoom, offset_x, offset_y - the controls above.
Outputs are image, mask (a real MASK tensor for compositing), and mask_bw (the same mask as a viewable 3-channel image, for wiring into IMAGE-only nodes or just eyeballing).
The gotcha that will bite you: "transparent" isn't alpha
A ComfyUI IMAGE tensor has no alpha channel, so transparent background doesn't give you RGBA. The node carries transparency through the mask output instead - under "transparent", the RGB pixels behind the mask are blacked out, and you're expected to composite over your real scene using that mask (e.g. through this pack's Image Blend Pro or any alpha-composite node). If you wire only the image output to a plain Save Image with background set to transparent, you'll get a black box. Use the mask. That's what it's for.
Install
ComfyUI Manager is the easy route - search "MachinePaintingNodes". Manual:
cd ComfyUI/custom_nodes
git clone https://github.com/machinepainting/ComfyUI-MachinePaintingNodes.git
pip install -r requirements.txt
then restart ComfyUI. The whole pack (not just this node) pulls opencv-python-headless, numpy<3, and rembg - rembg drags onnxruntime along, so install is chunkier than a transform deserves. That's the pack's price of entry, not this node's.
Small print
The node is an output node, so it shows an in-node preview (checkerboard behind transparent areas) and saves a temp preview PNG each run. One real limitation: it transforms the first frame of a batch - feed it 4 images and only frame 0 comes out, so don't route video through it. And if "fixed" rotation seems to ignore your carefully set 12.5Β°, it isn't broken; it snapped to the nearest 45Β°. That's the feature.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | β | |
| maskopt | MASK | β | |
| canvas_widthopt | INT | 00β8192 | β |
| canvas_heightopt | INT | 00β8192 | β |
| backgroundopt | COMBO | transparent | 3 options: transparent, black, white |
| rotation_methodopt | COMBO | free | 2 options: free, fixed |
| rotation_angleopt | FLOAT | 0.0-180β180 | β |
| zoomopt | FLOAT | 0.0-100β100 | β |
| offset_xopt | FLOAT | 0.0-100β100 | β |
| offset_yopt | FLOAT | 0.0-100β100 | β |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | β |
| mask | MASK | β |
| mask_bw | IMAGE | β |