looking for a definition for the CustomMult gains in the .arp profile


I’m using ART for developing RAW photos and I have included a white balance card in my photos. I’d like to measure the white balance from the card and apply that white balance in ART.

I am using command line processing so I have set up a script to edit the .arp profile and set the White Balance / Setting to CustomMult and to set the values in Multipliers. I know where the white balance card is in the photo, so I am using Python rawpy (which uses libraw) to read the average raw camera red, green and blue values from the white balance card. I am reading these values before any colour transformation or demosaicing is applied by libraw.

My problem is that when I set the ART Multipliers using the values from libraw, the output image (viewed in ART or via TIFF 16-bit export) has a very strong colour cast. I have checked the verbose output of ART and I can see that my Multiplier values are being picked up in the “preprocessing” step.

The Multiplier values that I am measuring also do not match the values I get when I use the Customer Multiplier Pick tool in the ART GUI.

In what colour space are the CustomMult Multipliers defined? In which part of the pipeline are they applied?

Thanks to the ART devs for a great tool (and to the RT devs as well)!



unfortunately, computing the WB multipliers is a bit messy… for legacy reasons, the coefficients are defined in sRGB space, and they are also relative to the “reference WB” that is used internally during demosaicing and other operations on raw data. You can see the code for converting from the raw data to the right multipliers in the function ToolPanelCoordinator::getWBPresets() (in rtgui/wbpresets.cc).
In retrospect, it would have been better to store the multipliers in camera space, just like you would find them in the image metadata. I will think about how to do this in a backwards-compatible way. Until then, doing this via a batch script might be challenging I’m afraid…

Thanks Alberto, that’s really helpful. So I can see 3 options for my script:

  1. Emulate ToolPanelCoordinator::getWBPresets() in my script, however I would need some way to determine the “reference WB” (which is presumably what src->get_pre_mul() is retrieving). I would also need the camera matrix which I can get from the ART camera constants in the source code.
  2. Run ART twice: once to get the ART sRGB values for the white card, and a second time to apply my measured WB.
  3. Write a custom wbpresets.json file with my measured WB gains.

Of these options (3) seems the simplest and least dependent on ART internals.

Meanwhile, I’d like to clarify the WB algorithm in ART. My understanding of how WB should be applied to a RAW image is:

  1. Start with the WB red and blue multipliers in camera colour space (the same space as the multipliers in the image metadata, as you say) as a colour vector WBCV (with green = 1)
  2. Iteratively solve for the correlated colour temperature (CCT) and tint, by initialising the CCT to a nominal value CCTn, interpolating the camera forward matrices between the 2 supplied illuminants to CCTn giving FMn, applying FMn to WBCV to get XYZ values, calculating the CCT and Duv (tint), and then iterating until CCTn = CCT
  3. Multiply the raw colour channels by the WBCV
  4. Demosaic the raw image
  5. Apply the estimated camera forward matrix FMn

Does that sound right? Is this what ART is doing?

  1. Write a custom wbpresets.json file with my measured WB gains.

It looks like this won’t work, as the preset isn’t saved into the .arp profile. Instead the preset is used by the GUI to calculate a CCT and tint, which are then saved to the profile.

For (2):

  1. Run ART twice: once to get the ART sRGB values for the white card, and a second time to apply my measured WB.

I would need a way to run ART the first time with the “reference WB” that you mentioned. Would setting the White Balance / Setting = Camera and using an sRGB output ICC profile with gamma =1.0 do the trick?

One approach to keep it backwards-compatible might be to add a new CustomPreMult option for White Balance / Setting, for which the multipliers are in camera RGB space. This could be exposed in the GUI as an additional item on the White Balance / Method drop-down list, perhaps labelled “Custom pre-multipliers”. The current CustomMult option would need to be kept for compatibility with existing profiles.


Pretty much, except there’s no matrix interpolation in step 2, the temperature is computed using always the d65 matrix. Then the matrices (and luts, if present) are interpolated later when applying the DCP profile, if you use that.

Regarding enabling the input of multipliers in camera space, I’m thinking of a solution that would not require gui changes. I’ll let you know when I have something.


if you use the current master head, you can enter multipliers in camera space. Just make sure that you set


in the .arp if you do this programmatically.


Well this is fantastic! I’ve just tried it out on a pair of photos of the same scene with different cameras and flashes and I’m getting a beautiful colour match after measuring and setting the white balance gains programmatically from a white balance card in the scene.

Thank you so much for implementing this. I reckon there will be many users who appreciate this kind of direct control.

I tested the GUI with the changes, and I think it’s a really nice improvement. Before I was noticing some odd behaviour when I used the Custom Multipliers with Pick, such as:

  1. Colour cast even after selecting Pick
  2. Changes in values or colour when switching between Custom Temperature and Custom Multipliers
  3. The multipliers weren’t in the usual camera RGB space, so it was hard to compare with other software or against the values in the white balance EXIF tags

Now with the latest commit everything is much more consistent and stable.