Create, edit and apply 3D LUTs to your photographs — with a comfortable before/after preview and real batch processing.
🇬🇧 English · 🇮🇹 Italiano
Every adjustment in LUT Studio is a pure per-pixel colour function, so the whole
look bakes down into a single 3D LUT. What you see in the preview is exactly
what gets exported — as .cube, .3dl or HALD PNG — and exactly what the batch
writes to disk. The same LUT you build here works in Lightroom, Capture One,
DaVinci Resolve, Premiere, Affinity Photo or OBS.
- Grading that becomes a LUT — white balance and exposure in scene-linear light, contrast, highlights/shadows/whites/blacks, HSL across eight colour ranges, ASC-CDL lift/gamma/gain wheels, split toning, black & white, and monotone RGB tone curves.
- A preview you can actually judge — draggable split, side by side, A/B toggle, zoom to the cursor, pan, live histogram. Rendering happens off the UI thread, so the sliders stay responsive on 24-megapixel files.
- LUT library — point it at your LUT packs: folders are scanned
recursively and shown as a tree with counts and natural ordering
(
Look 2beforeLook 10). Search, favourites, recents, and a thumbnail grid that renders your own photo through every LUT in the library. - A different look for every photo — assign the current look (LUT + adjustments + strength) to any selection, see it labelled in the queue, and batch-process only the assigned photos, each with its own LUT.
- Crash-safe by design — assignments are written to disk the moment you make them, in JSON plus a human-readable CSV. Kill the app and your work is still there when it reopens.
- Real batch — multi-process, RAM-aware, with format/quality/bit-depth, resizing, EXIF and ICC preservation, subfolder mirroring, progress, per-file log and cancellation.
- Italian and English, following your system language, switchable from the View menu.
- Command line for large jobs and automation.
git clone https://github.com/IncludePetrol/LUTStudio.git
cd lut-studio
python3 -m pip install -r requirements.txt
python3 run.pyOn macOS you can also double-click start.command, which installs anything
missing and opens the app.
Installing as a package gives you the lutstudio and lutstudio-cli commands:
python3 -m pip install .Requirements: Python 3.10+, NumPy, Pillow, PySide6.
┌────────────┬───────────────────────────────┬──────────────────┐
│ Photo │ Before/after preview │ Adjustments │
│ queue │ (split, side by side, A/B) │ Curves │
│ + looks │ zoom, pan, histogram │ Library · LUT │
│ │ │ Batch │
└────────────┴───────────────────────────────┴──────────────────┘
You can drop photos, folders and .cube files straight onto the window.
One key, no modifiers. They work whenever you are not typing in a text
field; the classic combinations (Ctrl+O, Ctrl+S, …) keep working as
alternates. Press H (or F1) in the app for the same list.
| Looks | |
A |
assign the current look to the selection |
X |
remove the assigned look |
T |
assign to every photo in the queue |
E |
load the assigned look back into the panels to edit it |
M |
freeze the look as the base LUT |
Z |
reset the adjustments |
| Library | |
double-click · Enter |
apply and assign the LUT to the photo |
↑ ↓ |
try the LUTs one after another |
Space |
favourite |
C |
jump to the library search |
V |
switch list / thumbnails |
I |
add a LUT folder to the library |
| Batch | |
G |
process the assigned photos |
R |
process every photo |
| File | |
O / D |
open photos / open folder |
S / L |
save the photo / export the LUT |
| View | |
B / F / 1 |
before-after · fit · zoom 100% |
, . |
previous / next photo |
Alt+1…5 |
switch tool tab |
Del |
remove the selected photos from the queue |
Add one or more folders (Add folder…, Ctrl+L, or drop them in). They are
scanned recursively and shown folder by folder. .cube, .3dl and HALD
PNG/TIFF are recognised; PNGs that are not real HALD tables — the preview images
that ship with most LUT packs — are ignored automatically.
- List — arrows ↑↓ walk through the LUTs with the preview updating as you go, so a whole pack takes seconds to review. The active LUT is bold.
- Double-click (or
Enter) on a LUT does not just preview it: it is applied and assigned to the selected photos in one gesture — the fastest way to go through a shoot. - Thumbnails — the entire library as a grid, each tile being your photo through that LUT, with its name and source folder underneath. Tiles render lazily as you scroll, so thousands of LUTs open instantly.
The chosen LUT becomes the base LUT: dose it with the strength slider, grade on top of it, and export the combined result.
Pick a LUT, adjust, then select photos in the queue and hit Assign look to
selection (Ctrl+K, or right-click). A green dot with the look's name appears
under the file name — strength included. Come back to that photo and the look is
reloaded into the panels, ready to be tweaked and reassigned.
In the Batch tab, Assigned only (N) processes just those photos, each with its own LUT. Identical looks are baked once and shared between worker processes, so 300 photos with 5 looks cost the same as 300 photos with one.
Your work is saved to ~/.lutstudio/session.json (atomic write, with a .1
backup) on every change, alongside ~/.lutstudio/assignments.csv. Frozen looks
— the ones with no source file — are stored as .cube in
~/.lutstudio/frozen_looks/. On the next launch the queue and every assignment
come back on their own.
# apply a LUT to a folder, recursively, on 8 processes
lutstudio-cli apply ~/Photos/shoot -l look.cube -o ~/Photos/export -j 8
# apply a built-in preset, JPEG quality 92, long edge 2048 px
lutstudio-cli apply ~/Photos -p warm_film -o ~/export -f jpeg -q 92 --long-edge 2048
# bake a .cube out of a preset
lutstudio-cli bake -p teal_orange -s 65 -o teal.cube
# convert, resize or soften an existing LUT
lutstudio-cli convert look.cube look_soft.3dl --size 33 --strength 0.6
lutstudio-cli info *.cube
lutstudio-cli presets(Without installing the package: python3 -m lutstudio.cli …)
Everything the app keeps lives in ~/.lutstudio: library.json (your LUT
folders and favourites), session.json + assignments.csv (queue and assigned
looks), presets/ (your own presets), settings.json (language), crash.log.
Point LUTSTUDIO_HOME somewhere else to move or sandbox it.
- Photos are decoded at the resolution actually needed (JPEG draft mode): a thumbnail from a 24 MP file peaks at ~68 MB instead of ~965 MB.
- Queue thumbnails are generated only for visible rows, three at a time, so hundreds of large photos keep memory flat.
- Batch worker count adapts to available RAM as well as core count.
- LUT application is branch-free tetrahedral interpolation, working in place: 24 megapixels in ~2.6 s.
- JPEG export above 12 Mpx is written baseline instead of progressive, because progressive forces libjpeg to hold the whole file in a single buffer and fails on large, detailed photos.
- Unexpected errors do not close the app: they are logged to
~/.lutstudio/crash.log(which also captures native crashes) and reported once.
run.py GUI launcher
selftest.py engine self-test
start.command macOS launcher
tools/make_icon.py regenerates the app icon
lutstudio/
cli.py command line interface
core/
lut.py LUT3D: identity, .cube/.3dl/HALD, interpolation, mixing
grade.py grading pipeline and LUT baking
curves.py monotone curves (Fritsch–Carlson)
color.py sRGB ↔ linear, HSL, white balance
imageio.py image read/write, histogram, resizing
raw16.py 16-bit PNG/TIFF writers
batch.py multi-process batch engine
look.py a complete look, assignable to a photo
session.py automatic session persistence
library.py LUT folder library
presets.py built-in and personal presets
i18n.py Italian/English interface strings
gui/ main window, preview, panels, curve editor, library
python3 selftest.py # 27 checks on the engine, no GUI needed
python3 -m pyflakes lutstudio
python3 tools/make_icon.py # regenerate assets/icon*The self-test covers interpolation accuracy against direct grading, .cube and
.3dl round-trips, curve monotonicity, batch behaviour across processes,
per-photo looks and session persistence. It runs on every push through GitHub
Actions.
Created by Andrea Parolini.
Built with Python, PySide6, NumPy and Pillow.
Copyright © 2026 Andrea Parolini.
LUT Studio is free software, released under the GNU General Public License v3.0 or later. You may use, study, modify and share it; if you distribute it — modified or not — you must pass on the same freedoms and provide the source code under the same licence. The program comes with absolutely no warranty.
Attribution is required. Under section 7(b) of the GPL, every redistributed or modified version must keep the credit "LUT Studio — Andrea Parolini" and the copyright notice visible: in the About window, in the documentation, and in the NOTICE file that must travel with the program. Modified versions must also say clearly that they have been modified.