Nodes/CMYK Magic/CMYK Magic
ComfyUI Node

CMYK Magic

The ComfyUI node that prints your image like a 1948 comic, not a Photoshop filter

By marcsole96·Created 2 days ago·Updated 2 days ago· 0
CMYK Magic
  • image
  • image
  • plates
presetCustom
patternprint_dots
scale60
roughness20
brightness0
contrast0
ink_multiply60
ink_fade10
dot_gain35
plate_drift1.5
offset_angles60
rotate0
plate_renderuniform
tint_quantizeoff
seed0
ink_config{"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}]}

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.
  • pattern and scale - 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 with plate_render: benday for 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's control_after_generate to 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 under ComfyUI-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.

Categoryimage/print_look

Inputs (17)

NameTypeDefaultDescription
imageIMAGE
presetCOMBOCustomIn the UI, picking a preset loads its settings into the widgets and snaps back to Custom. Headless, a preset name overrides the widgets directly.
patternCOMBOprint_dots'random' picks a fresh pattern from the seed each run (pair with seed control_after_generate: randomize).
scaleFLOAT604–400Halftone pattern size. 60 = fine print, 400 = giant pop-art.
roughnessFLOAT200–100Distresses the pattern from clean press to worn analog.
brightnessFLOAT0-100–100
contrastFLOAT0-100–100
ink_multiplyFLOAT600–1000 = opaque paint, 100 = pure multiply. In between = the half-opaque real-ink mix.
ink_fadeFLOAT100–100Worn, mottled ink density.
dot_gainFLOAT350–100Ink 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_driftFLOAT1.50–30Random per-ink misregistration in px.
offset_anglesFLOAT600–90Screen-angle step between successive inks.
rotateFLOAT0-90–90
plate_renderCOMBOuniformbenday: 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_quantizeCOMBOoffSnap 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.
seedINT00–18446744073709550000
ink_configSTRING{"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)

NameTypeDescription
imageIMAGE
platesIMAGE