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
37 float CubicBezier::mControPointX1 = CONTROL_POINT_X1;
38 float CubicBezier::mControPointX2 = CONTROL_POINT_X2;
39 float CubicBezier::mControPointY1 = CONTROL_POINT_Y1;
40 float CubicBezier::mControPointY2 = CONTROL_POINT_Y2;
41 float CubicBezier::mDurationBase = DURATION_BASE;
42
GetZoomArray(const float & currentZoom,const float & targetZoom,const float & frameInterval)43 std::vector<float> CubicBezier::GetZoomArray(const float& currentZoom, const float& targetZoom,
44 const float& frameInterval)
45 {
46 float duration = GetDuration(currentZoom, targetZoom);
47 MEDIA_INFO_LOG("CubicBezier::GetZoomArray duration is:%{public}f", duration);
48 std::vector<float> result;
49 CHECK_RETURN_RET(duration == 0 || frameInterval == 0, result);
50 int arraySize = static_cast<int>(duration / frameInterval);
51 CHECK_RETURN_RET_ELOG(arraySize > MAX_ZOOM_ARRAY_SIZE, result,
52 "Error size, duration is:%{public}f, interval is:%{public}f", duration, frameInterval);
53 for (int i = 1; i <= arraySize; i++) {
54 float time = frameInterval * i / duration;
55 float zoom = (currentZoom + (targetZoom - currentZoom) * GetInterpolation(time));
56 result.push_back(zoom);
57 MEDIA_DEBUG_LOG("CubicBezier::GetZoomArray zoom is:%{public}f", zoom);
58 }
59 result.push_back(targetZoom);
60 return result;
61 }
62
GetDuration(const float & currentZoom,const float & targetZoom)63 float CubicBezier::GetDuration(const float& currentZoom, const float& targetZoom)
64 {
65 if (currentZoom == 0) {
66 return 0;
67 } else {
68 return (DURATION_SLOP * DURATION_POWER * abs(log(targetZoom / currentZoom)) + mDurationBase);
69 }
70 }
71
SetBezierValue(const std::vector<float> & zoomBezierValue)72 bool CubicBezier::SetBezierValue(const std::vector<float>& zoomBezierValue)
73 {
74 const size_t DURATION_BASE_INDEX = 0;
75 const size_t CONTROL_POINT_X1_INDEX = 1;
76 const size_t CONTROL_POINT_Y1_INDEX = 2;
77 const size_t CONTROL_POINT_X2_INDEX = 3;
78 const size_t CONTROL_POINT_Y2_INDEX = 4;
79
80 mDurationBase = zoomBezierValue[DURATION_BASE_INDEX];
81 mControPointX1 = zoomBezierValue[CONTROL_POINT_X1_INDEX];
82 mControPointY1 = zoomBezierValue[CONTROL_POINT_Y1_INDEX];
83 mControPointX2 = zoomBezierValue[CONTROL_POINT_X2_INDEX];
84 mControPointY2 = zoomBezierValue[CONTROL_POINT_Y2_INDEX];
85 return true;
86 }
87
GetCubicBezierY(const float & time)88 float CubicBezier::GetCubicBezierY(const float& time)
89 {
90 return CUBIC_BEZIER_MULTIPLE * (1- time) * (1 - time) * time * mControPointY1 +
91 CUBIC_BEZIER_MULTIPLE * (1- time) * time * time * mControPointY2 + time * time * time;
92 }
93
GetCubicBezierX(const float & time)94 float CubicBezier::GetCubicBezierX(const float& time)
95 {
96 return CUBIC_BEZIER_MULTIPLE * (1- time) * (1 - time) * time * mControPointX1 +
97 CUBIC_BEZIER_MULTIPLE * (1- time) * time * time * mControPointX2 + time * time * time;
98 }
99
BinarySearch(const float & value)100 float CubicBezier::BinarySearch(const float& value)
101 {
102 int low = 0;
103 int high = MAX_RESOLUTION;
104 int num = 0;
105 while (low <= high) {
106 num = num + 1;
107 int middle = (low + high) / 2;
108 float approximation = GetCubicBezierX(SERCH_STEP * middle);
109 if (approximation < value) {
110 low = middle + 1;
111 } else if (approximation > value) {
112 high = middle -1;
113 } else {
114 return middle;
115 }
116 }
117 return low;
118 }
119
GetInterpolation(const float & input)120 float CubicBezier::GetInterpolation(const float& input)
121 {
122 return GetCubicBezierY(SERCH_STEP * BinarySearch(input));
123 }
124 } // namespace CameraStandard
125 } // namespace OHOS