CMYK Magic
The ComfyUI node that prints your image like a 1948 comic, not a Photoshop filter
- image
- image
- plates
You've got a generated image you want to look printed - a riso-style poster, a Ben-Day comic panel, a vintage ad - and the usual filter nodes that lay dots on top of a colorized photo aren't doing it. CMYK Magic is not that. It treats your inks like real inks: you hand it up to eight colors plus a paper color, it solves for the best per-pixel mix of those inks to rebuild your image, screens each ink plate at its own angle with a print pattern, and stacks the plates bottom-up like a press run. Same family as the commercial Photoshop plugin Retratone, but procedural, seedable, and free. It's brand new with almost no community footprint yet, but the README and docs are unusually good. Pure torch and seeded: no model file, no API, no key - nothing to download beyond the node.
How it actually works
The pipeline is grade → separate → screen → stack, and the last three are where the print illusion lives. First each pixel becomes a set of per-ink coverage values. In Color Match mode the composite is affine in each ink's coverage, so the solve is an exact coordinate-descent least-squares pass (three closed-form sweeps); swap an ink color and the whole image re-separates around it. Tint mode instead is a gradient map: each ink owns a darkness band on the shadows→highlights axis.
Then each coverage plate is thresholded by a pattern field at its own angle into halftone dots, lines, waves, or grain. Two details make this read as press rather than filter: dots are Euclidean (past 50% the paper becomes the circles - the negative-dot holes of a real contact screen), and the screen is tone-calibrated, so a 20% call prints 20% and a blank plate doesn't fog grey. Finally the plates composite in print order over the paper color with an ink blend from opaque paint (0) to pure multiply (100) - real ink is translucent, and the stack is exactly that. Pattern pitch scales with image dimensions, and everything follows ComfyUI's device selection - CPU or GPU, no special setup.
The inputs that matter
There are a lot of widgets, but the ones a beginner actually touches:
preset- the fastest path in. Three dozen built-in looks, from Vintage Poster through the comic-era set (Craftint, DC, and Silver Age reproductions) down to Blueprint and 8-Bit Dither. Picking one loads its settings into the widgets and snaps back to Custom; tweaking anything flips you to Custom. A preset also writes hidden per-ink fields - angle, frequency, solid-only - so tick Per-ink angle / freq in the panel if you want to see everything it did.patternandscale- 17 screen styles (dots, hatch, waves, fan, spiral, mezzotint, bayer, solid) at a size from fine print (60) to giant pop-art (400).dot_gain,ink_fade,plate_drift- the worn-press trio: ink spread on absorbent stock, mottled ink density, per-plate misregistration in px. Crank all three for a sloppy letterpress, keep them low for a clean riso run.tint_quantize- snaps plates to the tint percentages a real colorist could call (25/50 gives the famous 64-color comic palette). Pair withplate_render: bendayfor multi-screen Ben-Day plates.ink_config- raw JSON for the ink set: colors, print order, paper, mode. In the browser you normally never touch this - the node ships its own panel that manages it visually, with pickable galleries, a live preview, per-ink patterns, and 🎲 randomize toggles. Random draws come from the seed: set the seed'scontrol_after_generateto randomize and every run is a new look, yet any result is reproducible by fixing its seed.
Outputs
image- the finished print (alpha preserved).plates- one separation per ink on white, batched in print order, like Retratone's Convert to Layers. The intended pairing: this node deliberately stops at the ink layer, so stack it underComfyUI-Print-Look's paper presets for the full artifact.
Install
Via ComfyUI Manager, search ComfyUI-CMYK-Magic, or:
cd ComfyUI/custom_nodes
git clone https://github.com/marcsole96/ComfyUI-CMYK-Magic.git
Then restart ComfyUI. The pack's pyproject.toml declares zero dependencies - pure torch, so no pip drama and no model downloads - and it works on both the classic canvas and the new Vue node renderer.
Gotchas
If the panel doesn't appear (headless, API mode), ink_config is plain JSON - you can still set colors and order by hand, and presets stick (the preset name overrides widgets directly there, unlike the UI's snap-back). Because pitch auto-scales with image size, the same scale won't look identical at 512 and at 2K - by design, so previews and upscales match each other rather than a fixed dot size. And give a preset a pass before hand-tuning; these encode real print history, and the docs explain each era's look.
Inputs (17)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| preset | COMBO | Custom | In the UI, picking a preset loads its settings into the widgets and snaps back to Custom. Headless, a preset name overrides the widgets directly. |
| pattern | COMBO | print_dots | 'random' picks a fresh pattern from the seed each run (pair with seed control_after_generate: randomize). |
| scale | FLOAT | 604–400 | Halftone pattern size. 60 = fine print, 400 = giant pop-art. |
| roughness | FLOAT | 200–100 | Distresses the pattern from clean press to worn analog. |
| brightness | FLOAT | 0-100–100 | — |
| contrast | FLOAT | 0-100–100 | — |
| ink_multiply | FLOAT | 600–100 | 0 = opaque paint, 100 = pure multiply. In between = the half-opaque real-ink mix. |
| ink_fade | FLOAT | 100–100 | Worn, mottled ink density. |
| dot_gain | FLOAT | 350–100 | Ink spread on absorbent paper: a called tint prints heavier than film. 0 = calibrated press (20% inks 20%), 100 = newsprint letterpress (20% grows to ~36%). |
| plate_drift | FLOAT | 1.50–30 | Random per-ink misregistration in px. |
| offset_angles | FLOAT | 600–90 | Screen-angle step between successive inks. |
| rotate | FLOAT | 0-90–90 | — |
| plate_render | COMBO | uniform | benday: each plate carries several screens at once like a real Ben-Day plate, light tints as dots, deep tints as a line/hatch sheet, 100% as an unscreened solid fill. Pair with tint_quantize comic_6 so the bands land on the colorist's tint calls. |
| tint_quantize | COMBO | off | Snap each plate to the tint percentages a colourist could call for (plus 0 and solid). 25/50 is what both Craftint and the Silver Age acetate system offered, 4 levels ^ 3 primaries = the 64-colour comic palette. 25/50/75 adds the call that arrived in the early 1980s. Flat stepped fields, no gradients. |
| seed | INT | 00–18446744073709550000 | — |
| ink_config | STRING | {"mode": "color_match", "background": "#f4efe6", "opaque_bottom": false, "inks": [{"color": "#e8c547", "on": true}, {"color": "#d1495b", "on": true}, {"color": "#30638e", "on": true}, {"color": "#1b1b25", "on": true}]} | Managed by the CMYK Magic panel. JSON: mode, background, opaque_bottom, inks (print order, first = bottom). |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| plates | IMAGE | — |