kviLL
kviLL

Reputation: 357

Why does RawPy/Libraw increase the brightness range when postprocessing?

I'm processing a raw photo1 with RawPy as follows:

import numpy as np
import rawpy

with rawpy.imread('my_picture.nef') as rpy:
    raw = rpy.raw_image
    print('Raw:', raw.shape, np.min(raw), np.max(raw))

    image = rpy.postprocess(
        output_bps=16,
        no_auto_bright=True,
        no_auto_scale=True,
        user_wb=(1, 1, 1, 1),
        gamma=(1, 1),
        user_black=0,
        user_sat=65535
    )

    print('Processed:', image.shape, np.min(image), np.max(image))

Which produces this output:

Raw: (4016, 6016) 157 4087
Processed: (4016, 6016, 3) 0 5589

My understanding is that the call to rpy.postprocess() is configured to not adjust the brightness at all, except as a side effect of demosaicing.2 So I have two questions:

  1. Why did the min/max values widen from 157–4087 to 0–5589?

  2. Is there any way to predict the min/max values after postprocessing? Ideally, I want a formula like "if your black/saturation levels are ___ and ___, then the widest possible range after postprocessing is ___ to ___."

Other Attempts and Demosaicing

I understand that 4087 is the max value of the Bayer-patterned pixels in the raw image, while 5589 is the maximum R, G, or B value of some pixel. Thus, I tried adding the color channels together:

>>> image = np.sum(image, axis=-1)
>>> np.min(image), np.max(image)
452 10743

This didn't help much, as I don't see a clear relationship between 157–4087 and 452–10743. But maybe that's because there's nothing solid white or black in the image? Thus, I also tried things like this:

with rawpy.imread('my_picture.nef') as rpy:
    rpy.raw_image[:] = 4095   # Or 0, or some other integer
    # OR
    rpy.raw_image[:] = np.random.randint(157, 4088, size=(4016, 6016))

    # Postprocessing like before ...

Interestingly, when the raw image is all the same pixel value (1000, 4095, etc.) the output values aren't scaled. The min/max stay about the same. But using random numbers is basically equivalent to the real photo. I don't understand this phenomenon either.


1 From a Nikon D3400, if that matters.

2 There's also the adjust_maximum_thr parameter, which I don't fully understand, but messing with it didn't seem to change anything here.

Upvotes: 0

Views: 19

Answers (0)

Related Questions