1 /*
2  * Copyright (C) 2014 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 com.android.camera;
18 
19 import android.app.Activity;
20 import android.content.Context;
21 import android.content.res.Configuration;
22 import android.view.Surface;
23 
24 import com.android.camera.debug.Log;
25 import com.android.camera.debug.Log.Tag;
26 import com.android.camera.util.CameraUtil;
27 import com.android.camera.util.Size;
28 
29 import java.util.ArrayList;
30 
31 /**
32  * Common utility methods used in capture modules.
33  */
34 public class CaptureModuleUtil {
35     private static final Tag TAG = new Tag("CaptureModuleUtil");
36 
getDeviceNaturalOrientation(Activity context)37     public static int getDeviceNaturalOrientation(Activity context) {
38         Configuration config = context.getResources().getConfiguration();
39         int rotation = CameraUtil.getDisplayRotation(context);
40 
41         if (((rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) &&
42                 config.orientation == Configuration.ORIENTATION_LANDSCAPE) ||
43                 ((rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) &&
44                 config.orientation == Configuration.ORIENTATION_PORTRAIT)) {
45             return Configuration.ORIENTATION_LANDSCAPE;
46         } else {
47             return Configuration.ORIENTATION_PORTRAIT;
48         }
49     }
50 
51     /**
52      * Equivalent to the
53      * {@link CameraUtil#getOptimalPreviewSize(java.util.List, double)}
54      * method for the camera1 api.
55      */
getOptimalPreviewSize(Size[] sizes, double targetRatio, Activity context)56     public static Size getOptimalPreviewSize(Size[] sizes, double targetRatio, Activity context) {
57         return getOptimalPreviewSize(sizes, targetRatio, null, context);
58     }
59 
60     /**
61      * Returns the best preview size based on the current display resolution,
62      * the available preview sizes, the target aspect ratio (typically the
63      * aspect ratio of the picture to be taken) as well as a maximum allowed
64      * tolerance. If tolerance is 'null', a default tolerance will be used.
65      */
getOptimalPreviewSize(Size[] sizes, double targetRatio, Double aspectRatioTolerance, Activity context)66     public static Size getOptimalPreviewSize(Size[] sizes,
67             double targetRatio, Double aspectRatioTolerance, Activity context) {
68         // TODO(andyhuibers): Don't hardcode this but use device's measurements.
69         final int MAX_ASPECT_HEIGHT = 1080;
70 
71         // Count sizes with height <= 1080p to mimic camera1 api behavior.
72         int count = 0;
73         for (Size s : sizes) {
74             if (s.getHeight() <= MAX_ASPECT_HEIGHT) {
75                 count++;
76             }
77         }
78         ArrayList<Size> camera1Sizes = new ArrayList<Size>(count);
79 
80         // Set array of all sizes with height <= 1080p
81         for (Size s : sizes) {
82             if (s.getHeight() <= MAX_ASPECT_HEIGHT) {
83                 camera1Sizes.add(new Size(s.getWidth(), s.getHeight()));
84             }
85         }
86 
87         int optimalIndex = CameraUtil
88                 .getOptimalPreviewSizeIndex(camera1Sizes, targetRatio,
89                         aspectRatioTolerance, context);
90 
91         if (optimalIndex == -1) {
92             return null;
93         }
94 
95         Size optimal = camera1Sizes.get(optimalIndex);
96         for (Size s : sizes) {
97             if (s.getWidth() == optimal.getWidth() && s.getHeight() == optimal.getHeight()) {
98                 return s;
99             }
100         }
101         return null;
102     }
103 
104     /**
105      * Selects the preview buffer dimensions that are closest in size to the
106      * size of the view containing the preview.
107      */
pickBufferDimensions(Size[] supportedPreviewSizes, double bestPreviewAspectRatio, Activity context)108     public static Size pickBufferDimensions(Size[] supportedPreviewSizes,
109             double bestPreviewAspectRatio,
110             Activity context) {
111         // Swap dimensions if the device is not in its natural orientation.
112         boolean swapDimens = (CameraUtil.getDisplayRotation(context) % 180) == 90;
113         // Swap dimensions if the device's natural orientation doesn't match
114         // the sensor orientation.
115         if (CaptureModuleUtil.getDeviceNaturalOrientation(context)
116                 == Configuration.ORIENTATION_PORTRAIT) {
117             swapDimens = !swapDimens;
118         }
119         double bestAspect = bestPreviewAspectRatio;
120         if (swapDimens) {
121             bestAspect = 1 / bestAspect;
122         }
123 
124         Size pick = CaptureModuleUtil.getOptimalPreviewSize(supportedPreviewSizes,
125                 bestPreviewAspectRatio, null, context);
126         Log.d(TAG, "Picked buffer size: " + pick.toString());
127         return pick;
128     }
129 }
130