Doug Kerr
Well-known member
The "Radiance HDR" family of color spaces comprises the RGBE and XYZE color spaces.
The RGBE color space
In this color space, the underlying coordinates are the linear sRGB values (what I sometime call r, g, and b); that is, the sRGB coordinate values before the application of "gamma precompensation".
Each coordinate is recorded in floating point form with an 8-bit fractional significand [more about that shortly] and an 8 bit exponent. However, the same exponent applies to all three coordinates. (It is the one suited to the largest coordinate value.) Thus there are a total of 32 bits stored per pixel, 8 each for R, G, B, and the common exponent, E.
If compression is used, it is of the run-length encoded (RLE) form.
The fractional significand
In some types of binary floating point representation (such as IEEE-754), the significand (sometimes called the mantissa) has a value (S) in this range:
1≤S<2
That is, in binary, the range is:
1.0000... through 1.1111... [yes, that is a binary point]
This being the case, the leading (units place) "1" need not be recorded, since its value is always known ("1"). Thus we can get, for example, 9 bits of precision by only recording 8 bits.
Of course, this only works if the exponent is always chosen such that the significand will be in the range mentioned. (The number represented is the significand times 2 to the power of the exponent.)
These "4 significant digit" "floating point" expressions would all represent the same value (the significands are all in binary, the rest in decimal):
10.01 x 2^7
1.001 x 2^8
0.1001 x 2^9
but we only use the second representation for that particular number so as to maintain the range of the significand that allows us to "know" its units digit and not have to record it.
But if we are going to have three coordinates, with values perhaps quite different, and force them to share a common exponent, this can't happen.
Imagine these three values, with separate "optimum" exponents, following the rule above:
R: 1.001 x 2^9
G: 1.010 x 2^8
B: 1.110 x 2^7
If we wish them to share a common exponent, we might think to do that this way:
R: 1.0010 x 2^9
G: 0.1010 x 2^9
B: 0.0111 x 2^9
But now we would have to store all the digits of each significand - we can no longer say that we "know" the value of the units digit. So we would have to store 5 bits for each value.
So in the RGBE system, we do just that. Well, not quite. Actually, by convention, those three values would be stored as:
R: 0.10010 x 2^9
G: 0.01010 x 2^9
B: 0.00111 x 2^9
And of course now we no longer need to store the units digit, which is always "0". But we have to store the same number of digits as before: 5.
This outlook follows a different norm for the range of the significand. If we don't saddle a scheme with the need to use the same exponent for several values, but just chose the "optimum" exponent for each value, then under this convention, the range of the significand, S will always be:
0.5≤S<1
That is, in binary, the range is:
0.1000... through 0.1111...
But in RGBE, where we must choose an exponent that suits the largest value and then make the other values use it, only for the largest value will the significand lie in the range just stated.
We see that in the earlier example for R, G, and B, where only for R (the largest value) does its significand lie in that range.
The exponent
As in many floating point schemes, the exponent is recorded with a bias (here +128) to allow representation of a range of negative and positive values.
I don't have the detailed specification, but from various hints, I suspect that the range of the exponent itself is ±126.
Black
When all coordinate values are below the range of the floating point scheme (near black), the significands are all recorded as 0 and the exponent is -128 (recorded, with its offset, as 0).
The "precision" of the scheme
In evaluating various color spaces, there is often concern about the "precision" of the encoding,. which we can think of as the ratio of size of an encoding step (the difference between adjacent values that have legitimate representations) and the average value of the adjacent "steps".
If we only think of the "largest" coordinate value (or others that are able to share the same exponent), that ratio depends on where in the range of the significant we lie. Here are two pairs of adjacent "steps" we could consider with the 8-bit significand of RGBE:
These are at the top of the range:
0.11111110
0.11111111
The difference between those is 0.00000001. The average of them is 0.111111101. The ratio is roughly 0.004, or 0.4%. (That is considered "not really a problem" with respect to banding.)
These are at the bottom of the range:
0.10000000
0.10000001
The difference between those is 0.00000001. The average of them is 0.100000001. The ratio is roughly 0.008, or 0.8%. (That, though coarser, is still considered "not really a problem" with respect to banding.)
Now, what about values that have to share an exponent that is "too big" for them? These are like voltages we measure with the voltmeter set on too large a scale (so it will fit all the voltages we are measuring). Their "precision" might be quite low.
Here would be a legitimate pair of adjacent significands (the worst case in the situation mentioned):
0.00000000
0.00000001
The difference between those is 0.00000001. The average of them is 0.000000001. The ratio is 2, or 200%!
The gamut
The gamut of the RGBE color space is the same as that of the sRGB color space.
The EYZE color space
In this color space, the underlying coordinates are the coordinates X, Y, and Z of the CIE XYZ color space.
The rest of the scheme works just exactly as we saw for the RGBE color space.
The gamut
The gamut of the XYZE color space is the same as that of the CIE XYZ color space. In chromaticity, it embraces the entire visual gamut (and then some).
The price we pay for that is that the precision, in terms of color perception, is less than for the RGBE color space, but still quite good.
Best regards,
Doug
The RGBE color space
In this color space, the underlying coordinates are the linear sRGB values (what I sometime call r, g, and b); that is, the sRGB coordinate values before the application of "gamma precompensation".
Each coordinate is recorded in floating point form with an 8-bit fractional significand [more about that shortly] and an 8 bit exponent. However, the same exponent applies to all three coordinates. (It is the one suited to the largest coordinate value.) Thus there are a total of 32 bits stored per pixel, 8 each for R, G, B, and the common exponent, E.
If compression is used, it is of the run-length encoded (RLE) form.
The fractional significand
In some types of binary floating point representation (such as IEEE-754), the significand (sometimes called the mantissa) has a value (S) in this range:
1≤S<2
That is, in binary, the range is:
1.0000... through 1.1111... [yes, that is a binary point]
This being the case, the leading (units place) "1" need not be recorded, since its value is always known ("1"). Thus we can get, for example, 9 bits of precision by only recording 8 bits.
Of course, this only works if the exponent is always chosen such that the significand will be in the range mentioned. (The number represented is the significand times 2 to the power of the exponent.)
These "4 significant digit" "floating point" expressions would all represent the same value (the significands are all in binary, the rest in decimal):
10.01 x 2^7
1.001 x 2^8
0.1001 x 2^9
but we only use the second representation for that particular number so as to maintain the range of the significand that allows us to "know" its units digit and not have to record it.
But if we are going to have three coordinates, with values perhaps quite different, and force them to share a common exponent, this can't happen.
Imagine these three values, with separate "optimum" exponents, following the rule above:
R: 1.001 x 2^9
G: 1.010 x 2^8
B: 1.110 x 2^7
If we wish them to share a common exponent, we might think to do that this way:
R: 1.0010 x 2^9
G: 0.1010 x 2^9
B: 0.0111 x 2^9
But now we would have to store all the digits of each significand - we can no longer say that we "know" the value of the units digit. So we would have to store 5 bits for each value.
So in the RGBE system, we do just that. Well, not quite. Actually, by convention, those three values would be stored as:
R: 0.10010 x 2^9
G: 0.01010 x 2^9
B: 0.00111 x 2^9
And of course now we no longer need to store the units digit, which is always "0". But we have to store the same number of digits as before: 5.
Actually, of course there is no "binary point" stored; it occurs by implication. Thus those three significands would be stored as:
R: 10010
G: 01010
B: 00111
But the program would treat them as I showed above.
R: 10010
G: 01010
B: 00111
But the program would treat them as I showed above.
This outlook follows a different norm for the range of the significand. If we don't saddle a scheme with the need to use the same exponent for several values, but just chose the "optimum" exponent for each value, then under this convention, the range of the significand, S will always be:
0.5≤S<1
That is, in binary, the range is:
0.1000... through 0.1111...
But in RGBE, where we must choose an exponent that suits the largest value and then make the other values use it, only for the largest value will the significand lie in the range just stated.
We see that in the earlier example for R, G, and B, where only for R (the largest value) does its significand lie in that range.
The exponent
As in many floating point schemes, the exponent is recorded with a bias (here +128) to allow representation of a range of negative and positive values.
I don't have the detailed specification, but from various hints, I suspect that the range of the exponent itself is ±126.
Black
When all coordinate values are below the range of the floating point scheme (near black), the significands are all recorded as 0 and the exponent is -128 (recorded, with its offset, as 0).
The "precision" of the scheme
In evaluating various color spaces, there is often concern about the "precision" of the encoding,. which we can think of as the ratio of size of an encoding step (the difference between adjacent values that have legitimate representations) and the average value of the adjacent "steps".
If we only think of the "largest" coordinate value (or others that are able to share the same exponent), that ratio depends on where in the range of the significant we lie. Here are two pairs of adjacent "steps" we could consider with the 8-bit significand of RGBE:
These are at the top of the range:
0.11111110
0.11111111
The difference between those is 0.00000001. The average of them is 0.111111101. The ratio is roughly 0.004, or 0.4%. (That is considered "not really a problem" with respect to banding.)
These are at the bottom of the range:
0.10000000
0.10000001
The difference between those is 0.00000001. The average of them is 0.100000001. The ratio is roughly 0.008, or 0.8%. (That, though coarser, is still considered "not really a problem" with respect to banding.)
Now, what about values that have to share an exponent that is "too big" for them? These are like voltages we measure with the voltmeter set on too large a scale (so it will fit all the voltages we are measuring). Their "precision" might be quite low.
Here would be a legitimate pair of adjacent significands (the worst case in the situation mentioned):
0.00000000
0.00000001
The difference between those is 0.00000001. The average of them is 0.000000001. The ratio is 2, or 200%!
The gamut
The gamut of the RGBE color space is the same as that of the sRGB color space.
The EYZE color space
In this color space, the underlying coordinates are the coordinates X, Y, and Z of the CIE XYZ color space.
The rest of the scheme works just exactly as we saw for the RGBE color space.
The gamut
The gamut of the XYZE color space is the same as that of the CIE XYZ color space. In chromaticity, it embraces the entire visual gamut (and then some).
The price we pay for that is that the precision, in terms of color perception, is less than for the RGBE color space, but still quite good.
Best regards,
Doug