Crop Box from Prepare Info
Getting the Crop Back Out as Four Integers
- prepare_info
- crop_x
- crop_y
- crop_width
- crop_height
Smart Photo Prepare decides where to crop, but a typed PORTRAIT_PREPARATION_INFO_V2 bundle isn't something you can plug into a node that wants four integers. This little reader is the adapter: it takes the info bundle and hands you crop_x, crop_y, crop_width, crop_height as plain INT outputs.
That's the entire node. One input, four outputs, no widgets, no settings, no processing. It exists because the pack's 2.0 design moved from "twenty sockets on one node" to "one typed bundle plus small local readers," and integers in source coordinates are a thing other nodes keep asking for.
When you actually need it
The coordinates always refer to the rectangle in the image you fed into preparation - after any upstream border removal, not the raw file. So crop_x/crop_y/crop_width/crop_height describe native_crop: the exact, unpadded source crop, not the padded, resized prepared_image.
Three real uses:
Pasting an edited result back into the original. You ran an editor on prepared_image, you liked the result, and now you want it in the full-frame photograph instead of a rectangular island. Stitch by Mask is the usual tool for that, and you need to place it somewhere sensible - the crop box is the geometry that tells you where the subject came from.
Anything that wants a box. A bbox-driven inpaint at original resolution, a crop-and-compare node, a debug overlay, a note node that records where the frame was taken. Four INTs is the lingua franca here; the bundle isn't.
Filename or metadata provenance. If you're building an output name from the crop, these are the numbers. They're integers in source pixels with no interpolation baked in, so they're safe to print.
Wiring
Nothing to it:
Smart Photo Prepare.prepare_info → Crop Box from Prepare Info.prepare_info
crop_x, crop_y, crop_width, crop_height → whatever needs them
The input is type-checked. Feed it something that isn't a preparation result and you get a TypeError telling you to connect the info output of Smart Photo Prepare - which is more useful than a silent zero, and it's the same pattern across the whole reader family.
Two things to keep in your head. First, crop_width/crop_height are the crop, so they can differ from the image's width and height whenever the editor tier has a different aspect ratio - that difference is exactly the source detail you gave up, and crop_loss_percent on Scale from Prepare Info puts a number on it. Second, if your plan padded the canvas, the crop box tells you nothing about the padding; dimensions on the prepared output are a separate reader.
Install
Readers ship with the pack, so there's nothing separate to install. ComfyUI Manager → PortraitUtils, then restart the ComfyUI server - a browser refresh alone won't register new Python nodes. Manually:
cd ComfyUI/custom_nodes
git clone https://github.com/heyburns/PortraitUtils
/path/to/ComfyUI/venv/bin/python -m pip install -r PortraitUtils/requirements.txt
It lands under PortraitUtils/Photo Edit V2/Readers. Dependencies are numpy, Pillow, opencv-python-headless, and tifffile - but this node touches none of them, so if it's missing, the problem is the pack failing to import, not this node. Check the console for an import error on startup.
One upgrade note: this is a 2.0 node. In 1.x, crop coordinates came out of the big preparation node as loose outputs. If an old workflow shows a missing node after you update the pack, this is one of the IDs that got replaced rather than aliased - reconnect prepare_info and rewire the four outputs.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| prepare_info | PORTRAIT_PREPARATION_INFO_V2 | — |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| crop_x | INT | — |
| crop_y | INT | — |
| crop_width | INT | — |
| crop_height | INT | — |