1 /*
2  * Copyright (c) 2021-2022 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 
16 #include "camera_log.h"
17 #include "cubic_bezier.h"
18 
19 namespace OHOS {
20 namespace CameraStandard {
21 namespace {
22 constexpr float CUBIC_BEZIER_MULTIPLE = 3.0;
23 constexpr float MAX_RESOLUTION = 4000.0;
24 constexpr float SERCH_STEP = 1.0 / MAX_RESOLUTION;
25 
26 constexpr float CONTROL_POINT_X1 = 0.4;
27 constexpr float CONTROL_POINT_X2 = 0.2;
28 constexpr float CONTROL_POINT_Y1 = 0.0;
29 constexpr float CONTROL_POINT_Y2 = 1.0;
30 
31 constexpr float DURATION_SLOP = 55.0;
32 constexpr float DURATION_BASE = 450.0;
33 constexpr float DURATION_POWER = 1.2;
34 constexpr int MAX_ZOOM_ARRAY_SIZE = 100;
35 }
36 
GetZoomArray(const float & currentZoom,const float & targetZoom,const float & frameInterval)37 std::vector<float> CubicBezier::GetZoomArray(const float& currentZoom, const float& targetZoom,
38     const float& frameInterval)
39 {
40     float duration = GetDuration(currentZoom, targetZoom);
41     MEDIA_INFO_LOG("CubicBezier::GetZoomArray duration is:%{public}f", duration);
42     std::vector<float> result;
43     CHECK_ERROR_RETURN_RET(duration == 0 || frameInterval == 0, result);
44     int arraySize = static_cast<int>(duration / frameInterval);
45     CHECK_ERROR_RETURN_RET_LOG(arraySize > MAX_ZOOM_ARRAY_SIZE, result,
46         "Error size, duration is:%{public}f, interval is:%{public}f", duration, frameInterval);
47     for (int i = 1; i <= arraySize; i++) {
48         float time = frameInterval * i / duration;
49         float zoom = (currentZoom + (targetZoom - currentZoom) * GetInterpolation(time));
50         result.push_back(zoom);
51         MEDIA_DEBUG_LOG("CubicBezier::GetZoomArray zoom is:%{public}f", zoom);
52     }
53     result.push_back(targetZoom);
54     return result;
55 }
56 
GetDuration(const float & currentZoom,const float & targetZoom)57 float CubicBezier::GetDuration(const float& currentZoom, const float& targetZoom)
58 {
59     if (currentZoom == 0) {
60         return 0;
61     } else {
62         return (DURATION_SLOP * DURATION_POWER * abs(log(targetZoom / currentZoom)) + DURATION_BASE);
63     }
64 }
65 
GetCubicBezierY(const float & time)66 float CubicBezier::GetCubicBezierY(const float& time)
67 {
68     return CUBIC_BEZIER_MULTIPLE * (1- time) * (1 - time) * time * CONTROL_POINT_Y1 +
69         CUBIC_BEZIER_MULTIPLE * (1- time) * time * time * CONTROL_POINT_Y2 + time * time * time;
70 }
71 
GetCubicBezierX(const float & time)72 float CubicBezier::GetCubicBezierX(const float& time)
73 {
74     return CUBIC_BEZIER_MULTIPLE * (1- time) * (1 - time) * time * CONTROL_POINT_X1 +
75         CUBIC_BEZIER_MULTIPLE * (1- time) * time * time * CONTROL_POINT_X2 + time * time * time;
76 }
77 
BinarySearch(const float & value)78 float CubicBezier::BinarySearch(const float& value)
79 {
80     int low = 0;
81     int high = MAX_RESOLUTION;
82     int num = 0;
83     while (low <= high) {
84         num = num + 1;
85         int middle = (low + high) / 2;
86         float approximation = GetCubicBezierX(SERCH_STEP * middle);
87         if (approximation < value) {
88             low = middle + 1;
89         } else if (approximation > value) {
90             high = middle -1;
91         } else {
92             return middle;
93         }
94     }
95     return low;
96 }
97 
GetInterpolation(const float & input)98 float CubicBezier::GetInterpolation(const float& input)
99 {
100     return GetCubicBezierY(SERCH_STEP * BinarySearch(input));
101 }
102 } // namespace CameraStandard
103 } // namespace OHOS