ComfyUI Node

CS Transform

Spin, scale, and slide an image — and its mask — around a pivot point

By claussteinmassl·Created 2 years ago·Updated 2 years ago· 1
CS Transform
  • image
  • mask
  • canvas
  • image
  • mask
position_x0
position_y0
pivot_x0
pivot_y0
rotation0.00
scale1.00
canvas_width1024
canvas_height1024
expand_canvasfalse
show_pivotfalse

Every compositing workflow eventually hits the same wall: you've got a subject you want to rotate, shrink, and drop somewhere else on the canvas, and the mask that belongs with it has to move exactly the same way or your inpainting region lands in the wrong place. CS Transform is a small utility that does scale, rotation, and translation around a chosen pivot point - and applies the identical transform to your image and its mask, so they stay glued together. Nothing about this is fancy, and nothing about it needs a model, a key, or a download. It's a two-function OpenCV wrapper, and sometimes that's exactly what you want.

Where people actually reach for it: relocating a subject before compositing it back with ImageCompositeMasked, re-aiming a mask before an inpaint pass (the crop-and-stitch school of inpainting lives on precise geometry), or pre-rotating something for an outpainting canvas. The whole point of the node is that image and mask transform as one unit, so you never have to eyeball-align them afterward.

How it works

Under the hood it's cv2.warpAffine run three times in a fixed order on a virtual canvas: scale around the pivot, then rotate around the pivot, then translate by your position_x / position_y offsets. The pivot is a point in canvas space - not necessarily inside the image - so you can rotate a picture around its corner, its center, or a point floating off to the side. Whatever you feed it as image goes through the pipeline; whatever you feed as mask goes through the exact same matrices, which is how they stay registered.

If you pass a canvas image, its dimensions override canvas_width / canvas_height entirely. expand_canvas (default off) computes the bounding box of the rotated image, grows the canvas to fit it, and centers the image on the bigger canvas so nothing gets chopped.

The inputs that matter

Most of these have sane defaults, so you'll touch three or four:

  • pivot_x / pivot_y - the point everything rotates and scales around. Defaults to 0,0 (top-left of the canvas).
  • position_x / position_y - final translation in canvas pixels.
  • rotation (degrees, -360 to 360) and scale (0 to 100, 1.0 = original size).
  • canvas_width / canvas_height - default 1024×1024. This is the trap: the node does not size the canvas from your image. Drop in a 2048px image and leave these at default and you're sampling a 1024×1024 window of it.
  • show_pivot - draws a marker at the pivot after transformation so you can verify it landed where you thought.

Outputs are image and mask, each optional. Feed it a mask with no image and you get a transformed mask back with None for the image.

Install

It's a one-node pack, installable like any other:

cd ComfyUI/custom_nodes
git clone https://github.com/claussteinmassl/ComfyUI-CS-CustomNodes

Then restart ComfyUI. Or just search "CS Transform" in ComfyUI Manager. There's no requirements.txt - it only uses numpy, opencv-python, and torch, all of which stock ComfyUI already ships. That's the whole install story; no models, no weights, nothing to download.

Gotchas worth knowing

  • The canvas crop trap above is the one that bites. Set expand_canvas on, or set the canvas size to match your input.
  • The output isn't the float convention ComfyUI expects. ComfyUI images are normally float tensors in [0, 1]; this node returns raw uint8 in [0, 255] straight from OpenCV, with no normalization step. Feed it into nodes that assume a 0–1 range and things look washed out or worse. Same story for the mask output. If something downstream renders wrong, check the dtype.
  • The "red" pivot dot is actually blue. cv2.circle writes a BGR (0,0,255), and ComfyUI tensors are RGB - so the marker lands in the blue channel. Harmless, but a little reminder that this pack talks to OpenCV, not to the ComfyUI convention.

The pack is a single initial commit with a handful of stars' worth of attention - don't expect updates or a community around it. But for "rotate this subject and its mask into place before compositing," it does the one job it claims, with zero dependencies. The two-function OpenCV wrapper is the whole pitch, and it's a fine one.

CategoryCS Custom Nodes/Transform

Inputs (13)

NameTypeDefaultDescription
position_xINT0-5000–5000
position_yINT0-5000–5000
pivot_xINT0-5000–5000
pivot_yINT0-5000–5000
rotationFLOAT0.00-360–360
scaleFLOAT1.000–100
canvas_widthINT10241–10000
canvas_heightINT10241–10000
expand_canvasBOOLEANfalse
show_pivotBOOLEANfalse
imageoptIMAGE
maskoptMASK
canvasoptIMAGE

Outputs (2)

NameTypeDescription
imageIMAGE
maskMASK