Hi,
I had posted a question about this yesterday, but I dont think that post was well-researched (my bad!). I am reposting after doing some digging around myself. Hopefully these questions are a little more pointed.
The comments that I am specifying below is after calling unpack(). I am trying to use libraw to read the CFA data and all metadata to build my own RAW processing pipeline. Hence, I am using libraw primarily to read the data.
1. Is the correct way to determine the black-level per channel to do black + cblack as one defines the baseline and cblack contains the corrections?
2. I noticed that Fuji X-trans and some DNG files define black-level over a region. Is this what is captured in the cblack[4] and cblack[5]? For a Fuji X-trans file in my test files, cblack[4] = cblack[5] = 6. The values from cblack[6] -> cblack[41] were 256. The black property was 0. Does it mean the black-level to use is actually 256? Similar for some DNG files, the values of cblack[4] and cblack[5] were 2.
3. Is it fair to say that cblack is meant to handle the two ways black-level is specified for different RAW files? When cblack[4] and cblack[5] is 0, is it fair to assume that cblack[0] -> cblack[3] values are to be taken as the per channel correction. And when cblack[4] and cblack[5] is non-zero, then you must use a repeated pattern of this region starting at the top-left of the visible area? Also what is the order or cblack[0...3] i.e. are they R G1 B G2 order or the Bayer pattern order?
4. Is the value of maximum the white-level or saturation? This seems to hold for DNG files and the WhiteLevel tag. Is maximum or linear_max more reliable? I was not clear what the comment about black-level not being subtracted when linear_max is not available meant.
Regards,
Dinesh
Yes, black/cblack reflects
Yes, black/cblack reflects different black level specifications in RAW metadata
black - single black level
cblack[0-3] per channel BL in channel numbering order (channel numbers are returned by COLOR(..))
cblack[4-5] defines pattern BL (e.g. 6x6 for X-Trans)
As a rule: black is base level and cblack is correction, so if black is non-zero and cblack[.. is non-zero (for given channel or row/col), resulting BL for pixel/channel is a sum of black + cblack[channel] + cblack[pattern]. In practice all three are rarely present.
white is either format maximum (defined by bits per pixel), or maximum value defined by metadata (DNG whitelevel).
linear_max is 'specular white' read from metadata (if present in file)
-- Alex Tutubalin @LibRaw LLC
Thanks!
Alex,
Thanks for this clarification. So it looks like my best bet would be to call raw2image() and subtract_black() to leverage libraw to do the black-level correction for me. I still would like to return the CFA data as a rows x columns matrix instead of the output of raw2image. I guess I have to add some custom logic to do the copying.
Also, it appears that raw2image() only returns the visible portion of the image. It typically has only 1 out of the 4 channels as non-zero. I am assuming this does not hold true for Fovean sensors or DNG files that are created from Sigma cameras?
Can I use the COLOR function for non-Bayer sensors? I have a DNG file that appears to be created from a Sigma camera. The output of COLOR(0, 0), COLOR(0, 1) returned 6.
Dinesh
COLOR() for non-bayer(x-trans
COLOR() for non-bayer(x-trans) data is useless, check filters too before use.
-- Alex Tutubalin @LibRaw LLC
Followup, 6 is intended value
Followup, 6 is intended value for non-bayer:
-- Alex Tutubalin @LibRaw LLC
A quick follow up
Alex,
For the black-levels that are specified in cblack[0]->cblack[3], do those also need to be applied starting at the visible region. I am assuming this is the case because the subtract_black_internal operates on imgdata.image which only operates on the visible image.
Also, for the white-levels, if linear_max is all zeros, then do I just assume maximum applies to all the channels.
Also, if both maximum and linear_max value is present, which value should I use?
Regards,
Dinesh
I do not know what you want
I do not know what you want to achieve, so I could not answer (both) your questions.
-- Alex Tutubalin @LibRaw LLC
Clarifying
Alex,
I am trying to apply my own black-level subtraction and image normalization. So, I just wanted to clarify on what image range I should apply the black-level subtraction. Also, I am not sure if I should use maximum or linear_max for normalization.
Dinesh
Dinesh
I don’t know what exactly you
I don’t know what exactly you are doing and what you mean by normalization.
Therefore, do as you think is right.
-- Alex Tutubalin @LibRaw LLC
Apologies for not being clear earlier
Alex,
I am trying to implement my own version of subtract_black. Following which I am trying to rescale the image to the range (0,1). For this, I need to know the black-level and white-level. Given, there are two properties that contain white-level information, I was curious to know which one to use if both maximum and linear_max are both populated.
Dinesh
As mentioned above:
As mentioned above:
> linear_max is 'specular white' read from metadata (if present in file)
Hope this helps.
-- Alex Tutubalin @LibRaw LLC
Inconsistent black and white values
Alex,
I noticed a few unexpected values for the black, maximum and linear_max fields when I was working with a collection of files in my repo.
1. For some files read from an Olympus XZ-1, linear_max values were lower than black values. linear_max reported values of {10, 10, 10, 10} but black was reported as {67, 67, 67, 67}.
2. For many files, when I do:
rp.open_file(fileName)
rp.unpack();
// memcpy the CFA data from rp.imgdata.rawdata.raw_image into my buffer
I expected the minimum values of the data in my buffer to be no less than value in black + cblack but I do see some entries that dont satisfy this. Does libraw do any additional processing on the CFA data at unpack()?
Also, before I perform my processing, I am trying to scale the CFA data into a full uint16 range. Hence, I require accurate values for minimum and maximum to use to perform this scaling. Not sure if I should use maximum or data_maximum or linear_max as the max-value.
Would appreciate your help.
Regards,
Dinesh
1) LibRaw uses Olympus
1) LibRaw uses Olympus SensorCalibration tag (1st value) as linear_max. It looks like this is not valid for specifically XZ-1 (XZ-2 and XZ-10 are ok). We'll issue some fix for that, thank you for the problem report.
2) For very dark (near-black, or just black w/ lens caps on) areas it is expected that some values are below black+cblack. For completely black shots (lens caps on), if no processing was performed (in camera) about half of pixels will be below that threshold.
3) linear_max is vendor specified (if any) 'specular white'
maximum is either guessed from format bit count (or bit count + linearization curve), or hardcoded (and may be adjusted with data_maximum is not turned off via params.adjust_maximum_thr).
maximum also may be adjusted on processing stage if LibRaw's exposure correction is used.
data_maximum is real data maximum calculated on current frame data.
There is no universal answer on 'what maximum should I use', it very depends on application targets.
-- Alex Tutubalin @LibRaw LLC
This patch fixes linear_max
This patch fixes linear_max for XZ1: https://github.com/LibRaw/LibRaw/commit/87792af903fc21d5157ee2f2ba194ff1...
(by not providing this value)
-- Alex Tutubalin @LibRaw LLC
Thanks!
I will try that once I upgrade to 0.20 release.