arkennemasis fal · Flux Control LoRA Canny Image to Image · $0.04/MP
Two images in, one composition out
- image
- control_lora_image
- images
- image_paths
- timings
- seed
- has_nsfw_concepts
- prompt
- info
Two image sockets and a denoise dial. That's the whole pitch, and it's a genuinely useful combination that people underuse.
The plain Canny node holds structure and lets the prompt invent everything else. This one adds a second image - real pixels to pull colour, tone and content from - and a strength value that decides how much of it survives. Composition from one picture, appearance from another.
How the two images divide the work
control_lora_image is the structure source. Canny edges are extracted from it (or you feed an edge map you made yourself) and the output is pinned to that layout.
image is the content/colour source and it is required on this node - that's the difference from the sibling node, where it's optional. Here the initial image is the point: below strength 1.0 you start from those pixels, not from noise.
strength defaults to 0.85. Read the tooltip literally, because it's the clearest statement of what the number means: 1.0 completely remakes the image, 0.0 preserves the original. So 0.85 is "mostly a remake, holding loosely onto the original's layout and colour". The bands people use in practice:
- 0.3–0.6 - you want the source recognisable; a restyle, a relight, a season change.
- 0.6–0.8 - moderate rework; new surfaces and materials, same object.
- 0.85–1.0 - the source is a suggestion. Composition survives, everything else is regenerated.
The most common mistake with denoise-style dials is running them too high for a subtle fix and then blaming the model for changing everything. If you want the jacket slightly darker, that's 0.4, not 0.85.
What this is actually for
The classic use is restaging: take a portrait and re-render it in a different environment, keeping the pose from the edge map and the skin tones and wardrobe colours from the photo. Or architectural visualisation - hold the building's lines from a photo and drive the materials from a render, or the reverse.
It's also the honest answer to "how do I get two references into one image without a LoRA". You're not teaching the model a style; you're giving it a skeleton and a palette and asking it to reconcile them. That works well when the two agree about geometry and badly when they don't - no setting fixes a reference whose perspective fights the edge map.
The settings that come with it
prompt drives the semantic content. control_lora_strength (default 1.0) is the Canny grip, and the community baseline for Flux ControlNets sits nearer 0.6, so reach for it if edges look traced. image_size defaults to square_hd, which means your source aspect ratio is not preserved - set custom and type in the dimensions, or you'll get a square remake of a non-square photo. num_inference_steps 28, seed -1, guidance_scale 3.5 (Flux guidance, not SDXL CFG), num_images, enable_safety_checker, output_format defaulting to jpeg.
Outputs
images for the graph, image_paths for the files in output/fal/fal-ai_flux-control-lora-canny_image-to-image/, and the diagnostics worth wiring up: timings, seed, has_nsfw_concepts, prompt, and info - a JSON blob with the request id, the cost estimate, the saved paths and fal's full answer.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/Hishamahmer/comfyui-arkennemasis
Restart ComfyUI, or install via ComfyUI-Manager → Install via Git URL. The pack's requirements.txt declares httpx, which only its Codex nodes need; the fal nodes are plain standard-library HTTP. No weights download, no GPU work.
FAL_KEY=your-key-from-fal.ai/dashboard/keys
in the .env beside run_nvidia_gpu.bat in the portable build (or your ComfyUI folder). No key field exists on the node - deliberately, so the key can't be saved into a workflow you share.
Cost
$0.04 per megapixel of output, so 1024×1024 ≈ 4¢ and 2048-wide ≈ 16¢, with the node's price badge tracking image_size and num_images. max_cost_usd (default $20, 0 disables) blocks the run before anything is uploaded if the estimate is over the cap.
Keep reuse_identical_run in mind while tuning: it defaults on, so re-queuing an unchanged graph returns the cached file rather than paying again. When you're sweeping strength in 0.05 steps, every value is a different run and a new charge - which is fine at four cents a look, but it's worth deciding where your sweep ends before you start.
When it fights you
The two images disagree. A front-on edge map with a three-quarter reference won't reconcile. Match the camera angle before you touch the settings.
Batch connected to a single-image socket. Both image and control_lora_image take one picture; send a batch and the node stops with a message rather than picking one for you.
Everything changed anyway. That's strength at 0.85 doing what it says. Drop it toward 0.5 and re-check.
Inputs (19)
| Name | Type | Default | Description |
|---|---|---|---|
| prompt | STRING | The prompt to generate an image from. | |
| image | IMAGE | URL of image to use for inpainting. or img2img | |
| image_size | COMBO | square_hd | The size of the generated image. 'custom' uses the width and height below. |
| image_size_width | INT | 102416–14142 | Width in pixels when image_size is 'custom'. |
| image_size_height | INT | 102416–14142 | Height in pixels when image_size is 'custom'. |
| num_inference_steps | INT | 281–50 | The number of inference steps to perform. |
| seed | INT | -1-1–2147483647 | The same seed and the same prompt given to the same version of the model will output the same image every time. -1 leaves it to the model. |
| loras | STRING | The LoRAs to use for the image generation. You can use any number of LoRAs and they will be merged together to generate the final image. JSON. Empty leaves it out. | |
| guidance_scale | FLOAT | 3.500–35 | The CFG (Classifier Free Guidance) scale is a measure of how close you want the model to stick to your prompt when looking for a related image to show you. |
| num_images | INT | 11–4 | The number of images to generate. |
| enable_safety_checker | BOOLEAN | true | If set to true, the safety checker will be enabled. Disabling it requires account authorization; unauthorized requests are always checked, and images flagged as unsafe are returned as black images. |
| output_format | COMBO | jpeg | The format of the generated image. |
| control_lora_image | IMAGE | The image to use for control lora. This is used to control the style of the generated image. | |
| control_lora_strength | FLOAT | 1.000–2 | The strength of the control lora. |
| strength | FLOAT | 0.850.01–1 | The strength to use for inpainting/image-to-image. Only used if the image_url is provided. 1.0 is completely remakes the image while 0.0 preserves the original. |
| max_cost_usdopt | FLOAT | 20.00–100000 | Safety cap. If the estimated cost of this run is above this many US dollars the node stops BEFORE sending anything to fal. 0 = no cap. |
| reuse_identical_runopt | BOOLEAN | true | If these exact inputs (the settings AND the same pictures/clips/audio) were already paid for and the files are still in output/fal, return them instead of paying again - also after a ComfyUI restart. Turn off for a fresh take with the same settings. |
| extra_jsonopt | STRING | Advanced: a JSON object merged into the request last, for any fal field this node has no box for. Example: {"seed": 7}. Leave empty normally. | |
| max_concurrentopt | INT | 11–32 | How many paid fal calls may run at the same time in one run, across every fal node. 1 (default) = one after another. This node starts its paid part only while fewer than this many fal calls are running. Once any fal node fails, the ones still waiting are not started, so nothing more is billed. |
Outputs (7)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | — |
| image_paths | STRING | — |
| timings | STRING | — |
| seed | INT | — |
| has_nsfw_concepts | STRING | — |
| prompt | STRING | — |
| info | STRING | JSON: request id, cost estimate, saved files and fal's full answer. |