Util.java revision 9cfab4bc18b8d9d905263c687e19c06df885dca7
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; 27c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Liimport android.hardware.Camera; 286227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatraimport android.hardware.Camera.Size; 29101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport android.util.Log; 306227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatraimport android.view.Display; 31ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Changimport android.view.Surface; 32601ce56b034f111b2875e7636776f2f359f6a156Owen Linimport android.view.View; 332c6c6174e2363fccb4e4f29b76290e99234fe140Owen Linimport android.view.animation.Animation; 342c6c6174e2363fccb4e4f29b76290e99234fe140Owen Linimport android.view.animation.TranslateAnimation; 35101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 36101d528d59f447847d5c6b7578642132c2b76f4fOwen Linimport java.io.Closeable; 371efb18228a45952d699af280482e1c51a4582690Owen Linimport java.util.List; 38101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 39101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin/** 40101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin * Collection of utility functions used in this package. 41101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin */ 42101d528d59f447847d5c6b7578642132c2b76f4fOwen Linpublic class Util { 4334fe2a9d33a5b4ce49862ce4558a36c62ba6d540Chih-Chung Chang private static final String TAG = "Util"; 442c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin public static final int DIRECTION_LEFT = 0; 452c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin public static final int DIRECTION_RIGHT = 1; 462c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin public static final int DIRECTION_UP = 2; 472c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin public static final int DIRECTION_DOWN = 3; 48101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 491efb18228a45952d699af280482e1c51a4582690Owen Lin public static final String REVIEW_ACTION = "com.android.camera.action.REVIEW"; 5035688439f40f00a1376dcfab6e6495989d82e433Wei-Ta Chen 51101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin private Util() { 52101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 53101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 54101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // Rotates the bitmap by the specified degree. 55101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // If a new bitmap is created, the original bitmap is recycled. 56101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin public static Bitmap rotate(Bitmap b, int degrees) { 579cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li return rotateAndMirror(b, degrees, false); 589cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li } 599cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li 609cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li // Rotates and/or mirrors the bitmap. If a new bitmap is created, the 619cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li // original bitmap is recycled. 629cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li public static Bitmap rotateAndMirror(Bitmap b, int degrees, boolean mirror) { 639cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li if ((degrees != 0 || mirror) && b != null) { 64101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Matrix m = new Matrix(); 65101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin m.setRotate(degrees, 66101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin (float) b.getWidth() / 2, (float) b.getHeight() / 2); 679cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li if (mirror) { 689cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li m.postScale(-1, 1); 699cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li degrees = (degrees + 360) % 360; 709cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li if (degrees == 0 || degrees == 180) { 719cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li m.postTranslate((float) b.getWidth(), 0); 729cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li } else if (degrees == 90 || degrees == 270) { 739cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li m.postTranslate((float) b.getHeight(), 0); 749cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li } else { 759cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li throw new IllegalArgumentException("Invalid degrees=" + degrees); 769cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li } 779cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li } 789cfab4bc18b8d9d905263c687e19c06df885dca7Wu-cheng Li 79101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin try { 80101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin Bitmap b2 = Bitmap.createBitmap( 81101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin b, 0, 0, b.getWidth(), b.getHeight(), m, true); 82101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (b != b2) { 83101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin b.recycle(); 84101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin b = b2; 85101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 86101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } catch (OutOfMemoryError ex) { 87101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // We have no memory to rotate. Return the original bitmap. 88101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 89101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 90101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return b; 91101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 92101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 93101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin /* 94ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang * Compute the sample size as a function of minSideLength 95ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang * and maxNumOfPixels. 963c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * minSideLength is used to specify that minimal width or height of a 973c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * bitmap. 983c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * maxNumOfPixels is used to specify the maximal size in pixels that is 993c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * tolerable in terms of memory usage. 100ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang * 101ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang * The function returns a sample size based on the constraints. 102ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang * Both size and minSideLength can be passed in as IImage.UNCONSTRAINED, 103ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang * which indicates no care of the corresponding constraint. 104ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang * The functions prefers returning a sample size that 105ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang * generates a smaller bitmap, unless minSideLength = IImage.UNCONSTRAINED. 1063c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * 1073c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * Also, the function rounds up the sample size to a power of 2 or multiple 1083c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * of 8 because BitmapFactory only honors sample size this way. 1093c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * For example, BitmapFactory downsamples an image by 2 even though the 1103c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen * request is 3. So we round up the sample size to avoid OOM. 111101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin */ 112ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang public static int computeSampleSize(BitmapFactory.Options options, 113ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang int minSideLength, int maxNumOfPixels) { 1143c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen int initialSize = computeInitialSampleSize(options, minSideLength, 1153c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen maxNumOfPixels); 1163c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen 1173c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen int roundedSize; 118522e836abc90bcb2d4e7a4ac37e269154d06c715Chih-Chung Chang if (initialSize <= 8) { 1193c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen roundedSize = 1; 1203c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen while (roundedSize < initialSize) { 1213c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen roundedSize <<= 1; 1223c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen } 1233c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen } else { 1243c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen roundedSize = (initialSize + 7) / 8 * 8; 1253c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen } 1263c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen 1273c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen return roundedSize; 1283c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen } 1293c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen 1303c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen private static int computeInitialSampleSize(BitmapFactory.Options options, 1313c21008c953cf6177f7771c176fa81d336e74ed8Wei-Ta Chen int minSideLength, int maxNumOfPixels) { 132ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang double w = options.outWidth; 133ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang double h = options.outHeight; 134ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang 135ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang int lowerBound = (maxNumOfPixels == IImage.UNCONSTRAINED) ? 1 : 136ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels)); 137ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang int upperBound = (minSideLength == IImage.UNCONSTRAINED) ? 128 : 138ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang (int) Math.min(Math.floor(w / minSideLength), 139ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang Math.floor(h / minSideLength)); 140ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang 141f2c7e983fafaf7639a6ad090a93d1892015777edWei-Ta Chen if (upperBound < lowerBound) { 142f2c7e983fafaf7639a6ad090a93d1892015777edWei-Ta Chen // return the larger one when there is no overlapping zone. 143f2c7e983fafaf7639a6ad090a93d1892015777edWei-Ta Chen return lowerBound; 144f2c7e983fafaf7639a6ad090a93d1892015777edWei-Ta Chen } 145f2c7e983fafaf7639a6ad090a93d1892015777edWei-Ta Chen 146ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang if ((maxNumOfPixels == IImage.UNCONSTRAINED) && 147ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang (minSideLength == IImage.UNCONSTRAINED)) { 148ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang return 1; 149ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang } else if (minSideLength == IImage.UNCONSTRAINED) { 150ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang return lowerBound; 151ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang } else { 152ce033a5871a0b678521411f9a3acaee2ab279178Chih-Chung Chang return upperBound; 153101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 154101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 155101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 156bbc2f2f15a865cf0330cd78a6ea67177c5863b3bOwen Lin public static <T> int indexOf(T [] array, T s) { 157101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin for (int i = 0; i < array.length; i++) { 158101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (array[i].equals(s)) { 159101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return i; 160101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 161101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 162101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin return -1; 163101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 164101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 165724e9b3db93677b753c1267a716e30e6cf5ff3b6Chih-Chung Chang public static void closeSilently(Closeable c) { 166101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin if (c == null) return; 167101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin try { 168101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin c.close(); 169101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } catch (Throwable t) { 170101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin // do nothing 171101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 172101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin } 173101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin 174cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang public static Bitmap makeBitmap(byte[] jpegData, int maxNumOfPixels) { 175cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang try { 176cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang BitmapFactory.Options options = new BitmapFactory.Options(); 177cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang options.inJustDecodeBounds = true; 178cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, 179cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang options); 180cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang if (options.mCancel || options.outWidth == -1 181cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang || options.outHeight == -1) { 182cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang return null; 183cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang } 184cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang options.inSampleSize = computeSampleSize( 185cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang options, IImage.UNCONSTRAINED, maxNumOfPixels); 186cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang options.inJustDecodeBounds = false; 187cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang 188cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang options.inDither = false; 189cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang options.inPreferredConfig = Bitmap.Config.ARGB_8888; 190cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang return BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, 191cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang options); 192cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang } catch (OutOfMemoryError ex) { 193cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang Log.e(TAG, "Got oom exception ", ex); 194cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang return null; 195cd972b0cd67d7a45084d9757ebd49b8f22989eddChih-Chung Chang } 196c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang } 197c1c20e9ce386c1f660059acaede591d2d718995aChih-Chung Chang 198341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang public static void Assert(boolean cond) { 199341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang if (!cond) { 200341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang throw new AssertionError(); 201341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang } 202341ad98e59d92769e1cc8ba68fa86c72dce0543bChih-Chung Chang } 203059daa36dc6e83ca24a16d9b99925e71010bccebOwen Lin 2043f3c857e3f34650c15d764810335024654b0fcc3Owen Lin public static void showFatalErrorAndFinish( 2053f3c857e3f34650c15d764810335024654b0fcc3Owen Lin final Activity activity, String title, String message) { 2063f3c857e3f34650c15d764810335024654b0fcc3Owen Lin DialogInterface.OnClickListener buttonListener = 2073f3c857e3f34650c15d764810335024654b0fcc3Owen Lin new DialogInterface.OnClickListener() { 2083f3c857e3f34650c15d764810335024654b0fcc3Owen Lin public void onClick(DialogInterface dialog, int which) { 2093f3c857e3f34650c15d764810335024654b0fcc3Owen Lin activity.finish(); 2103f3c857e3f34650c15d764810335024654b0fcc3Owen Lin } 2113f3c857e3f34650c15d764810335024654b0fcc3Owen Lin }; 2123f3c857e3f34650c15d764810335024654b0fcc3Owen Lin new AlertDialog.Builder(activity) 2133f3c857e3f34650c15d764810335024654b0fcc3Owen Lin .setCancelable(false) 2143f3c857e3f34650c15d764810335024654b0fcc3Owen Lin .setIcon(android.R.drawable.ic_dialog_alert) 2153f3c857e3f34650c15d764810335024654b0fcc3Owen Lin .setTitle(title) 2163f3c857e3f34650c15d764810335024654b0fcc3Owen Lin .setMessage(message) 2173f3c857e3f34650c15d764810335024654b0fcc3Owen Lin .setNeutralButton(R.string.details_ok, buttonListener) 2183f3c857e3f34650c15d764810335024654b0fcc3Owen Lin .show(); 2193f3c857e3f34650c15d764810335024654b0fcc3Owen Lin } 2202c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin 221c1f2e3021bf7b12f2a33561e09bd0ab32530382eOwen Lin public static Animation slideOut(View view, int to) { 2222c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin view.setVisibility(View.INVISIBLE); 2232c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin Animation anim; 2242c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin switch (to) { 2252c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin case DIRECTION_LEFT: 2262c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin anim = new TranslateAnimation(0, -view.getWidth(), 0, 0); 2272c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin break; 2282c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin case DIRECTION_RIGHT: 2292c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin anim = new TranslateAnimation(0, view.getWidth(), 0, 0); 2302c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin break; 2312c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin case DIRECTION_UP: 2322c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin anim = new TranslateAnimation(0, 0, 0, -view.getHeight()); 2332c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin break; 2342c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin case DIRECTION_DOWN: 2352c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin anim = new TranslateAnimation(0, 0, 0, view.getHeight()); 2362c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin break; 2372c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin default: 2382c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin throw new IllegalArgumentException(Integer.toString(to)); 2392c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin } 2402c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin anim.setDuration(500); 2412c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin view.startAnimation(anim); 242c1f2e3021bf7b12f2a33561e09bd0ab32530382eOwen Lin return anim; 2432c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin } 2442c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin 245c1f2e3021bf7b12f2a33561e09bd0ab32530382eOwen Lin public static Animation slideIn(View view, int from) { 2462c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin view.setVisibility(View.VISIBLE); 2472c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin Animation anim; 2482c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin switch (from) { 2492c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin case DIRECTION_LEFT: 2502c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin anim = new TranslateAnimation(-view.getWidth(), 0, 0, 0); 2512c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin break; 2522c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin case DIRECTION_RIGHT: 2532c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin anim = new TranslateAnimation(view.getWidth(), 0, 0, 0); 2542c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin break; 2552c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin case DIRECTION_UP: 2562c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin anim = new TranslateAnimation(0, 0, -view.getHeight(), 0); 2572c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin break; 2582c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin case DIRECTION_DOWN: 2592c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin anim = new TranslateAnimation(0, 0, view.getHeight(), 0); 2602c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin break; 2612c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin default: 2622c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin throw new IllegalArgumentException(Integer.toString(from)); 2632c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin } 2642c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin anim.setDuration(500); 2652c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin view.startAnimation(anim); 266c1f2e3021bf7b12f2a33561e09bd0ab32530382eOwen Lin return anim; 2672c6c6174e2363fccb4e4f29b76290e99234fe140Owen Lin } 26873e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin 26973e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin public static <T> T checkNotNull(T object) { 27073e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin if (object == null) throw new NullPointerException(); 27173e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin return object; 27273e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin } 27373e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin 27473e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin public static boolean equals(Object a, Object b) { 27573e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin return (a == b) || (a == null ? false : a.equals(b)); 27673e782de608cbe2ddffd75c055009ff2e208f78bOwen Lin } 2774de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 2784de149ceb47f2c251f646419907424bfb67d2b64Owen Lin public static boolean isPowerOf2(int n) { 2794de149ceb47f2c251f646419907424bfb67d2b64Owen Lin return (n & -n) == n; 2804de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 2814de149ceb47f2c251f646419907424bfb67d2b64Owen Lin 2824de149ceb47f2c251f646419907424bfb67d2b64Owen Lin public static int nextPowerOf2(int n) { 2834de149ceb47f2c251f646419907424bfb67d2b64Owen Lin n -= 1; 2844de149ceb47f2c251f646419907424bfb67d2b64Owen Lin n |= n >>> 16; 2854de149ceb47f2c251f646419907424bfb67d2b64Owen Lin n |= n >>> 8; 2864de149ceb47f2c251f646419907424bfb67d2b64Owen Lin n |= n >>> 4; 2874de149ceb47f2c251f646419907424bfb67d2b64Owen Lin n |= n >>> 2; 2884de149ceb47f2c251f646419907424bfb67d2b64Owen Lin n |= n >>> 1; 2894de149ceb47f2c251f646419907424bfb67d2b64Owen Lin return n + 1; 2904de149ceb47f2c251f646419907424bfb67d2b64Owen Lin } 29133be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin 29233be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin public static float distance(float x, float y, float sx, float sy) { 29333be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin float dx = x - sx; 29433be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin float dy = y - sy; 29533be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin return (float) Math.sqrt(dx * dx + dy * dy); 29633be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin } 29733be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin 29833be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin public static int clamp(int x, int min, int max) { 29933be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin if (x > max) return max; 30033be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin if (x < min) return min; 30133be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin return x; 30233be45a1abaf6a8d611fb87b18945c84ab76c229Owen Lin } 303ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang 3044aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li public static int getDisplayRotation(Activity activity) { 305ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang int rotation = activity.getWindowManager().getDefaultDisplay() 306ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang .getRotation(); 307ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang switch (rotation) { 3084aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li case Surface.ROTATION_0: return 0; 3094aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li case Surface.ROTATION_90: return 90; 3104aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li case Surface.ROTATION_180: return 180; 3114aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li case Surface.ROTATION_270: return 270; 312ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang } 3134aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li return 0; 3144aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li } 315ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang 3164aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li public static void setCameraDisplayOrientation(Activity activity, 317c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li int cameraId, Camera camera) { 318c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li // See android.hardware.Camera.setCameraDisplayOrientation for 319c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li // documentation. 320c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li Camera.CameraInfo info = new Camera.CameraInfo(); 321c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li Camera.getCameraInfo(cameraId, info); 3224aaa2130af7241f128ee561cafd17a4fb560b92cWu-cheng Li int degrees = getDisplayRotation(activity); 323c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li int result; 324c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { 325c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li result = (info.orientation + degrees) % 360; 326c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li result = (360 - result) % 360; // compensate the mirror 327c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li } else { // back-facing 328c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li result = (info.orientation - degrees + 360) % 360; 329c1dd72054122befb49aa1ca11ffa589b00186f80Wu-cheng Li } 330ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang camera.setDisplayOrientation(result); 331ac9d0a1ce538eb4bd50cba3b257737a05b9ac4e5Chih-Chung Chang } 3326227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra 3336227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra public static Size getOptimalPreviewSize(Activity currentActivity, 3346227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra List<Size> sizes, double targetRatio) { 3356227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra final double ASPECT_TOLERANCE = 0.05; 3366227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra if (sizes == null) return null; 3376227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra 3386227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra Size optimalSize = null; 3396227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra double minDiff = Double.MAX_VALUE; 3406227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra 3416227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra // Because of bugs of overlay and layout, we sometimes will try to 3426227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra // layout the viewfinder in the portrait orientation and thus get the 3436227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra // wrong size of mSurfaceView. When we change the preview size, the 3446227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra // new overlay will be created before the old one closed, which causes 3456227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra // an exception. For now, just get the screen size 3466227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra 3476227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra Display display = currentActivity.getWindowManager().getDefaultDisplay(); 3486227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra int targetHeight = Math.min(display.getHeight(), display.getWidth()); 3496227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra 3506227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra if (targetHeight <= 0) { 3516227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra // We don't know the size of SurfaceView, use screen height 3526227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra targetHeight = display.getHeight(); 3536227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra } 3546227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra 3556227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra // Try to find an size match aspect ratio and size 3566227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra for (Size size : sizes) { 3576227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra double ratio = (double) size.width / size.height; 3586227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue; 3596227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra if (Math.abs(size.height - targetHeight) < minDiff) { 3606227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra optimalSize = size; 3616227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra minDiff = Math.abs(size.height - targetHeight); 3626227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra } 3636227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra } 3646227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra 3656227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra // Cannot find the one match the aspect ratio, ignore the requirement 3666227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra if (optimalSize == null) { 3676227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra Log.v(TAG, "No preview size match the aspect ratio"); 3686227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra minDiff = Double.MAX_VALUE; 3696227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra for (Size size : sizes) { 3706227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra if (Math.abs(size.height - targetHeight) < minDiff) { 3716227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra optimalSize = size; 3726227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra minDiff = Math.abs(size.height - targetHeight); 3736227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra } 3746227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra } 3756227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra } 3766227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra return optimalSize; 3776227fa641518492a6b660c78463da18d9ec8fcd8Nipun Kwatra } 378101d528d59f447847d5c6b7578642132c2b76f4fOwen Lin} 379