PhotoUI.java revision db8f97582d09cd36eee8cfe4ed43182bff63f8bd
1d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb/* 26432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu * Copyright (C) 2012 The Android Open Source Project 3d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb * 4d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb * Licensed under the Apache License, Version 2.0 (the "License"); 5d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb * you may not use this file except in compliance with the License. 6d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb * You may obtain a copy of the License at 7d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb * 8d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb * http://www.apache.org/licenses/LICENSE-2.0 9d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb * 10d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb * Unless required by applicable law or agreed to in writing, software 11d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb * distributed under the License is distributed on an "AS IS" BASIS, 12d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb * See the License for the specific language governing permissions and 14d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb * limitations under the License. 15d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb */ 16d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 17d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolbpackage com.android.camera; 18d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 19db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liuimport android.app.Dialog; 20db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liuimport android.content.DialogInterface; 2137f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberlingimport android.graphics.Bitmap; 226432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liuimport android.graphics.Matrix; 236432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liuimport android.graphics.SurfaceTexture; 24d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolbimport android.hardware.Camera; 25d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolbimport android.hardware.Camera.Face; 2637f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberlingimport android.os.AsyncTask; 27f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liuimport android.view.GestureDetector; 28f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liuimport android.view.MotionEvent; 29d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolbimport android.view.View; 30d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolbimport android.view.ViewGroup; 31d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 32d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolbimport com.android.camera.FocusOverlayManager.FocusUI; 331045fefdf22bd58fa911b100e7db5750f7efa3e6Angus Kongimport com.android.camera.cameradevice.CameraManager; 345596b4c902dcb685928b43678f428746ca5ffd08Angus Kongimport com.android.camera.debug.Log; 35d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolbimport com.android.camera.ui.FaceView; 36f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liuimport com.android.camera.ui.PreviewOverlay; 3706db742814dd635d100639f977fcfdc904deb778Doris Liuimport com.android.camera.ui.PreviewStatusListener; 38b50b5cbfbc0a67db6fc43373363b10381c9c61a3Angus Kongimport com.android.camera.util.CameraUtil; 39db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liuimport com.android.camera.widget.AspectRatioDialogLayout; 40db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liuimport com.android.camera.widget.AspectRatioSelector; 41db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liuimport com.android.camera.widget.LocationDialogLayout; 428e963a5a6016d246184ed65906f9d103e92b17e2Sascha Haeberlingimport com.android.camera2.R; 43b50b5cbfbc0a67db6fc43373363b10381c9c61a3Angus Kong 44b50b5cbfbc0a67db6fc43373363b10381c9c61a3Angus Kongimport java.util.List; 45d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 46482de029dc20e0a577388a602985fb31c3200309Doris Liupublic class PhotoUI implements PreviewStatusListener, 479e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong CameraManager.CameraFaceDetectionCallback { 48d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 495596b4c902dcb685928b43678f428746ca5ffd08Angus Kong private static final Log.Tag TAG = new Log.Tag("PhotoUI"); 5037f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling private static final int DOWN_SAMPLE_FACTOR = 4; 5170da918464276b110c43868caa272c97baadb89eDoris Liu private static final float UNSET = 0f; 520f3c4b4fc9ac87d7d4c3d04c3cb3426c711f57eaSpike Sprague 53f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liu private final PreviewOverlay mPreviewOverlay; 54482de029dc20e0a577388a602985fb31c3200309Doris Liu private final FocusUI mFocusUI; 55e2914fddcd6d4f78d812ef818d43364d9aa469d4Sascha Haeberling private final CameraActivity mActivity; 56e2914fddcd6d4f78d812ef818d43364d9aa469d4Sascha Haeberling private final PhotoController mController; 57d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 58e2914fddcd6d4f78d812ef818d43364d9aa469d4Sascha Haeberling private final View mRootView; 59db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu private Dialog mDialog = null; 60d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 61d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu // TODO: Remove face view logic if UX does not bring it back within a month. 62d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu private FaceView mFaceView = null; 6336e56fba281292255a01ee00b4bee067fa09ab59Doris Liu private DecodeImageForReview mDecodeTaskForReview = null; 64d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 65d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb private int mZoomMax; 66d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb private List<Integer> mZoomRatios; 67d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 68d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb private int mPreviewWidth = 0; 69d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb private int mPreviewHeight = 0; 7070da918464276b110c43868caa272c97baadb89eDoris Liu private float mAspectRatio = UNSET; 710744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 7206db742814dd635d100639f977fcfdc904deb778Doris Liu private final GestureDetector.OnGestureListener mPreviewGestureListener 7306db742814dd635d100639f977fcfdc904deb778Doris Liu = new GestureDetector.SimpleOnGestureListener() { 7406db742814dd635d100639f977fcfdc904deb778Doris Liu @Override 7506db742814dd635d100639f977fcfdc904deb778Doris Liu public boolean onSingleTapUp(MotionEvent ev) { 7606db742814dd635d100639f977fcfdc904deb778Doris Liu mController.onSingleTapUp(null, (int) ev.getX(), (int) ev.getY()); 7706db742814dd635d100639f977fcfdc904deb778Doris Liu return true; 7806db742814dd635d100639f977fcfdc904deb778Doris Liu } 7906db742814dd635d100639f977fcfdc904deb778Doris Liu }; 80db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu private final DialogInterface.OnDismissListener mOnDismissListener 81db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu = new DialogInterface.OnDismissListener() { 82db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu @Override 83db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu public void onDismiss(DialogInterface dialog) { 84db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu mDialog = null; 85db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu } 86db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu }; 870744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 8806db742814dd635d100639f977fcfdc904deb778Doris Liu @Override 8906db742814dd635d100639f977fcfdc904deb778Doris Liu public GestureDetector.OnGestureListener getGestureListener() { 9006db742814dd635d100639f977fcfdc904deb778Doris Liu return mPreviewGestureListener; 9106db742814dd635d100639f977fcfdc904deb778Doris Liu } 9206db742814dd635d100639f977fcfdc904deb778Doris Liu 934a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu @Override 94d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren public View.OnTouchListener getTouchListener() { 95d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren return null; 96d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren } 97d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren 98d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren @Override 994a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu public void onPreviewLayoutChanged(View v, int left, int top, int right, 1004a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { 1014a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu int width = right - left; 1024a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu int height = bottom - top; 1034a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu if (mPreviewWidth != width || mPreviewHeight != height) { 1044a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu mPreviewWidth = width; 1054a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu mPreviewHeight = height; 106d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 1074a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu } 108d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 10970da918464276b110c43868caa272c97baadb89eDoris Liu @Override 11070da918464276b110c43868caa272c97baadb89eDoris Liu public boolean shouldAutoAdjustTransformMatrixOnLayout() { 11170da918464276b110c43868caa272c97baadb89eDoris Liu return true; 11270da918464276b110c43868caa272c97baadb89eDoris Liu } 11370da918464276b110c43868caa272c97baadb89eDoris Liu 11470da918464276b110c43868caa272c97baadb89eDoris Liu @Override 11570da918464276b110c43868caa272c97baadb89eDoris Liu public boolean shouldAutoAdjustBottomBar() { 11670da918464276b110c43868caa272c97baadb89eDoris Liu return true; 11770da918464276b110c43868caa272c97baadb89eDoris Liu } 11870da918464276b110c43868caa272c97baadb89eDoris Liu 11911ddd7389b89e9a876eba607e246e8b8d0dfecdfDoris Liu @Override 12011ddd7389b89e9a876eba607e246e8b8d0dfecdfDoris Liu public void onPreviewFlipped() { 12111ddd7389b89e9a876eba607e246e8b8d0dfecdfDoris Liu mController.updateCameraOrientation(); 12211ddd7389b89e9a876eba607e246e8b8d0dfecdfDoris Liu } 12311ddd7389b89e9a876eba607e246e8b8d0dfecdfDoris Liu 12436e56fba281292255a01ee00b4bee067fa09ab59Doris Liu private class DecodeTask extends AsyncTask<Void, Void, Bitmap> { 12537f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling private final byte [] mData; 126e2914fddcd6d4f78d812ef818d43364d9aa469d4Sascha Haeberling private final int mOrientation; 127e2914fddcd6d4f78d812ef818d43364d9aa469d4Sascha Haeberling private final boolean mMirror; 128c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu 12929da2db13029f8896018836693139a05d1139362Doris Liu public DecodeTask(byte[] data, int orientation, boolean mirror) { 13037f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling mData = data; 131ce2acbcb77225b6d429a23e00f69aadde8c2378bDoris Liu mOrientation = orientation; 13229da2db13029f8896018836693139a05d1139362Doris Liu mMirror = mirror; 133c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu } 134c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu 135c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu @Override 13636e56fba281292255a01ee00b4bee067fa09ab59Doris Liu protected Bitmap doInBackground(Void... params) { 13737f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling // Decode image in background. 138ce2acbcb77225b6d429a23e00f69aadde8c2378bDoris Liu Bitmap bitmap = CameraUtil.downSample(mData, DOWN_SAMPLE_FACTOR); 13929da2db13029f8896018836693139a05d1139362Doris Liu if (mOrientation != 0 || mMirror) { 140ce2acbcb77225b6d429a23e00f69aadde8c2378bDoris Liu Matrix m = new Matrix(); 14129da2db13029f8896018836693139a05d1139362Doris Liu if (mMirror) { 14229da2db13029f8896018836693139a05d1139362Doris Liu // Flip horizontally 14329da2db13029f8896018836693139a05d1139362Doris Liu m.setScale(-1f, 1f); 14429da2db13029f8896018836693139a05d1139362Doris Liu } 145cec75e408a2d451b90bac5f06e10906ffcafff33Andy Huibers m.preRotate(mOrientation); 146ce2acbcb77225b6d429a23e00f69aadde8c2378bDoris Liu return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), m, 147ce2acbcb77225b6d429a23e00f69aadde8c2378bDoris Liu false); 148ce2acbcb77225b6d429a23e00f69aadde8c2378bDoris Liu } 149ce2acbcb77225b6d429a23e00f69aadde8c2378bDoris Liu return bitmap; 15037f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling } 15137f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling } 152c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu 15336e56fba281292255a01ee00b4bee067fa09ab59Doris Liu private class DecodeImageForReview extends DecodeTask { 15436e56fba281292255a01ee00b4bee067fa09ab59Doris Liu public DecodeImageForReview(byte[] data, int orientation, boolean mirror) { 15536e56fba281292255a01ee00b4bee067fa09ab59Doris Liu super(data, orientation, mirror); 15636e56fba281292255a01ee00b4bee067fa09ab59Doris Liu } 15736e56fba281292255a01ee00b4bee067fa09ab59Doris Liu 15836e56fba281292255a01ee00b4bee067fa09ab59Doris Liu @Override 15936e56fba281292255a01ee00b4bee067fa09ab59Doris Liu protected void onPostExecute(Bitmap bitmap) { 16036e56fba281292255a01ee00b4bee067fa09ab59Doris Liu if (isCancelled()) { 16136e56fba281292255a01ee00b4bee067fa09ab59Doris Liu return; 16236e56fba281292255a01ee00b4bee067fa09ab59Doris Liu } 16336e56fba281292255a01ee00b4bee067fa09ab59Doris Liu mDecodeTaskForReview = null; 16436e56fba281292255a01ee00b4bee067fa09ab59Doris Liu } 16536e56fba281292255a01ee00b4bee067fa09ab59Doris Liu } 16636e56fba281292255a01ee00b4bee067fa09ab59Doris Liu 167d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public PhotoUI(CameraActivity activity, PhotoController controller, View parent) { 168d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb mActivity = activity; 169d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb mController = controller; 170d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb mRootView = parent; 171d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 172f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu ViewGroup moduleRoot = (ViewGroup) mRootView.findViewById(R.id.module_layout); 173d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb mActivity.getLayoutInflater().inflate(R.layout.photo_module, 174e2914fddcd6d4f78d812ef818d43364d9aa469d4Sascha Haeberling moduleRoot, true); 175d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb initIndicators(); 176482de029dc20e0a577388a602985fb31c3200309Doris Liu mFocusUI = (FocusUI) mRootView.findViewById(R.id.focus_overlay); 177f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liu mPreviewOverlay = (PreviewOverlay) mRootView.findViewById(R.id.preview_overlay); 1786432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu } 1796432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu 180482de029dc20e0a577388a602985fb31c3200309Doris Liu public FocusUI getFocusUI() { 181482de029dc20e0a577388a602985fb31c3200309Doris Liu return mFocusUI; 182482de029dc20e0a577388a602985fb31c3200309Doris Liu } 183482de029dc20e0a577388a602985fb31c3200309Doris Liu 184d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu public void updatePreviewAspectRatio(float aspectRatio) { 185d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu if (aspectRatio <= 0) { 186d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu Log.e(TAG, "Invalid aspect ratio: " + aspectRatio); 187d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu return; 188d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu } 189d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu if (aspectRatio < 1f) { 190d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu aspectRatio = 1f / aspectRatio; 191d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu } 192d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu 193d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu if (mAspectRatio != aspectRatio) { 194d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu mAspectRatio = aspectRatio; 195d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu // Update transform matrix with the new aspect ratio. 19670da918464276b110c43868caa272c97baadb89eDoris Liu mController.updatePreviewAspectRatio(mAspectRatio); 197d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu } 198d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu } 199d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu 200dcccc510652b835fdbd39310a07849af8203052aAngus Kong @Override 2016432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { 202d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren mController.onPreviewUIReady(); 2036432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu } 204d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 205dcccc510652b835fdbd39310a07849af8203052aAngus Kong @Override 2066432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { 2076432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu // Ignored, Camera does all the work for us 2086432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu } 2096432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu 210dcccc510652b835fdbd39310a07849af8203052aAngus Kong @Override 2116432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { 212d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren mController.onPreviewUIDestroyed(); 213d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren return true; 2146432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu } 2156432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu 2167b265a6b2f55c6ae7afc30e63ba324c4084a5d8eztenghui @Override 2176432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu public void onSurfaceTextureUpdated(SurfaceTexture surface) { 218d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 219d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 220d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public View getRootView() { 221d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb return mRootView; 222d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 223d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 224d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb private void initIndicators() { 2250744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen // TODO init toggle buttons on bottom bar here 226d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 227d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 228b1641f5df0cf839b54385ea4d2e43521620fc237Erin Dahlgren public void onCameraOpened(Camera.Parameters params) { 229eb3134f6ecc42f7d98625ca2c0ddfb06c9f07c43Spike Sprague initializeZoom(params); 230eb3134f6ecc42f7d98625ca2c0ddfb06c9f07c43Spike Sprague } 231eb3134f6ecc42f7d98625ca2c0ddfb06c9f07c43Spike Sprague 2320a6a8d8e4e1c9796aac606379a42970cdffb8911Erin Dahlgren public void animateCapture(final byte[] jpegData, int orientation, boolean mirror) { 2330a6a8d8e4e1c9796aac606379a42970cdffb8911Erin Dahlgren // Decode jpeg byte array and then animate the jpeg 2340a6a8d8e4e1c9796aac606379a42970cdffb8911Erin Dahlgren DecodeTask task = new DecodeTask(jpegData, orientation, mirror); 2350a6a8d8e4e1c9796aac606379a42970cdffb8911Erin Dahlgren task.execute(); 236eb3134f6ecc42f7d98625ca2c0ddfb06c9f07c43Spike Sprague } 237d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 238d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb // called from onResume but only the first time 239ffbc43c3dd3c94a968a41431fb07645a13696c4aKevin Gabayan public void initializeFirstTime() { 2400744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 241d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 242d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 243d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb // called from onResume every other time 244d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void initializeSecondTime(Camera.Parameters params) { 245d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb initializeZoom(params); 246d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb if (mController.isImageCaptureIntent()) { 247d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb hidePostCaptureAlert(); 248d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 249357b7673f03d9b45d281d585cc3f4f87dc7d727bErin Dahlgren // Removes pie menu. 250d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 251d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 252db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu public void showLocationAndAspectRatioDialog( 253db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu final PhotoModule.LocationDialogCallback locationCallback, 254db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu final PhotoModule.AspectRatioDialogCallback aspectRatioDialogCallback) { 255db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu setDialog(new Dialog(mActivity, 256db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu android.R.style.Theme_Black_NoTitleBar_Fullscreen)); 257db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu final LocationDialogLayout locationDialogLayout = (LocationDialogLayout) mActivity 258db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu .getLayoutInflater().inflate(R.layout.location_dialog_layout, null); 259db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu locationDialogLayout.setLocationTaggingSelectionListener( 260db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu new LocationDialogLayout.LocationTaggingSelectionListener() { 261db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu @Override 262db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu public void onLocationTaggingSelected(boolean selected) { 263db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu // Update setting. 264db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu locationCallback.onLocationTaggingSelected(selected); 265db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu // Go to next page. 266db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu showAspectRatioDialog(aspectRatioDialogCallback, mDialog); 267db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu } 268db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu }); 269db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu mDialog.setContentView(locationDialogLayout, new ViewGroup.LayoutParams( 270db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 271db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu mDialog.show(); 272db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu } 273db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu 274db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu /** 275db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu * Dismisses previous dialog if any, sets current dialog to the given dialog, 276db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu * and set the on dismiss listener for the given dialog. 277db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu * @param dialog dialog to show 278db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu */ 279db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu private void setDialog(Dialog dialog) { 280db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu if (mDialog != null) { 281db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu mDialog.setOnDismissListener(null); 282db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu mDialog.dismiss(); 283db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu } 284db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu mDialog = dialog; 285db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu if (mDialog != null) { 286db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu mDialog.setOnDismissListener(mOnDismissListener); 287db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu } 288db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu } 289db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu 290db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu public void showAspectRatioDialog(final PhotoModule.AspectRatioDialogCallback callback) { 291db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu setDialog(new Dialog(mActivity, android.R.style.Theme_Black_NoTitleBar_Fullscreen)); 292db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu showAspectRatioDialog(callback, mDialog); 293db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu } 294db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu 295db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu private void showAspectRatioDialog(final PhotoModule.AspectRatioDialogCallback callback, 296db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu final Dialog aspectRatioDialog) { 297db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu if (aspectRatioDialog == null) { 298db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu Log.e(TAG, "Dialog for aspect ratio is null."); 299db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu return; 300db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu } 301db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu final AspectRatioDialogLayout aspectRatioDialogLayout = 302db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu (AspectRatioDialogLayout) mActivity 303db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu .getLayoutInflater().inflate(R.layout.aspect_ratio_dialog_layout, null); 304db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu aspectRatioDialogLayout.initialize( 305db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu new AspectRatioDialogLayout.AspectRatioChangedListener() { 306db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu @Override 307db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu public void onAspectRatioChanged(AspectRatioSelector.AspectRatio aspectRatio) { 308db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu aspectRatioDialog.dismiss(); 309db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu // callback to set picture size. 310db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu callback.onAspectRatioSelected(aspectRatio); 311db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu } 312db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu }, callback.get4x3AspectRatioText(), callback.get16x9AspectRatioText(), 313db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu callback.getCurrentAspectRatio()); 314db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu aspectRatioDialog.setContentView(aspectRatioDialogLayout, new ViewGroup.LayoutParams( 315db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 316db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu aspectRatioDialog.show(); 3176a83d528b09c55ade6ad44b82c81d4476ac57441Doris Liu } 3186a83d528b09c55ade6ad44b82c81d4476ac57441Doris Liu 319d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void initializeZoom(Camera.Parameters params) { 320f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liu if ((params == null) || !params.isZoomSupported()) return; 321d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb mZoomMax = params.getMaxZoom(); 322d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb mZoomRatios = params.getZoomRatios(); 323d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb // Currently we use immediate zoom for fast zooming to get better UX and 324d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb // there is no plan to take advantage of the smooth zoom. 325f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liu // TODO: Need to setup a path to AppUI to do this 326f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liu mPreviewOverlay.setupZoom(mZoomMax, params.getZoom(), mZoomRatios, new ZoomChangeListener()); 327d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 328d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 329c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu public void animateFlash() { 3301dfe7828fd60741b9752553af3ee439c04e758a0Doris Liu mController.startPreCaptureAnimation(); 331c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu } 332c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu 333d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public boolean onBackPressed() { 334d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb // In image capture mode, back button should: 335d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb // 1) if there is any popup, dismiss them, 2) otherwise, get out of 336d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb // image capture 337d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb if (mController.isImageCaptureIntent()) { 338c3679c0961521165499380c77344acc69072b2acDoris Liu mController.onCaptureCancelled(); 339d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb return true; 340d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } else if (!mController.isCameraIdle()) { 341d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb // ignore backs while we're taking a picture 342d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb return true; 343d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } else { 344c3679c0961521165499380c77344acc69072b2acDoris Liu return false; 345d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 346d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 347d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 34836e56fba281292255a01ee00b4bee067fa09ab59Doris Liu protected void showCapturedImageForReview(byte[] jpegData, int orientation, boolean mirror) { 34936e56fba281292255a01ee00b4bee067fa09ab59Doris Liu mDecodeTaskForReview = new DecodeImageForReview(jpegData, orientation, mirror); 35036e56fba281292255a01ee00b4bee067fa09ab59Doris Liu mDecodeTaskForReview.execute(); 3514efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 3524efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mActivity.getCameraAppUI().transitionToIntentReviewLayout(); 353d31cdfeb1035df8ba939e877031769f0df247aa6Doris Liu pauseFaceDetection(); 354d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 355d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 356d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb protected void hidePostCaptureAlert() { 35736e56fba281292255a01ee00b4bee067fa09ab59Doris Liu if (mDecodeTaskForReview != null) { 35836e56fba281292255a01ee00b4bee067fa09ab59Doris Liu mDecodeTaskForReview.cancel(true); 35936e56fba281292255a01ee00b4bee067fa09ab59Doris Liu } 360d31cdfeb1035df8ba939e877031769f0df247aa6Doris Liu resumeFaceDetection(); 361d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 362d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 363d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void setDisplayOrientation(int orientation) { 364d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb if (mFaceView != null) { 365d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb mFaceView.setDisplayOrientation(orientation); 366d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 367d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 368d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 369f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liu private class ZoomChangeListener implements PreviewOverlay.OnZoomChangedListener { 370d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb @Override 371d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void onZoomValueChanged(int index) { 372f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liu mController.onZoomChanged(index); 373d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 374d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 375d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb @Override 376d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void onZoomStart() { 377d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 378d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 379d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb @Override 380d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void onZoomEnd() { 381d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 382d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 383d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 3846432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu public void setSwipingEnabled(boolean enable) { 3856432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu mActivity.setSwipingEnabled(enable); 386d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 387d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 388d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void onPause() { 389d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb if (mFaceView != null) mFaceView.clear(); 390db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu if (mDialog != null) { 391db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu mDialog.dismiss(); 392db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu } 393d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 394d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 395d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void clearFaces() { 3960744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen if (mFaceView != null) { 3970744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen mFaceView.clear(); 3980744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 399d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 400d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 401d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void pauseFaceDetection() { 402d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb if (mFaceView != null) mFaceView.pause(); 403d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 404d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 405d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void resumeFaceDetection() { 406d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb if (mFaceView != null) mFaceView.resume(); 407d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 408d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 409d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void onStartFaceDetection(int orientation, boolean mirror) { 410d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu if (mFaceView != null) { 411d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu mFaceView.clear(); 412d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu mFaceView.setVisibility(View.VISIBLE); 413d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu mFaceView.setDisplayOrientation(orientation); 414d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu mFaceView.setMirror(mirror); 415d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu mFaceView.resume(); 416d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu } 417d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 418d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 419d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb @Override 4209e76552adff6ecf8b8e4070ecd61699cb6d18269Angus Kong public void onFaceDetection(Face[] faces, CameraManager.CameraProxy camera) { 421d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu if (mFaceView != null) { 422d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu mFaceView.setFaces(faces); 423d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu } 424d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 425d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 42659401045bf479b2617c981075aec92190ec59aebDoris Liu /** 4272bacca795a1b0adb0daf515c43c48234b44bbba5Angus Kong * Returns a {@link com.android.camera.ui.PreviewStatusListener.PreviewAreaChangedListener} 42859401045bf479b2617c981075aec92190ec59aebDoris Liu * that should be registered to listen to preview area change. 42959401045bf479b2617c981075aec92190ec59aebDoris Liu */ 4302bacca795a1b0adb0daf515c43c48234b44bbba5Angus Kong public PreviewAreaChangedListener getPreviewAreaSizeChangedListener() { 43159401045bf479b2617c981075aec92190ec59aebDoris Liu return mFaceView; 43259401045bf479b2617c981075aec92190ec59aebDoris Liu } 43359401045bf479b2617c981075aec92190ec59aebDoris Liu 434d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb} 435