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