1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.camera.core.impl.utils;
18 
19 import android.view.Surface;
20 
21 import androidx.camera.core.Logger;
22 import androidx.camera.core.impl.ImageOutputConfig.RotationValue;
23 
24 /**
25  * Contains utility methods related to camera orientation.
26  */
27 public final class CameraOrientationUtil {
28     private static final String TAG = "CameraOrientationUtil";
29 
30     // Do not allow instantiation
CameraOrientationUtil()31     private CameraOrientationUtil() {
32     }
33 
34     /**
35      * Calculates the delta between a source rotation and destination rotation.
36      *
37      * <p>A typical use of this method would be calculating the angular difference between the
38      * display orientation (destRotationDegrees) and camera sensor orientation
39      * (sourceRotationDegrees).
40      *
41      * @param destRotationDegrees   The destination rotation relative to the device's natural
42      *                              rotation.
43      * @param sourceRotationDegrees The source rotation relative to the device's natural rotation.
44      * @param isOppositeFacing      Whether the source and destination planes are facing opposite
45      *                              directions.
46      */
getRelativeImageRotation( int destRotationDegrees, int sourceRotationDegrees, boolean isOppositeFacing)47     public static int getRelativeImageRotation(
48             int destRotationDegrees, int sourceRotationDegrees, boolean isOppositeFacing) {
49         int result;
50         if (isOppositeFacing) {
51             result = (sourceRotationDegrees - destRotationDegrees + 360) % 360;
52         } else {
53             result = (sourceRotationDegrees + destRotationDegrees) % 360;
54         }
55         if (Logger.isVerboseEnabled(TAG)) {
56             Logger.d(
57                     TAG,
58                     String.format(
59                             "getRelativeImageRotation: destRotationDegrees=%s, "
60                                     + "sourceRotationDegrees=%s, isOppositeFacing=%s, "
61                                     + "result=%s",
62                             destRotationDegrees, sourceRotationDegrees, isOppositeFacing, result));
63         }
64         return result;
65     }
66 
67     /**
68      * Converts rotation constant values defined in {@link Surface} to their equivalent in
69      * degrees.
70      *
71      * <p>Valid values for the relative rotation are {@link Surface#ROTATION_0}, {@link
72      * Surface#ROTATION_90}, {@link Surface#ROTATION_180}, {@link Surface#ROTATION_270}.
73      *
74      * @param rotation One of the rotation constant values from {@link Surface}.
75      * @return The equivalent rotation value in degrees.
76      * @throws IllegalArgumentException If the provided rotation value is not one of those
77      * defined in {@link Surface}.
78      */
surfaceRotationToDegrees(@otationValue int rotation)79     public static int surfaceRotationToDegrees(@RotationValue int rotation) {
80         int rotationDegrees;
81         switch (rotation) {
82             case Surface.ROTATION_0:
83                 rotationDegrees = 0;
84                 break;
85             case Surface.ROTATION_90:
86                 rotationDegrees = 90;
87                 break;
88             case Surface.ROTATION_180:
89                 rotationDegrees = 180;
90                 break;
91             case Surface.ROTATION_270:
92                 rotationDegrees = 270;
93                 break;
94             default:
95                 throw new IllegalArgumentException("Unsupported surface rotation: " + rotation);
96         }
97 
98         return rotationDegrees;
99     }
100 
101     /**
102      * Converts rotation degrees to their equivalent in values defined in {@link Surface}.
103      *
104      * <p>Valid values for the relative rotation are {@link Surface#ROTATION_0}, {@link
105      * Surface#ROTATION_90}, {@link Surface#ROTATION_180}, {@link Surface#ROTATION_270}.
106      *
107      * @param degrees The rotation value in degrees.
108      * @return One of the constant rotation values defined in {@link Surface}.
109      * @throws IllegalArgumentException If the provided rotation degrees doesn't fall into any
110      *                                  one of those defined in {@link Surface}.
111      */
112     @RotationValue
degreesToSurfaceRotation(int degrees)113     public static int degreesToSurfaceRotation(int degrees) {
114         int surfaceRotation = Surface.ROTATION_0;
115         switch (degrees) {
116             case 0:
117                 surfaceRotation = Surface.ROTATION_0;
118                 break;
119             case 90:
120                 surfaceRotation = Surface.ROTATION_90;
121                 break;
122             case 180:
123                 surfaceRotation = Surface.ROTATION_180;
124                 break;
125             case 270:
126                 surfaceRotation = Surface.ROTATION_270;
127                 break;
128             default:
129                 throw new IllegalStateException("Invalid sensor rotation: " + degrees);
130         }
131 
132         return surfaceRotation;
133     }
134 }
135