Nodes/comfyui-kepri-nodes-pack/Kepri Image Finalize (Resize + Crop/Pad + Bg)
ComfyUI Node

Kepri Image Finalize (Resize + Crop/Pad + Bg)

The one node that finishes every product photo

By wearekhepri·Created 5 months ago·Updated 2 months ago· 1
Kepri Image Finalize (Resize + Crop/Pad + Bg)
  • background_color
  • image
  • mask
  • background_image
  • image
  • mask
  • over_zoom_risk
longest_edge2048
aspect_ratio1:1
background_modecolor
background_opacity1.00
padding_unitpercent
padding_h0
padding_w0
framingfull_view
framing_data
max_crop_frac0.22
aspect_ratio_override

If your workflow ends in a rat's nest of Crop, Resize, Pad and composite nodes, this is the node that eats them all. KepriImageFinalize is the flagship of the Kepri pack, and it's the terminal step of exactly one job: take a cut-out (from RMBG-2.0, BiRefNet, whatever your background-removal step was), and turn it into a finished, framed, on-background product photo in a single torch-only pass.

It was built by Kepri, a fashion-reseller startup, to run their production pipelines on Modal and RunPod - so it's API-first, every parameter is a wire, and it's tuned for the boring chores that eat your afternoon: re-centering the object, adding breathing room, hitting a target aspect ratio at a target resolution, and compositing a background without any of it looking off.

How it works

The node resolves the object mask in priority order: a wired mask input wins, otherwise the embedded alpha of an RGBA image, otherwise the whole frame. It finds the mask's bounding box, re-centers the object, applies padding, frames to the canvas, and only then composites the background - order matters, because padding changes how much of a background image shows.

The one widget that rules them all is background_mode:

  • transparent - outputs an RGBA image. The alpha rides inside the IMAGE tensor, so a plain SaveImage writes a real transparent PNG.
  • color - a flat #RRGGBB fill picked with a native browser color swatch (the KEPRI_COLOR widget, not a hand-rolled canvas), plus background_opacity for solid-to-semi-transparent.
  • image_preset - cover-crops your wired background_image (concrete, marble, wood) to the final canvas. The mode wins over any wired background image, deliberately, so you can keep one workflow and switch campaigns by injecting just the mode.

framing has two modes: full_view fits the whole object with padding around it (the default), and details fills the format by cropping - for close-ups where the object is already cut by the photo frame and padding would render as ugly bars. Wire in framing_data from KepriFramingAnalysis and the node goes fully adaptive, resolving each axis independently and guarding the crop with max_crop_frac.

The inputs that matter

  • longest_edge (2048) - resolution of the longest side of the final canvas. Drop this for low-res previews, keep it for e-commerce output.
  • aspect_ratio - 1:1, 4:3, 16:9, original, and friends. original uses the object's own bounding-box ratio.
  • padding_h / padding_w - breathing room around the centered object, in percent of the object or pixels of the output. Zero means "as large as possible in the frame."

Outputs: image (RGB, or RGBA in transparent mode), mask (final alpha), and over_zoom_risk, a boolean that fires when the adaptive crop guard had to cap the zoom - wire it to a preview and log it in production.

Install

It ships in the comfyui-kepri-nodes-pack, so you get all five Kepri nodes at once. In ComfyUI Manager, search "comfyui-kepri-nodes-pack" and install; or the manual way:

cd ComfyUI/custom_nodes
git clone https://github.com/wearekhepri/comfyui-kepri-nodes-pack

Restart ComfyUI and refresh the browser; the nodes appear under Kepri. One gotcha: the README's own clone command points at wearekhepri/comfyui-kepri.git, which is the wrong URL - the real repo is comfyui-kepri-nodes-pack. And there are zero extra dependencies: no requirements.txt, no model downloads. The models live in your other nodes, not this pack.

Where people get burned

The big one: your transparent PNG comes out black. That happens when the alpha is a separate MASK output feeding SaveImage - ComfyUI drops it and writes black. Keep the alpha inside the IMAGE (transparent mode) or save the MASK path correctly. Related trap: core Load Image's MASK output is the inverted alpha (the inpainting convention), so feed an RGBA image directly or stick an InvertMask in the path. The node itself is forgiving - malformed colors or framing_data strings fall back to sane behavior instead of crashing, which is the production pedigree showing.

CategoryKepri/Background

Inputs (15)

NameTypeDefaultDescription
longest_edgeINT204864–8192
aspect_ratioCOMBO1:110 options: original, 1:1, 4:3, 3:4, 16:9, 9:16, +4
background_modeCOMBOcolor3 options: transparent, color, image_preset
background_colorKEPRI_COLOR#FFFFFFCouleur de fond (mode 'color'). Clique la pastille = sélecteur de couleur natif du navigateur. Format #RRGGBB.
background_opacityFLOAT1.000–1Opacité du fond (mode 'color' uniquement). 1 = couleur pleine, 0 = fond transparent, entre = fond semi-transparent (l'opacité est portée par la sortie mask).
padding_unitCOMBOpercent2 options: percent, pixels
padding_hINT00–4096Marge verticale (haut ET bas) autour de l'objet centré. Unité = padding_unit ci-dessus. En 'percent' = % de la hauteur de l'objet (ex: 10) ; en 'pixels' = nb de px dans la résolution finale. Appliqué AVANT le fond.
padding_wINT00–4096Marge horizontale (gauche ET droite) autour de l'objet centré. Unité = padding_unit ci-dessus. En 'percent' = % de la largeur de l'objet (ex: 10) ; en 'pixels' = nb de px dans la résolution finale. Appliqué AVANT le fond.
imageoptIMAGE
maskoptMASK
background_imageoptIMAGE
framingoptCOMBOfull_viewfull_view = objet entier : il rentre en entier dans le format, le padding ajoute de la marge autour. details = photo close-up où l'objet est déjà coupé par le cadre : remplit le format cible (cover) en rognant le minimum, centré, sur le côté le plus long ; padding_h/padding_w/padding_unit ignorés.
framing_dataoptSTRINGMétadonnées de cadrage packées venant de KepriFramingAnalysis (ex. 'details;T=1,B=0,L=0,R=0;mT=0,mB=42,mL=30,mR=30'). Si branché : override le widget framing et pilote le padding/crop ADAPTATIF par axe (bord collé = 0 pad + ancrage ; bord libre = padding donné + extension du fond ; axe collé des 2 côtés = cover). Vide/absent = widget framing, comportement inchangé.
max_crop_fracoptFLOAT0.220–0.9Garde-fou sur-zoom du mode adaptatif. Quand un axe collé des 2 côtés (cover) force l'autre axe à déborder, fraction maximale de l'objet rognable sur cet axe ; au-delà le rognage est PLAFONNÉ à cette valeur et seul le manque restant devient des bandes de fond sur l'axe collé (+ over_zoom_risk=True). Curseur continu : 0 = jamais rogner (bandes maxi), 0.9 = quasi toujours plein cadre. N'agit que si framing_data est branché.
aspect_ratio_overrideoptSTRINGFormat branchable qui override le widget aspect_ratio. Permet de piloter PLUSIEURS KepriImageFinalize depuis une seule source (ex. primitive STRING dans le graph blending → le finalize transparent du subgraph background ET le recadrage de la plaque restent synchro). Accepte 'original' ou tout couple entier 'L:H' (ex. '1:1', '16:9'). Vide/absent ou invalide = widget aspect_ratio, comportement inchangé.

Outputs (3)

NameTypeDescription
imageIMAGE
maskMASK
over_zoom_riskBOOLEAN