Superside SKU Reference Sheet
One ruler for every product view
- front
- side
- three_quarter
- three_quarter_additional
- image
- info
The Superside pack is, almost node for node, a set of thin wrappers around fal.ai endpoints. This one isn't: no network call, no key, no per-run cost - it's PIL and numpy work dressed as a node.
Why you'd reach for it
You have three or four photographs of the same product - front, side, 3/4 - and you want them on one sheet at the same apparent size, plus a strip of close-ups. The obvious way is a chain: Normalize each view, stitch, resize. It doesn't work, and the README has the receipt. On one catalogue SKU the product was 2117 / 2105 / 2114 px wide across the three views but 754 / 808 / 891 px tall. Each Normalize sized its canvas from its own product, so the canvases came out 897 / 961 / 1060 and the stitcher resized whole panels against each other. Three apparent scales, one sheet.
You can't tune that chain out of the problem, because every node in it sees a single image and none can pick a shared pixels-per-unit. This node holds all the views at once, so it can - and that matters, since a sheet of views is exactly what you hand a multi-reference editing model (Seedream, Nano Banana, GPT Image) when a product must stay consistent across angles.
What it does with your pixels
Per view, it finds the product box by comparing pixels against the backdrop, which it estimates as the median of the four corner patches - it learns your catalogue's background rather than being told. background_threshold is how far a pixel must differ to count as product. It crops each view to that box, then computes one scale factor across every panel and applies it to all of them together, which is the whole trick: a millimetre of frame is the same number of pixels in every panel. Two panels per row, the odd view out filling the next, and the finished sheet is scaled once at the end for max_long_side.
The inputs worth setting
front is required; side, three_quarter and three_quarter_additional are optional and the layout follows how many you wire. Beyond that, most runs touch three:
max_long_side- default 5000, and a cap rather than a target. The sheet is built around 2600 px wide, so on defaults you're leaving it as built.background_threshold- default 12. Raise it when a soft shadow is read as product, lower it when a pale frame gets cut off. The one knob you'll actually tune, per catalogue.auto_logo- default off, which keeps the run entirely offline.
image is the sheet; info is JSON - views used, the shared scale, detail captions, final sheet size. This isn't an output node, so send it to SaveImage or PreviewImage as usual.
The DETAILS strip
auto_bridge and auto_joint are both on by default, and both crop fixed fractions of the product box rather than detecting anything, because on eyewear those sit in the same place every time. The README is blunt about why: asked to ground "the bridge between the two lenses", Florence-2 returned the whole frame on 3 of 5 frames, since a bridge is part of a continuous structure with no edge of its own. The fixed fractions were right 5 of 5. The joint is right 10 of 11 and misses on wrap-around sports frames whose temple sits further back - override that one through detail_boxes, which takes a JSON list of {view, x1, y1, x2, y2, caption}. view is 0-based over the connected views (front first) and the coordinates are 0–1 fractions of that view's product box.
auto_logo is the only part that leaves your machine, and it's the fiddly one: Florence-2 proposes one candidate per view, then a vision model picks the crop that carries a mark, because the logo sits on the lens for one brand and the temple for another and Florence returns no confidence to choose by. It needs api_key and costs a detection per view plus a vision call per SKU. Find nothing and the slot is dropped; the sheet still builds.
Install
ComfyUI Manager, search "Superside". Or:
cd ComfyUI/custom_nodes
git clone https://github.com/Superside/comfyui-superside-nodes.git
pip install -r requirements.txt
Then restart. Requirements are fal-client, pillow, numpy, torch and requests; ComfyUI already ships pillow, numpy and torch, so you're only really adding fal-client, and even that goes unused unless auto_logo is on. No model downloads.
Where it goes wrong
margin_percent leaves no room for the views- the margins ate the row. Lower it.- A bad product box. A shot where the product touches the frame edge poisons the corner-patch backdrop estimate, and a soft shadow trips the threshold. Fix at source, or nudge
background_threshold. detail_boxes is not valid JSON- it raises rather than guessing. Trailing commas will get you.- No logo in the strip. Either
api_keyis blank (it warns and moves on) or the vision pass answered "none". Nothing fails; you just get a shorter strip. - The key caveat. The pack falls back to a
FAL_KEYenv var whenapi_keyis blank. Fine on a box you own; on a shared backend keep pasting the key into the widget, because that input is the only access control there is.
Inputs (13)
| Name | Type | Default | Description |
|---|---|---|---|
| front | IMAGE | — | |
| sideopt | IMAGE | — | |
| three_quarteropt | IMAGE | — | |
| three_quarter_additionalopt | IMAGE | — | |
| max_long_sideopt | INT | 5000512–8192 | Longest side of the finished sheet, in pixels. |
| margin_percentopt | FLOAT | 6.00–25 | Breathing room around the product inside each panel, as a percentage of the panel's short side. |
| gap_pxopt | INT | 140–120 | Width of the dividers between panels. These exist so the editing model reads the panels as separate photographs rather than one blended image. |
| background_thresholdopt | FLOAT | 121–80 | How far a pixel must differ from the backdrop to count as product. Raise it when a soft shadow is being picked up, lower it when a pale frame is being cut off. |
| detail_boxesopt | STRING | Close-ups for the DETAILS strip, as a JSON list of {view, x1, y1, x2, y2, caption}. view is 0-based over the connected views; x1..y2 are 0-1 fractions of that view's product box. Leave empty for no hand-picked details. | |
| auto_bridgeopt | BOOLEAN | true | Put a close-up of the bridge in the DETAILS strip, cut from the centre of the front view. No API call - the bridge is in the same place on every frame. |
| auto_jointopt | BOOLEAN | true | Put a close-up of the joint between the lateral support and the front in the DETAILS strip, cut from the outer upper corner of a three-quarter view (or the side view). No API call. |
| auto_logoopt | BOOLEAN | false | Find the brand logo and put it first in the DETAILS strip. Florence-2 proposes one candidate per view and the vision model picks the one carrying a mark, so the logo is found whether it sits on the lens or on the temple. Needs api_key; costs one detection per view plus one vision call, once per SKU. |
| api_keyopt | STRING | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| info | STRING | — |