Pipeline Architectures & Color Science: White Balance vs. Demosaicing in darktable and ART

Hello everyone,

I have been analyzing the pipeline architectures and color science concepts behind darktable and ART regarding the relationship between White Balance (WB) and demosaicing. I put together a summary of my thoughts and findings, and I would love to hear your insights or corrections.

The Ideal Color Science Pipeline

From a color science perspective, a proper raw processing pipeline should conceptually look like this:
RAW → Black Point → Linearization → RAW White Balance (Channel Gains) → Demosaicing → Camera RGB → Input Profile (Camera → XYZ or → Working Color Space)

— At this stage, the image stops being camera-specific —

→ Chromatic Adaptation (Bradford, etc.), Exposure (if needed) → Channel Mixer → Local Adjustments → Filmic / Tone Mapping → Output Profile

There are two fundamentally different types of “white balance” here:

  1. The RAW White Balance: This is part of the sensor characterization.
  2. The Chromatic Adaptation (e.g., Bradford): Other color transformations that operate on a fully reconstructed, tri-stimulus color image.

One could easily imagine a RAW converter that does not apply any white balance prior to demosaicing. While colorimetrically elegant and more aligned with classic color management, the trade-off is that the demosaicing algorithm would have to work with unbalanced channels. Many established interpolation algorithms deliver inferior results under these conditions because their directional decisions depend heavily on channel ratios. This is why software like darktable or ART introduces sensor-side white balance early in the pipeline.

However, from a software engineering perspective, this practical solution slightly violates the Single Responsibility Principle:

  • A module named White Balance should ideally only handle white balance.
  • A module named Demosaicing should solely perform interpolation.

In reality, these are two entirely different mathematical operations:

  • Case 1: Camera White Balance (“As Shot”)
    RAW → R *= 2.1; G *= 1.0; B *= 1.6 → Demosaicing
    These are pure channel gains applied directly to the CFA (Color Filter Array) data.
  • Case 2: Bradford Adaptation
    Linear RGB → XYZ → Bradford Matrix → XYZ → RGB
    This is a proper chromatic adaptation operating on full color vectors.

Mathematically, these two methods share almost nothing. The RAW white balance is part of sensor calibration, whereas a Bradford adaptation works with a fully formed color image.


  1. The darktable Architecture (The “Feedback Loop” Problem)

In darktable’s classic architecture, the White Balance module is positioned before the Demosaicing module in the pixel pipe.

  • How the code works: The white balance module applies RGB multipliers directly to the incomplete RAW mosaic data. Only after this step does the demosaicing module interpolate the missing color values. Algorithms like AMaZE or RCD use these already white-balanced pixel values to detect edges and compute gradients.
  • Why it degrades ICC profile precision: If you modify the multipliers in the White Balance module, the input data for the demosaicing stage shifts. The demosaicing is recomputed, causing minor variations in the fine color and brightness gradients on a pixel level. Because the pixels now have a different mathematical “history” due to the altered demosaicing, the foundation for the subsequent input ICC profile is no longer 100% accurate.
  • The Modern Solution (Color Calibration): To bypass this inaccuracy, darktable introduced the modern scene-referred workflow. The classic White Balance module is locked to a fixed Camera Reference (based on D65). This keeps the demosaicing mathematically stable and identical. The actual user-controlled white balance happens much further down the pipeline via the Color Calibration module using a Chromatic Adaptation Transform (CAT) matrix, after the input ICC profile has been applied.

  1. The ART / RawTherapee Architecture

In ART (and its upstream codebase, RawTherapee), the pipeline is designed differently to eliminate this issue at its root. ART utilizes a Camera Standard Matrix (often extracted from Adobe DNG specifications or dcraw/RawSpeed) to perform demosaicing in a mathematically neutral space.

  1. Pre-Decoupling: Demosaicing occurs based strictly on native sensor data and a fixed, camera-specific reference.
  2. White Balance as a Linear Multiplier: Moving the white balance sliders in ART does not retroactively change the demosaicing behavior. The multipliers are applied linearly to the already debayered (interpolated) RGB pixels.
  3. Stability for ICC Profiles: Since the demosaicing output remains identical regardless of your creative white balance adjustments, the mathematical integrity for the subsequent input ICC profile is perfectly preserved.

Direct Architectural Comparison

Criterion darktable (Classic Mode) darktable (Modern Mode) ART / RawTherapee
Pipe Order WB → Demosaic → ICC WB (Fix D65) → Demosaic → ICC → CAT Demosaic (Fix Matrix) → WB → ICC
Demosaic changes with WB shift? Yes (Causes minor pixel-level color shifts) No (Locked to D65 reference) No (Calculated with native camera matrix)
ICC Profile Precision Can become imprecise. Highly precise. Highly precise.

Conclusion & Important Caveat

If you use the old white balance slider in darktable, you inadvertently shift the mathematical foundation of the demosaicing stage, which can degrade the precision of your input ICC profile. ART avoids this architectural pitfall by completely decoupling the demosaicing stage from user-defined white balance multipliers.

However, a crucial nuance exists in darktable’s modern approach: applying complex, non-linear ICC profiles (like LUT-based profiles) before the linear Color Calibration (CAT) module introduces mathematical inconsistencies. Because the Color Calibration module expects purely linear input data, darktable’s manual explicitly recommends avoiding complex profiles when the CAT module is active.

Consequently, while darktable’s modern workflow achieves demosaicing stability, its ICC-before-CAT ordering sacrifices precision when utilizing bespoke or complex custom color profiles—a trade-off that ART’s pipeline architecture does not require.

4 Likes

That is well thought out and well written, but I don’t have the capacity to digest it all right now. I’ll go back through it, later.

Thanks

2 Likes

In darktable, demosaic uses camera WB, which is reverted before the ICC profile is applied, and then chromatic adaptation is performed. A PR will also make manual WB available for the same process. I posted about this some time ago.

1 Like

"Thank you for clarifying that! That is indeed a very elegant mathematical workaround.

If I understand correctly, darktable applies the ‘As Shot’ WB coefficients to feed balanced channels into the demosaicing algorithm for optimal edge/gradient detection, but then immediately inverts (undoes) that multiplication right after demosaicing. This essentially reverts the fully interpolated pixels back to their native camera-RAW exposure state before handing them over to the input ICC profile.

That is clever, as it conceptually gives the pipeline the best of both worlds: artifact-free demosaicing and a mathematically pristine foundation for the ICC profile.

The upcoming PR making this inversion dynamic for manual WB changes as well sounds like a fantastic upgrade to eliminate any remaining edge-case discrepancies. Thanks for pointing that out!"

1 Like

I don’t either but without looking I don’t think this is accurate…

Demosaicing algorithms (which reconstruct a full-color image from the camera’s Bayer sensor data) rely on comparing neighboring pixels. If the color channels aren’t balanced first, the demosaicing algorithm can get confused by the raw green-heavy sensor data, resulting in edge artifacts, false colors, or “zippering” as it is called but perhaps this is just my assumption …

Though it seems that WB is listed after Demosaic in the ART pipeline…

https://artraweditor.github.io/Pipeline

Found it:

1 Like

It’s possible to apply the matrix for D65, that’s what darktable does in camera reference mode, so the image is not fully white balanced, but is much better than without any matrix. Maybe ART also does something similar. I haven’t looked at its code and I’m not at my computer.

Yes that was my understanding too. It works with a camera specific matrix. I am no expert, but my thinking is that depending on the used algorithm demosaicing may be a bit less perfect than in completely balanced state but is not green and dark.

"That is a great clarification regarding how darktable handles the inversion process, thank you!

However, it brings up an interesting workflow consequence regarding the current code state versus the upcoming PR you mentioned.

If the current implementation only applies this inversion to the ‘As Shot’ (or D65 camera reference) white balance coefficients, it implies that we cannot use the legacy White Balance module for manual adjustments when a custom input ICC profile is active. Doing so would break the inversion logic and reintroduce the demosaicing feedback loop that degrades the ICC profile’s foundation.

So, in the current version of darktable, the only mathematically clean way to use a custom ICC profile (like a 2.5D DCamProf profile) is to:

  1. Keep the legacy WB module strictly locked to camera reference.
  2. Load the custom ICC profile in the input color profile module.
  3. Perform the actual, user-defined white balance in the Color Calibration (CAT) module.

Even though the manual warns against using complex profiles before the CAT module due to linearity concerns, a 2.5D profile from DCamProf preserves luminance linearity, which mitigates the risk of a mathematical breakdown.

Am I correct in assuming that the upcoming PR will finally allow us to dynamically use manual adjustments in the legacy WB module without ruining the ICC profile’s base, because it will compute the inversion dynamically based on the user’s manual coefficients?"

Fun that you take a interest in the white balancing topic and color adaption topic @Thomas_Link!

Would you mind sharing some background on what your motivation is for the deep dive? Do you want learn to get better results, help out improving the methods of darktable or ART, or something else?

I can recommend reading some of the spektrafilm diskussions here spektrafilm tech discussions and also learn about vkdt input device transform for alternative methods. If you are interested in a further deep dive into what an “ideal” method should look like.

Finally, please disclose any use of AI/LLMs in your writing if you use one, your text unfortunately trigger my warning bells, I’m sorry if I’m misstaken.

2 Likes

I am not a programmer but having AI run through the code the demosaic is fired when you change the wb coefficients and the data fed to the demosaic aligorithms is corrected and scaled in rtengine/rawimagesource.cc and then passed to the select aligo for demosaic…

So WB is coming before demosaic and they are not decoupled… at least from an AI code analysis

Why is that?

If you’re using AI, please see this:

4 Likes

So, for a while now I’ve been doing one white balance, pre-demosaic. Don’t particularly understand the specifics, but it has been intimated that the modern demosaic algoriththms work properly with white-balanced data, so cool beans.

Also, I removed an early transform to a working colorspace, seemed to cause more problems than it solved. So now, I only do one color transform, at export, from camera space to export space.

Now, I’m not a particularly persnickety person, mostly I look for good 'nuf in my small proofs. But, everything seems to turn out nice, no matter what camera profile, matrix or xyzlut. My tone curve is at the end of the pipeline, and it just does tonality, no color shenanigans. What am I doing wrong here:

I know the brightest yellow is getting a bit lost, but I’ve tried various color-preservation tools in other softwares and it ends up looking artificial.

Anyway, FWIW, probably not much.

Edit: this is with rawproc, my hack raw processor where I can order the tool chain any way I want, for good or ill…

2 Likes

@jandren and @Donatzsky:
Yes, the text was translated by AI (Gemini). Given the context of many previous discussions, it probably didn’t just translate my text word for word but also spiced it up a bit.
But that doesn’t mean the AI created the content. The content is my own and was developed through many different chats and iterations with Gemini and ChatGPT (which I had to keep refining and correcting because they also wrote a lot of nonsense at first), my own study of the dcamprof manual and the darktable manual, as well as posts here in the forum.
I summarized what ultimately seemed most plausible to me in German in my own document and had Gemini translate it back.
Unfortunately, my English is very poor, and I can’t manage without a translator.
I sincerely apologize for this, but please understand my dilemma too.
(This text was translated using DeepL, not AI.)

Translated with DeepL.com (free version)

4 Likes

Well, I used to shoot film (slides), then switched to digital, but until now I’ve only taken JPEGs without any post-processing.

Now that I’m retired, I’ve treated myself to an expensive camera (A7RV) as a “reward,” so to speak, and I want to make the most of its potential—but since I have more time now and consider it a hobby, I’m going with RAW processing.
Commercial software is out of the question for me. Right now, I’m deciding between Darktable and ART.

Until two months ago, I didn’t have the slightest clue about color theory—absolutely none. But given my background as an engineer, I’m used to breaking things down, understanding them, and putting them back together. I simply don’t want to just apply the software; I want to understand what I’m doing and why I’m doing it this way and not another. That’s the background.

Translated with DeepL.com (free version)

7 Likes

Here’s how I’m thinking about it—though maybe I’m wrong and there’s a flaw in my reasoning:

  1. I take a reference image of my color chart.
  2. I load it into DT or ART and save it as a TIFF.
  3. This TIFF is based on the RGB multipliers displayed in the WB module (e.g., RGB = 2.66; 1.0; 1.5).
  4. Based on this, I use dcamprof (after scanning it in first, of course) to create the LUT or simply a linear transformation matrix (it doesn’t matter). This transformation handles the transition from camera RGB to XYZ.
  5. Now I take a photo. To obtain “realistic” colors (at least as the eye would see them if it hadn’t yet adapted, or if it were seeing only the pure color without any texture), I apply the previously defined transformation.
  6. However, the previously defined matrix is based on the aforementioned multipliers. If the multipliers are different, the matrix (or LUT) also changes.
  7. I want to apply white balance (WB) to my photo. In the classic approach, however, this changes the multipliers and thus also the basis for demosaicing. As a result, the mathematical basis on which the transformation matrix was derived is no longer exactly correct (there is a feedback loop).

I now distinguish between RAW white balance, which provides the multipliers for demosaicing (which takes place in the camera’s RGB color space), and chromatic white balance, which takes place in an objective color space (XYZ).

As I understand it, the RAW white balance in the photo must be exactly the same as in the reference image from the color chart. Otherwise, the transformation won’t be correct. After that, you could perform a chromatic white balance within the color space.

I likely got lost in all that but basically I feel like as I understood things, you have 2 options when you choose to make and use lut icc profiles…You white balance the chart using the most neutral patch and then you are making a lut that always expects white balanced data. This profile can then be used as widely as the lut allows…or you don’t wb and you make the profile and this is something that you would use to correct very controlled or unique lighting…in this case you are letting the profile make a correction for the white balance…

But maybe there is more nuance to what you are looking for…

2 Likes

White balancing actually does two things, combined into one operation:

  1. skewing the data to make white things ‘white’ based on the non-linear spectral power distribution of the illuminant
  2. skewing the data to make white things ‘white’ based on the camera’s non-linear spectral sensitivity

The two things are mixed in the raw capture, so doing one multiplication with the right multipliers takes care of both. And, having a known-white reference in the capture (or an adjacent one taken in the same scene) makes determining the correct multipliers simple.

Thing is, multiplying the data of each channel by a different multiplier is a rather coarse way of skewing the data, and separate from the gamut transform. To Todd’s point, the white balance operation can be glommed into the chromatic gamut transform by shooting a target shot in the same light of the scene, NOT white-balancing the target shot render, and making the camera profile from it. I’ve tried this and it works like a treat, but it bolloxes the use of any other chromatic tool because all of that needs to be done in the camera->export (or ->display) gamut transform.

Anyhoo, another missive from bear-of-little-brain…

2 Likes

@priort and @ggbutcher:
Thanks! I completely agree with Option 2; I think I understand that.

I’m still having trouble understanding Option 1 (or maybe I’m just confused). If I perform a white balance using my chart, it will result in slightly different multipliers than if I do it for my photo. However, my ICC file is based on the multipliers I had in my chart. If different multipliers result from the white balance adjustment on my photo, my ICC file is no longer correct (I think—that’s my understanding). So I’d have to use the same multipliers in my photo as I have in the chart (but then the photo wouldn’t be perfectly balanced anymore).

1 Like