Util.java revision 1efb18228a45952d699af280482e1c51a4582690
1101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin/*
2101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * Copyright (C) 2009 The Android Open Source Project
3101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin *
4101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * Licensed under the Apache License, Version 2.0 (the "License");
5101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * you may not use this file except in compliance with the License.
6101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * You may obtain a copy of the License at
7101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin *
8101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin *      http://www.apache.org/licenses/LICENSE-2.0
9101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin *
10101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * Unless required by applicable law or agreed to in writing, software
11101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * distributed under the License is distributed on an "AS IS" BASIS,
12101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * See the License for the specific language governing permissions and
14101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * limitations under the License.
15101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin */
16101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin
17937fc48b37fafe3ffc8f4b52bd9a171bbb4d3a37Owen Linpackage com.android.camera;
18101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin
191efb18228a45952d699af280482e1c51a4582690Owen Linimport com.android.camera.gallery.IImage;
201efb18228a45952d699af280482e1c51a4582690Owen Lin
213f3c857e3f34650c15d764810335024654b0fcc3Owen Linimport android.app.Activity;
223f3c857e3f34650c15d764810335024654b0fcc3Owen Linimport android.app.AlertDialog;
233f3c857e3f34650c15d764810335024654b0fcc3Owen Linimport android.content.DialogInterface;
24101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport android.graphics.Bitmap;
25101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport android.graphics.BitmapFactory;
26101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport android.graphics.Matrix;
276227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatraimport android.hardware.Camera.Size;
28101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport android.util.Log;
296227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatraimport android.view.Display;
30ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Changimport android.view.Surface;
31601ce56b034f111b2875e7636776f2f359f6a156Owen Linimport android.view.View;
322c6c6174e2363fccb4e4f29b76290e99234fe140Owen Linimport android.view.animation.Animation;
332c6c6174e2363fccb4e4f29b76290e99234fe140Owen Linimport android.view.animation.TranslateAnimation;
34101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin
35101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport java.io.Closeable;
361efb18228a45952d699af280482e1c51a4582690Owen Linimport java.util.List;
37101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin
38101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin/**
39101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * Collection of utility functions used in this package.
40101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin */
41101d528d59f447847d5c6b7578642132c2b76f4fOwen Linpublic class Util {
4234fe2a9d33a5b4ce49862ce4558a36c62ba6d540Chih-Chung Chang    private static final String TAG = "Util";
432c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin    public static final int DIRECTION_LEFT = 0;
442c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin    public static final int DIRECTION_RIGHT = 1;
452c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin    public static final int DIRECTION_UP = 2;
462c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin    public static final int DIRECTION_DOWN = 3;
47101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin
481efb18228a45952d699af280482e1c51a4582690Owen Lin    public static final String REVIEW_ACTION = "com.android.camera.action.REVIEW";
4935688439f40f00a1376dcfab6e6495989d82e433Wei-Ta Chen
50101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin    private Util() {
51101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin    }
52101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin
53101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin    // Rotates the bitmap by the specified degree.
54101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin    // If a new bitmap is created, the original bitmap is recycled.
55101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin    public static Bitmap rotate(Bitmap b, int degrees) {
56101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin        if (degrees != 0 && b != null) {
57101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin            Matrix m = new Matrix();
58101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin            m.setRotate(degrees,
59101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin                    (float) b.getWidth() / 2, (float) b.getHeight() / 2);
60101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin            try {
61101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin                Bitmap b2 = Bitmap.createBitmap(
62101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin                        b, 0, 0, b.getWidth(), b.getHeight(), m, true);
63101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin                if (b != b2) {
64101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin                    b.recycle();
65101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin                    b = b2;
66101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin                }
67101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin            } catch (OutOfMemoryError ex) {
68101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin                // We have no memory to rotate. Return the original bitmap.
69101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin            }
70101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin        }
71101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin        return b;
72101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin    }
73101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin
74101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin    /*
75ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang     * Compute the sample size as a function of minSideLength
76ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang     * and maxNumOfPixels.
773c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen     * minSideLength is used to specify that minimal width or height of a
783c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen     * bitmap.
793c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen     * maxNumOfPixels is used to specify the maximal size in pixels that is
803c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen     * tolerable in terms of memory usage.
81ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang     *
82ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang     * The function returns a sample size based on the constraints.
83ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang     * Both size and minSideLength can be passed in as IImage.UNCONSTRAINED,
84ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang     * which indicates no care of the corresponding constraint.
85ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang     * The functions prefers returning a sample size that
86ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang     * generates a smaller bitmap, unless minSideLength = IImage.UNCONSTRAINED.
873c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen     *
883c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen     * Also, the function rounds up the sample size to a power of 2 or multiple
893c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen     * of 8 because BitmapFactory only honors sample size this way.
903c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen     * For example, BitmapFactory downsamples an image by 2 even though the
913c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen     * request is 3. So we round up the sample size to avoid OOM.
92101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin     */
93ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang    public static int computeSampleSize(BitmapFactory.Options options,
94ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang            int minSideLength, int maxNumOfPixels) {
953c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen        int initialSize = computeInitialSampleSize(options, minSideLength,
963c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen                maxNumOfPixels);
973c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen
983c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen        int roundedSize;
99522e836abc90bcb2d4e7a4ac37e269154d06c715Chih-Chung Chang        if (initialSize <= 8) {
1003c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen            roundedSize = 1;
1013c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen            while (roundedSize < initialSize) {
1023c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen                roundedSize <<= 1;
1033c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen            }
1043c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen        } else {
1053c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen            roundedSize = (initialSize + 7) / 8 * 8;
1063c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen        }
1073c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen
1083c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen        return roundedSize;
1093c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen    }
1103c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen
1113c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen    private static int computeInitialSampleSize(BitmapFactory.Options options,
1123c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen            int minSideLength, int maxNumOfPixels) {
113ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang        double w = options.outWidth;
114ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang        double h = options.outHeight;
115ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang
116ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang        int lowerBound = (maxNumOfPixels == IImage.UNCONSTRAINED) ? 1 :
117ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang                (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
118ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang        int upperBound = (minSideLength == IImage.UNCONSTRAINED) ? 128 :
119ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang                (int) Math.min(Math.floor(w / minSideLength),
120ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang                Math.floor(h / minSideLength));
121ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang
122f2c7e983fafaf7639a6ad090a93d1892015777edWei-Ta Chen        if (upperBound < lowerBound) {
123f2c7e983fafaf7639a6ad090a93d1892015777edWei-Ta Chen            // return the larger one when there is no overlapping zone.
124f2c7e983fafaf7639a6ad090a93d1892015777edWei-Ta Chen            return lowerBound;
125f2c7e983fafaf7639a6ad090a93d1892015777edWei-Ta Chen        }
126f2c7e983fafaf7639a6ad090a93d1892015777edWei-Ta Chen
127ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang        if ((maxNumOfPixels == IImage.UNCONSTRAINED) &&
128ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang                (minSideLength == IImage.UNCONSTRAINED)) {
129ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang            return 1;
130ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang        } else if (minSideLength == IImage.UNCONSTRAINED) {
131ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang            return lowerBound;
132ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang        } else {
133ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang            return upperBound;
134101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin        }
135101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin    }
136101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin
137bbc2f2f15a865cf0330cd78a6ea67177c5863b3bOwen Lin    public static <T>  int indexOf(T [] array, T s) {
138101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin        for (int i = 0; i < array.length; i++) {
139101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin            if (array[i].equals(s)) {
140101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin                return i;
141101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin            }
142101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin        }
143101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin        return -1;
144101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin    }
145101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin
146724e9b3db93677b753c1267a716e30e6cf5ff3b6Chih-Chung Chang    public static void closeSilently(Closeable c) {
147101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin        if (c == null) return;
148101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin        try {
149101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin            c.close();
150101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin        } catch (Throwable t) {
151101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin            // do nothing
152101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin        }
153101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin    }
154101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin
155cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang    public static Bitmap makeBitmap(byte[] jpegData, int maxNumOfPixels) {
156cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang        try {
157cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang            BitmapFactory.Options options = new BitmapFactory.Options();
158cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang            options.inJustDecodeBounds = true;
159cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang            BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length,
160cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang                    options);
161cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang            if (options.mCancel || options.outWidth == -1
162cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang                    || options.outHeight == -1) {
163cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang                return null;
164cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang            }
165cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang            options.inSampleSize = computeSampleSize(
166cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang                    options, IImage.UNCONSTRAINED, maxNumOfPixels);
167cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang            options.inJustDecodeBounds = false;
168cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang
169cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang            options.inDither = false;
170cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang            options.inPreferredConfig = Bitmap.Config.ARGB_8888;
171cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang            return BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length,
172cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang                    options);
173cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang        } catch (OutOfMemoryError ex) {
174cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang            Log.e(TAG, "Got oom exception ", ex);
175cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang            return null;
176cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang        }
177c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang    }
178c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang
179341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang    public static void Assert(boolean cond) {
180341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang        if (!cond) {
181341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang            throw new AssertionError();
182341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang        }
183341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang    }
184059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin
1853f3c857e3f34650c15d764810335024654b0fcc3Owen Lin    public static void showFatalErrorAndFinish(
1863f3c857e3f34650c15d764810335024654b0fcc3Owen Lin            final Activity activity, String title, String message) {
1873f3c857e3f34650c15d764810335024654b0fcc3Owen Lin        DialogInterface.OnClickListener buttonListener =
1883f3c857e3f34650c15d764810335024654b0fcc3Owen Lin                new DialogInterface.OnClickListener() {
1893f3c857e3f34650c15d764810335024654b0fcc3Owen Lin            public void onClick(DialogInterface dialog, int which) {
1903f3c857e3f34650c15d764810335024654b0fcc3Owen Lin                activity.finish();
1913f3c857e3f34650c15d764810335024654b0fcc3Owen Lin            }
1923f3c857e3f34650c15d764810335024654b0fcc3Owen Lin        };
1933f3c857e3f34650c15d764810335024654b0fcc3Owen Lin        new AlertDialog.Builder(activity)
1943f3c857e3f34650c15d764810335024654b0fcc3Owen Lin                .setCancelable(false)
1953f3c857e3f34650c15d764810335024654b0fcc3Owen Lin                .setIcon(android.R.drawable.ic_dialog_alert)
1963f3c857e3f34650c15d764810335024654b0fcc3Owen Lin                .setTitle(title)
1973f3c857e3f34650c15d764810335024654b0fcc3Owen Lin                .setMessage(message)
1983f3c857e3f34650c15d764810335024654b0fcc3Owen Lin                .setNeutralButton(R.string.details_ok, buttonListener)
1993f3c857e3f34650c15d764810335024654b0fcc3Owen Lin                .show();
2003f3c857e3f34650c15d764810335024654b0fcc3Owen Lin    }
2012c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin
202c1f2e3021bf7b12f2a33561e09bd0ab32530382eOwen Lin    public static Animation slideOut(View view, int to) {
2032c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin        view.setVisibility(View.INVISIBLE);
2042c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin        Animation anim;
2052c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin        switch (to) {
2062c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin            case DIRECTION_LEFT:
2072c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin                anim = new TranslateAnimation(0, -view.getWidth(), 0, 0);
2082c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin                break;
2092c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin            case DIRECTION_RIGHT:
2102c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin                anim = new TranslateAnimation(0, view.getWidth(), 0, 0);
2112c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin                break;
2122c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin            case DIRECTION_UP:
2132c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin                anim = new TranslateAnimation(0, 0, 0, -view.getHeight());
2142c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin                break;
2152c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin            case DIRECTION_DOWN:
2162c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin                anim = new TranslateAnimation(0, 0, 0, view.getHeight());
2172c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin                break;
2182c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin            default:
2192c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin                throw new IllegalArgumentException(Integer.toString(to));
2202c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin        }
2212c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin        anim.setDuration(500);
2222c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin        view.startAnimation(anim);
223c1f2e3021bf7b12f2a33561e09bd0ab32530382eOwen Lin        return anim;
2242c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin    }
2252c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin
226c1f2e3021bf7b12f2a33561e09bd0ab32530382eOwen Lin    public static Animation slideIn(View view, int from) {
2272c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin        view.setVisibility(View.VISIBLE);
2282c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin        Animation anim;
2292c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin        switch (from) {
2302c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin            case DIRECTION_LEFT:
2312c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin                anim = new TranslateAnimation(-view.getWidth(), 0, 0, 0);
2322c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin                break;
2332c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin            case DIRECTION_RIGHT:
2342c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin                anim = new TranslateAnimation(view.getWidth(), 0, 0, 0);
2352c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin                break;
2362c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin            case DIRECTION_UP:
2372c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin                anim = new TranslateAnimation(0, 0, -view.getHeight(), 0);
2382c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin                break;
2392c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin            case DIRECTION_DOWN:
2402c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin                anim = new TranslateAnimation(0, 0, view.getHeight(), 0);
2412c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin                break;
2422c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin            default:
2432c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin                throw new IllegalArgumentException(Integer.toString(from));
2442c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin        }
2452c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin        anim.setDuration(500);
2462c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin        view.startAnimation(anim);
247c1f2e3021bf7b12f2a33561e09bd0ab32530382eOwen Lin        return anim;
2482c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin    }
24973e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin
25073e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin    public static <T> T checkNotNull(T object) {
25173e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin        if (object == null) throw new NullPointerException();
25273e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin        return object;
25373e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin    }
25473e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin
25573e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin    public static boolean equals(Object a, Object b) {
25673e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin        return (a == b) || (a == null ? false : a.equals(b));
25773e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin    }
2584de149ceb47f2c251f646419907424bfb67d2b64Owen Lin
2594de149ceb47f2c251f646419907424bfb67d2b64Owen Lin    public static boolean isPowerOf2(int n) {
2604de149ceb47f2c251f646419907424bfb67d2b64Owen Lin        return (n & -n) == n;
2614de149ceb47f2c251f646419907424bfb67d2b64Owen Lin    }
2624de149ceb47f2c251f646419907424bfb67d2b64Owen Lin
2634de149ceb47f2c251f646419907424bfb67d2b64Owen Lin    public static int nextPowerOf2(int n) {
2644de149ceb47f2c251f646419907424bfb67d2b64Owen Lin        n -= 1;
2654de149ceb47f2c251f646419907424bfb67d2b64Owen Lin        n |= n >>> 16;
2664de149ceb47f2c251f646419907424bfb67d2b64Owen Lin        n |= n >>> 8;
2674de149ceb47f2c251f646419907424bfb67d2b64Owen Lin        n |= n >>> 4;
2684de149ceb47f2c251f646419907424bfb67d2b64Owen Lin        n |= n >>> 2;
2694de149ceb47f2c251f646419907424bfb67d2b64Owen Lin        n |= n >>> 1;
2704de149ceb47f2c251f646419907424bfb67d2b64Owen Lin        return n + 1;
2714de149ceb47f2c251f646419907424bfb67d2b64Owen Lin    }
27233be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin
27333be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin    public static float distance(float x, float y, float sx, float sy) {
27433be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin        float dx = x - sx;
27533be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin        float dy = y - sy;
27633be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin        return (float) Math.sqrt(dx * dx + dy * dy);
27733be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin    }
27833be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin
27933be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin    public static int clamp(int x, int min, int max) {
28033be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin        if (x > max) return max;
28133be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin        if (x < min) return min;
28233be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin        return x;
28333be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin    }
284ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang
2854aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li    public static int getDisplayRotation(Activity activity) {
286ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang        int rotation = activity.getWindowManager().getDefaultDisplay()
287ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang                .getRotation();
288ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang        switch (rotation) {
2894aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li            case Surface.ROTATION_0: return 0;
2904aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li            case Surface.ROTATION_90: return 90;
2914aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li            case Surface.ROTATION_180: return 180;
2924aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li            case Surface.ROTATION_270: return 270;
293ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang        }
2944aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li        return 0;
2954aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li    }
296ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang
2974aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li    public static void setCameraDisplayOrientation(Activity activity,
2984aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li            int cameraId, android.hardware.Camera camera) {
2994aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li        android.hardware.Camera.CameraInfo info =
3004aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li                new android.hardware.Camera.CameraInfo();
3014aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li        android.hardware.Camera.getCameraInfo(cameraId, info);
3024aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li        int degrees = getDisplayRotation(activity);
303c97d23826a28dd725951eccb62651244f9fb8228Wu-cheng Li        int result = (info.orientation - degrees + 360) % 360;
304ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang        camera.setDisplayOrientation(result);
305ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang    }
3066227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra
3076227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra    public static Size getOptimalPreviewSize(Activity currentActivity,
3086227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra            List<Size> sizes, double targetRatio) {
3096227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra        final double ASPECT_TOLERANCE = 0.05;
3106227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra        if (sizes == null) return null;
3116227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra
3126227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra        Size optimalSize = null;
3136227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra        double minDiff = Double.MAX_VALUE;
3146227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra
3156227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra        // Because of bugs of overlay and layout, we sometimes will try to
3166227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra        // layout the viewfinder in the portrait orientation and thus get the
3176227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra        // wrong size of mSurfaceView. When we change the preview size, the
3186227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra        // new overlay will be created before the old one closed, which causes
3196227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra        // an exception. For now, just get the screen size
3206227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra
3216227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra        Display display = currentActivity.getWindowManager().getDefaultDisplay();
3226227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra        int targetHeight = Math.min(display.getHeight(), display.getWidth());
3236227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra
3246227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra        if (targetHeight <= 0) {
3256227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra            // We don't know the size of SurfaceView, use screen height
3266227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra            targetHeight = display.getHeight();
3276227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra        }
3286227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra
3296227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra        // Try to find an size match aspect ratio and size
3306227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra        for (Size size : sizes) {
3316227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra            double ratio = (double) size.width / size.height;
3326227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
3336227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra            if (Math.abs(size.height - targetHeight) < minDiff) {
3346227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra                optimalSize = size;
3356227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra                minDiff = Math.abs(size.height - targetHeight);
3366227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra            }
3376227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra        }
3386227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra
3396227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra        // Cannot find the one match the aspect ratio, ignore the requirement
3406227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra        if (optimalSize == null) {
3416227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra            Log.v(TAG, "No preview size match the aspect ratio");
3426227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra            minDiff = Double.MAX_VALUE;
3436227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra            for (Size size : sizes) {
3446227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra                if (Math.abs(size.height - targetHeight) < minDiff) {
3456227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra                    optimalSize = size;
3466227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra                    minDiff = Math.abs(size.height - targetHeight);
3476227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra                }
3486227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra            }
3496227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra        }
3506227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra        return optimalSize;
3516227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra    }
352101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin}
353