Hi everyone,
First of all, a huge shoutout to @masterpiga. Their “Color Harmonizer” module concept on this forum was the spark that planted the seed for this project.
As a portrait photographer coming from Capture One, I’ve missed a dedicated tool designed specifically to unify skin tones in darktable. I have a slight IT background, but I haven’t actually written a line of code since the late 20th century—back when our biggest tech fear was the Y2K bug! ![]()
So, taking conceptual inspiration from C1’s skin tone tool, I decided to build upon masterpiga’s foundation. With the patient coding guidance and assistance of AI (Gemini, and a bit of Claude), the original code was heavily adapted and overhauled to introduce specialized masking and uniformity logic, all while taking advantage of the perceptual JzCzhz color space already implemented in the original concept.
It is currently working on my machine (CPU & OpenCL), and I’ve built a macOS DMG for anyone willing to test it out, help me hunt down bugs, fine-tune it, point out poorly implemented areas, and suggest improvements.
Key Features & Under the Hood:
- Polar/Pizza-Slice Masking: Instead of a cartesian bell curve, the internal selection mask relies on independent Hue (angle) and Chroma (radius) distances. This is designed to prevent accidentally selecting opposite hues (like magentas or greens) when widening the selection.
- Asymmetric Shadow Protection: The chroma distance calculation heavily penalizes under-saturated pixels. The goal here is to naturally protect beards, hair, and deep shadows from being affected by the skin correction.
- Independent Uniformity: You can compress the variance of the skin around your target using 3 independent sliders: Hue Uniformity, Saturation Uniformity, and Lightness Uniformity, in order to preserve the 3D volume (J_z) of the face.
- Plateau Opacity Boost: The Selection Opacity slider can be pushed up to 300% (clamped at 100% under the hood). This creates a “Top-Hat” or plateau mask: it densifies the selection on the skin without widening the hue footprint on the vectorscope.
- Generic Editor usage: While optimized for skin by default (using a 2.5:1 Hue/Chroma tolerance ratio), a “Chroma Tolerance” slider is available in the mask tweaks. By increasing it, the module can be repurposed to unify skies, foliage, or clothing that have broader saturation variances.
Recommended Workflow for Portraits (and a question for the devs):
In practice, this module is meant to be used alongside darktable’s masking system. A standard workflow is to create a mask in a previous module (e.g., Color Balance RGB) to desaturate everything that is not the skin (background, clothes, lips, and makeup areas). Then, in the Skin Tone Editor, simply load that exact same mask as a Raster Mask and invert it. This restricts the module exclusively to your subject, letting the internal color picker operate purely on the skin without catching similar hues in the background or altering the makeup.
Crucially, this workaround also isolates the skin tones in darktable’s global vectorscope. By effectively hiding the background colors, you get a clean, uncluttered view of the skin’s hue and chroma footprint, making it much easier to adjust your target and observe the uniformity compression.
I’m currently using this workflow because of darktable’s architecture (the global vectorscope reads the entire input of the pipe at that point). If anyone smarter than me has an idea on how to restrict the vectorscope display only to the pixels selected by the module’s internal mask, I’m all ears!
How to test it:
- macOS users: You can download the ready-to-use .dmg here: darktable-arm64.dmg
- Linux/Windows users: You can check out the code and compile from my branch here: Darktable Skin Tone Editor
A Final Word:
I’m sharing this primarily as a fun personal project to help push the conversation forward. My ultimate goal is simply for darktable to have an outstanding skin tone module—whether it ends up being this specific code, or something entirely different and better designed by someone else (which I would absolutely love!). I am a photographer first and foremost, and I just want the best possible tool for the job.
I would love to get your feedback, especially from devs like @donatzsky who are exploring similar color variance concepts, and from fellow portrait photographers.
Let me know what you think!
Automated message from his AI assistant: I helped him write the code, but honestly, this French guy speaks English so poorly that I had to translate and formulate this post to save your eyes. Please be kind!
