Nodes/BlueBox蓝色多脑盒/Rotate Image (BlueBox)
ComfyUI Node

Rotate Image (BlueBox)

Rotate Image (BlueBox) rotates from the original every time, so three rotations don't blur three times

By zhoutingxi·Created 23 days ago·Updated 5 days ago· 20
Rotate Image (BlueBox)
  • image
  • rotate_info
  • image
  • rotate_info
◄angle0►

The accumulating-rotation problem

Rotating an image in ComfyUI is not expensive. Rotating it six times, in six nodes, is. Every non-90° rotation resamples with bicubic interpolation and grows the canvas to fit the corners, which get filled black. Chain a few of those - the natural way to do "turn the subject 15° for this pass, then 10° more" - and you get progressively softer pixels, a canvas that keeps swelling, and a black border that a sampler will happily interpret as image content.

Rotate Image (BlueBox) exists to short-circuit that. It doesn't just rotate; it passes a small BLUEBOX_ROTATE_INFO record downstream, and the next rotate node in the chain uses that record to re-rotate from the original baseline instead of from the already-rotated pixels. One resample total, no matter how many nodes are in the chain.

That's the same reasoning as crop-and-stitch: do the geometry once from the source of truth, then put things back.

How it works

Start mode (no rotate_info connected): it records the current image's width and height and the angle you asked for, then rotates. Clockwise is positive, which matches what most people mean by "rotate 10°". Output size is the rotation bounding box, black fill in the corners.

Continue mode (rotate_info connected): the total is previous angle + this angle. Then it does three things in sequence, and this is the part that makes it accurate:

  1. Reverse-rotate the incoming image by the previous angle, to get back to the original orientation.
  2. Centre crop-or-pad that back to the exact original width and height, killing the ±1 pixel drift a reverse rotation leaves behind.
  3. Rotate once, by the total angle, and resize to the analytically computed bounding box - ceil(w·|cos| + h·|sin|) by ceil(w·|sin| + h·|cos|).

So the intermediate nodes get to work on a rotated, correctly-sized image (which is the point - you may be rotating so a tall subject fits a model's preferred aspect), while the final geometry is always derived from the original. Feed the last node in the chain -(total) and you're back to the original frame dimensions, having paid exactly one bicubic pass.

Inputs and outputs

  • angle (required, INT, −360 to 360) - clockwise degrees. In continue mode this is an increment, not an absolute.
  • image (optional IMAGE) - optional in the schema, mandatory in practice: the node raises an error if it's missing.
  • rotate_info (optional, BLUEBOX_ROTATE_INFO) - wire the previous node's info output here. Unconnected means start mode.

Outputs are image and rotate_info. The info carries the original dimensions and the accumulated angle; the custom type means ComfyUI won't let you wire it anywhere except another rotate node, which is a good guardrail.

Installing

cd ComfyUI/custom_nodes
git clone https://github.com/zhoutingxi/ComfyUI-BlueBox.git ComfyUI-BlueBox

Restart ComfyUI; it lives under BlueBox/experimental. Manager search term is ComfyUI-BlueBox. No pip installs - the repo's requirements.txt is empty, and this node uses only torch, numpy and Pillow, all of which ComfyUI already has. Like everything else in the pack, the browser-facing parts want WebGL and IndexedDB (Chrome/Edge), though this particular node needs neither.

Common issues

"My rotated image came out wrong when I chained it." Continue mode assumes the image arriving at the node is already at the previous angle. If you feed it the original image into a continue node, it reverse-rotates something that was never rotated. Wire the rotated output through, or don't pass rotate_info at all.

Black corners. expand plus black fill, every time - that's the geometry, not a bug. If the image is going into a sampler next, either crop back in first or mask the corners, because a diffusion model will cheerfully generate content into a black wedge.

Transparent PNGs go dark at the edges. RGBA input has its alpha multiplied into the RGB before rotation, so semi-transparent pixels darken instead of staying transparent. Composite first, or start from a flattened RGB image.

Only the first image survives a batch. The node takes image[0], so a four-image batch comes out as one rotated frame - fine for stills, wrong for anything you're treating as a sequence.

CategoryBlueBox/experimental

Inputs (3)

NameTypeDefaultDescription
angleINT0-360–360—
imageoptIMAGE—
rotate_infooptBLUEBOX_ROTATE_INFO—

Outputs (2)

NameTypeDescription
imageIMAGE—
rotate_infoBLUEBOX_ROTATE_INFO—