Util.java revision 1efb18228a45952d699af280482e1c51a4582690
1c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger/* 2c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * Copyright (C) 2009 The Android Open Source Project 3c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * 4c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * Licensed under the Apache License, Version 2.0 (the "License"); 5c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * you may not use this file except in compliance with the License. 63f417819926108853433df184fbb358aaa85cefcAndroid Chromium Automerger * You may obtain a copy of the License at 7c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * 8c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * http://www.apache.org/licenses/LICENSE-2.0 9c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * 10c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * Unless required by applicable law or agreed to in writing, software 11c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * distributed under the License is distributed on an "AS IS" BASIS, 12c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * See the License for the specific language governing permissions and 14c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * limitations under the License. 15c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger */ 16c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 17c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerpackage com.android.camera; 18c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 19c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport com.android.camera.gallery.IImage; 20c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 21c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.app.Activity; 22c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.app.AlertDialog; 23c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.content.DialogInterface; 24c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.graphics.Bitmap; 25c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.graphics.BitmapFactory; 26c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.graphics.Matrix; 27c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.hardware.Camera.Size; 28c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.util.Log; 29c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.view.Display; 30c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.view.Surface; 31c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.view.View; 32c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.view.animation.Animation; 33c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport android.view.animation.TranslateAnimation; 34c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 35c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport java.io.Closeable; 36c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerimport java.util.List; 37c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 38c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger/** 39c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * Collection of utility functions used in this package. 40c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger */ 41c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automergerpublic class Util { 42c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger private static final String TAG = "Util"; 43c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger public static final int DIRECTION_LEFT = 0; 44c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger public static final int DIRECTION_RIGHT = 1; 45c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger public static final int DIRECTION_UP = 2; 46c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger public static final int DIRECTION_DOWN = 3; 47c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 48c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger public static final String REVIEW_ACTION = "com.android.camera.action.REVIEW"; 49c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 50c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger private Util() { 51c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 52c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 53c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger // Rotates the bitmap by the specified degree. 54c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger // If a new bitmap is created, the original bitmap is recycled. 55c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger public static Bitmap rotate(Bitmap b, int degrees) { 56c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger if (degrees != 0 && b != null) { 57c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger Matrix m = new Matrix(); 58c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger m.setRotate(degrees, 59c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger (float) b.getWidth() / 2, (float) b.getHeight() / 2); 60c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger try { 61c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger Bitmap b2 = Bitmap.createBitmap( 62c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger b, 0, 0, b.getWidth(), b.getHeight(), m, true); 63c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger if (b != b2) { 64c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger b.recycle(); 65c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger b = b2; 66c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 67c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } catch (OutOfMemoryError ex) { 68c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger // We have no memory to rotate. Return the original bitmap. 69c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 70c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 71c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger return b; 72a715e94c5d62236fb7b1e050f175ed825a6373baAndroid Chromium Automerger } 73c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 74c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger /* 75c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * Compute the sample size as a function of minSideLength 76c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * and maxNumOfPixels. 77c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * minSideLength is used to specify that minimal width or height of a 78c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * bitmap. 79c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * maxNumOfPixels is used to specify the maximal size in pixels that is 80c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * tolerable in terms of memory usage. 81c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * 82c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * The function returns a sample size based on the constraints. 83c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * Both size and minSideLength can be passed in as IImage.UNCONSTRAINED, 84c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * which indicates no care of the corresponding constraint. 85c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * The functions prefers returning a sample size that 86c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * generates a smaller bitmap, unless minSideLength = IImage.UNCONSTRAINED. 87c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * 88c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * Also, the function rounds up the sample size to a power of 2 or multiple 89c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * of 8 because BitmapFactory only honors sample size this way. 90c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * For example, BitmapFactory downsamples an image by 2 even though the 91c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger * request is 3. So we round up the sample size to avoid OOM. 92c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger */ 93c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger public static int computeSampleSize(BitmapFactory.Options options, 94c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger int minSideLength, int maxNumOfPixels) { 95c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger int initialSize = computeInitialSampleSize(options, minSideLength, 96c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger maxNumOfPixels); 97c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 98c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger int roundedSize; 99c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger if (initialSize <= 8) { 100c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger roundedSize = 1; 101c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger while (roundedSize < initialSize) { 102c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger roundedSize <<= 1; 103c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 104c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } else { 105c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger roundedSize = (initialSize + 7) / 8 * 8; 106c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 1078fc9c2daac27392f17b3c5ea83528686fe683ff0Android Chromium Automerger 108c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger return roundedSize; 109c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 110c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 111c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger private static int computeInitialSampleSize(BitmapFactory.Options options, 112c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger int minSideLength, int maxNumOfPixels) { 113c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger double w = options.outWidth; 114c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger double h = options.outHeight; 115c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 116c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger int lowerBound = (maxNumOfPixels == IImage.UNCONSTRAINED) ? 1 : 117c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels)); 118c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger int upperBound = (minSideLength == IImage.UNCONSTRAINED) ? 128 : 119c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger (int) Math.min(Math.floor(w / minSideLength), 120c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger Math.floor(h / minSideLength)); 121c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 122c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger if (upperBound < lowerBound) { 123c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger // return the larger one when there is no overlapping zone. 124c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger return lowerBound; 125c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 126a715e94c5d62236fb7b1e050f175ed825a6373baAndroid Chromium Automerger 127c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger if ((maxNumOfPixels == IImage.UNCONSTRAINED) && 128c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger (minSideLength == IImage.UNCONSTRAINED)) { 129c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger return 1; 130c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } else if (minSideLength == IImage.UNCONSTRAINED) { 131c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger return lowerBound; 132c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } else { 133c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger return upperBound; 134c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 135c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 136c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 137c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger public static <T> int indexOf(T [] array, T s) { 138c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger for (int i = 0; i < array.length; i++) { 139c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger if (array[i].equals(s)) { 140c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger return i; 141c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 142c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 143c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger return -1; 144c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 145c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 146c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger public static void closeSilently(Closeable c) { 147c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger if (c == null) return; 148c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger try { 149c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger c.close(); 150c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } catch (Throwable t) { 151c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger // do nothing 152c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 153c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 154c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 155c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger public static Bitmap makeBitmap(byte[] jpegData, int maxNumOfPixels) { 156c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger try { 157c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger BitmapFactory.Options options = new BitmapFactory.Options(); 158c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger options.inJustDecodeBounds = true; 159c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, 160c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger options); 161c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger if (options.mCancel || options.outWidth == -1 162c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger || options.outHeight == -1) { 163c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger return null; 164c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 165c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger options.inSampleSize = computeSampleSize( 166c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger options, IImage.UNCONSTRAINED, maxNumOfPixels); 167c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger options.inJustDecodeBounds = false; 168c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 169c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger options.inDither = false; 170c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger options.inPreferredConfig = Bitmap.Config.ARGB_8888; 171c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger return BitmapFactory.decodeByteArray(jpegData, 0, jpegData.length, 172c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger options); 173c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } catch (OutOfMemoryError ex) { 174c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger Log.e(TAG, "Got oom exception ", ex); 175c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger return null; 176c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 177c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 178c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 179c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger public static void Assert(boolean cond) { 180c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger if (!cond) { 181c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger throw new AssertionError(); 182c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 183c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 184c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 185c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger public static void showFatalErrorAndFinish( 186c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger final Activity activity, String title, String message) { 187c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger DialogInterface.OnClickListener buttonListener = 188c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger new DialogInterface.OnClickListener() { 189c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger public void onClick(DialogInterface dialog, int which) { 190c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger activity.finish(); 191c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 192c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger }; 193c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger new AlertDialog.Builder(activity) 194c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger .setCancelable(false) 195c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger .setIcon(android.R.drawable.ic_dialog_alert) 196c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger .setTitle(title) 197c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger .setMessage(message) 198c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger .setNeutralButton(R.string.details_ok, buttonListener) 199c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger .show(); 200c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 201c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 202c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger public static Animation slideOut(View view, int to) { 203c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger view.setVisibility(View.INVISIBLE); 204c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger Animation anim; 205c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger switch (to) { 206c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger case DIRECTION_LEFT: 207c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger anim = new TranslateAnimation(0, -view.getWidth(), 0, 0); 208c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger break; 209c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger case DIRECTION_RIGHT: 210c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger anim = new TranslateAnimation(0, view.getWidth(), 0, 0); 211c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger break; 212c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger case DIRECTION_UP: 213c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger anim = new TranslateAnimation(0, 0, 0, -view.getHeight()); 214c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger break; 215c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger case DIRECTION_DOWN: 216c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger anim = new TranslateAnimation(0, 0, 0, view.getHeight()); 217c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger break; 218c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger default: 219c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger throw new IllegalArgumentException(Integer.toString(to)); 220c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 221c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger anim.setDuration(500); 222c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger view.startAnimation(anim); 223c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger return anim; 224c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 225c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 226c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger public static Animation slideIn(View view, int from) { 227c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger view.setVisibility(View.VISIBLE); 228c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger Animation anim; 229c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger switch (from) { 230c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger case DIRECTION_LEFT: 231c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger anim = new TranslateAnimation(-view.getWidth(), 0, 0, 0); 232c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger break; 233c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger case DIRECTION_RIGHT: 234c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger anim = new TranslateAnimation(view.getWidth(), 0, 0, 0); 235c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger break; 236c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger case DIRECTION_UP: 237c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger anim = new TranslateAnimation(0, 0, -view.getHeight(), 0); 238c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger break; 239c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger case DIRECTION_DOWN: 240c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger anim = new TranslateAnimation(0, 0, view.getHeight(), 0); 241c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger break; 242c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger default: 243c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger throw new IllegalArgumentException(Integer.toString(from)); 244c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 245c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger anim.setDuration(500); 246c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger view.startAnimation(anim); 247c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger return anim; 2488fa39d2e728ea8254a0cbd268c32772e8749c18dAndroid Chromium Automerger } 249c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 250c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger public static <T> T checkNotNull(T object) { 251c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger if (object == null) throw new NullPointerException(); 252c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger return object; 253c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 254c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 255c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger public static boolean equals(Object a, Object b) { 256c1f5fc681b0495f5e16a6c7a693d767dbefcfa5fTorne (Richard Coles) return (a == b) || (a == null ? false : a.equals(b)); 257c1f5fc681b0495f5e16a6c7a693d767dbefcfa5fTorne (Richard Coles) } 258c1f5fc681b0495f5e16a6c7a693d767dbefcfa5fTorne (Richard Coles) 259c1f5fc681b0495f5e16a6c7a693d767dbefcfa5fTorne (Richard Coles) public static boolean isPowerOf2(int n) { 260baf4b7536eee2d8fefabdab9be2901c4b04f1c85Android Chromium Automerger return (n & -n) == n; 26170d70cb2626549aed2f50d8c08082ab27f9f1077Torne (Richard Coles) } 262c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 263c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger public static int nextPowerOf2(int n) { 264c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger n -= 1; 265c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger n |= n >>> 16; 266c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger n |= n >>> 8; 267c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger n |= n >>> 4; 268c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger n |= n >>> 2; 269c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger n |= n >>> 1; 270c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger return n + 1; 271c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 272c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 273c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger public static float distance(float x, float y, float sx, float sy) { 274c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger float dx = x - sx; 275c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger float dy = y - sy; 276c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger return (float) Math.sqrt(dx * dx + dy * dy); 277c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 278c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 279c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger public static int clamp(int x, int min, int max) { 280c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger if (x > max) return max; 281c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger if (x < min) return min; 282c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger return x; 283c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 284c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 285c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger public static int getDisplayRotation(Activity activity) { 286c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger int rotation = activity.getWindowManager().getDefaultDisplay() 287c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger .getRotation(); 288c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger switch (rotation) { 2890fac7502a6e87bf94f7ec9e56364012aad1031e5Android Chromium Automerger case Surface.ROTATION_0: return 0; 290a715e94c5d62236fb7b1e050f175ed825a6373baAndroid Chromium Automerger case Surface.ROTATION_90: return 90; 291b3d0e079a65545810a4c3b5fc0852b028d0d617eBo Liu case Surface.ROTATION_180: return 180; 292b3d0e079a65545810a4c3b5fc0852b028d0d617eBo Liu case Surface.ROTATION_270: return 270; 293c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 294c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger return 0; 295c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 296c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 297c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger public static void setCameraDisplayOrientation(Activity activity, 298c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger int cameraId, android.hardware.Camera camera) { 299c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger android.hardware.Camera.CameraInfo info = 300c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger new android.hardware.Camera.CameraInfo(); 301c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger android.hardware.Camera.getCameraInfo(cameraId, info); 302c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger int degrees = getDisplayRotation(activity); 303c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger int result = (info.orientation - degrees + 360) % 360; 304c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger camera.setDisplayOrientation(result); 305c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 306c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 307c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger public static Size getOptimalPreviewSize(Activity currentActivity, 308c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger List<Size> sizes, double targetRatio) { 3098e6b6de2b0230c99212993c460bbeed9342bee30Dehao Chen final double ASPECT_TOLERANCE = 0.05; 3108e6b6de2b0230c99212993c460bbeed9342bee30Dehao Chen if (sizes == null) return null; 311c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 312c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger Size optimalSize = null; 313c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger double minDiff = Double.MAX_VALUE; 314c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 315c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger // Because of bugs of overlay and layout, we sometimes will try to 316c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger // layout the viewfinder in the portrait orientation and thus get the 317c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger // wrong size of mSurfaceView. When we change the preview size, the 318c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger // new overlay will be created before the old one closed, which causes 319c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger // an exception. For now, just get the screen size 320c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 321c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger Display display = currentActivity.getWindowManager().getDefaultDisplay(); 322c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger int targetHeight = Math.min(display.getHeight(), display.getWidth()); 323c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 324c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger if (targetHeight <= 0) { 325c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger // We don't know the size of SurfaceView, use screen height 326c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger targetHeight = display.getHeight(); 327c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 328c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 329c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger // Try to find an size match aspect ratio and size 330c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger for (Size size : sizes) { 331c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger double ratio = (double) size.width / size.height; 332c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue; 333c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger if (Math.abs(size.height - targetHeight) < minDiff) { 334c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger optimalSize = size; 335c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger minDiff = Math.abs(size.height - targetHeight); 336c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 337c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 338c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger 339c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger // Cannot find the one match the aspect ratio, ignore the requirement 340c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger if (optimalSize == null) { 341c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger Log.v(TAG, "No preview size match the aspect ratio"); 342c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger minDiff = Double.MAX_VALUE; 343c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger for (Size size : sizes) { 344c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger if (Math.abs(size.height - targetHeight) < minDiff) { 345c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger optimalSize = size; 346c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger minDiff = Math.abs(size.height - targetHeight); 347c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 348c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 349c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 350c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger return optimalSize; 351c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger } 352c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger} 353c79d9ef8f90b520414940bdc79164b9d18e5627bAndroid Chromium Automerger