1a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling/*
2a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling * Copyright (C) 2014 The Android Open Source Project
3a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling *
4a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling * Licensed under the Apache License, Version 2.0 (the "License");
5a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling * you may not use this file except in compliance with the License.
6a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling * You may obtain a copy of the License at
7a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling *
8a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling *      http://www.apache.org/licenses/LICENSE-2.0
9a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling *
10a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling * Unless required by applicable law or agreed to in writing, software
11a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling * distributed under the License is distributed on an "AS IS" BASIS,
12a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling * See the License for the specific language governing permissions and
14a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling * limitations under the License.
15a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling */
16a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling
17a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberlingpackage com.android.camera;
18a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling
19a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberlingimport android.content.Context;
20a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberlingimport android.content.res.Configuration;
21a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberlingimport android.view.Surface;
22a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling
23a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberlingimport com.android.camera.debug.Log;
24a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberlingimport com.android.camera.debug.Log.Tag;
25a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberlingimport com.android.camera.util.CameraUtil;
26e3dfd5a433e39d76578b379fe1539864cf924ceeSascha Haeberlingimport com.android.camera.util.Size;
27a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling
28a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberlingimport java.util.ArrayList;
29a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling
30a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling/**
31a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling * Common utility methods used in capture modules.
32a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling */
33a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberlingpublic class CaptureModuleUtil {
34a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling    private static final Tag TAG = new Tag("CaptureModuleUtil");
35a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling
36a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling    public static int getDeviceNaturalOrientation(Context context) {
37a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        Configuration config = context.getResources().getConfiguration();
38a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        int rotation = CameraUtil.getDisplayRotation(context);
39a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling
40a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        if (((rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) &&
41a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling                config.orientation == Configuration.ORIENTATION_LANDSCAPE) ||
42a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling                ((rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) &&
43a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling                config.orientation == Configuration.ORIENTATION_PORTRAIT)) {
44a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling            return Configuration.ORIENTATION_LANDSCAPE;
45a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        } else {
46a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling            return Configuration.ORIENTATION_PORTRAIT;
47a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        }
48a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling    }
49a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling
50a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling    /**
51a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling     * Equivalent to the
52a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling     * {@link CameraUtil#getOptimalPreviewSize(android.content.Context, java.util.List, double)}
53a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling     * method for the camera1 api.
54a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling     */
55a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling    public static Size getOptimalPreviewSize(Context context, Size[] sizes,
56a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling            double targetRatio) {
57a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        // TODO(andyhuibers): Don't hardcode this but use device's measurements.
58a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        final int MAX_ASPECT_HEIGHT = 1080;
59a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling
60a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        // Count sizes with height <= 1080p to mimic camera1 api behavior.
61a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        int count = 0;
62a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        for (Size s : sizes) {
63a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling            if (s.getHeight() <= MAX_ASPECT_HEIGHT) {
64a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling                count++;
65a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling            }
66a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        }
67f2627903d11faf47c5052884bc2b23e27b8d5f94Sascha Haeberling        ArrayList<Size> camera1Sizes = new ArrayList<Size>(count);
68a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling
69a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        // Set array of all sizes with height <= 1080p
70a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        for (Size s : sizes) {
71a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling            if (s.getHeight() <= MAX_ASPECT_HEIGHT) {
72f2627903d11faf47c5052884bc2b23e27b8d5f94Sascha Haeberling                camera1Sizes.add(new Size(s.getWidth(), s.getHeight()));
73a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling            }
74a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        }
75a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling
76a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        int optimalIndex = CameraUtil
77a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling                .getOptimalPreviewSizeIndex(context, camera1Sizes, targetRatio);
78a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling
79a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        if (optimalIndex == -1) {
80a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling            return null;
81a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        }
82a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling
83f2627903d11faf47c5052884bc2b23e27b8d5f94Sascha Haeberling        Size optimal = camera1Sizes.get(optimalIndex);
84a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        for (Size s : sizes) {
85f2627903d11faf47c5052884bc2b23e27b8d5f94Sascha Haeberling            if (s.getWidth() == optimal.getWidth() && s.getHeight() == optimal.getHeight()) {
86a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling                return s;
87a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling            }
88a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        }
89a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        return null;
90a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling    }
91a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling
92a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling    /**
93a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling     * Selects the preview buffer dimensions that are closest in size to the
94a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling     * size of the view containing the preview.
95a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling     */
96a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling    public static Size pickBufferDimensions(Size[] supportedPreviewSizes,
97a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling            double bestPreviewAspectRatio,
98a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling            Context context) {
99a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        // Swap dimensions if the device is not in its natural orientation.
100a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        boolean swapDimens = (CameraUtil.getDisplayRotation(context) % 180) == 90;
101a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        // Swap dimensions if the device's natural orientation doesn't match
102a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        // the sensor orientation.
103a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        if (CaptureModuleUtil.getDeviceNaturalOrientation(context)
104a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling                == Configuration.ORIENTATION_PORTRAIT) {
105a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling            swapDimens = !swapDimens;
106a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        }
107a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        double bestAspect = bestPreviewAspectRatio;
108a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        if (swapDimens) {
109a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling            bestAspect = 1 / bestAspect;
110a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        }
111a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling
112a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        Size pick = CaptureModuleUtil.getOptimalPreviewSize(context, supportedPreviewSizes,
113a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling                bestPreviewAspectRatio);
114a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        Log.d(TAG, "Picked buffer size: " + pick.toString());
115a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling        return pick;
116a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling    }
117a5c41b83304218f05a6454bf40fc6d236c218338Sascha Haeberling}
118