Panel Compositor (PanelComposer)
The node that finally stitches your manga page together
- images
- page_image
This is the payoff node of ComfyUI-PanelComposer. Panel Layout Provider decides the page geometry, you generate each panel separately, and Panel Compositor does the part everyone used to do by hand in Photoshop or Clip Studio: laying every panel image into its shape on the page, carving the gutters, and handing you one finished page_image. If the pack is a comic factory, this is the assembly line at the end.
The workflow shape is: Panel Layout Provider → per-panel dimensions → generate each panel with your own sampler chain → wire every panel image (in order!) into Panel Compositor along with the same layout_json → out comes the page. The compositor performs no generation of its own - all the geometry comes from layout_json, which is why the two nodes stay in lockstep.
How it works
Two details matter here. First, the images input is a list of independently-sized image tensors, not a single batched IMAGE. That's deliberate: ComfyUI's native IMAGE batching requires uniform height and width, and your panels will never be uniform. The node opts into list-mode input so each panel can be any size. Second, each image is fitted to its panel's bounding box, then masked to the actual polygon shape, and the gutter is carved by eroding that mask - so the gap between panels is real negative space, not just background showing through.
Extra images beyond the panel count get dropped by position; missing ones render as a numbered placeholder swatch in the same palette the Layout Provider preview uses, so a partial page still shows the full layout. That's a feature - you can eyeball panel 4 while panels 1-3 regenerate.
The inputs that matter
layout_json- the layout string straight out of Panel Layout Provider.images- your generated panel images, in the same order as the layout's panels. Order is everything.fit_mode- how each image fills its panel, and the setting you'll actually fiddle with. The author's own tooltip is the best summary: cover fills the panel and crops overflow; contain fits inside and pads the rest; stretch fills the box exactly and ignores aspect ratio;fit_to_shapewarps the image to match non-rectangular panels.scale_algo- the resampling filter for any resizing.lanczosby default, which is right.gutter_px(default 6) andgutter_color(default#000000) - the width and color of the gaps between panels.gutter_coloralso fills whatever paddingcontainleaves behind, so on a light page you'll want to change it from black.canvas_mode-auto(the default) uses the layout's own canvas size fromlayout_json, so the two nodes can't silently disagree about the page. The other modes -fixed_preset,fixed_custom, andscale_to_input- set the canvas independently, withscale_to_inputderiving it from your actual input images (largestorsmallest).
On fit_to_shape, and where the gotcha lives
cover, contain, and stretch all fill the panel's rectangular bounding box and then crop away whatever doesn't belong to the panel's actual shape. On a plain rectangle that's invisible. On angled panels - wedges, diagonals, notches - the angled edge slices through a rectangle-fitted image, cutting part of it off. fit_to_shape instead warps the whole image so its corners and edges land on the panel's actual polygon vertices, so nothing gets sliced. It's the reason the pack supports non-rectangular layouts at all, and it's flagged experimental: the README only verifies it against the built-in presets. On a hand-drawn custom shape, check the result - the warping can get weird with concave panels.
How to install it
cd ComfyUI/custom_nodes
git clone https://github.com/INuBq8/ComfyUI-PanelComposer
Restart ComfyUI. ComfyUI Manager users: search "PanelComposer". No extra dependencies beyond Pillow (ComfyUI ships it), no model downloads, no API keys.
Common issues
The one that will bite you first is image order. The compositor matches images to panels by position, not by content - if you generated with right_to_left reading order and feed the images left-to-right, your finished page reads backwards. (A reversed-image gotcha the pack doesn't save you from: you may need to reorder inputs yourself for RTL.) Second, a black gutter_color with contain padding on a white comic page looks jarring - set both deliberately. And if layout_json ever fails to parse, the error message will tell you it's missing required fields or has a malformed polygon, which usually means the layout string got mangled in transit rather than anything wrong with your images.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| layout_json | STRING | — | |
| images | IMAGE | — | |
| canvas_mode | COMBO | 4 options: auto, fixed_preset, fixed_custom, scale_to_input | |
| aspect_ratio | COMBO | 10 options: 1:1 (Square), 9:7, 4:3 (Standard), A4, 19:13, 3:2 (Classic Photo), +4 | |
| fixed_preset_size | COMBO | 3 options: 1080p, 2K, 4K | |
| fixed_custom_megapixels | FLOAT | 2.00.1–64 | — |
| page_orientation | COMBO | 3 options: auto, portrait, landscape | |
| scale_to_input_mode | COMBO | 2 options: largest, smallest | |
| fit_mode | COMBO | cover: fill panel, crop overflow. contain: fit inside panel, pad the rest. stretch: fill panel exactly, ignore aspect ratio. fit_to_shape: warp image to match non-rectangular panels (EXPERIMENTAL — only the built-in presets are verified; check the result on custom/drawn shapes). | |
| scale_algo | COMBO | lanczos | 4 options: nearest, bilinear, bicubic, lanczos |
| gutter_px | INT | 60–256 | — |
| gutter_color | STRING | #000000 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| page_image | IMAGE | — |