Skip to content
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

Allow for larger excursions of min, max content boost #215

Merged
merged 1 commit into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 28 additions & 14 deletions examples/ultrahdr_app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,17 +244,20 @@ static bool writeFile(const char* filename, uhdr_raw_image_t* img) {

class UltraHdrAppInput {
public:
UltraHdrAppInput(
const char* hdrIntentRawFile, const char* sdrIntentRawFile,
const char* sdrIntentCompressedFile, const char* gainmapCompressedFile,
const char* gainmapMetadataCfgFile, const char* exifFile, const char* outputFile,
size_t width, size_t height, uhdr_img_fmt_t hdrCf = UHDR_IMG_FMT_32bppRGBA1010102,
uhdr_img_fmt_t sdrCf = UHDR_IMG_FMT_32bppRGBA8888,
uhdr_color_gamut_t hdrCg = UHDR_CG_DISPLAY_P3, uhdr_color_gamut_t sdrCg = UHDR_CG_BT_709,
uhdr_color_transfer_t hdrTf = UHDR_CT_HLG, int quality = 95,
uhdr_color_transfer_t oTf = UHDR_CT_HLG, uhdr_img_fmt_t oFmt = UHDR_IMG_FMT_32bppRGBA1010102,
bool isHdrCrFull = false, int gainmapScaleFactor = 4, int gainmapQuality = 85,
bool enableMultiChannelGainMap = false, float gamma = 1.0f, bool enableGLES = false)
UltraHdrAppInput(const char* hdrIntentRawFile, const char* sdrIntentRawFile,
const char* sdrIntentCompressedFile, const char* gainmapCompressedFile,
const char* gainmapMetadataCfgFile, const char* exifFile, const char* outputFile,
size_t width, size_t height,
uhdr_img_fmt_t hdrCf = UHDR_IMG_FMT_32bppRGBA1010102,
uhdr_img_fmt_t sdrCf = UHDR_IMG_FMT_32bppRGBA8888,
uhdr_color_gamut_t hdrCg = UHDR_CG_DISPLAY_P3,
uhdr_color_gamut_t sdrCg = UHDR_CG_BT_709,
uhdr_color_transfer_t hdrTf = UHDR_CT_HLG, int quality = 95,
uhdr_color_transfer_t oTf = UHDR_CT_HLG,
uhdr_img_fmt_t oFmt = UHDR_IMG_FMT_32bppRGBA1010102, bool isHdrCrFull = false,
int gainmapScaleFactor = 4, int gainmapQuality = 85,
bool enableMultiChannelGainMap = false, float gamma = 1.0f,
bool enableGLES = false, uhdr_enc_preset_t encPreset = UHDR_USAGE_REALTIME)
: mHdrIntentRawFile(hdrIntentRawFile),
mSdrIntentRawFile(sdrIntentRawFile),
mSdrIntentCompressedFile(sdrIntentCompressedFile),
Expand All @@ -279,6 +282,7 @@ class UltraHdrAppInput {
mUseMultiChannelGainMap(enableMultiChannelGainMap),
mGamma(gamma),
mEnableGLES(enableGLES),
mEncPreset(encPreset),
mMode(0){};

UltraHdrAppInput(const char* gainmapMetadataCfgFile, const char* uhdrFile, const char* outputFile,
Expand Down Expand Up @@ -308,6 +312,7 @@ class UltraHdrAppInput {
mUseMultiChannelGainMap(false),
mGamma(1.0f),
mEnableGLES(enableGLES),
mEncPreset(UHDR_USAGE_REALTIME),
mMode(1){};

~UltraHdrAppInput() {
Expand Down Expand Up @@ -387,6 +392,7 @@ class UltraHdrAppInput {
const bool mUseMultiChannelGainMap;
const float mGamma;
const bool mEnableGLES;
const uhdr_enc_preset_t mEncPreset;
const int mMode;

uhdr_raw_image_t mRawP010Image{};
Expand Down Expand Up @@ -683,6 +689,7 @@ bool UltraHdrAppInput::encode() {
RET_IF_ERR(uhdr_enc_set_using_multi_channel_gainmap(handle, mUseMultiChannelGainMap))
RET_IF_ERR(uhdr_enc_set_gainmap_scale_factor(handle, mMapDimensionScaleFactor))
RET_IF_ERR(uhdr_enc_set_gainmap_gamma(handle, mGamma))
RET_IF_ERR(uhdr_enc_set_preset(handle, mEncPreset))
if (mEnableGLES) {
RET_IF_ERR(uhdr_enable_gpu_acceleration(handle, mEnableGLES))
}
Expand Down Expand Up @@ -1348,6 +1355,9 @@ static void usage(const char* name) {
"real number (1.0 : default)].\n");
fprintf(stderr,
" -M select multi channel gain map, optional. [0:disable (default), 1:enable]. \n");
fprintf(
stderr,
" -D select encoding preset, optional. [0:real time (default), 1:best quality]. \n");
fprintf(stderr, " -x binary input resource containing exif data to insert, optional. \n");
fprintf(stderr, "\n## decoder options : \n");
fprintf(stderr, " -j ultra hdr compressed input resource, required. \n");
Expand Down Expand Up @@ -1425,7 +1435,7 @@ static void usage(const char* name) {
fprintf(stderr, "\n## encode at high quality :\n");
fprintf(stderr,
" ultrahdr_app -m 0 -p hdr_intent.raw -y sdr_intent.raw -w 640 -h 480 -c <select> -C "
"<select> -t <select> -s 1 -M 1 -Q 98 -q 98\n");
"<select> -t <select> -s 1 -M 1 -Q 98 -q 98 -D 1\n");

fprintf(stderr, "\n## decode api :\n");
fprintf(stderr, " ultrahdr_app -m 1 -j cosmat_1920x1080_hdr.jpg \n");
Expand All @@ -1435,7 +1445,7 @@ static void usage(const char* name) {
}

int main(int argc, char* argv[]) {
char opt_string[] = "p:y:i:g:f:w:h:C:c:t:q:o:O:m:j:e:a:b:z:R:s:M:Q:G:x:u:";
char opt_string[] = "p:y:i:g:f:w:h:C:c:t:q:o:O:m:j:e:a:b:z:R:s:M:Q:G:x:u:D:";
char *hdr_intent_raw_file = nullptr, *sdr_intent_raw_file = nullptr, *uhdr_file = nullptr,
*sdr_intent_compressed_file = nullptr, *gainmap_compressed_file = nullptr,
*gainmap_metadata_cfg_file = nullptr, *output_file = nullptr, *exif_file = nullptr;
Expand All @@ -1456,6 +1466,7 @@ int main(int argc, char* argv[]) {
int compute_psnr = 0;
float gamma = 1.0f;
bool enable_gles = false;
uhdr_enc_preset_t enc_preset = UHDR_USAGE_REALTIME;
int ch;
while ((ch = getopt_s(argc, argv, opt_string)) != -1) {
switch (ch) {
Expand Down Expand Up @@ -1541,6 +1552,9 @@ int main(int argc, char* argv[]) {
case 'u':
enable_gles = atoi(optarg_s) == 1 ? true : false;
break;
case 'D':
enc_preset = static_cast<uhdr_enc_preset_t>(atoi(optarg_s));
break;
default:
usage(argv[0]);
return -1;
Expand Down Expand Up @@ -1568,7 +1582,7 @@ int main(int argc, char* argv[]) {
gainmap_compressed_file, gainmap_metadata_cfg_file, exif_file,
output_file ? output_file : "out.jpeg", width, height, hdr_cf, sdr_cf, hdr_cg, sdr_cg,
hdr_tf, quality, out_tf, out_cf, use_full_range_color_hdr, gainmap_scale_factor,
gainmap_compression_quality, use_multi_channel_gainmap, gamma, enable_gles);
gainmap_compression_quality, use_multi_channel_gainmap, gamma, enable_gles, enc_preset);
if (!appInput.encode()) return -1;
if (compute_psnr == 1) {
if (!appInput.decode()) return -1;
Expand Down
4 changes: 4 additions & 0 deletions fuzzer/ultrahdr_enc_fuzzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ void UltraHdrEncFuzzer::process() {
// gainmap scale factor
auto gm_scale_factor = mFdp.ConsumeIntegralInRange<int>(1, 128);

// encoding speed preset
auto enc_preset = static_cast<uhdr_enc_preset_t>(mFdp.ConsumeIntegralInRange<int>(0, 1));

std::unique_ptr<uint32_t[]> bufferHdr = nullptr;
std::unique_ptr<uint16_t[]> bufferYHdr = nullptr;
std::unique_ptr<uint16_t[]> bufferUVHdr = nullptr;
Expand Down Expand Up @@ -265,6 +268,7 @@ void UltraHdrEncFuzzer::process() {
ON_ERR(uhdr_enc_set_quality(enc_handle, gainmap_quality, UHDR_GAIN_MAP_IMG))
ON_ERR(uhdr_enc_set_gainmap_scale_factor(enc_handle, gm_scale_factor))
ON_ERR(uhdr_enc_set_using_multi_channel_gainmap(enc_handle, multi_channel_gainmap))
ON_ERR(uhdr_enc_set_preset(enc_handle, enc_preset))

uhdr_error_info_t status = {UHDR_CODEC_OK, 0, ""};
if (muxSwitch == 0 || muxSwitch == 1) { // api 0 or api 1
Expand Down
18 changes: 4 additions & 14 deletions lib/include/ultrahdr/gainmapmath.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ struct GainLUT {

GainLUT(uhdr_gainmap_metadata_ext_t* metadata, float displayBoost) {
this->mGammaInv = 1.0f / metadata->gamma;
float boostFactor = displayBoost > 0 ? displayBoost / metadata->max_content_boost : 1.0f;
float boostFactor = displayBoost > 0 ? displayBoost / metadata->hdr_capacity_max : 1.0f;
for (int32_t idx = 0; idx < kGainFactorNumEntries; idx++) {
float value = static_cast<float>(idx) / static_cast<float>(kGainFactorNumEntries - 1);
float logBoost = log2(metadata->min_content_boost) * (1.0f - value) +
Expand Down Expand Up @@ -540,23 +540,17 @@ void transformYuv444(uhdr_raw_image_t* image, const std::array<float, 9>& coeffs

/*
* Calculate the 8-bit unsigned integer gain value for the given SDR and HDR
* luminances in linear space, and the hdr ratio to encode against.
*
* Note: since this library always uses gamma of 1.0, offsetSdr of 0.0, and
* offsetHdr of 0.0, this function doesn't handle different metadata values for
* these fields.
* luminances in linear space and gainmap metadata fields.
*/
uint8_t encodeGain(float y_sdr, float y_hdr, uhdr_gainmap_metadata_ext_t* metadata);
uint8_t encodeGain(float y_sdr, float y_hdr, uhdr_gainmap_metadata_ext_t* metadata,
float log2MinContentBoost, float log2MaxContentBoost);
float computeGain(float sdr, float hdr);
uint8_t affineMapGain(float gainlog2, float mingainlog2, float maxgainlog2, float gamma);

/*
* Calculates the linear luminance in nits after applying the given gain
* value, with the given hdr ratio, to the given sdr input in the range [0, 1].
*
* Note: similar to encodeGain(), this function only supports gamma 1.0,
* offsetSdr 0.0, offsetHdr 0.0, hdrCapacityMin 1.0, and hdrCapacityMax equal to
* gainMapMax, as this library encodes.
*/
Color applyGain(Color e, float gain, uhdr_gainmap_metadata_ext_t* metadata);
Color applyGain(Color e, float gain, uhdr_gainmap_metadata_ext_t* metadata, float displayBoost);
Expand All @@ -565,10 +559,6 @@ Color applyGainLUT(Color e, float gain, GainLUT& gainLUT);
/*
* Apply gain in R, G and B channels, with the given hdr ratio, to the given sdr input
* in the range [0, 1].
*
* Note: similar to encodeGain(), this function only supports gamma 1.0,
* offsetSdr 0.0, offsetHdr 0.0, hdrCapacityMin 1.0, and hdrCapacityMax equal to
* gainMapMax, as this library encodes.
*/
Color applyGain(Color e, Color gain, uhdr_gainmap_metadata_ext_t* metadata);
Color applyGain(Color e, Color gain, uhdr_gainmap_metadata_ext_t* metadata, float displayBoost);
Expand Down
3 changes: 2 additions & 1 deletion lib/include/ultrahdr/jpegr.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ class JpegR {
size_t mapDimensionScaleFactor = kMapDimensionScaleFactorDefault,
int mapCompressQuality = kMapCompressQualityDefault,
bool useMultiChannelGainMap = kUseMultiChannelGainMapDefault,
float gamma = kGainMapGammaDefault);
float gamma = kGainMapGammaDefault, uhdr_enc_preset_t preset = UHDR_USAGE_REALTIME);

/*!\brief Encode API-0.
*
Expand Down Expand Up @@ -571,6 +571,7 @@ class JpegR {
int mMapCompressQuality; // gain map quality factor
bool mUseMultiChannelGainMap; // enable multichannel gain map
float mGamma; // gain map gamma parameter
uhdr_enc_preset_t mEncPreset; // encoding speed preset
};

struct GlobalTonemapOutputs {
Expand Down
1 change: 1 addition & 0 deletions lib/include/ultrahdr/ultrahdrcommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ struct uhdr_encoder_private : uhdr_codec_private {
int m_gainmap_scale_factor;
bool m_use_multi_channel_gainmap;
float m_gamma;
uhdr_enc_preset_t m_enc_preset;

// internal data
std::unique_ptr<ultrahdr::uhdr_compressed_image_ext_t> m_compressed_output_buffer;
Expand Down
26 changes: 21 additions & 5 deletions lib/src/gainmapmath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ SamplePixelFn getSamplePixelFn(uhdr_img_fmt_t format) {
float getMaxDisplayMasteringLuminance(uhdr_color_transfer_t transfer) {
switch (transfer) {
case UHDR_CT_LINEAR:
// TODO: configure maxCLL correctly for linear tf
// TODO: configure MDML correctly for linear tf
return kHlgMaxNits;
case UHDR_CT_HLG:
return kHlgMaxNits;
Expand Down Expand Up @@ -647,6 +647,22 @@ uint8_t encodeGain(float y_sdr, float y_hdr, uhdr_gainmap_metadata_ext_t* metada
return static_cast<uint8_t>(gain_normalized_gamma * 255.0f);
}

float computeGain(float sdr, float hdr) {
if (sdr == 0.0f) return 0.0f; // for sdr black return no gain
if (hdr == 0.0f) { // for hdr black, return a gain large enough to attenuate the sdr pel
float offset = (1.0f / 64);
return log2(offset / (offset + sdr));
}
return log2(hdr / sdr);
}

uint8_t affineMapGain(float gainlog2, float mingainlog2, float maxgainlog2, float gamma) {
float mappedVal = (gainlog2 - mingainlog2) / (maxgainlog2 - mingainlog2);
if (gamma != 1.0f) mappedVal = pow(mappedVal, gamma);
mappedVal *= 255;
return CLIP3(mappedVal + 0.5f, 0, 255);
}

Color applyGain(Color e, float gain, uhdr_gainmap_metadata_ext_t* metadata) {
gain = pow(gain, 1.0f / metadata->gamma);
float logBoost =
Expand All @@ -659,7 +675,7 @@ Color applyGain(Color e, float gain, uhdr_gainmap_metadata_ext_t* metadata, floa
gain = pow(gain, 1.0f / metadata->gamma);
float logBoost =
log2(metadata->min_content_boost) * (1.0f - gain) + log2(metadata->max_content_boost) * gain;
float gainFactor = exp2(logBoost * displayBoost / metadata->max_content_boost);
float gainFactor = exp2(logBoost * displayBoost / metadata->hdr_capacity_max);
return e * gainFactor;
}

Expand Down Expand Up @@ -694,9 +710,9 @@ Color applyGain(Color e, Color gain, uhdr_gainmap_metadata_ext_t* metadata, floa
log2(metadata->max_content_boost) * gain.g;
float logBoostB = log2(metadata->min_content_boost) * (1.0f - gain.b) +
log2(metadata->max_content_boost) * gain.b;
float gainFactorR = exp2(logBoostR * displayBoost / metadata->max_content_boost);
float gainFactorG = exp2(logBoostG * displayBoost / metadata->max_content_boost);
float gainFactorB = exp2(logBoostB * displayBoost / metadata->max_content_boost);
float gainFactorR = exp2(logBoostR * displayBoost / metadata->hdr_capacity_max);
float gainFactorG = exp2(logBoostG * displayBoost / metadata->hdr_capacity_max);
float gainFactorB = exp2(logBoostB * displayBoost / metadata->hdr_capacity_max);
return {{{e.r * gainFactorR, e.g * gainFactorG, e.b * gainFactorB}}};
}

Expand Down
Loading