• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "ge_tone_mapping_helper.h"
16 
17 #include <algorithm>
18 #include <mutex>
19 
20 #include "ge_edge_light_shader_filter.h"
21 #include "ge_log.h"
22 
23 namespace OHOS {
24 namespace Rosen {
25 
26 namespace {
27 // Bezier curves describing tone mapping rule, anchors define
28 const std::vector<Vector2f> g_hdrCurveAnchors = {
29     {0.0f, 0.0f}, {0.75f, 0.75f}, {1.0f, 0.95f}, {1.25f, 0.97f},
30     {1.5f, 0.98f}, {1.75f, 0.9875f}, {1.90f, 0.995f}, {2.0f, 1.0f},
31 };
32 
33 // Bezier curves describing tone mapping rule, control points define
34 const std::vector<Vector2f> g_hdrCurveControlPoint = {
35     {0.375f, 0.375f}, {0.875f, 0.875f}, {1.125f, 0.9625f}, {1.375f, 0.9725f},
36     {1.625f, 0.98f}, {1.825f, 0.99f}, {1.95f, 0.998f},  // 1 less than anchors
37 };
38 
39 constexpr float SDR_LUMINANCE = 1.0f;
40 }  // namespace
41 
GetBrightnessMapping(float headroom,Vector4f & input)42 Vector4f GEToneMappingHelper::GetBrightnessMapping(float headroom, Vector4f& input)
43 {
44     float highValue = std::max({input.x_, input.y_, input.z_, SDR_LUMINANCE});
45     float compressRatio = GetBrightnessMapping(headroom, highValue) / highValue;
46     Vector4f output;
47     output.x_ = input.x_ * compressRatio;
48     output.y_ = input.y_ * compressRatio;
49     output.z_ = input.z_ * compressRatio;
50     output.w_ = input.w_;
51     return output;
52 }
53 
GetBrightnessMapping(float headroom,float input)54 float GEToneMappingHelper::GetBrightnessMapping(float headroom, float input)
55 {
56     if (ROSEN_GE(headroom, EFFECT_MAX_LUMINANCE)) {
57         return input;
58     }
59     int rangeIndex = -1;
60     for (auto point : g_hdrCurveAnchors) {
61         if (input <= point.x_) {
62             break;
63         }
64         rangeIndex++;
65     }
66     if (rangeIndex == -1) {
67         return 0.0f;
68     }
69     if ((rangeIndex >= static_cast<int>(g_hdrCurveAnchors.size()) - 1) ||
70         (rangeIndex >= static_cast<int>(g_hdrCurveControlPoint.size()))) {
71         return headroom;
72     }
73 
74     // calculate new hdr bightness via bezier curve
75     Vector2f start = g_hdrCurveAnchors[rangeIndex];
76     Vector2f end = g_hdrCurveAnchors[rangeIndex + 1];
77     Vector2f control = g_hdrCurveControlPoint[rangeIndex];
78 
79     float y = 0.0f;
80     if (CalcBezierResultY(start, end, control, input, y)) {
81         y = ((EFFECT_MAX_LUMINANCE - headroom) * y + (headroom - SDR_LUMINANCE) * input) /
82             (EFFECT_MAX_LUMINANCE - SDR_LUMINANCE);  // linear interpolation
83         LOGD("GEToneMappingHelper::GetBrightnessMapping y is %{public}f", y);
84         return std::clamp(y, 0.0f, headroom);
85     }
86     return std::clamp(input, 0.0f, headroom);
87 }
88 
GetBrightnessMapping(float brightness,Drawing::Color4f & input)89 Drawing::Color4f GEToneMappingHelper::GetBrightnessMapping(float brightness, Drawing::Color4f& input)
90 {
91     float highValue = std::max({input.redF_, input.greenF_, input.blueF_, SDR_LUMINANCE});
92     float compressRatio = GetBrightnessMapping(brightness, highValue) / highValue;
93     Drawing::Color4f output;
94     output.redF_ = input.redF_ * compressRatio;
95     output.greenF_ = input.greenF_ * compressRatio;
96     output.blueF_ = input.blueF_ * compressRatio;
97     output.alphaF_ = input.alphaF_;
98     return output;
99 }
100 
CalcBezierResultY(const Vector2f & start,const Vector2f & end,const Vector2f & control,float x,float & y)101 bool GEToneMappingHelper::CalcBezierResultY(
102     const Vector2f& start, const Vector2f& end, const Vector2f& control, float x, float& y)
103 {
104     const float a = start[0] - 2 * control[0] + end[0];
105     const float b = 2 * (control[0] - start[0]);
106     const float c = start[0] - x;
107     const float discriminant = b * b - 4 * a * c;
108 
109     float t = 0.0f;
110     if (ROSEN_LNE(discriminant, 0.0f)) {
111         return false;
112     } else if (ROSEN_EQ(a, 0.0f)) {
113         t = -c / b;
114     } else {
115         const float sqrtD = std::sqrt(discriminant);
116         const float t1 = (-b + sqrtD) / (2.0 * a);
117         const float t2 = (-b - sqrtD) / (2.0 * a);
118         if (ROSEN_GE(t1, 0.0f) && ROSEN_LE(t1, 1.0f)) {
119             t = t1;
120         } else if (ROSEN_GE(t2, 0.0f) && ROSEN_LE(t2, 1.0f)) {
121             t = t2;
122         }
123     }
124 
125     y = start[1] + t * (2.0f * (control[1] - start[1]) + t * (start[1] - 2.0f * control[1] + end[1]));
126     return true;
127 }
128 
129 } // Rosen
130 } // OHOS
131