Color: Lightroom Preset (XMP)
Your Lightroom Presets, Read by ComfyUI (Approximately)
- image
- mask
- image
- params_json
- report
You have years of Lightroom presets. You now generate images in ComfyUI. The obvious wish is "apply my presets to generated images", and the obvious obstacle is that a preset isn't an image transformation - it's a list of slider values that only Adobe's engine knows how to interpret.
Color: Lightroom Preset (XMP) (JHPixelProLightroomPreset) reads that list and replays it through the pack's own ColorLab engine. Same panels, same shape of controls, completely independent implementation. So: an approximation, written for this pack, and the docs say so in as many words. Judge it by eye. Expect something in the neighbourhood, not a pixel match.
What it reads
Both formats. .xmp is parsed as an XMP packet and every crs: (camera-raw-settings) property is collected, whether it's an attribute of rdf:Description or a child element. .lrtemplate - the older Lightroom format - is tokenised as a Lua table literal and only its value.settings table is read. No Lua runs. Files over 4 MB are refused.
Then the translation, panel by panel:
- Basic: Exposure, Contrast, Highlights, Shadows, Whites, Blacks (2012 process), Texture, Clarity, Dehaze, Vibrance, Saturation. Exposure is applied in linear light, like Lightroom.
- White balance: relative Temp/Tint. An absolute Kelvin setting gets converted to a relative shift via the mired difference from the photo's as-shot white - an approximation, and the
reportsays so. - Tone curve: point curves (master, R, G, B) plus the parametric region curve, rebuilt as a LUT and combined.
- HSL: hue/saturation/luminance for all eight colour bands.
- Color Grading: shadows, midtones, highlights wheels with luminance, plus Balance. Note Lightroom Classic still stores shadow/highlight grading hue and saturation under the legacy
SplitToning*keys whileColorGrade*holds midtones - both get mapped. - B&W conversion and mixer, including magenta. Calibration primaries and shadow tint. Effects: grain and post-crop vignette.
What it can't do, and tells you
Creative profiles (Adobe's "Vintage 06" and friends) are Adobe's own colour tables and simply aren't in the preset file. Local masks, lens corrections, sharpening and noise reduction aren't translated either. Everything skipped is listed in the report output - named, not silently dropped. A tile or preset with missing parts is worth checking before you build a look around it.
The three outputs
image - graded.
params_json - the preset as ColorLab settings. Wire into ColorLab to keep tweaking with sliders, or into Apply ColorLab Preset to reuse it.
report - what was applied and what wasn't. This is the honest half of the node.
Inputs
image, preset (a dropdown built from /ComfyUI/models/lightroom_presets/, .xmp and .lrtemplate), strength (0–2, Lightroom's Amount), plus optional preset_path (a full path that overrides the list), tone_engine (local = the edge-aware tools, closer to Lightroom; legacy = the older engine) and mask to limit where the look lands.
Drop your .xmp collection into that folder, restart or let the node's file-watch pick it up - it re-runs automatically when the preset file changes on disk. Sub-folders become collections in the node's thumbnail browser, and favourites/recents live in a .jh_presets.json inside the preset folder, so copying the folder moves them too.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/jetthuangai/ComfyUI-JH-PixelPro.git
cd ComfyUI-JH-PixelPro
pip install -r requirements.txt # the Python that runs ComfyUI
mkdir -p ComfyUI/models/lightroom_presets # drop your .xmp / .lrtemplate here
ComfyUI Manager: search ComfyUI-JH-PixelPro → Install → restart → Add Node → ComfyUI-JH-PixelPro → color. Deps: kornia>=0.7, mediapipe>=0.10.33, opencv-python-headless>=4.8, scipy>=1.10, PyTorch from ComfyUI. Two sample presets ship with the pack (Classic BW.lrtemplate, Warm Film.xmp), so the dropdown isn't empty on day one - and that's the fastest way to see whether the translation is close enough for you.
Where people get burned
- A raw-tuned preset on a generated image. Presets made for raw files push Exposure, Shadows and Dehaze hard because raw data has headroom. On a PNG from a sampler, start at
strength0.6. - Colour looks wrong and the report mentions white balance. An absolute Kelvin in the preset was approximated. Fix it with
wb_temperaturein ColorLab. - An orange "!" on a preset. Something's missing, usually a creative profile - check that preset's
reportbefore you commit. - Expecting sharpening. Never applied, by design. Add Smart Sharpen after.
The genuinely useful framing here: this node is a bridge for your library, not a Lightroom emulator. Colour grading is one of the last areas where people have a decade of muscle memory invested in another tool, and having those sliders land in a graph - even approximately - is worth more than a from-scratch "looks" node with 200 bundled presets you didn't choose.
Pack: Apache-2.0, JH (@jetthuangai), v1.10.0, 64 nodes, EN/VI docs. No Reddit corpus footprint - searching the pack name returns one unrelated Chrome extension - so there's no community verdict on translation accuracy. Compare one preset side by side, on a photo, and decide for yourself.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | Image to grade. | |
| preset | COMBO | Presets in /tmp/ComfyUI/models/lightroom_presets (.xmp / .lrtemplate). | |
| strength | FLOAT | 1.000–2 | Like Lightroom's preset Amount. 0 = original. |
| preset_pathopt | STRING | Full path to a preset file; overrides the list. | |
| tone_engineopt | COMBO | local | local = edge-aware tone tools, closer to Lightroom. |
| maskopt | MASK | Optional mask limiting where the preset applies. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | Image with the preset applied. |
| params_json | STRING | The preset as ColorLab settings: connect to ColorLab or Apply ColorLab Preset. |
| report | STRING | Which Lightroom settings were applied and which are not supported. |