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; 226c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liuimport android.graphics.RectF; 236432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liuimport android.graphics.SurfaceTexture; 24d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolbimport android.hardware.Camera.Face; 2537f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberlingimport android.os.AsyncTask; 26f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liuimport android.view.GestureDetector; 27f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liuimport android.view.MotionEvent; 28d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolbimport android.view.View; 29d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolbimport android.view.ViewGroup; 30b4a2222950f627a39267636fba19649974cb8734Spike Spragueimport android.widget.FrameLayout; 31b4a2222950f627a39267636fba19649974cb8734Spike Spragueimport android.widget.ImageView; 32d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 3300a764a3b6d9072413d18b441c759d4a604223b4Senpo Huimport com.android.camera.captureintent.PictureDecoder; 3462b4c3c0da3abd397b3790820359927784c50bc2Andy Huibersimport com.android.camera.debug.DebugPropertyHelper; 355596b4c902dcb685928b43678f428746ca5ffd08Angus Kongimport com.android.camera.debug.Log; 366c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liuimport com.android.camera.ui.CountDownView; 37d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolbimport com.android.camera.ui.FaceView; 38f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liuimport com.android.camera.ui.PreviewOverlay; 3906db742814dd635d100639f977fcfdc904deb778Doris Liuimport com.android.camera.ui.PreviewStatusListener; 40987ee64612e2510004fdf08536746c87234d01c1Paul Rohdeimport com.android.camera.ui.focus.FocusRing; 418e963a5a6016d246184ed65906f9d103e92b17e2Sascha Haeberlingimport com.android.camera2.R; 425a344964cb003525727c31d295ca3a592c245606Sol Boucherimport com.android.ex.camera2.portability.CameraAgent; 434c1bffecc94cedf56d188eca40bd65a854746413Sascha Haeberlingimport com.android.ex.camera2.portability.CameraCapabilities; 445a344964cb003525727c31d295ca3a592c245606Sol Boucherimport com.android.ex.camera2.portability.CameraSettings; 45b50b5cbfbc0a67db6fc43373363b10381c9c61a3Angus Kong 46482de029dc20e0a577388a602985fb31c3200309Doris Liupublic class PhotoUI implements PreviewStatusListener, 475a344964cb003525727c31d295ca3a592c245606Sol Boucher CameraAgent.CameraFaceDetectionCallback, PreviewStatusListener.PreviewAreaChangedListener { 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; 54987ee64612e2510004fdf08536746c87234d01c1Paul Rohde private final FocusRing mFocusRing; 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. 6262b4c3c0da3abd397b3790820359927784c50bc2Andy Huibers private final FaceView mFaceView; 6336e56fba281292255a01ee00b4bee067fa09ab59Doris Liu private DecodeImageForReview mDecodeTaskForReview = null; 64d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 652192fbaaf598d4440a8d537a70095ea56bc9a5ebSol Boucher private float mZoomMax; 66d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 67d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb private int mPreviewWidth = 0; 68d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb private int mPreviewHeight = 0; 6970da918464276b110c43868caa272c97baadb89eDoris Liu private float mAspectRatio = UNSET; 700744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 71b4a2222950f627a39267636fba19649974cb8734Spike Sprague private ImageView mIntentReviewImageView; 72b4a2222950f627a39267636fba19649974cb8734Spike Sprague 7306db742814dd635d100639f977fcfdc904deb778Doris Liu private final GestureDetector.OnGestureListener mPreviewGestureListener 7406db742814dd635d100639f977fcfdc904deb778Doris Liu = new GestureDetector.SimpleOnGestureListener() { 7506db742814dd635d100639f977fcfdc904deb778Doris Liu @Override 7606db742814dd635d100639f977fcfdc904deb778Doris Liu public boolean onSingleTapUp(MotionEvent ev) { 7706db742814dd635d100639f977fcfdc904deb778Doris Liu mController.onSingleTapUp(null, (int) ev.getX(), (int) ev.getY()); 7806db742814dd635d100639f977fcfdc904deb778Doris Liu return true; 7906db742814dd635d100639f977fcfdc904deb778Doris Liu } 8006db742814dd635d100639f977fcfdc904deb778Doris Liu }; 81db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu private final DialogInterface.OnDismissListener mOnDismissListener 82db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu = new DialogInterface.OnDismissListener() { 83db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu @Override 84db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu public void onDismiss(DialogInterface dialog) { 85db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu mDialog = null; 86db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu } 87db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu }; 884c1bffecc94cedf56d188eca40bd65a854746413Sascha Haeberling private final CountDownView mCountdownView; 890744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 9006db742814dd635d100639f977fcfdc904deb778Doris Liu @Override 9106db742814dd635d100639f977fcfdc904deb778Doris Liu public GestureDetector.OnGestureListener getGestureListener() { 9206db742814dd635d100639f977fcfdc904deb778Doris Liu return mPreviewGestureListener; 9306db742814dd635d100639f977fcfdc904deb778Doris Liu } 9406db742814dd635d100639f977fcfdc904deb778Doris Liu 954a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu @Override 96d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren public View.OnTouchListener getTouchListener() { 97d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren return null; 98d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren } 99d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren 100d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren @Override 1014a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu public void onPreviewLayoutChanged(View v, int left, int top, int right, 1024a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { 1034a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu int width = right - left; 1044a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu int height = bottom - top; 1054a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu if (mPreviewWidth != width || mPreviewHeight != height) { 1064a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu mPreviewWidth = width; 1074a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu mPreviewHeight = height; 108d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 1094a010db8a60008b2bf67b93b64f77f63affc29f3Doris Liu } 110d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 11170da918464276b110c43868caa272c97baadb89eDoris Liu @Override 11270da918464276b110c43868caa272c97baadb89eDoris Liu public boolean shouldAutoAdjustTransformMatrixOnLayout() { 11370da918464276b110c43868caa272c97baadb89eDoris Liu return true; 11470da918464276b110c43868caa272c97baadb89eDoris Liu } 11570da918464276b110c43868caa272c97baadb89eDoris Liu 11670da918464276b110c43868caa272c97baadb89eDoris Liu @Override 11711ddd7389b89e9a876eba607e246e8b8d0dfecdfDoris Liu public void onPreviewFlipped() { 11811ddd7389b89e9a876eba607e246e8b8d0dfecdfDoris Liu mController.updateCameraOrientation(); 11911ddd7389b89e9a876eba607e246e8b8d0dfecdfDoris Liu } 12011ddd7389b89e9a876eba607e246e8b8d0dfecdfDoris Liu 12108b0cddea8e7390bd21053d3049ea165c759d4dbDoris Liu /** 1226c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu * Starts the countdown timer. 1236c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu * 1246c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu * @param sec seconds to countdown 1256c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu */ 1266c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu public void startCountdown(int sec) { 1276c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu mCountdownView.startCountDown(sec); 1286c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu } 1296c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu 1306c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu /** 1316c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu * Sets a listener that gets notified when the countdown is finished. 1326c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu */ 1336c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu public void setCountdownFinishedListener(CountDownView.OnCountDownStatusListener listener) { 1346c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu mCountdownView.setCountDownStatusListener(listener); 1356c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu } 1366c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu 1376c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu /** 1386c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu * Returns whether the countdown is on-going. 1396c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu */ 1406c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu public boolean isCountingDown() { 1416c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu return mCountdownView.isCountingDown(); 1426c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu } 1436c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu 1446c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu /** 1456c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu * Cancels the on-going countdown, if any. 1466c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu */ 1476c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu public void cancelCountDown() { 1486c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu mCountdownView.cancelCountDown(); 1496c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu } 1506c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu 1516c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu @Override 1526c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu public void onPreviewAreaChanged(RectF previewArea) { 1536c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu if (mFaceView != null) { 1546c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu mFaceView.onPreviewAreaChanged(previewArea); 1556c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu } 1566c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu mCountdownView.onPreviewAreaChanged(previewArea); 1576c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu } 1586c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu 15936e56fba281292255a01ee00b4bee067fa09ab59Doris Liu private class DecodeTask extends AsyncTask<Void, Void, Bitmap> { 16037f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling private final byte [] mData; 161e2914fddcd6d4f78d812ef818d43364d9aa469d4Sascha Haeberling private final int mOrientation; 162e2914fddcd6d4f78d812ef818d43364d9aa469d4Sascha Haeberling private final boolean mMirror; 163c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu 16429da2db13029f8896018836693139a05d1139362Doris Liu public DecodeTask(byte[] data, int orientation, boolean mirror) { 16537f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling mData = data; 166ce2acbcb77225b6d429a23e00f69aadde8c2378bDoris Liu mOrientation = orientation; 16729da2db13029f8896018836693139a05d1139362Doris Liu mMirror = mirror; 168c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu } 169c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu 170c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu @Override 17136e56fba281292255a01ee00b4bee067fa09ab59Doris Liu protected Bitmap doInBackground(Void... params) { 17237f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling // Decode image in background. 17300a764a3b6d9072413d18b441c759d4a604223b4Senpo Hu return PictureDecoder.decode(mData, DOWN_SAMPLE_FACTOR, mOrientation, mMirror); 17437f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling } 17537f3611bbdc787c996a99894dcef7d8fb77e3f7cSascha Haeberling } 176c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu 17736e56fba281292255a01ee00b4bee067fa09ab59Doris Liu private class DecodeImageForReview extends DecodeTask { 17836e56fba281292255a01ee00b4bee067fa09ab59Doris Liu public DecodeImageForReview(byte[] data, int orientation, boolean mirror) { 17936e56fba281292255a01ee00b4bee067fa09ab59Doris Liu super(data, orientation, mirror); 18036e56fba281292255a01ee00b4bee067fa09ab59Doris Liu } 18136e56fba281292255a01ee00b4bee067fa09ab59Doris Liu 18236e56fba281292255a01ee00b4bee067fa09ab59Doris Liu @Override 18336e56fba281292255a01ee00b4bee067fa09ab59Doris Liu protected void onPostExecute(Bitmap bitmap) { 18436e56fba281292255a01ee00b4bee067fa09ab59Doris Liu if (isCancelled()) { 18536e56fba281292255a01ee00b4bee067fa09ab59Doris Liu return; 18636e56fba281292255a01ee00b4bee067fa09ab59Doris Liu } 187b4a2222950f627a39267636fba19649974cb8734Spike Sprague 188b4a2222950f627a39267636fba19649974cb8734Spike Sprague mIntentReviewImageView.setImageBitmap(bitmap); 189b4a2222950f627a39267636fba19649974cb8734Spike Sprague showIntentReviewImageView(); 190b4a2222950f627a39267636fba19649974cb8734Spike Sprague 19136e56fba281292255a01ee00b4bee067fa09ab59Doris Liu mDecodeTaskForReview = null; 19236e56fba281292255a01ee00b4bee067fa09ab59Doris Liu } 19336e56fba281292255a01ee00b4bee067fa09ab59Doris Liu } 19436e56fba281292255a01ee00b4bee067fa09ab59Doris Liu 195d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public PhotoUI(CameraActivity activity, PhotoController controller, View parent) { 196d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb mActivity = activity; 197d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb mController = controller; 198d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb mRootView = parent; 199d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 200f55f3c461c5a6ae6b61fa75562ca01683aa93f9aDoris Liu ViewGroup moduleRoot = (ViewGroup) mRootView.findViewById(R.id.module_layout); 201d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb mActivity.getLayoutInflater().inflate(R.layout.photo_module, 202e2914fddcd6d4f78d812ef818d43364d9aa469d4Sascha Haeberling moduleRoot, true); 203d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb initIndicators(); 204987ee64612e2510004fdf08536746c87234d01c1Paul Rohde mFocusRing = (FocusRing) mRootView.findViewById(R.id.focus_ring); 205f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liu mPreviewOverlay = (PreviewOverlay) mRootView.findViewById(R.id.preview_overlay); 2066c75164c89f3bbd4f894b9c49a7914a24268a999Doris Liu mCountdownView = (CountDownView) mRootView.findViewById(R.id.count_down_view); 20762b4c3c0da3abd397b3790820359927784c50bc2Andy Huibers // Show faces if we are in debug mode. 20862b4c3c0da3abd397b3790820359927784c50bc2Andy Huibers if (DebugPropertyHelper.showCaptureDebugUI()) { 20962b4c3c0da3abd397b3790820359927784c50bc2Andy Huibers mFaceView = (FaceView) mRootView.findViewById(R.id.face_view); 21062b4c3c0da3abd397b3790820359927784c50bc2Andy Huibers } else { 21162b4c3c0da3abd397b3790820359927784c50bc2Andy Huibers mFaceView = null; 21262b4c3c0da3abd397b3790820359927784c50bc2Andy Huibers } 213b4a2222950f627a39267636fba19649974cb8734Spike Sprague 214b4a2222950f627a39267636fba19649974cb8734Spike Sprague if (mController.isImageCaptureIntent()) { 21502b9b9af097ac7886ec1d23392cd87c9fbcb186fSpike Sprague initIntentReviewImageView(); 216b4a2222950f627a39267636fba19649974cb8734Spike Sprague } 217b4a2222950f627a39267636fba19649974cb8734Spike Sprague } 218b4a2222950f627a39267636fba19649974cb8734Spike Sprague 21902b9b9af097ac7886ec1d23392cd87c9fbcb186fSpike Sprague private void initIntentReviewImageView() { 22002b9b9af097ac7886ec1d23392cd87c9fbcb186fSpike Sprague mIntentReviewImageView = (ImageView) mRootView.findViewById(R.id.intent_review_imageview); 221b4a2222950f627a39267636fba19649974cb8734Spike Sprague mActivity.getCameraAppUI().addPreviewAreaChangedListener( 222b4a2222950f627a39267636fba19649974cb8734Spike Sprague new PreviewStatusListener.PreviewAreaChangedListener() { 223b4a2222950f627a39267636fba19649974cb8734Spike Sprague @Override 224b4a2222950f627a39267636fba19649974cb8734Spike Sprague public void onPreviewAreaChanged(RectF previewArea) { 225b4a2222950f627a39267636fba19649974cb8734Spike Sprague FrameLayout.LayoutParams params = 226b4a2222950f627a39267636fba19649974cb8734Spike Sprague (FrameLayout.LayoutParams) mIntentReviewImageView.getLayoutParams(); 227b4a2222950f627a39267636fba19649974cb8734Spike Sprague params.width = (int) previewArea.width(); 228b4a2222950f627a39267636fba19649974cb8734Spike Sprague params.height = (int) previewArea.height(); 229b4a2222950f627a39267636fba19649974cb8734Spike Sprague params.setMargins((int) previewArea.left, (int) previewArea.top, 0, 0); 230b4a2222950f627a39267636fba19649974cb8734Spike Sprague mIntentReviewImageView.setLayoutParams(params); 231b4a2222950f627a39267636fba19649974cb8734Spike Sprague } 232b4a2222950f627a39267636fba19649974cb8734Spike Sprague }); 233b4a2222950f627a39267636fba19649974cb8734Spike Sprague } 234b4a2222950f627a39267636fba19649974cb8734Spike Sprague 235b4a2222950f627a39267636fba19649974cb8734Spike Sprague /** 236b4a2222950f627a39267636fba19649974cb8734Spike Sprague * Show the image review over the live preview for intent captures. 237b4a2222950f627a39267636fba19649974cb8734Spike Sprague */ 238b4a2222950f627a39267636fba19649974cb8734Spike Sprague public void showIntentReviewImageView() { 239b4a2222950f627a39267636fba19649974cb8734Spike Sprague if (mIntentReviewImageView != null) { 240b4a2222950f627a39267636fba19649974cb8734Spike Sprague mIntentReviewImageView.setVisibility(View.VISIBLE); 241b4a2222950f627a39267636fba19649974cb8734Spike Sprague } 2426432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu } 2436432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu 244b4a2222950f627a39267636fba19649974cb8734Spike Sprague /** 245b4a2222950f627a39267636fba19649974cb8734Spike Sprague * Hide the image review over the live preview for intent captures. 246b4a2222950f627a39267636fba19649974cb8734Spike Sprague */ 247b4a2222950f627a39267636fba19649974cb8734Spike Sprague public void hideIntentReviewImageView() { 248b4a2222950f627a39267636fba19649974cb8734Spike Sprague if (mIntentReviewImageView != null) { 249b4a2222950f627a39267636fba19649974cb8734Spike Sprague mIntentReviewImageView.setVisibility(View.INVISIBLE); 250b4a2222950f627a39267636fba19649974cb8734Spike Sprague } 251b4a2222950f627a39267636fba19649974cb8734Spike Sprague } 252b4a2222950f627a39267636fba19649974cb8734Spike Sprague 253b4a2222950f627a39267636fba19649974cb8734Spike Sprague 254987ee64612e2510004fdf08536746c87234d01c1Paul Rohde public FocusRing getFocusRing() { 255987ee64612e2510004fdf08536746c87234d01c1Paul Rohde return mFocusRing; 256482de029dc20e0a577388a602985fb31c3200309Doris Liu } 257482de029dc20e0a577388a602985fb31c3200309Doris Liu 258d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu public void updatePreviewAspectRatio(float aspectRatio) { 259d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu if (aspectRatio <= 0) { 260d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu Log.e(TAG, "Invalid aspect ratio: " + aspectRatio); 261d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu return; 262d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu } 263d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu if (aspectRatio < 1f) { 264d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu aspectRatio = 1f / aspectRatio; 265d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu } 266d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu 267d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu if (mAspectRatio != aspectRatio) { 268d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu mAspectRatio = aspectRatio; 269d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu // Update transform matrix with the new aspect ratio. 27070da918464276b110c43868caa272c97baadb89eDoris Liu mController.updatePreviewAspectRatio(mAspectRatio); 271d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu } 272d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu } 273d053a5b2aa8cd9cb09bd40962b305ef34e7d404bDoris Liu 274dcccc510652b835fdbd39310a07849af8203052aAngus Kong @Override 2756432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { 276d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren mController.onPreviewUIReady(); 2776432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu } 278d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 279dcccc510652b835fdbd39310a07849af8203052aAngus Kong @Override 2806432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { 2816432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu // Ignored, Camera does all the work for us 2826432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu } 2836432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu 284dcccc510652b835fdbd39310a07849af8203052aAngus Kong @Override 2856432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { 286d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren mController.onPreviewUIDestroyed(); 287d8de077f72b04cee1bdf26e5ca1678ac5297bd71Erin Dahlgren return true; 2886432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu } 2896432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu 2907b265a6b2f55c6ae7afc30e63ba324c4084a5d8eztenghui @Override 2916432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu public void onSurfaceTextureUpdated(SurfaceTexture surface) { 292d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 293d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 294d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb private void initIndicators() { 2950744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen // TODO init toggle buttons on bottom bar here 296d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 297d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 2986607dae6c4d1ee5bbf572695c2042d4d9129a730Angus Kong public void onCameraOpened(CameraCapabilities capabilities, CameraSettings settings) { 2996607dae6c4d1ee5bbf572695c2042d4d9129a730Angus Kong initializeZoom(capabilities, settings); 300eb3134f6ecc42f7d98625ca2c0ddfb06c9f07c43Spike Sprague } 301eb3134f6ecc42f7d98625ca2c0ddfb06c9f07c43Spike Sprague 3020a6a8d8e4e1c9796aac606379a42970cdffb8911Erin Dahlgren public void animateCapture(final byte[] jpegData, int orientation, boolean mirror) { 3030a6a8d8e4e1c9796aac606379a42970cdffb8911Erin Dahlgren // Decode jpeg byte array and then animate the jpeg 3040a6a8d8e4e1c9796aac606379a42970cdffb8911Erin Dahlgren DecodeTask task = new DecodeTask(jpegData, orientation, mirror); 3050a6a8d8e4e1c9796aac606379a42970cdffb8911Erin Dahlgren task.execute(); 306eb3134f6ecc42f7d98625ca2c0ddfb06c9f07c43Spike Sprague } 307d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 308d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb // called from onResume but only the first time 309ffbc43c3dd3c94a968a41431fb07645a13696c4aKevin Gabayan public void initializeFirstTime() { 3100744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen 311d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 312d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 313d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb // called from onResume every other time 3146607dae6c4d1ee5bbf572695c2042d4d9129a730Angus Kong public void initializeSecondTime(CameraCapabilities capabilities, CameraSettings settings) { 3156607dae6c4d1ee5bbf572695c2042d4d9129a730Angus Kong initializeZoom(capabilities, settings); 316d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb if (mController.isImageCaptureIntent()) { 317d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb hidePostCaptureAlert(); 318d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 319d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 320d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 3216607dae6c4d1ee5bbf572695c2042d4d9129a730Angus Kong public void initializeZoom(CameraCapabilities capabilities, CameraSettings settings) { 3226607dae6c4d1ee5bbf572695c2042d4d9129a730Angus Kong if ((capabilities == null) || settings == null || 3236607dae6c4d1ee5bbf572695c2042d4d9129a730Angus Kong !capabilities.supports(CameraCapabilities.Feature.ZOOM)) { 3241d943647c5b632588c4858ded04770e846341f1bSascha Haeberling return; 3251d943647c5b632588c4858ded04770e846341f1bSascha Haeberling } 3262192fbaaf598d4440a8d537a70095ea56bc9a5ebSol Boucher mZoomMax = capabilities.getMaxZoomRatio(); 327d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb // Currently we use immediate zoom for fast zooming to get better UX and 328d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb // there is no plan to take advantage of the smooth zoom. 329f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liu // TODO: Need to setup a path to AppUI to do this 3302192fbaaf598d4440a8d537a70095ea56bc9a5ebSol Boucher mPreviewOverlay.setupZoom(mZoomMax, settings.getCurrentZoomRatio(), 3316607dae6c4d1ee5bbf572695c2042d4d9129a730Angus Kong new ZoomChangeListener()); 332d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 333d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 334c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu public void animateFlash() { 3351dfe7828fd60741b9752553af3ee439c04e758a0Doris Liu mController.startPreCaptureAnimation(); 336c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu } 337c2e9abdcb39a9b8070889ff7a7d829b3eda0c51bDoris Liu 338d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public boolean onBackPressed() { 339d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb // In image capture mode, back button should: 340d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb // 1) if there is any popup, dismiss them, 2) otherwise, get out of 341d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb // image capture 342d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb if (mController.isImageCaptureIntent()) { 343c3679c0961521165499380c77344acc69072b2acDoris Liu mController.onCaptureCancelled(); 344d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb return true; 345d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } else if (!mController.isCameraIdle()) { 346d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb // ignore backs while we're taking a picture 347d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb return true; 348d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } else { 349c3679c0961521165499380c77344acc69072b2acDoris Liu return false; 350d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 351d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 352d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 35336e56fba281292255a01ee00b4bee067fa09ab59Doris Liu protected void showCapturedImageForReview(byte[] jpegData, int orientation, boolean mirror) { 35436e56fba281292255a01ee00b4bee067fa09ab59Doris Liu mDecodeTaskForReview = new DecodeImageForReview(jpegData, orientation, mirror); 35536e56fba281292255a01ee00b4bee067fa09ab59Doris Liu mDecodeTaskForReview.execute(); 3564efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren 3574efa8b54c1df4e06f2d3caed2568015a737f9ddaErin Dahlgren mActivity.getCameraAppUI().transitionToIntentReviewLayout(); 358d31cdfeb1035df8ba939e877031769f0df247aa6Doris Liu pauseFaceDetection(); 359d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 360d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 361d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb protected void hidePostCaptureAlert() { 36236e56fba281292255a01ee00b4bee067fa09ab59Doris Liu if (mDecodeTaskForReview != null) { 36336e56fba281292255a01ee00b4bee067fa09ab59Doris Liu mDecodeTaskForReview.cancel(true); 36436e56fba281292255a01ee00b4bee067fa09ab59Doris Liu } 365d31cdfeb1035df8ba939e877031769f0df247aa6Doris Liu resumeFaceDetection(); 366d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 367d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 368d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void setDisplayOrientation(int orientation) { 369d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb if (mFaceView != null) { 370d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb mFaceView.setDisplayOrientation(orientation); 371d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 372d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 373d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 374f9e4f8fbd1f761443d7a1eecbb5aa221ed3a06a8Doris Liu private class ZoomChangeListener implements PreviewOverlay.OnZoomChangedListener { 375d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb @Override 3762192fbaaf598d4440a8d537a70095ea56bc9a5ebSol Boucher public void onZoomValueChanged(float ratio) { 3772192fbaaf598d4440a8d537a70095ea56bc9a5ebSol Boucher mController.onZoomChanged(ratio); 378d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 379d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 380d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb @Override 381d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void onZoomStart() { 382d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 383d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 384d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb @Override 385d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void onZoomEnd() { 386d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 387d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 388d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 3896432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu public void setSwipingEnabled(boolean enable) { 3906432cd65159731a28d9239426b0f0f4d7c44fa98Doris Liu mActivity.setSwipingEnabled(enable); 391d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 392d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 393d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void onPause() { 3941d943647c5b632588c4858ded04770e846341f1bSascha Haeberling if (mFaceView != null) { 3951d943647c5b632588c4858ded04770e846341f1bSascha Haeberling mFaceView.clear(); 3961d943647c5b632588c4858ded04770e846341f1bSascha Haeberling } 397db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu if (mDialog != null) { 398db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu mDialog.dismiss(); 399db8f97582d09cd36eee8cfe4ed43182bff63f8bdDoris Liu } 4007351415ddfaf7f563a4a12c9204e6feb20fdf49dAlan Newberger // recalculate aspect ratio when restarting. 4017351415ddfaf7f563a4a12c9204e6feb20fdf49dAlan Newberger mAspectRatio = 0.0f; 402d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 403d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 404d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void clearFaces() { 4050744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen if (mFaceView != null) { 4060744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen mFaceView.clear(); 4070744e4ab3ec5f0270bdad33e7c477f52ba680bbdMarco Nelissen } 408d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 409d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 410d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void pauseFaceDetection() { 4111d943647c5b632588c4858ded04770e846341f1bSascha Haeberling if (mFaceView != null) { 4121d943647c5b632588c4858ded04770e846341f1bSascha Haeberling mFaceView.pause(); 4131d943647c5b632588c4858ded04770e846341f1bSascha Haeberling } 414d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 415d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 416d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void resumeFaceDetection() { 4171d943647c5b632588c4858ded04770e846341f1bSascha Haeberling if (mFaceView != null) { 4181d943647c5b632588c4858ded04770e846341f1bSascha Haeberling mFaceView.resume(); 4191d943647c5b632588c4858ded04770e846341f1bSascha Haeberling } 420d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 421d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 422d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb public void onStartFaceDetection(int orientation, boolean mirror) { 423d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu if (mFaceView != null) { 424d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu mFaceView.clear(); 425d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu mFaceView.setVisibility(View.VISIBLE); 426d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu mFaceView.setDisplayOrientation(orientation); 427d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu mFaceView.setMirror(mirror); 428d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu mFaceView.resume(); 429d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu } 430d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 431d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 432d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb @Override 4335a344964cb003525727c31d295ca3a592c245606Sol Boucher public void onFaceDetection(Face[] faces, CameraAgent.CameraProxy camera) { 434d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu if (mFaceView != null) { 435d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu mFaceView.setFaces(faces); 436d27ea7be496ae823fa88b98760c1a9d9ce0d554dDoris Liu } 437d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb } 438d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb 439d6954f337e20365fc24ecffdd6f30e17c6b31effMichael Kolb} 440