Nodes/PortraitUtils/Input & Crop Config
ComfyUI Node

Input & Crop Config

Fill this in once, then stop thinking about cropping

By heyburns·Created about a year ago·Updated 23 days ago· 3
Input & Crop Config
    • crop_config
    ◄autocrop_section── AUTOCROP · SOLID BORDER REMOVAL ──►
    ◄autocrop_strip_bottom_bannertrue►
    ◄autocrop_detect_borderstrue►
    ◄autocrop_fuzz_tolerance0.07►
    ◄autocrop_edge_uniformity0.85►
    ◄autocrop_pad_px0►
    ◄smart_crop_section── SMART CROP · SUBJECT / NATIVE SIZE ──►
    ◄smart_cropfalse►
    ◄resolution_policyAuto (preserve detail)►
    ◄forced_aspect_ratioAuto►
    ◄subject_mask►
    ◄padding_fillEdge extension►

    What it's for

    Every photo workflow has the same eight or ten decisions before anything interesting happens: is there a border to remove, do you want the frame tight or loose, what aspect ratio, what resolution for the model you're running, what do you call the thing you're cropping to. PortraitUtils 2.0 puts those into one node that emits one wire.

    This is the pack's answer to socket sprawl. The 1.x line had a central config node with a socket per setting, which meant twenty wires and a Set/Get mess. Here, Input & Crop Config emits a single typed PORTRAIT_CROP_CONFIG_V2 bundle. Consumers pull what they need out of it - Intelligent AutoCrop reads only the border section, Smart Photo Prepare reads the framing and resolution section - and small reader nodes exist for the cases where you need a plain STRING or INT back.

    It's a new pack (2.0 landed October 2026) with essentially no Reddit footprint yet, so you won't find a thread about it. The upside of that: the documentation in the repo is current and unusually honest about what the node doesn't do.

    What's actually in the bundle

    The two …_section widgets are single-option enums used purely as visual dividers - ── AUTOCROP · SOLID BORDER REMOVAL ── and ── SMART CROP · SUBJECT / NATIVE SIZE ──. Leave them alone.

    AutoCrop half. autocrop_detect_borders (solid-border scans on every edge), autocrop_strip_bottom_banner (the dark lettering footer - turn this on if you're working with Alamy-style host images; it defaults on), autocrop_fuzz_tolerance (0.07 by default, how much colour variation still counts as a solid border) and autocrop_edge_uniformity (0.85 - the fraction of an edge row that must match). autocrop_pad_px keeps N pixels of detected border, which is how you leave a deliberate thin frame instead of butting the photo against the canvas.

    Smart Crop half. smart_crop off keeps the widest safe frame; on frames tighter around whatever your subject mask says. resolution_policy is the one that actually changes your output dimensions:

    • Auto (preserve detail) - the recommended default. Picks the smallest automatic tier that avoids downscaling.
    • Auto (closest scale) - picks the smallest resize instead.
    • Force 1 MP, Force 1.5 MP, Force 2K (~4 MP) - the last is Qwen Image 2.1 only, and 1.5 MP is an explicitly experimental larger output for FireRed rather than one of its documented native tiers.

    Then forced_aspect_ratio (Auto, 1:1, 4:3, 3:4, 3:2, 2:3, 16:9, 9:16) and subject_mask, a multiline string that isn't used by this node at all - it's the prompt your segmentation node will read out via a reader. One optional widget sits outside the required set: padding_fill (Edge extension, Black, White), which only affects canvas that Smart Photo Prepare adds.

    Wiring it

    One output, crop_config. Wire it straight into AutoCrop and Photo Prepare, or park it on a Set node and pick it up anywhere. Keep pixel inputs separate - the pack deliberately leaves images, masks and colour references outside the bundle, which is why previews and cache behaviour stay predictable.

    Input & Crop Config ──┬─> Intelligent AutoCrop (reads border section)
                          └─> Smart Photo Prepare (reads framing + resolution)
                               └─> (reader) Crop Prompt from Config ─> your segmenter
    

    Where people get burned

    A typed bundle will not connect to a plain STRING, INT or FLOAT input. If a third-party segmenter or upscaler wants a primitive, that's what the reader nodes are for - Crop Prompt from Config, Seed from Config, Scale from Config, and so on. People also try "Convert widget to input" on the bundle's consumer and get confused when the socket won't take their PrimitiveString.

    The other cost is inherent to the pattern: a config that lives somewhere else in the graph can go stale without you noticing, and you'll be debugging a crop decision you set two hours ago. Keep the config node somewhere you can see it, and use one Set node, not five.

    Install

    ComfyUI Manager → search PortraitUtils (publisher heyburns, GPLv3), or 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
    

    Dependencies are numpy, Pillow>=9.1, opencv-python-headless>=4.10.0.84 and tifffile, installed into ComfyUI's own Python - not your system Python. One OpenCV wheel variant only. Restart the server after installing; refreshing the browser won't reload nodes.

    CategoryPortraitUtils/Config V2

    Inputs (12)

    NameTypeDefaultDescription
    autocrop_sectionCOMBO── AUTOCROP · SOLID BORDER REMOVAL ──1 options: ── AUTOCROP · SOLID BORDER REMOVAL ──
    autocrop_strip_bottom_bannerBOOLEANtrueRemove a dark text/banner strip touching the bottom edge before border detection.
    autocrop_detect_bordersBOOLEANtrueRemove uniform solid borders before subject framing.
    autocrop_fuzz_toleranceFLOAT0.070–0.5Color variation tolerated while identifying a solid border.
    autocrop_edge_uniformityFLOAT0.850–1Fraction of an edge row/column that must match the border color.
    autocrop_pad_pxINT00–256Pixels of detected border to retain on each cropped edge.
    smart_crop_sectionCOMBO── SMART CROP · SUBJECT / NATIVE SIZE ──1 options: ── SMART CROP · SUBJECT / NATIVE SIZE ──
    smart_cropBOOLEANfalseOFF keeps the widest safe frame. ON frames more tightly around the subject mask.
    resolution_policyCOMBOAuto (preserve detail)Auto: FireRed uses ~1 MP workflow presets; Klein can use 1/1.5 MP; Qwen 2.1 can also use 2K (~4 MP). Force 1.5 MP is an experimental larger output for FireRed. Force 2K is Qwen 2.1 only.
    forced_aspect_ratioCOMBOAutoForce an exact output aspect family, or use Auto for minimal cropping.
    subject_maskSTRING—
    padding_filloptCOMBOEdge extensionSmart Photo Prepare only: fill added canvas with Black, White, or repeated edge pixels. Does not change crop/protection decisions or AutoCrop border removal.

    Outputs (1)

    NameTypeDescription
    crop_configPORTRAIT_CROP_CONFIG_V2—