Implement a correct RAW image processing procedure

I'm trying to write a raw image converter, thanks to LibRaw and the ecosystem around it which made my journey easier.

I've read the image processing code from LibRaw, but I'm not sure I understand the procedure correctly. If someone can point me to the right direction, it would be very helpful.

Let's assume the raw image is RGB rather than using CFA. This is what I do when a pixel is acquired:

  • 1. Black level subtraction. All three channels minus the corresponding black level.
  • 2. Scale the values. The channels scale according to the white and black level range.
  • 3. Clipping. Clip the pixel values in case they go beyond the target boundaries, e.g. 0 or max.
  • 4. White balancing. Multiply the white balance acquired by the raw library, i.e., wb_coeffs.
  • 5. Colour space conversion. Convert the values from camera colour space to the target colour space, e.g. sRGB. First, I query the adobe matrix table using the camera ID, I call this matrix "xyz_2_cam". Second, I take "rgb_2_xyz" from LibRaw and multiply it with "xyz_2_cam", then use "pseudo_inverse" to inverse it getting "cam_2_xyz".
// rgb_2_xyz is the matrix for sRGB to xyz conversion:
static const Matrix<double> rgb_2_xyz = {
                {0.4124564, 0.3575761, 0.1804375},
                {0.2126729, 0.7151522, 0.0721750},
                {0.0193339, 0.1191920, 0.9503041}

This process doesn't produce the colour I wanted (LibRaw colour).

I don't know a better place for seeking help, thank you!


For step 5: look into LibRaw:

For step 5: look into LibRaw::cam_xyz_coeff() source, it takes 'adobe ColorMatrix1/2' as cam_xyz and splits it into daylight color balance (pre_mul) and camera2srgb matrix (_rgb_cam).

For steps 2-4: scaling (usually) will not result into values above clipping (whitepoint), if whitepoint is scaled too. But WB may result into too big values that need to be clipped (so called 'pink clouds' problem), so either WB first, or WB + scaling + clipping in one step.

-- Alex Tutubalin @LibRaw LLC

Thank you

Hi Alex,

Thank you for answering my question in detail. I know similar questions popped many times in the past, I appreciate your patience.

I've reorganised the sequence of steps 2-4 and I will check LibRaw::cam_xyz_coeff() several more times : )

Thanks again!

Thank you

Hi Alex,

I'd like to say thank you, my program is now generating the correct colour based on your suggestion.

I'm moving forward to understand the tonal curves, hopefully I can reproduce the same results as "copy_mem_image".