-
Notifications
You must be signed in to change notification settings - Fork 40
Added offset to gain computation in low-luminance regions #358
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
Added an offset kComputeGainOffset to the computeGain function to prevent excessive gain in low-luminance regions for both SDR and HDR calculations. This adjustment helps stabilize gain computation.
f8f7a18
to
1eb503f
Compare
There is a change that restricts gain for low-luminance regions. 720dbed. What is the problem this change is trying to resolve? |
In the current version, there is an issue where even a slight luminance difference between SDR and HDR—especially in low-luminance regions (<1 nit)—can result in excessively large gain values. For example, if SDR is 0 nits and HDR is 0.003 nits, the gain becomes 30,001×. Such extreme gain values broaden the range of GainMapMin and GainMapMax, which in turn leads to a degradation in Ultra HDR image quality. This pull request suppresses excessive gain in low-luminance regions and improves the overall quality of Ultra HDR images. Below is the Gain Map metadata of the Ultra HDR image initially attached. Gainmap metadata (without offset)<x:xmpmeta
xmlns:x="adobe:ns:meta/"
x:xmptk="Adobe XMP Core 5.1.2">
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description
xmlns:hdrgm="http://ns.adobe.com/hdr-gain-map/1.0/"
hdrgm:Version="1.0"
hdrgm:GainMapMin="-14.3"
hdrgm:GainMapMax="5.29289"
hdrgm:Gamma="1"
hdrgm:OffsetSDR="1e-07"
hdrgm:OffsetHDR="1e-07"
hdrgm:HDRCapacityMin="0"
hdrgm:HDRCapacityMax="2.30045"
hdrgm:BaseRenditionIsHDR="False"/>
</rdf:RDF>
</x:xmpmeta> Gainmap metadata (with offset)<x:xmpmeta
xmlns:x="adobe:ns:meta/"
x:xmptk="Adobe XMP Core 5.1.2">
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description
xmlns:hdrgm="http://ns.adobe.com/hdr-gain-map/1.0/"
hdrgm:Version="1.0"
hdrgm:GainMapMin="-2.36361"
hdrgm:GainMapMax="1.81413"
hdrgm:Gamma="1"
hdrgm:OffsetSDR="1e-07"
hdrgm:OffsetHDR="1e-07"
hdrgm:HDRCapacityMin="0"
hdrgm:HDRCapacityMax="2.30045"
hdrgm:BaseRenditionIsHDR="False"/>
</rdf:RDF>
</x:xmpmeta> |
Those low sdr pixel should trigger this and gain must get clamped? |
This image was generated by setting both kSdrOffset and kHdrOffset to 1.0 in the current library, but the quality significantly degraded. This is likely because kSdrOffset and kHdrOffset are also referenced during rendering. <x:xmpmeta
xmlns:x="adobe:ns:meta/"
x:xmptk="Adobe XMP Core 5.1.2">
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description
xmlns:hdrgm="http://ns.adobe.com/hdr-gain-map/1.0/"
hdrgm:Version="1.0"
hdrgm:GainMapMin="-1.85716"
hdrgm:GainMapMax="2.29692"
hdrgm:Gamma="1"
hdrgm:OffsetSDR="1"
hdrgm:OffsetHDR="1"
hdrgm:HDRCapacityMin="0"
hdrgm:HDRCapacityMax="2.30045"
hdrgm:BaseRenditionIsHDR="False"/>
</rdf:RDF>
</x:xmpmeta> |
float computeGain(float sdr, float hdr) {
float gain = log2((hdr + kHdrOffset) / (sdr + kSdrOffset));
if (sdr < 2.f / 255.0f) {
// If sdr is zero and hdr is non zero, it can result in very large gain values. In compression -
// decompression process, if the same sdr pixel increases to 1, the hdr recovered pixel will
// blow out. Dont allow dark pixels to signal large gains.
gain = (std::min)(gain, 2.3f);
}
if (gain < -4.0)
{
// dump log...
}
return gain;
} Below is a dump of the sdr and hdr values when gain < -4 or gain > 4 occurred at the end of the computeGain function. gain < -4
gain > 4
|
This was my thinking while computing gainmap coefficients,
If y_hdr is 0 nits, this expression evaluates to -inf. This will restrict an accurate computation of min content boost. To overcome its better to modify the expression as,
The computation if (sdr == 0.0f) return 0.0f; is only partially correct. This handles the most trivial case. Consider the scenario where the input given for encoding is yuv. During gainmap computation this yuv input is converted to rgb using yuv to rgb color space conversion equations. These rgb values are not yet rounded to the nearest integer between 0 - 255. Their values are float values between 0 - 255. Consider this value, 1/1024 as the response after doing color space conversion. This value would later be represented as 0 during sdr encoding. Corresponding to this pixel, lets say we have a hdr source whose value is 0.1. Now gainmap is computed as log2(0.1 * 1024) = 22.19. The same sdr source say after compression and decompression process, the pixel that was 1/1024 which maps to 0 at the source say got flipped to 1 (possible due to dct - quantization and dequantization - idct process, a 1024 fold increase), then after the applyGainMap, this pixel will blow up. In other words, smaller the sdr / darker the sdr pixel, higher the effects of gainmap coefficient to quantization errors. It's best to limit the gainmap coefficient for dark pixels. How dark? Our concern arises if 0 value is becoming 1. Values less than 1/255 are at risk. For safety I would like to restrict the gain for pixels with values < 2/255.
You can always tune these. The kOffsets that are used in the gainmap computation should not be significant in comparison with the domain of sdr/hdr. Larger values like 1 can reduce the spread of gainmap min and max, but it will seriously undermine the ability to recover the original signal. |
These computations are further clamped here,
As I mentioned, these can always be tuned, but we thought this excursion should allow a user to represent black from white and viceversa. Although such color/tone shifts wont occur between hdr and sdr renditions of a image, as part of mathematical operations we allowed it. If your requirements dont need it, then you can pass capacity max and min via command line arguments. |
Added an offset kComputeGainOffset to the computeGain function to prevent excessive gain in low-luminance regions for both SDR and HDR calculations. This adjustment helps stabilize gain computation.
Simulation
gain_offset.xlsx
The kComputeGainOffset prevents gain spikes in low-luminance regions, but as a side effect, it reduces HDR luminance. This effect is simulated in the attached XLSX file.
Test
The hlg.raw file is attached as hlg.zip.
The sdr.rgba file is attached as sdr.zip.
Result