Comfy for Advertising - OOH Visualization
概要
This ComfyUI workflow helps brand and creative teams quickly place an existing poster into realistic Out-of-Home (OOH) scenarios. It’s organized in two clear stages. STEP 1 – POSTER REFORMAT takes your source poster and non-destructively reformats it to multiple aspect ratios (vertical, horizontal, square, or custom) while preserving the original design. This stage is driven by LoadImage, PrimitiveNode (for width/height values), PrimitiveBoolean (to enable/disable formats), ComfySwitchNode (to route only the formats you want), and BatchImagesNode (to package multiple outputs).
SaveImage captures clean, reformatted versions ready for placement.
STEP 2 – OOH VISUALIZATION composites a chosen reformatted poster into a real or described environment. You can supply a location photo with LoadImage via the IMAGE ENVIRONMENT group or describe a scene in plain language (for example, "OOH billboard in downtown San Francisco, on top of a two-story building, pedestrian eye level") in the PROMPT ENVIRONMENT group. GeminiImage2Node is used as a prompt helper to convert your plain-language description into structured scene notes and file-name context.
Two custom processing nodes (ae42e662-5e2b-4f52-b31d-267bd68f1c6f and 88b611c3-ce43-4e7a-a59f-dd16f57a8853) handle the perspective mapping and blending of the poster onto the target surface, so you can fine-tune scale, skew, and overlay strength for believable placement. SaveImage then outputs the final mockups, optionally in batches, so you can compare formats and scenes side by side.
入力するもの
- ワークフローを読み込み中
ComfyUI で実行できます。 このワークフローはこのページでは実行できません。すべてが読み込まれた状態でComfy Cloudで開くか、ご自身のComfyUI用にダウンロードしてください。
Cloudで試す例を試す
ワークフローの内部
ノードグラフの読み取り専用プレビューです。ノードを編集するには、Comfy Cloudで開くかダウンロードしてください。
Loading the graph
Open full-size workflow preview- 作成者
- ComfyUI
カスタムノードが必要です
- ワークフローを読み込み中
コードからこのワークフローを使用する
可能な場合はワークフローグラフと入力から生成されます。それ以外の場合は保存された例が表示されます。料金が発生する場合があるため、コードを実行する前に認証情報とエンドポイントを確認してください。
What you need
- Runs on
- Comfy Cloud
- キー
- COMFY_API_KEY
- ファイル
- コードによって URL からアップロードされます
有料の Cloud プランとクレジットが必要です。
# Python 3.10+: pip install comfy-sdk==0.4.0
import os
from comfy_sdk import Comfy
api_key = os.environ.get("COMFY_API_KEY", "").strip()
if not api_key: raise RuntimeError("Set COMFY_API_KEY")
os.environ.setdefault("COMFY_BASE_URL", "https://cloud.comfy.org")
client = Comfy(api_key=api_key)
workflow = client.workflows.from_json({
"64": {
"class_type": "SaveImage",
"inputs": {
"filename_prefix": "Poster_Resize_Custom",
"images": [
"252:251",
0
]
},
"_meta": {
"title": "Save Image"
}
},
"66": {
"class_type": "LoadImage",
"inputs": {
"image": "UPLOADED_image_FILENAME"
},
"_meta": {
"title": "INPUT POSTER"
}
},
"127": {
"class_type": "GeminiImage2Node",
"inputs": {
"aspect_ratio": "1:1",
"images": [
"128",
0
],
"model": "gemini-3-pro-image-preview",
"prompt": "visualize this poster (keep its aspect ratio) to a OOH billboard in the street of downtown San Francisco, on top of a two story building. Shot from the perspective of a pedestrian",
"resolution": "2K",
"response_modalities": "IMAGE+TEXT",
"seed": 0,
"system_prompt": "You are an expert image-generation engine. You must ALWAYS produce an image.\nInterpret all user input—regardless of format, intent, or abstraction—as literal visual directives for image composition.\nIf a prompt is conversational or lacks specific visual details, you must creatively invent a concrete visual scenario that depicts the concept.\nPrioritize generating the visual representation above any text, formatting, or conversational requests."
},
"_meta": {
"title": "Nano Banana Pro (Google Gemini Image)"
}
},
"128": {
"class_type": "LoadImage",
"inputs": {
"image": "UPLOADED_image_2_FILENAME"
},
"_meta": {
"title": "INPUT POSTER"
}
},
"129": {
"class_type": "SaveImage",
"inputs": {
"filename_prefix": "Poster_Mockup",
"images": [
"136",
0
]
},
"_meta": {
"title": "Save Image"
}
},
"135": {
"class_type": "BatchImagesNode",
"inputs": {
"images.image0": [
"142",
0
],
"images.image1": [
"235:162",
0
]
},
"_meta": {
"title": "Batch Images"
}
},
"136": {
"class_type": "ComfySwitchNode",
"inputs": {
"on_false": [
"127",
0
],
"on_true": [
"138",
0
],
"switch": [
"141",
0
]
},
"_meta": {
"title": "If/Else Switch"
}
},
"138": {
"class_type": "GeminiImage2Node",
"inputs": {
"aspect_ratio": "auto",
"images": [
"135",
0
],
"model": "gemini-3-pro-image-preview",
"prompt": "replace the billboard of the first image to the poster of the second image",
"resolution": "2K",
"response_modalities": "IMAGE+TEXT",
"seed": 303461698342474,
"system_prompt": "You are an expert image-generation engine. You must ALWAYS produce an image.\nInterpret all user input—regardless of format, intent, or abstraction—as literal visual directives for image composition.\nIf a prompt is conversational or lacks specific visual details, you must creatively invent a concrete visual scenario that depicts the concept.\nPrioritize generating the visual representation above any text, formatting, or conversational requests."
},
"_meta": {
"title": "Nano Banana Pro (Google Gemini Image)"
}
},
"141": {
"class_type": "PrimitiveBoolean",
"inputs": {
"value": True
},
"_meta": {
"title": "SWITCH TO IMAGE ENVIRONMENT"
}
},
"142": {
"class_type": "LoadImage",
"inputs": {
"image": "UPLOADED_image_3_FILENAME"
},
"_meta": {
"title": "IMAGE"
}
},
"243": {
"class_type": "SaveImage",
"inputs": {
"filename_prefix": "Poster_Resize1",
"images": [
"252:250",
0
]
},
"_meta": {
"title": "Save Image"
}
},
"245": {
"class_type": "SaveImage",
"inputs": {
"filename_prefix": "Poster_Resize2",
"images": [
"252:249",
0
]
},
"_meta": {
"title": "Save Image"
}
},
"247": {
"class_type": "SaveImage",
"inputs": {
"filename_prefix": "Poster_Resize3",
"images": [
"252:248",
0
]
},
"_meta": {
"title": "Save Image"
}
},
"235:152": {
"class_type": "Paste By Mask",
"inputs": {
"image_base": [
"235:230",
0
],
"image_to_paste": [
"235:229",
0
],
"mask": [
"235:229",
0
],
"resize_behavior": "keep_ratio_fit"
},
"_meta": {
"title": "Paste By Mask"
}
},
"235:153": {
"class_type": "ImageToMask",
"inputs": {
"channel": "red",
"image": [
"235:152",
0
]
},
"_meta": {
"title": "Convert Image to Mask"
}
},
"235:158": {
"class_type": "ImageToMask",
"inputs": {
"channel": "red",
"image": [
"235:231",
0
]
},
"_meta": {
"title": "Convert Image to Mask"
}
},
"235:159": {
"class_type": "InvertMask",
"inputs": {
"mask": [
"235:153",
0
]
},
"_meta": {
"title": "Invert Mask"
}
},
"235:162": {
"class_type": "ImageRemoveAlpha+",
"inputs": {
"image": [
"235:165",
0
]
},
"_meta": {
"title": "🔧 Image Remove Alpha"
}
},
"235:163": {
"class_type": "Get Image Size",
"inputs": {
"image": [
"128",
0
]
},
"_meta": {
"title": "Get Image Size"
}
},
"235:165": {
"class_type": "Paste By Mask",
"inputs": {
"image_base": [
"235:231",
0
],
"image_to_paste": [
"128",
0
],
"mask": [
"235:152",
0
],
"resize_behavior": "keep_ratio_fit"
},
"_meta": {
"title": "Paste By Mask"
}
},
"235:168": {
"class_type": "MaskComposite",
"inputs": {
"destination": [
"235:158",
0
],
"operation": "add",
"source": [
"235:159",
0
],
"x": 0,
"y": 0
},
"_meta": {
"title": "Combine Masks"
}
},
"235:191": {
"class_type": "FluxResolutionNode",
"inputs": {
"aspect_ratio": "1:1 (Perfect Square)",
"custom_aspect_ratio": "1:1",
"custom_ratio": False,
"divisible_by": "8",
"megapixel": "2.1"
},
"_meta": {
"title": "Flux Resolution Calc"
}
},
"235:229": {
"class_type": "LayerUtility: ColorImage V2",
"inputs": {
"color": "#ffffff",
"custom_height": [
"235:163",
1
],
"custom_width": [
"235:163",
0
],
"size": "custom"
},
"_meta": {
"title": "LayerUtility: ColorImage V2"
}
},
"235:230": {
"class_type": "LayerUtility: ColorImage V2",
"inputs": {
"color": "#000000",
"custom_height": [
"235:191",
1
],
"custom_width": [
"235:191",
0
],
"size": "custom"
},
"_meta": {
"title": "LayerUtility: ColorImage V2"
}
},
"235:231": {
"class_type": "LayerUtility: ColorImage V2",
"inputs": {
"color": "#ffffff",
"custom_height": [
"235:191",
1
],
"custom_width": [
"235:191",
0
],
"size": "custom"
},
"_meta": {
"title": "LayerUtility: ColorImage V2"
}
},
"252:131": {
"class_type": "StringConcatenate",
"inputs": {
"delimiter": "",
"string_a": "Resize the OOH poster to ",
"string_b": "3:1"
},
"_meta": {
"title": "Concatenate Text"
}
},
"252:132": {
"class_type": "StringConcatenate",
"inputs": {
"delimiter": "",
"string_a": [
"252:131",
0
],
"string_b": " aspect ratio. Only move and rescale elements to fit the new format. Maintain all original typography, colors, graphics, logos, and visual hierarchy exactly as they are. No design changes."
},
"_meta": {
"title": "Concatenate Text"
}
},
"252:248": {
"class_type": "ComfySwitchNode",
"inputs": {
"on_false": [
"66",
0
],
"on_true": [
"252:260",
0
],
"switch": True
},
"_meta": {
"title": "If/Else Switch"
}
},
"252:249": {
"class_type": "ComfySwitchNode",
"inputs": {
"on_false": [
"66",
0
],
"on_true": [
"252:259",
0
],
"switch": True
},
"_meta": {
"title": "If/Else Switch"
}
},
"252:250": {
"class_type": "ComfySwitchNode",
"inputs": {
"on_false": [
"66",
0
],
"on_true": [
"252:258",
0
],
"switch": True
},
"_meta": {
"title": "If/Else Switch"
}
},
"252:251": {
"class_type": "ComfySwitchNode",
"inputs": {
"on_false": [
"66",
0
],
"on_true": [
"252:264",
0
],
"switch": True
},
"_meta": {
"title": "If/Else Switch"
}
},
"252:258": {
"class_type": "GeminiNanoBanana2",
"inputs": {
"aspect_ratio": "9:16",
"images": [
"66",
0
],
"model": "Nano Banana 2 (Gemini 3.1 Flash Image)",
"prompt": "Resize this OOH poster to the new aspect ratio. Only move and rescale elements to fit the new format. Maintain all original typography, colors, graphics, logos, and visual hierarchy exactly as they are. No design changes.",
"resolution": "2K",
"response_modalities": "IMAGE",
"seed": 806105455324093,
"system_prompt": "You are an expert image-generation engine. You must ALWAYS produce an image.\nInterpret all user input—regardless of format, intent, or abstraction—as literal visual directives for image composition.\nIf a prompt is conversational or lacks specific visual details, you must creatively invent a concrete visual scenario that depicts the concept.\nPrioritize generating the visual representation above any text, formatting, or conversational requests.",
"thinking_level": "HIGH"
},
"_meta": {
"title": "Nano Banana 2"
}
},
"252:259": {
"class_type": "GeminiNanoBanana2",
"inputs": {
"aspect_ratio": "16:9",
"images": [
"66",
0
],
"model": "Nano Banana 2 (Gemini 3.1 Flash Image)",
"prompt": "Resize this OOH poster to the new aspect ratio. Only move and rescale elements to fit the new format. Maintain all original typography, colors, graphics, logos, and visual hierarchy exactly as they are. No design changes.",
"resolution": "2K",
"response_modalities": "IMAGE",
"seed": 952769964755599,
"system_prompt": "You are an expert image-generation engine. You must ALWAYS produce an image.\nInterpret all user input—regardless of format, intent, or abstraction—as literal visual directives for image composition.\nIf a prompt is conversational or lacks specific visual details, you must creatively invent a concrete visual scenario that depicts the concept.\nPrioritize generating the visual representation above any text, formatting, or conversational requests.",
"thinking_level": "HIGH"
},
"_meta": {
"title": "Nano Banana 2"
}
},
"252:260": {
"class_type": "GeminiNanoBanana2",
"inputs": {
"aspect_ratio": "1:1",
"images": [
"66",
0
],
"model": "Nano Banana 2 (Gemini 3.1 Flash Image)",
"prompt": "Resize this OOH poster to the new aspect ratio. Only move and rescale elements to fit the new format. Maintain all original typography, colors, graphics, logos, and visual hierarchy exactly as they are. No design changes.",
"resolution": "2K",
"response_modalities": "IMAGE",
"seed": 521333244527813,
"system_prompt": "You are an expert image-generation engine. You must ALWAYS produce an image.\nInterpret all user input—regardless of format, intent, or abstraction—as literal visual directives for image composition.\nIf a prompt is conversational or lacks specific visual details, you must creatively invent a concrete visual scenario that depicts the concept.\nPrioritize generating the visual representation above any text, formatting, or conversational requests.",
"thinking_level": "HIGH"
},
"_meta": {
"title": "Nano Banana 2"
}
},
"252:264": {
"class_type": "GeminiNanoBanana2",
"inputs": {
"aspect_ratio": "auto",
"images": [
"66",
0
],
"model": "Nano Banana 2 (Gemini 3.1 Flash Image)",
"prompt": [
"252:132",
0
],
"resolution": "2K",
"response_modalities": "IMAGE",
"seed": 188565245405213,
"system_prompt": "You are an expert image-generation engine. You must ALWAYS produce an image.\nInterpret all user input—regardless of format, intent, or abstraction—as literal visual directives for image composition.\nIf a prompt is conversational or lacks specific visual details, you must creatively invent a concrete visual scenario that depicts the concept.\nPrioritize generating the visual representation above any text, formatting, or conversational requests.",
"thinking_level": "HIGH"
},
"_meta": {
"title": "Nano Banana 2"
}
}
})
# Replace each example.com URL with a public URL of your file.
workflow.set_input("66", "image", client.assets.from_url("https://example.com/replace-with-a-url/image"))
workflow.set_input("128", "image", client.assets.from_url("https://example.com/replace-with-a-url/image_2"))
workflow.set_input("142", "image", client.assets.from_url("https://example.com/replace-with-a-url/image_3"))
# run() also passes api_key to the partner nodes in this workflow.
job = client.run(workflow, api_key=api_key)よくある質問
You can do either. Use IMAGE ENVIRONMENT with LoadImage to supply a real location photo, or use PROMPT ENVIRONMENT if you want GeminiImage2Node to turn your plain-language description into scene notes and file-name context. You can switch between paths with the provided switches.
STEP 1 reformats by resizing and padding/cropping according to the PrimitiveNode dimensions you set, driven by toggles in PrimitiveBoolean and routing via ComfySwitchNode. This preserves your design while producing standard OOH-friendly canvases (vertical, horizontal, square, or custom).
They handle the OOH placement step: warping the selected poster to match the billboard plane and blending it into the scene. Use their UI controls to fine-tune perspective (corner/scale/rotation) and the blend for a realistic result.
Yes. Enable the formats you want with the PrimitiveBoolean switches in STEP 1. Then, in STEP 2, connect those outputs to your chosen environment path. BatchImagesNode and SaveImage will export a consistent set of mockups in one run.