How does RAW black point subtraction work?

NateW

Well-known member
Messages
100
Reaction score
39
I’ve been trying to improve my understanding of how raw photo processing works, but I think I’m getting hung up on black point subtraction. RawDigger tells me that the black point for my A7IV is 512. I’m assuming that this is 512 out of 16383 (.03125), and not after scaling to fill the full 16bit range (.0078125), correct?

So, if 512 is 9 bits of data, how is the camera encoding 14stops of linear dynamic range in only the upper 5 bits of data? Is the data encoding only linear after black point subtraction is performed?

And if the camera black point is 9 log2 DNS (512/16383) why does the photon transfer curve show that noise maxes out around 6 log2 DNs (64/16383)?

Sorry in advance, I know these are elementary questions. Just trying to locate the misunderstanding them might stem from. Thanks!
 
The black point bias is added after ADC encoding, so you still get 14 EVs, just with black_level fewer values in the final EV. In other words, the highest represented ADC value is 2^14 - black_level instead of 2^14
 
Last edited:
I’ve been trying to improve my understanding of how raw photo processing works, but I think I’m getting hung up on black point subtraction. RawDigger tells me that the black point for my A7IV is 512. I’m assuming that this is 512 out of 16383 (.03125), and not after scaling to fill the full 16bit range (.0078125), correct?

So, if 512 is 9 bits of data, how is the camera encoding 14stops of linear dynamic range in only the upper 5 bits of data? Is the data encoding only linear after black point subtraction is performed?
Linear means that for a given increase in signal, the encoded output always changes by the same amount. It does not mean that zero output corresponds to zero signal.

Ignoring the low order bits would mean counting 0, 512, 1024, 1536, 2048, 2560 etc.

Assume that the signal captured is 1 digital count (DN) above black level, within a possible range of [0 ... 16383].

If your black level is 512, this gives an output of 513, or binary 00 0001 0000 0001

At 5 counts above black level, the output is 517, or binary 00 0001 0000 0101.

So we do use the low order bits, but instead of 16383 levels above zero, we only have (16383-512) = 15871 possible values, a dynamic range of 13.95 log2 DNs. This is close enough to 14 bits for most purposes.

The reason we do this is that read noise can take us below the black level, and we need to capture these negative values for accurate handling of shadow noise, for instance when stacking multiple images. If we used conventional signed integers, we would need an extra bit to denote sign, which be largely wasted. A black level of 512 is easily subtracted in post processing and means we only waste 0.05 bits of potential information.
And if the camera black point is 9 log2 DNS (512/16383) why does the photon transfer curve show that noise maxes out around 6 log2 DNs (64/16383)?
According to Bill Claff's PhotonsToPhotos site, Sony A7iv (inverse) gain is 4.707e- / DN, so saturation is 77115 e-. Assuming Poisson statistics, noise standard deviation is the square root of this, so 278 e- at max output.

At 4.707 e- / DN this gives 59 DN, which is 5.9 log2 DN.

66ccccb02afb4c00bfdf869dab49c980.jpg.png


I believe the curve above shows signal in electrons, not DN. From Bill's article:
The standard Photon Transfer Curve is a log10-log10 curve of noise in electrons versus signal in electrons.

Because we are interested in photography rather than engineering, we will use log2 rather than log10 throughout this article.
It is the noise in the Poisson-distributed noise in the signal (and other contributions) which the photon transfer curve measures.
Sorry in advance, I know these are elementary questions. Just trying to locate the misunderstanding them might stem from.
Hope this helps.

--
Alan Robinson
 
I’ve been trying to improve my understanding of how raw photo processing works, but I think I’m getting hung up on black point subtraction. RawDigger tells me that the black point for my A7IV is 512. I’m assuming that this is 512 out of 16383 (.03125), and not after scaling to fill the full 16bit range (.0078125), correct?

So, if 512 is 9 bits of data, how is the camera encoding 14stops of linear dynamic range in only the upper 5 bits of data? Is the data encoding only linear after black point subtraction is performed?

And if the camera black point is 9 log2 DNS (512/16383) why does the photon transfer curve show that noise maxes out around 6 log2 DNs (64/16383)?

Sorry in advance, I know these are elementary questions. Just trying to locate the misunderstanding them might stem from. Thanks!
Simply, it's just a number subtracted from each image value, for the reasons described above. Basically, if a black level tag is found in the metadata, subtract it, if none is found, don't. My Nikon D7000 provides pre-subtracted raw data, my Z 6 does not.

Some camera's provided black levels aren't right or optional, so the software has to step in with an alternate. See RawTherapee's. camconst.json file for examples.
 
I’ve been trying to improve my understanding of how raw photo processing works, but I think I’m getting hung up on black point subtraction. RawDigger tells me that the black point for my A7IV is 512. I’m assuming that this is 512 out of 16383 (.03125), and not after scaling to fill the full 16bit range (.0078125), correct?
If such a value is given, then that is where black is supposed to be in that raw image. They wouldn't tell you that value of 512 if it wasn't still biasing all the values. Some cameras subtract it before writing the raw data, but they will report zero as the black point.
So, if 512 is 9 bits of data, how is the camera encoding 14stops of linear dynamic range in only the upper 5 bits of data? Is the data encoding only linear after black point subtraction is performed?
You have a misunderstanding of bits. They are logarithmic; you can't just add and subtract them for addition and subtraction; such actions are actually multiplication and division. 14 bits of values minus 5 bits of values actually leaves :

16384 - 512 = 15872. You calculate the bits needed for 15872 values by dividing the log of 15872 by the log of 2:

log(15872)/log(2) = 13.954 bits. Think about it; the 14th bit gave you 8192 more values than the 8192 values of 13 bits. You only lose 512 of those values to the black point bias.
And if the camera black point is 9 log2 DNS (512/16383) why does the photon transfer curve show that noise maxes out around 6 log2 DNs (64/16383)?
Bill is already subtracting the blackpoint.
Sorry in advance, I know these are elementary questions. Just trying to locate the misunderstanding them might stem from. Thanks!
No self-respecting conversion is going to ignore the blackpoint when it is higher than zero. You can't get correct color when you leave the bias in. However, it is more accurate to maintain original readout values of less than 512 as negative numbers, rather than clipping to 0 (everything 512 or less becomes zero) if you want minimal artifacts for very weak signals, and only clip the data at the last stage to create a display image. All interpolation and resizing is best done when negative values are maintained. This clips less signal and maintains linearity.

--
Beware of correct answers to wrong questions.
John
http://www.pbase.com/image/55384958.jpg
 
Last edited:
The black point bias is added after ADC encoding,
I don’t think so. I think the ADCs zero count point is below the sensor black point. Otherwise, how do we get encoded values below the black point?
so you still get 14 EVs, just with black_level fewer values in the final EV. In other words, the highest represented ADC value is 2^14 - black_level instead of 2^14
 
The black point bias is added after ADC encoding,
I don’t think so. I think the ADCs zero count point is below the sensor black point. Otherwise, how do we get encoded values below the black point?
Yup. It's an offset before the ADC (or inherent to its internal operation), not after it. As others have pointed out, read noise can create negative values and if you want to average it out over multiple exposures, having what is effectively either an abs() function or clamp at zero will make that fail.

Everything else about Horshack's post was OK though.
 
The black point bias is added after ADC encoding,
I don’t think so. I think the ADCs zero count point is below the sensor black point. Otherwise, how do we get encoded values below the black point?
By having the ADC's output biased, which is then scaled to the black level bias recorded in the ADU value.
Well, we agree on the bias part, if by bias you mean that the ADC is unipolar with respect to an arbitrary voltage, but bipolar (with an odd encoding) with respect to the black point. But what’s the purpose of adding some number to the ADC count? That seems to be to be an unnecessary complication with overflow side effects.

Oh, one possible reason just occurred to me: calibration. But if that’s necessary, why not handle it in the metadata?

--
https://blog.kasson.com
 
Last edited:
I’ve been trying to improve my understanding of how raw photo processing works, but I think I’m getting hung up on black point subtraction. RawDigger tells me that the black point for my A7IV is 512. I’m assuming that this is 512 out of 16383 (.03125), and not after scaling to fill the full 16bit range (.0078125), correct?
If such a value is given, then that is where black is supposed to be in that raw image. They wouldn't tell you that value of 512 if it wasn't still biasing all the values. Some cameras subtract it before writing the raw data, but they will report zero as the black point.
So, if 512 is 9 bits of data, how is the camera encoding 14stops of linear dynamic range in only the upper 5 bits of data? Is the data encoding only linear after black point subtraction is performed?
You have a misunderstanding of bits. They are logarithmic; you can't just add and subtract them for addition and subtraction; such actions are actually multiplication and division. 14 bits of values minus 5 bits of values actually leaves :

16384 - 512 = 15872. You calculate the bits needed for 15872 values by dividing the log of 15872 by the log of 2:

log(15872)/log(2) = 13.954 bits. Think about it; the 14th bit gave you 8192 more values than the 8192 values of 13 bits. You only lose 512 of those values to the black point bias.
And if the camera black point is 9 log2 DNS (512/16383) why does the photon transfer curve show that noise maxes out around 6 log2 DNs (64/16383)?
Bill is already subtracting the blackpoint.
Sorry in advance, I know these are elementary questions. Just trying to locate the misunderstanding them might stem from. Thanks!
No self-respecting conversion is going to ignore the blackpoint when it is higher than zero. You can't get correct color when you leave the bias in. However, it is more accurate to maintain original readout values of less than 512 as negative numbers, rather than clipping to 0 (everything 512 or less becomes zero) if you want minimal artifacts for very weak signals, and only clip the data at the last stage to create a display image. All interpolation and resizing is best done when negative values are maintained. This clips less signal and maintains linearity.
John, makes perfect sense, but I'm struggling with order of operations. I just did a "scrabble" of operations in my hack software, putting black subtract after the interpolation operations but I couldn't resolve its place after all the other things, demosaic, white balance, tone curve. It simply didn't produce a decent result unless it was first in the order.
 
The black point bias is added after ADC encoding,
I don’t think so. I think the ADCs zero count point is below the sensor black point. Otherwise, how do we get encoded values below the black point?
By having the ADC's output biased, which is then scaled to the black level bias recorded in the ADU value.
Well, we agree on the bias part, if by bias you mean that the ADC is unipolar with respect to an arbitrary voltage, but bipolar (with an odd encoding) with respect to the black point. But what’s the purpose of adding some number to the ADC count? That seems to be to be an unnecessary complication with overflow side effects.

Oh, one possible reason just occurred to me: calibration. But if that’s necessary, why not handle it in the metadata?
 
The black point bias is added after ADC encoding,
I don’t think so. I think the ADCs zero count point is below the sensor black point. Otherwise, how do we get encoded values below the black point?
By having the ADC's output biased, which is then scaled to the black level bias recorded in the ADU value.
Well, we agree on the bias part, if by bias you mean that the ADC is unipolar with respect to an arbitrary voltage, but bipolar (with an odd encoding) with respect to the black point. But what’s the purpose of adding some number to the ADC count? That seems to be to be an unnecessary complication with overflow side effects.

Oh, one possible reason just occurred to me: calibration. But if that’s necessary, why not handle it in the metadata?
When I wrote my OP I was thinking in terms of the internal ADC operation and how it might convert the internal sampled voltage into a signless output ADU. To me that would be by applying a large positive bias against the internal representation. I didn't mean to suggest the bias was applied externally to the ADC, although on re-reading my OP that's not very clear.
I believe most cameras now use single ramp ADCs, not SA ones, so the ADC is just a counter and a comparator. The ramp comes from a shared DAC.



I am ignoring CDS.
 
I’ve been trying to improve my understanding of how raw photo processing works, but I think I’m getting hung up on black point subtraction. RawDigger tells me that the black point for my A7IV is 512. I’m assuming that this is 512 out of 16383 (.03125), and not after scaling to fill the full 16bit range (.0078125), correct?
If such a value is given, then that is where black is supposed to be in that raw image. They wouldn't tell you that value of 512 if it wasn't still biasing all the values. Some cameras subtract it before writing the raw data, but they will report zero as the black point.
So, if 512 is 9 bits of data, how is the camera encoding 14stops of linear dynamic range in only the upper 5 bits of data? Is the data encoding only linear after black point subtraction is performed?
You have a misunderstanding of bits. They are logarithmic; you can't just add and subtract them for addition and subtraction; such actions are actually multiplication and division. 14 bits of values minus 5 bits of values actually leaves :

16384 - 512 = 15872. You calculate the bits needed for 15872 values by dividing the log of 15872 by the log of 2:

log(15872)/log(2) = 13.954 bits. Think about it; the 14th bit gave you 8192 more values than the 8192 values of 13 bits. You only lose 512 of those values to the black point bias.
And if the camera black point is 9 log2 DNS (512/16383) why does the photon transfer curve show that noise maxes out around 6 log2 DNs (64/16383)?
Bill is already subtracting the blackpoint.
Sorry in advance, I know these are elementary questions. Just trying to locate the misunderstanding them might stem from. Thanks!
No self-respecting conversion is going to ignore the blackpoint when it is higher than zero. You can't get correct color when you leave the bias in. However, it is more accurate to maintain original readout values of less than 512 as negative numbers, rather than clipping to 0 (everything 512 or less becomes zero) if you want minimal artifacts for very weak signals, and only clip the data at the last stage to create a display image. All interpolation and resizing is best done when negative values are maintained. This clips less signal and maintains linearity.
John, makes perfect sense, but I'm struggling with order of operations. I just did a "scrabble" of operations in my hack software, putting black subtract after the interpolation operations but I couldn't resolve its place after all the other things, demosaic, white balance, tone curve. It simply didn't produce a decent result unless it was first in the order.
Black point subtraction needs to be done before application of the compromise matrix. It is conceivable that it could be incorporated into the LUTs.
 
I’ve been trying to improve my understanding of how raw photo processing works, but I think I’m getting hung up on black point subtraction. RawDigger tells me that the black point for my A7IV is 512. I’m assuming that this is 512 out of 16383 (.03125), and not after scaling to fill the full 16bit range (.0078125), correct?
If such a value is given, then that is where black is supposed to be in that raw image. They wouldn't tell you that value of 512 if it wasn't still biasing all the values. Some cameras subtract it before writing the raw data, but they will report zero as the black point.
So, if 512 is 9 bits of data, how is the camera encoding 14stops of linear dynamic range in only the upper 5 bits of data? Is the data encoding only linear after black point subtraction is performed?
You have a misunderstanding of bits. They are logarithmic; you can't just add and subtract them for addition and subtraction; such actions are actually multiplication and division. 14 bits of values minus 5 bits of values actually leaves :

16384 - 512 = 15872. You calculate the bits needed for 15872 values by dividing the log of 15872 by the log of 2:

log(15872)/log(2) = 13.954 bits. Think about it; the 14th bit gave you 8192 more values than the 8192 values of 13 bits. You only lose 512 of those values to the black point bias.
And if the camera black point is 9 log2 DNS (512/16383) why does the photon transfer curve show that noise maxes out around 6 log2 DNs (64/16383)?
Bill is already subtracting the blackpoint.
Sorry in advance, I know these are elementary questions. Just trying to locate the misunderstanding them might stem from. Thanks!
No self-respecting conversion is going to ignore the blackpoint when it is higher than zero. You can't get correct color when you leave the bias in. However, it is more accurate to maintain original readout values of less than 512 as negative numbers, rather than clipping to 0 (everything 512 or less becomes zero) if you want minimal artifacts for very weak signals, and only clip the data at the last stage to create a display image. All interpolation and resizing is best done when negative values are maintained. This clips less signal and maintains linearity.
John, makes perfect sense, but I'm struggling with order of operations. I just did a "scrabble" of operations in my hack software, putting black subtract after the interpolation operations but I couldn't resolve its place after all the other things, demosaic, white balance, tone curve. It simply didn't produce a decent result unless it was first in the order.
Black point subtraction needs to be done before application of the compromise matrix. It is conceivable that it could be incorporated into the LUTs.
 
I’ve been trying to improve my understanding of how raw photo processing works, but I think I’m getting hung up on black point subtraction. RawDigger tells me that the black point for my A7IV is 512. I’m assuming that this is 512 out of 16383 (.03125), and not after scaling to fill the full 16bit range (.0078125), correct?
If such a value is given, then that is where black is supposed to be in that raw image. They wouldn't tell you that value of 512 if it wasn't still biasing all the values. Some cameras subtract it before writing the raw data, but they will report zero as the black point.
So, if 512 is 9 bits of data, how is the camera encoding 14stops of linear dynamic range in only the upper 5 bits of data? Is the data encoding only linear after black point subtraction is performed?
You have a misunderstanding of bits. They are logarithmic; you can't just add and subtract them for addition and subtraction; such actions are actually multiplication and division. 14 bits of values minus 5 bits of values actually leaves :

16384 - 512 = 15872. You calculate the bits needed for 15872 values by dividing the log of 15872 by the log of 2:

log(15872)/log(2) = 13.954 bits. Think about it; the 14th bit gave you 8192 more values than the 8192 values of 13 bits. You only lose 512 of those values to the black point bias.
And if the camera black point is 9 log2 DNS (512/16383) why does the photon transfer curve show that noise maxes out around 6 log2 DNs (64/16383)?
Bill is already subtracting the blackpoint.
Sorry in advance, I know these are elementary questions. Just trying to locate the misunderstanding them might stem from. Thanks!
No self-respecting conversion is going to ignore the blackpoint when it is higher than zero. You can't get correct color when you leave the bias in. However, it is more accurate to maintain original readout values of less than 512 as negative numbers, rather than clipping to 0 (everything 512 or less becomes zero) if you want minimal artifacts for very weak signals, and only clip the data at the last stage to create a display image. All interpolation and resizing is best done when negative values are maintained. This clips less signal and maintains linearity.
John, makes perfect sense, but I'm struggling with order of operations. I just did a "scrabble" of operations in my hack software, putting black subtract after the interpolation operations but I couldn't resolve its place after all the other things, demosaic, white balance, tone curve. It simply didn't produce a decent result unless it was first in the order.
Black point subtraction needs to be done before application of the compromise matrix. It is conceivable that it could be incorporated into the LUTs.
I don't use a working profile, no color matrix until export.
Are you not editing in a colormetric space?
It really didn't like being anywhere but at the front, right after import.
 
No self-respecting conversion is going to ignore the blackpoint when it is higher than zero. You can't get correct color when you leave the bias in. However, it is more accurate to maintain original readout values of less than 512 as negative numbers, rather than clipping to 0 (everything 512 or less becomes zero) if you want minimal artifacts for very weak signals, and only clip the data at the last stage to create a display image. All interpolation and resizing is best done when negative values are maintained. This clips less signal and maintains linearity.
I'm working on trying to reverse-engineer's Adobe's blackpoint handling. So far I already established it's not doing simple subtraction (link). By comparison, a cursory check of RawTherapee indicates it does do simple subtraction - the same experiment performed in that link yields identical output for RawTherapee (ie, modifying a blackframe raw so that the ADU values below black level are clamped to the black level yields the same output as the original blackframe raw with the ADU values unomdified).
 
No self-respecting conversion is going to ignore the blackpoint when it is higher than zero. You can't get correct color when you leave the bias in. However, it is more accurate to maintain original readout values of less than 512 as negative numbers, rather than clipping to 0 (everything 512 or less becomes zero) if you want minimal artifacts for very weak signals, and only clip the data at the last stage to create a display image. All interpolation and resizing is best done when negative values are maintained. This clips less signal and maintains linearity.
I'm working on trying to reverse-engineer's Adobe's blackpoint handling. So far I already established it's not doing simple subtraction (link). By comparison, a cursory check of RawTherapee indicates it does do simple subtraction - the same experiment performed in that link yields identical output for RawTherapee (ie, modifying a blackframe raw so that the ADU values below black level are clamped to the black level yields the same output as the original blackframe raw with the ADU values unomdified).
When I do black point subtraction, I do it in a signed representation, so there’s no clamping at that point. I use double precision floating point, which is immense overkill.
 
No self-respecting conversion is going to ignore the blackpoint when it is higher than zero. You can't get correct color when you leave the bias in. However, it is more accurate to maintain original readout values of less than 512 as negative numbers, rather than clipping to 0 (everything 512 or less becomes zero) if you want minimal artifacts for very weak signals, and only clip the data at the last stage to create a display image. All interpolation and resizing is best done when negative values are maintained. This clips less signal and maintains linearity.
I'm working on trying to reverse-engineer's Adobe's blackpoint handling. So far I already established it's not doing simple subtraction (link). By comparison, a cursory check of RawTherapee indicates it does do simple subtraction - the same experiment performed in that link yields identical output for RawTherapee (ie, modifying a blackframe raw so that the ADU values below black level are clamped to the black level yields the same output as the original blackframe raw with the ADU values unomdified).
When I do black point subtraction, I do it in a signed representation, so there’s no clamping at that point. I use double precision floating point, which is immense overkill.
That's how I do it in Octave as well. I think RT uses 32-bit floating point, but it still seems to be clamping to the black level nonetheless.
 
Last edited:

Keyboard shortcuts

Back
Top