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