From: mirsfang@gmail.com To: ffmpeg-devel@ffmpeg.org Cc: mirs <fangpengcheng@bilibili.com> Subject: [FFmpeg-devel] [PATCH v1 1/1] avfilter/vf_tonemap: add herimte tone mapping Date: Thu, 8 Sep 2022 20:41:44 +0800 Message-ID: <20220908124143.86053-1-mirsfang@gmail.com> (raw) From: mirs <fangpengcheng@bilibili.com> Signed-off-by: mirs <fangpengcheng@bilibili.com> add tonemapping hermite,this looks close real hdr display --- libavfilter/vf_tonemap.c | 65 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/libavfilter/vf_tonemap.c b/libavfilter/vf_tonemap.c index d1087e6bd9..3fb2bdfa2c 100644 --- a/libavfilter/vf_tonemap.c +++ b/libavfilter/vf_tonemap.c @@ -48,6 +48,7 @@ enum TonemapAlgorithm { TONEMAP_REINHARD, TONEMAP_HABLE, TONEMAP_MOBIUS, + TONEMAP_HERMITE, TONEMAP_MAX, }; @@ -106,6 +107,66 @@ static float mobius(float in, float j, double peak) return (b * b + 2.0f * b * j + j * j) / (b - a) * (in + a) / (in + b); } +static float hermite(float in) { + /* + * in theory, max mastering lumi 、max content lumi frome packet side data, + * display max lumi from Display system value,current value is R-REP-BT.2390 max value + */ + float max_mastering_lumi = 1000.0f; + float max_content_lumi = 1000.0f; + float display_max_lumi = 400.0f; // Terminal domain 400NITS is the maximum lumen of a normal screen + + float max_in_lumi = FFMAX(max_mastering_lumi,max_content_lumi); + float max_out_lumi = display_max_lumi; + float nits = in * (display_max_lumi / max_mastering_lumi); + + // clamp + if (nits < 0) { + nits = 0.0; + } else if (nits > max_in_lumi) { + nits = max_in_lumi; + } + + if (max_in_lumi <= max_out_lumi) { + nits *= max_out_lumi / max_in_lumi; + } else { + // three control points + const float x0 = 10.0f; + const float y0 = 17.0; + float x1 = max_out_lumi * 0.75; + float y1 = x1; + float x2 = x1 + (max_in_lumi - x1) / 2.0; + float y2 = y1 + (max_out_lumi - y1) * 0.75; + // horizontal distances between the last three control points + float h12 = x2 - x1; + float h23 = max_in_lumi - x2; + // tangents at the last three control points + float m1 = (y2 - y1) / h12; + float m3 = (max_out_lumi - y2) / h23; + float m2 = (m1 + m3) / 2.0; + + if (nits < x0) { + // scale [0.0, x0] to [0.0, y0] linearly + float slope = y0 / x0; + nits *= slope; + } else if (nits < x1) { + // scale [x0, x1] to [y0, y1] linearly + float slope = (y1 - y0) / (x1 - x0); + nits = y0 + (nits - x0) * slope; + } else if (nits < x2) { + // scale [x1, x2] to [y1, y2] using Hermite interp + float t = (nits - x1) / h12; + nits = (y1 * (1.0 + 2.0 * t) + h12 * m1 * t) * (1.0 - t) * (1.0 - t) +(y2 * (3.0 - 2.0 * t) + h12 * m2 * (t - 1.0)) * t * t; + } else { + // scale [x2, maxInLumi] to [y2, maxOutLumi] using Hermite interp + float t = (nits - x2) / h23; + nits = (y2 * (1.0 + 2.0 * t) + h23 * m2 * t) * (1.0 - t) * (1.0 - t) +(max_out_lumi * (3.0 - 2.0 * t) + h23 * m3 * (t - 1.0)) * t * t; + } + } + + return nits; +} + #define MIX(x,y,a) (x) * (1 - (a)) + (y) * (a) static void tonemap(TonemapContext *s, AVFrame *out, const AVFrame *in, const AVPixFmtDescriptor *desc, int x, int y, double peak) @@ -163,6 +224,9 @@ static void tonemap(TonemapContext *s, AVFrame *out, const AVFrame *in, case TONEMAP_MOBIUS: sig = mobius(sig, s->param, peak); break; + case TONEMAP_HERMITE: + sig = hermite(sig); + break; } /* apply the computed scale factor to the color, @@ -291,6 +355,7 @@ static const AVOption tonemap_options[] = { { "reinhard", 0, 0, AV_OPT_TYPE_CONST, {.i64 = TONEMAP_REINHARD}, 0, 0, FLAGS, "tonemap" }, { "hable", 0, 0, AV_OPT_TYPE_CONST, {.i64 = TONEMAP_HABLE}, 0, 0, FLAGS, "tonemap" }, { "mobius", 0, 0, AV_OPT_TYPE_CONST, {.i64 = TONEMAP_MOBIUS}, 0, 0, FLAGS, "tonemap" }, + { "hermite", 0, 0, AV_OPT_TYPE_CONST, {.i64 = TONEMAP_HERMITE}, 0, 0, FLAGS, "tonemap" }, { "param", "tonemap parameter", OFFSET(param), AV_OPT_TYPE_DOUBLE, {.dbl = NAN}, DBL_MIN, DBL_MAX, FLAGS }, { "desat", "desaturation strength", OFFSET(desat), AV_OPT_TYPE_DOUBLE, {.dbl = 2}, 0, DBL_MAX, FLAGS }, { "peak", "signal peak override", OFFSET(peak), AV_OPT_TYPE_DOUBLE, {.dbl = 0}, 0, DBL_MAX, FLAGS }, -- 2.32.1 (Apple Git-133) _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
next reply other threads:[~2022-09-08 12:42 UTC|newest] Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top 2022-09-08 12:41 mirsfang [this message] 2022-09-08 13:04 ` mirs fang 2022-09-08 13:22 mirsfang
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20220908124143.86053-1-mirsfang@gmail.com \ --to=mirsfang@gmail.com \ --cc=fangpengcheng@bilibili.com \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git