Analyze Product Lighting
It reads your product photo's lighting so the AI-generated scene actually matches
- product_image
- product_mask
- positive_prompt
- negative_prompt
- shadow_dir
If you've ever dropped a product photo onto an AI-generated background and watched it float there like a sticker, you already know the problem this node exists to fix. The background has its own lighting - sun from the left, cool shadows, whatever the model hallucinated - and your product was shot under different light entirely. They don't agree, and the eye knows instantly. AnalyzeProductLighting is the first half of the ComfyUI-RealProductScene pack, and its whole job is to make the background defer to the product's light instead of the other way around.
It sits before the KSampler in the pipeline. You feed it your cutout product plus a scene description, and it writes the actual prompt used to generate an empty background - empty, because the pack's core rule is that AI never redraws your product. The product pixels come 100% from your original PNG. The AI only gets to make the world around it, and this node makes sure that world is lit like the one your product was photographed in.
How it works
No neural networks, no API calls, no keys. The name oversells it slightly: this is classical image statistics, which is exactly why it's fast and free. It rebuilds your product into RGBA, then measures four things with PIL's ImageStat:
- Color temperature - warm vs. cool, from the R-B balance
- Brightness - high-key, low-key, or balanced
- Softness - the luminance spread inside the product (hard directional light vs. soft diffused)
- Light direction - it compares masked brightness of the left/right and top/bottom halves
Those four adjectives get assembled into a "lighting clause" and slotted into the pack's scene prompt template along with your scene, style, and camera text. That template also hammers home "EMPTY - do NOT include any product" and "9:16 portrait, suitable as a stable starting frame for image-to-video." The analysis also decides shadow_dir, because if light comes from the left, the shadow should fall right - and the composite node downstream needs to know that.
The inputs that matter
Most are plain text fields with sane defaults (scene, visual_style, camera, reserved_space). The two you'll actually touch:
product_image+product_mask- both outputs of aLoadImagenode, and the image must be a cutout with real transparency. No alpha and the node raises a clear error on purpose; this pack deliberately does not auto-cutout for you.lighting_mode-autouses the measured profile. Flip tomanualand type your own lighting clause intomanual_lightingwhen the auto read misses (e.g. a product with mixed materials that fools the stats).
The outputs
Three strings: positive_prompt → CLIP Text Encode (positive), negative_prompt → CLIP Text Encode (negative), and shadow_dir → wired straight into CompositeProductScene. That last one is the glue that keeps the two halves of the pack consistent.
Install
Grab the whole pack - the composite node ships in the same repo, so installing once gets you both. Via ComfyUI Manager, search ComfyUI-RealProductScene, or:
cd ComfyUI/custom_nodes
git clone https://github.com/yorimi-tamai/ComfyUI-RealProductScene.git
pip install -r ComfyUI-RealProductScene/requirements.txt
# restart ComfyUI
The requirements are just Pillow (usually already present) plus opencv-python, which only the CLI's swap backend needs. Restart and both nodes appear under the product-scene category.
One thing to get straight: this node needs no model of its own. The pack's example workflow generates its backgrounds with a z-image-turbo stack (z_image_turbo_bf16.safetensors, a qwen_3_4b.safetensors CLIP loaded as lumina2, and ae.safetensors), which you do have to download separately with their own licenses. But the nodes themselves are model-agnostic - swap that generation segment for any checkpoint you like, and you can also import any other text encoder since it just emits plain strings.
Troubleshooting
The one error you're basically guaranteed to hit once: "not a cutout." You fed a JPEG, or forgot to wire the mask. Make sure you're loading a transparent PNG and passing both IMAGE and MASK. And if the generated scene's light still feels wrong in the composite, don't fight it - switch to manual mode and spell out the light: "soft warm light from camera right, shallow falloff." You get full control without learning anything about image statistics. That's the quiet win of this pack: it's a friendly prompt factory with good defaults, and the manual override is always there when the defaults aren't good enough.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| product_image | IMAGE | — | |
| product_mask | MASK | — | |
| scene | STRING | modern minimalist living room | — |
| visual_style | STRING | high-end commercial product photography | — |
| camera | STRING | eye-level medium shot | — |
| reserved_space | STRING | clean, empty tabletop at the lower-center of the frame, ready to place the product | — |
| lighting_mode | COMBO | auto | 2 options: auto, manual |
| manual_lighting | STRING | soft natural light, from the upper left, balanced exposure | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| positive_prompt | STRING | — |
| negative_prompt | STRING | — |
| shadow_dir | STRING | — |