Skip to main content

Color grading library with LUT loading machinery, cinematic grades, and film-stock approximations

Project description

color-fx

Color grading library with 60 grades, full LUT machinery, and optional ACES support.

PyPI CI


Install

pip install color-fx

That pulls in pydantic, numpy, Pillow, opencv-python-headless, and ffmpeg-python (~80 MB). You also need ffmpeg >= 6.0 on your PATH.

Extras:

Extra What it adds Approx size
pip install color-fx[sklearn] scikit-image + scikit-learn for KMeans skin-tone refinement ~140 MB
pip install color-fx[aces] colour-science + OpenColorIO for ACES and BT.2020 workflows ~250 MB
pip install color-fx[all] Both of the above ~310 MB

The base install works without either extra.


5-minute tour

Apply a named grade to a video:

from color_fx import apply_grade, GradeConfig

apply_grade(
    video="raw.mp4",
    grade="nordic_desaturation_standard",
    output="graded.mp4",
    config=GradeConfig(
        grade="nordic_desaturation_standard",
        intensity_override=0.6,
        preserve_skin_tones=True,
    ),
)

Load and apply your own LUT:

from color_fx import load_lut, apply_lut

lut = load_lut("/path/to/MyKodak2383.cube")
apply_lut(video="raw.mp4", lut=lut, output="graded.mp4", strength=0.8)

Chain multiple grades in one pass:

from color_fx import apply_grade_chain

apply_grade_chain(
    video="raw.mp4",
    grades=[
        {"grade": "log_to_rec709"},
        {"grade": "warm_print_film_inspired"},
        {"grade": "shadow_lift", "config": {"intensity_override": 0.3}},
    ],
    output="layered.mp4",
)

The 60 grades

Three categories. 60 slugs total.

cinematic_grades (30)

Ten cinematic looks, each in three intensities: subtle (0.35), standard (0.70), bold (1.0).

Slug Display name
nordic_desaturation_subtle Nordic Desaturation — Subtle
nordic_desaturation_standard Nordic Desaturation — Standard
nordic_desaturation_bold Nordic Desaturation — Bold
golden_hour_subtle Golden Hour — Subtle
golden_hour_standard Golden Hour — Standard
golden_hour_bold Golden Hour — Bold
cold_steel_subtle Cold Steel — Subtle
cold_steel_standard Cold Steel — Standard
cold_steel_bold Cold Steel — Bold
warm_contrast_subtle Warm Contrast — Subtle
warm_contrast_standard Warm Contrast — Standard
warm_contrast_bold Warm Contrast — Bold
muted_earth_subtle Muted Earth — Subtle
muted_earth_standard Muted Earth — Standard
muted_earth_bold Muted Earth — Bold
high_contrast_bw_subtle High Contrast B&W — Subtle
high_contrast_bw_standard High Contrast B&W — Standard
high_contrast_bw_bold High Contrast B&W — Bold
cyberpunk_neon_subtle Cyberpunk Neon — Subtle
cyberpunk_neon_standard Cyberpunk Neon — Standard
cyberpunk_neon_bold Cyberpunk Neon — Bold
natural_flat_subtle Natural Flat — Subtle
natural_flat_standard Natural Flat — Standard
natural_flat_bold Natural Flat — Bold
deep_shadows_subtle Deep Shadows — Subtle
deep_shadows_standard Deep Shadows — Standard
deep_shadows_bold Deep Shadows — Bold
summer_fade_subtle Summer Fade — Subtle
summer_fade_standard Summer Fade — Standard
summer_fade_bold Summer Fade — Bold

film_stock_emulation (15)

Nine base film-stock approximations plus six cross-stock combination grades.

Film stock approximations — entries in the film_stock_emulation category (Warm Print Film, Cool Cinematic Stock, Punchy Consumer Film, Grainy Black and White Stock, Instant Photo Vintage, Super 8 Film, 16mm Documentary, 35mm Prestige, Saturated Three-Strip Look, Expired Film, and the cross-stock combos) are approximations based on publicly-documented characteristics of named film stocks. They are NOT licensed or measured emulations. For production-grade film emulation requiring true spectral measurements, use commercial offerings (Kharma, FilmUnlimited, Cinematch).

Slug Display name
warm_print_film_inspired Warm Print Film
cool_cinematic_stock Cool Cinematic Stock
punchy_consumer_film Punchy Consumer Film
grainy_bw_stock Grainy Black and White Stock
instant_photo_vintage Instant Photo Vintage
super8_film Super 8 Film
16mm_documentary 16mm Documentary
35mm_prestige 35mm Prestige
saturated_three_strip Saturated Three-Strip Look
expired_film Expired Film
cross_warm_cool Cross: Warm Print + Cool Cinematic
cross_punchy_prestige Cross: Punchy Consumer + 35mm Prestige
cross_super8_bw Cross: Super 8 + Grainy B&W
cross_vintage_expired Cross: Instant Photo + Expired Film
cross_documentary_prestige Cross: 16mm Documentary + 35mm Prestige

luts_and_curves (15)

Pure math operations: S-curves, log conversions, channel adjustments.

Slug Display name
log_to_rec709 Log to Rec.709
s_curve_gentle S-Curve (Gentle)
s_curve_strong S-Curve (Strong)
shadow_lift Shadow Lift
highlight_rolloff Highlight Rolloff
split_tone_warm_cool Split Toning: Warm Shadows / Cool Highlights
split_tone_cool_warm Split Toning: Cool Shadows / Warm Highlights
gamma_correction_rec709 Gamma Correction (Rec.709)
channel_mixer_warm Channel Mixer: Warm
channel_mixer_cool Channel Mixer: Cool
hsl_vibrance HSL Vibrance
hsl_saturation_boost HSL Saturation Boost
crush_blacks Crush Blacks
lift_shadows_matte Lift Shadows (Matte)
identity Identity (pass-through)

LUT loading

No bundled LUTs — color-fx ships LUT machinery (read, apply, bake, interpolate) but does NOT ship any .cube files. Bring your own LUTs from free repositories (FreshLuts, Lutify.me free pack) or commercial vendors.

Read .cube or .3dl files:

from color_fx import load_lut, save_lut, apply_lut, bake_grade_to_lut

lut = load_lut("/path/to/MyGrade.cube")    # or .3dl
print(lut.title, lut.size, lut.dimensions)  # e.g. "My Grade" 33 3

apply_lut(video="raw.mp4", lut=lut, output="out.mp4", strength=0.85)

Bake any named grade out to a .cube file for use in DaVinci Resolve or Premiere:

bake_grade_to_lut(grade="nordic_desaturation_bold", output="nordic_bold.cube", size=33)
save_lut(lut, "custom.cube", title="My Custom Grade")

Convert between formats:

from color_fx.lut import convert_lut
convert_lut(input="my_grade.3dl", output="my_grade.cube")

Both trilinear and tetrahedral 3D-LUT interpolation are available. Tetrahedral is the default and is more accurate for most film-print-style grades.

ACES note: with pip install color-fx[aces], you can specify working_color_space="ACEScg" in GradeConfig and the library routes the transform through OpenColorIO automatically. Without the extra, that field is accepted but ignored and the library processes in Rec.709.


Engines

Three base engines cover all 60 grades:

Engine Module Grades
grade_recipe engines/grade_recipe.py 30 cinematic grades (10 looks × 3 intensities)
film_emulation engines/film_emulation.py 15 film-stock approximations (9 base + 6 cross combos)
curve_or_lut engines/curve_or_lut.py 15 LUT and curve primitives

Each grade recipe computes an internal 33x33x33 or 65x65x65 LUT at startup and caches it for the duration of a render. The film emulation engine also drives a grain overlay and optional halation simulation on top of the grade LUT.


GradeConfig

All API functions accept an optional GradeConfig. Every field has a safe default.

Field Type Default Description
grade str Grade slug (required)
intensity_override float | None None Override catalog intensity, 0–1
region tuple[int,int,int,int] | None None Apply only within (x, y, w, h)
mask_image str | None None Path to a greyscale mask image
preserve_skin_tones bool False HSV-based skin-tone protection
lut_strength float 1.0 Blend between identity (0) and full LUT (1)
interpolation "trilinear" | "tetrahedral" "tetrahedral" 3D LUT interpolation method
working_color_space "Rec.709" | "Rec.2020" | "ACES2065-1" | "ACEScg" "Rec.709" Requires [aces] for non-Rec.709
display_color_space "Rec.709" | "Rec.2020" | "P3-D65" "Rec.709" Output color space
video_codec str "libx264" ffmpeg video codec
audio_codec str "copy" ffmpeg audio handling

The model uses extra="forbid", so passing unknown fields raises a validation error at call time rather than silently doing the wrong thing.


CLI

All subcommands accept --help.

Apply a grade:

color-fx apply --video raw.mp4 --grade nordic_desaturation_standard --out graded.mp4
color-fx apply --video raw.mp4 --grade warm_print_film_inspired --intensity 0.5 --out out.mp4

Chain grades from a YAML config:

color-fx chain --video raw.mp4 --config chain.yaml --out out.mp4

LUT operations:

color-fx apply-lut --video raw.mp4 --lut my.cube --strength 0.8 --out graded.mp4
color-fx bake-lut --grade warm_print_film_inspired --size 33 --out warm_print.cube
color-fx convert-lut --input my.3dl --output my.cube

Catalog discovery:

color-fx list                               # all 60 grades, one slug per line
color-fx list --category cinematic_grades   # 30 grades in that category
color-fx list --include-skipped             # 60 + 15 video-fx-overlap stubs with redirect notes
color-fx categories                         # prints the 3 category names
color-fx info nordic_desaturation_bold      # full metadata, disclaimer if film stock

ACES (requires [aces] extra):

color-fx aces list
color-fx aces apply --video raw.mp4 --view "ACES 1.1 SDR Video" --out aces.mp4

Preview (generates a synthetic gradient video to inspect the grade):

color-fx preview --grade vintage_film_fade_standard --out preview.mp4

Schema (for LLM integration):

color-fx schema --pretty

Composition

color-fx is a peer of optic-fx, video-fx, and cut-fx. It does not import any of them.

A typical pipeline:

import subprocess

# 1. Cut and assemble with cut-fx / video-fx
# 2. Color grade with color-fx
from color_fx import apply_grade
apply_grade(video="assembled.mp4", grade="nordic_desaturation_standard", output="graded.mp4")

# 3. Add optical effects with optic-fx
from optic_fx import apply_effect
apply_effect(video="graded.mp4", effect="anamorphic_lens_flare_standard", output="final.mp4")

color-fx intentionally does NOT include Teal and Orange, Bleach Bypass, or other grades that overlap with video-fx's cinematic_color category. Use video_fx.apply_effect("teal_and_orange") for those. Running color-fx list --include-skipped shows each overlap slug and the exact video-fx call to use instead.


Disclaimers

Film stock approximations — entries in the film_stock_emulation category are approximations based on publicly-documented characteristics of named film stocks. They are NOT licensed or measured emulations. The library carries explicit disclaimer text in the catalog for every film-stock entry; get_grade_info() and color-fx info <slug> surface this text at runtime.

No bundled LUTs — color-fx ships LUT machinery but does not ship any .cube files.

ACES pathway — the optional ACES OCIO config is NOT bundled in the wheel. It is downloaded at first use when the [aces] extra is installed. Internet access is required the first time.


What this is NOT

  • Not a real-time preview tool. It processes video files via ffmpeg.
  • Not a video editor or timeline tool. Use cut-fx or video-fx for that.
  • Not a licensed film-emulation product. Film stocks are approximations only.
  • Not a replacement for DaVinci Resolve's node-based pipeline. It is a Python library for programmatic and batch color grading.
  • Not affiliated with or endorsed by any film stock manufacturer or camera brand.

Provenance

Built at Trollfabriken AITrix AB for the CineForge pipeline cinematic grading work, AIMOS Insight municipal report visual polish, SocKartan civic-transparency stylization, and the Timelock Film AB festival slate's color-grading pass.

Source: https://github.com/tomastimelock/color-fx PyPI: https://pypi.org/project/color-fx/ License: MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

color_fx-0.1.0.tar.gz (154.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

color_fx-0.1.0-py3-none-any.whl (68.3 kB view details)

Uploaded Python 3

File details

Details for the file color_fx-0.1.0.tar.gz.

File metadata

  • Download URL: color_fx-0.1.0.tar.gz
  • Upload date:
  • Size: 154.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for color_fx-0.1.0.tar.gz
Algorithm Hash digest
SHA256 891bf21afffb4a0a5242f10db80e1bb7fcf1ef63d54c8fc7b4e6029314fe5fdb
MD5 c3741ed355706099fd7298a8fafb627e
BLAKE2b-256 b95520d2f1b400e03b32b0e8f6c4126fef98d8d3369164c1dbc5b526af99ea54

See more details on using hashes here.

Provenance

The following attestation bundles were made for color_fx-0.1.0.tar.gz:

Publisher: release.yml on tomastimelock/color-fx

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file color_fx-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: color_fx-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 68.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for color_fx-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 793696978ece206fc53e3237ef96a0d8242048efb793cdb0834a0ad54b5611ee
MD5 9d47e850e37109d3a5a142fcef1b49bb
BLAKE2b-256 2b1b9049c6243d152496d71e1e7bc67fa9f9cd1e63909695ac404310b709aaf1

See more details on using hashes here.

Provenance

The following attestation bundles were made for color_fx-0.1.0-py3-none-any.whl:

Publisher: release.yml on tomastimelock/color-fx

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page