1bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen/* 2bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * Copyright (C) 2011 The Android Open Source Project 3bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * 4bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * Licensed under the Apache License, Version 2.0 (the "License"); 5bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * you may not use this file except in compliance with the License. 6bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * You may obtain a copy of the License at 7bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * 8bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * http://www.apache.org/licenses/LICENSE-2.0 9bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * 10bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * Unless required by applicable law or agreed to in writing, software 11bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * distributed under the License is distributed on an "AS IS" BASIS, 12bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * See the License for the specific language governing permissions and 14bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen * limitations under the License. 15bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen */ 16bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 17bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenpackage com.android.camera.panorama; 18bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 195f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wangimport com.android.camera.ActivityBase; 20d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Liimport com.android.camera.CameraDisabledException; 21d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Liimport com.android.camera.CameraHardwareException; 22d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Liimport com.android.camera.CameraHolder; 23a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kongimport com.android.camera.Exif; 24d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Liimport com.android.camera.MenuHelper; 25d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Liimport com.android.camera.ModePicker; 26a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kongimport com.android.camera.OnClickAttr; 27d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Liimport com.android.camera.R; 28ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kongimport com.android.camera.RotateDialogController; 29fcdf619d92701052621a96572d956d047e07cf24Angus Kongimport com.android.camera.ShutterButton; 30d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Liimport com.android.camera.Storage; 31a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kongimport com.android.camera.Thumbnail; 32d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Liimport com.android.camera.Util; 33749d056cd82ebfe6e613596d9e22dd355aeeec41Chung-yih Wangimport com.android.camera.ui.PopupManager; 34d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wangimport com.android.camera.ui.Rotatable; 35a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kongimport com.android.camera.ui.RotateImageView; 36d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wangimport com.android.camera.ui.RotateLayout; 37a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kongimport com.android.camera.ui.SharePopup; 38d1cff41cd8ae0fc6e9df1050730bb5e47bd364afWu-cheng Li 399a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagnerimport android.content.ContentResolver; 40bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.content.Context; 41174b8b7fc4d55e8c63eb3ed0b71f1519a13e345dAngus Kongimport android.content.res.AssetFileDescriptor; 42d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wangimport android.content.pm.ActivityInfo; 43057040c0e19834d98719143c2627a9f0df3e4c35Angus Kongimport android.content.res.Resources; 44142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kongimport android.graphics.Bitmap; 45142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kongimport android.graphics.BitmapFactory; 468a2c41754655a3733175fce81fb7506ff7022959Angus Kongimport android.graphics.ImageFormat; 47bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.graphics.PixelFormat; 488a2c41754655a3733175fce81fb7506ff7022959Angus Kongimport android.graphics.Rect; 4941a2e9735136f372de95652d0828600282c8e967mbansalimport android.graphics.SurfaceTexture; 508a2c41754655a3733175fce81fb7506ff7022959Angus Kongimport android.graphics.YuvImage; 516f6ea6ab6dad370d2cc378be91a2649ae44b2c94Angus Kongimport android.hardware.Camera.Parameters; 526f6ea6ab6dad370d2cc378be91a2649ae44b2c94Angus Kongimport android.hardware.Camera.Size; 53bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.hardware.Sensor; 54bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.hardware.SensorManager; 55e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chenimport android.media.ExifInterface; 561461b5333aab31faee65272d64c2ac7f9809d4d0Eino-Ville Talvalaimport android.media.MediaActionSound; 57a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kongimport android.net.Uri; 58bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.os.Bundle; 598a2c41754655a3733175fce81fb7506ff7022959Angus Kongimport android.os.Handler; 60ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kongimport android.os.Message; 61174b8b7fc4d55e8c63eb3ed0b71f1519a13e345dAngus Kongimport android.os.ParcelFileDescriptor; 6262bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kongimport android.os.PowerManager; 63bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.util.Log; 64a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kongimport android.view.Gravity; 65c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kongimport android.view.Menu; 661413860cab487d4dfeaf9856e553665dadc5ef1cWu-cheng Liimport android.view.MenuItem; 67c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kongimport android.view.OrientationEventListener; 68bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.view.View; 69d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wangimport android.view.ViewGroup; 70a959d05b52ac4b27dcdfe3d3a4e72220cf69d47aWei-Ta Chenimport android.view.Window; 71bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.view.WindowManager; 72bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport android.widget.ImageView; 73fbc5751416caa3a0d065ae15f56d1fb0253552c5Angus Kongimport android.widget.TextView; 74bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 75ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kongimport java.io.ByteArrayOutputStream; 769a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagnerimport java.io.File; 77e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chenimport java.io.IOException; 78bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chenimport java.util.List; 79bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 80a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong/** 81a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong * Activity to handle panorama capturing. 82a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong */ 835f6e354a6e2a77aa935fcefeb33a9baa67d48aafChung-yih Wangpublic class PanoramaActivity extends ActivityBase implements 84fcdf619d92701052621a96572d956d047e07cf24Angus Kong ModePicker.OnModeChangeListener, SurfaceTexture.OnFrameAvailableListener, 85fcdf619d92701052621a96572d956d047e07cf24Angus Kong ShutterButton.OnShutterButtonListener, 8636839102e03107e3fb121197036365a58ec2686eAngus Kong MosaicRendererSurfaceViewRenderer.MosaicSurfaceCreateListener { 87ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong public static final int DEFAULT_SWEEP_ANGLE = 160; 88bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen public static final int DEFAULT_BLEND_MODE = Mosaic.BLENDTYPE_HORIZONTAL; 89bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen public static final int DEFAULT_CAPTURE_PIXELS = 960 * 720; 90bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 912f9ed6f52580b8fecb77ec3ca123a804eea89f8cAngus Kong private static final int MSG_LOW_RES_FINAL_MOSAIC_READY = 1; 92a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong private static final int MSG_RESET_TO_PREVIEW_WITH_THUMBNAIL = 2; 9322d4b7fbace56c03092eb088a4df98e04a6681afAngus Kong private static final int MSG_GENERATE_FINAL_MOSAIC_ERROR = 3; 9459a140990af1ba6d2c9aa627047a02e50c8dd0e1Angus Kong private static final int MSG_RESET_TO_PREVIEW = 4; 95bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang private static final int MSG_CLEAR_SCREEN_DELAY = 5; 96bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang 97bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang private static final int SCREEN_DELAY = 2 * 60 * 1000; 9894f592fc405ca45b8794007cd9083c3250924b50Wei-Ta Chen 99ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong private static final String TAG = "PanoramaActivity"; 10098f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen private static final int PREVIEW_STOPPED = 0; 10198f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen private static final int PREVIEW_ACTIVE = 1; 102a466abbd54caa8100a1ef6584a5b0db78224a125Angus Kong private static final int CAPTURE_STATE_VIEWFINDER = 0; 103a466abbd54caa8100a1ef6584a5b0db78224a125Angus Kong private static final int CAPTURE_STATE_MOSAIC = 1; 10441a2e9735136f372de95652d0828600282c8e967mbansal 10543b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen // Speed is in unit of deg/sec 106e47b5624a1aa3cc7bd9763852bed4ac3215a77b2Wei-Ta Chen private static final float PANNING_SPEED_THRESHOLD = 20f; 10743b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen 108a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong // Ratio of nanosecond to second 109a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong private static final float NS2S = 1.0f / 1000000000.0f; 110142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 111142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong private boolean mPausing; 112142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 1137648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li private View mPanoLayout; 114a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong private View mCaptureLayout; 115a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong private View mReviewLayout; 116bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private ImageView mReview; 117d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang private RotateLayout mCaptureIndicator; 118057040c0e19834d98719143c2627a9f0df3e4c35Angus Kong private PanoProgressBar mPanoProgressBar; 119215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong private PanoProgressBar mSavingProgressBar; 1208b0e23544474480345937c0c0985429f61569761Angus Kong private View mFastIndicationBorder; 1216108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong private View mLeftIndicator; 1226108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong private View mRightIndicator; 1232faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong private MosaicRendererSurfaceView mMosaicView; 124fbc5751416caa3a0d065ae15f56d1fb0253552c5Angus Kong private TextView mTooFastPrompt; 125fcdf619d92701052621a96572d956d047e07cf24Angus Kong private ShutterButton mShutterButton; 126215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong private Object mWaitObject = new Object(); 127142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 1285fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong private String mPreparePreviewString; 12922d4b7fbace56c03092eb088a4df98e04a6681afAngus Kong private String mDialogTitle; 130d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang private String mDialogOkString; 131d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang private String mDialogPanoramaFailedString; 1322f9ed6f52580b8fecb77ec3ca123a804eea89f8cAngus Kong 133fa959aede9b1fe9d510108e883a2f16cf28c9033Angus Kong private int mIndicatorColor; 134fa959aede9b1fe9d510108e883a2f16cf28c9033Angus Kong private int mIndicatorColorFast; 135fa959aede9b1fe9d510108e883a2f16cf28c9033Angus Kong 136c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private float mCompassValueX; 137c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private float mCompassValueY; 138c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private float mCompassValueXStart; 139c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private float mCompassValueYStart; 140c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private float mCompassValueXStartBuffer; 141c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private float mCompassValueYStartBuffer; 142c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private int mCompassThreshold; 143c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private int mTraversedAngleX; 144c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private int mTraversedAngleY; 145c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private long mTimestamp; 146c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong 147a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong private RotateImageView mThumbnailView; 148a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong private Thumbnail mThumbnail; 149a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong private SharePopup mSharePopup; 150a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong 151bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private int mPreviewWidth; 152bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private int mPreviewHeight; 15398f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen private int mCameraState; 15441a2e9735136f372de95652d0828600282c8e967mbansal private int mCaptureState; 155bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private SensorManager mSensorManager; 156bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private Sensor mSensor; 15762bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong private PowerManager.WakeLock mPartialWakeLock; 158a72d73cbac59db43d413291e4db66763be08143arepo sync private ModePicker mModePicker; 1598a2c41754655a3733175fce81fb7506ff7022959Angus Kong private MosaicFrameProcessor mMosaicFrameProcessor; 1608a2c41754655a3733175fce81fb7506ff7022959Angus Kong private long mTimeTaken; 161ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong private Handler mMainHandler; 1622faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong private SurfaceTexture mSurfaceTexture; 163142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong private boolean mThreadRunning; 164e1178a73fd5756771d25d0b8375452450f509e99mbansal private boolean mCancelComputation; 1652faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong private float[] mTransformMatrix; 16643b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen private float mHorizontalViewAngle; 1672d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen private float mVerticalViewAngle; 168c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong 169d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen // Prefer FOCUS_MODE_INFINITY to FOCUS_MODE_CONTINUOUS_VIDEO because of 170d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen // getting a better image quality by the former. 171d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen private String mTargetFocusMode = Parameters.FOCUS_MODE_INFINITY; 172d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen 173c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private PanoOrientationEventListener mOrientationEventListener; 17422400adc90877480c3229d0ee86df9a6736c66cdAngus Kong // The value could be 0, 90, 180, 270 for the 4 different orientations measured in clockwise 175c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong // respectively. 176c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private int mDeviceOrientation; 177e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen private int mDeviceOrientationAtCapture; 178e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen private int mCameraOrientation; 1795201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner private int mOrientationCompensation; 180142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 181ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong private RotateDialogController mRotateDialog; 182ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong 1831461b5333aab31faee65272d64c2ac7f9809d4d0Eino-Ville Talvala private MediaActionSound mCameraSound; 18490089f9eddde732725c43dcad07f4567ed8cb776Wu-cheng Li 1857648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li private class MosaicJpeg { 1867648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li public MosaicJpeg(byte[] data, int width, int height) { 1877648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li this.data = data; 1887648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li this.width = width; 1897648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li this.height = height; 19013e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong this.isValid = true; 19113e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong } 19213e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong 19313e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong public MosaicJpeg() { 19413e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong this.data = null; 19513e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong this.width = 0; 19613e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong this.height = 0; 19713e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong this.isValid = false; 1987648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li } 1997648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li 2007648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li public final byte[] data; 2017648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li public final int width; 2027648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li public final int height; 20313e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong public final boolean isValid; 2047648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li } 2057648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li 206c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong private class PanoOrientationEventListener extends OrientationEventListener { 207c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong public PanoOrientationEventListener(Context context) { 208c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong super(context); 209c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong } 210c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong 211c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong @Override 212c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong public void onOrientationChanged(int orientation) { 2135201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner // We keep the last known orientation. So if the user first orient 2145201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner // the camera then point the camera to floor or sky, we still have 2155201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner // the correct orientation. 216c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong if (orientation == ORIENTATION_UNKNOWN) return; 217131cf9886c4f34431598be0b1f5b7aaa915277ccEino-Ville Talvala mDeviceOrientation = Util.roundOrientation(orientation, mDeviceOrientation); 2185201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner // When the screen is unlocked, display rotation may change. Always 2195201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner // calculate the up-to-date orientationCompensation. 2205201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner int orientationCompensation = mDeviceOrientation 2215201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner + Util.getDisplayRotation(PanoramaActivity.this); 2225201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner if (mOrientationCompensation != orientationCompensation) { 2235201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner mOrientationCompensation = orientationCompensation; 2245201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner setOrientationIndicator(mOrientationCompensation); 2255201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner } 226c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong } 227c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong } 228c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong 2295201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner private void setOrientationIndicator(int degree) { 2305201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner if (mSharePopup != null) mSharePopup.setOrientation(degree); 2315201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner } 2325201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner 233bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen @Override 234c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong public boolean onCreateOptionsMenu(Menu menu) { 235c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong super.onCreateOptionsMenu(menu); 236c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong 237c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong addBaseMenuItems(menu); 238c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong return true; 239c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong } 240c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong 2411413860cab487d4dfeaf9856e553665dadc5ef1cWu-cheng Li @Override 2421413860cab487d4dfeaf9856e553665dadc5ef1cWu-cheng Li public boolean onPrepareOptionsMenu(Menu menu) { 2431413860cab487d4dfeaf9856e553665dadc5ef1cWu-cheng Li super.onPrepareOptionsMenu(menu); 2441413860cab487d4dfeaf9856e553665dadc5ef1cWu-cheng Li // Only show the menu when idle. 2451413860cab487d4dfeaf9856e553665dadc5ef1cWu-cheng Li boolean idle = (mCaptureState == CAPTURE_STATE_VIEWFINDER && !mThreadRunning); 2461413860cab487d4dfeaf9856e553665dadc5ef1cWu-cheng Li for (int i = 0; i < menu.size(); i++) { 2471413860cab487d4dfeaf9856e553665dadc5ef1cWu-cheng Li MenuItem item = menu.getItem(i); 2481413860cab487d4dfeaf9856e553665dadc5ef1cWu-cheng Li item.setVisible(idle); 2491413860cab487d4dfeaf9856e553665dadc5ef1cWu-cheng Li item.setEnabled(idle); 2501413860cab487d4dfeaf9856e553665dadc5ef1cWu-cheng Li } 2511413860cab487d4dfeaf9856e553665dadc5ef1cWu-cheng Li 2521413860cab487d4dfeaf9856e553665dadc5ef1cWu-cheng Li return true; 2531413860cab487d4dfeaf9856e553665dadc5ef1cWu-cheng Li } 2541413860cab487d4dfeaf9856e553665dadc5ef1cWu-cheng Li 255c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong private void addBaseMenuItems(Menu menu) { 256c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong MenuHelper.addSwitchModeMenuItem(menu, ModePicker.MODE_CAMERA, new Runnable() { 257c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong public void run() { 258c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong switchToOtherMode(ModePicker.MODE_CAMERA); 259c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong } 260c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong }); 261c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong MenuHelper.addSwitchModeMenuItem(menu, ModePicker.MODE_VIDEO, new Runnable() { 262c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong public void run() { 263c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong switchToOtherMode(ModePicker.MODE_VIDEO); 264c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong } 265c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong }); 266c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong } 267c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong 268c159dfe54fbc0f055a1d760f1614db4a8bcec94cAngus Kong @Override 269bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen public void onCreate(Bundle icicle) { 270bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen super.onCreate(icicle); 271bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 272a959d05b52ac4b27dcdfe3d3a4e72220cf69d47aWei-Ta Chen Window window = getWindow(); 273a959d05b52ac4b27dcdfe3d3a4e72220cf69d47aWei-Ta Chen Util.enterLightsOutMode(window); 274a959d05b52ac4b27dcdfe3d3a4e72220cf69d47aWei-Ta Chen Util.initializeScreenBrightness(window, getContentResolver()); 275bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 276bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen createContentView(); 277bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 278bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); 279bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); 280bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen if (mSensor == null) { 281bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); 282bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 28362bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); 28462bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Panorama"); 2858a2c41754655a3733175fce81fb7506ff7022959Angus Kong 286c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong mOrientationEventListener = new PanoOrientationEventListener(this); 287c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong 2882faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mTransformMatrix = new float[16]; 2892faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong 2905fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong mPreparePreviewString = 2915fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong getResources().getString(R.string.pano_dialog_prepare_preview); 29222d4b7fbace56c03092eb088a4df98e04a6681afAngus Kong mDialogTitle = getResources().getString(R.string.pano_dialog_title); 293d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang mDialogOkString = getResources().getString(R.string.dialog_ok); 294d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang mDialogPanoramaFailedString = 295d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang getResources().getString(R.string.pano_dialog_panorama_failed); 2961461b5333aab31faee65272d64c2ac7f9809d4d0Eino-Ville Talvala mCameraSound = new MediaActionSound(); 2975fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong 298ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong mMainHandler = new Handler() { 299ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong @Override 300ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong public void handleMessage(Message msg) { 301ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong switch (msg.what) { 3022f9ed6f52580b8fecb77ec3ca123a804eea89f8cAngus Kong case MSG_LOW_RES_FINAL_MOSAIC_READY: 3035fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong onBackgroundThreadFinished(); 304142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong showFinalMosaic((Bitmap) msg.obj); 305215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong saveHighResMosaic(); 306142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong break; 307a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong case MSG_RESET_TO_PREVIEW_WITH_THUMBNAIL: 3085fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong onBackgroundThreadFinished(); 30962bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong // If the activity is paused, save the thumbnail to the file here. 31062bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong // If not, it will be saved in onPause. 31162bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong if (mPausing) saveThumbnailToFile(); 312a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong // Set the thumbnail bitmap here because mThumbnailView must be accessed 313a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong // from the UI thread. 3149a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner updateThumbnailButton(); 3159a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner 316db288b8686e5bcecef620176b934b00eb0742597Wu-cheng Li // Share popup may still have the reference to the old thumbnail. Clear it. 317db288b8686e5bcecef620176b934b00eb0742597Wu-cheng Li mSharePopup = null; 318142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong resetToPreview(); 319142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong break; 32022d4b7fbace56c03092eb088a4df98e04a6681afAngus Kong case MSG_GENERATE_FINAL_MOSAIC_ERROR: 32122d4b7fbace56c03092eb088a4df98e04a6681afAngus Kong onBackgroundThreadFinished(); 3223eaaa3f1fc7b3079e0edc66ed61d5e48b7cc44ccAngus Kong if (mPausing) { 3233eaaa3f1fc7b3079e0edc66ed61d5e48b7cc44ccAngus Kong resetToPreview(); 3243eaaa3f1fc7b3079e0edc66ed61d5e48b7cc44ccAngus Kong } else { 325ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong mRotateDialog.showAlertDialog( 326ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong mDialogTitle, mDialogPanoramaFailedString, 327ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong mDialogOkString, new Runnable() { 328ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong @Override 329ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong public void run() { 330ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong resetToPreview(); 331ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong }}, 332ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong null, null); 3333eaaa3f1fc7b3079e0edc66ed61d5e48b7cc44ccAngus Kong } 33422d4b7fbace56c03092eb088a4df98e04a6681afAngus Kong break; 33513e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong case MSG_RESET_TO_PREVIEW: 336e1178a73fd5756771d25d0b8375452450f509e99mbansal onBackgroundThreadFinished(); 337e1178a73fd5756771d25d0b8375452450f509e99mbansal resetToPreview(); 338bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang break; 339bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang case MSG_CLEAR_SCREEN_DELAY: 340bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang getWindow().clearFlags(WindowManager.LayoutParams. 341bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang FLAG_KEEP_SCREEN_ON); 342bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang break; 343ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong } 344142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong clearMosaicFrameProcessorIfNeeded(); 345ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong } 346ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong }; 347d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang } 34859a140990af1ba6d2c9aa627047a02e50c8dd0e1Angus Kong 34980583a299a9c8964cf09e482380c3bda0670ad6fChih-yu Huang private void setupCamera() throws CameraHardwareException, CameraDisabledException { 350bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen openCamera(); 351bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen Parameters parameters = mCameraDevice.getParameters(); 352bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen setupCaptureParams(parameters); 353bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen configureCamera(parameters); 354bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 355bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 356ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong private void releaseCamera() { 357ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong if (mCameraDevice != null) { 358142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong mCameraDevice.setPreviewCallbackWithBuffer(null); 359ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong CameraHolder.instance().release(); 360ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong mCameraDevice = null; 36198f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen mCameraState = PREVIEW_STOPPED; 362ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong } 363ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong } 364ac86e91982dbb64eac089aa8ccf23bddb51f27f1Angus Kong 36580583a299a9c8964cf09e482380c3bda0670ad6fChih-yu Huang private void openCamera() throws CameraHardwareException, CameraDisabledException { 36680583a299a9c8964cf09e482380c3bda0670ad6fChih-yu Huang int backCameraId = CameraHolder.instance().getBackCameraId(); 36780583a299a9c8964cf09e482380c3bda0670ad6fChih-yu Huang mCameraDevice = Util.openCamera(this, backCameraId); 36880583a299a9c8964cf09e482380c3bda0670ad6fChih-yu Huang mCameraOrientation = Util.getCameraOrientation(backCameraId); 369bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 370bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 371bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private boolean findBestPreviewSize(List<Size> supportedSizes, boolean need4To3, 372bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen boolean needSmaller) { 373bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen int pixelsDiff = DEFAULT_CAPTURE_PIXELS; 374bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen boolean hasFound = false; 3758a2c41754655a3733175fce81fb7506ff7022959Angus Kong for (Size size : supportedSizes) { 376bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen int h = size.height; 377bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen int w = size.width; 378bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen // we only want 4:3 format. 379bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen int d = DEFAULT_CAPTURE_PIXELS - h * w; 38094f592fc405ca45b8794007cd9083c3250924b50Wei-Ta Chen if (needSmaller && d < 0) { // no bigger preview than 960x720. 381bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen continue; 382bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 383bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen if (need4To3 && (h * 4 != w * 3)) { 384bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen continue; 385bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 386bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen d = Math.abs(d); 387bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen if (d < pixelsDiff) { 388bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mPreviewWidth = w; 389bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mPreviewHeight = h; 390bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen pixelsDiff = d; 391bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen hasFound = true; 392bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 393bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 394bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen return hasFound; 395bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 396bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 397bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private void setupCaptureParams(Parameters parameters) { 398bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen List<Size> supportedSizes = parameters.getSupportedPreviewSizes(); 399bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen if (!findBestPreviewSize(supportedSizes, true, true)) { 400bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen Log.w(TAG, "No 4:3 ratio preview size supported."); 401bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen if (!findBestPreviewSize(supportedSizes, false, true)) { 402bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen Log.w(TAG, "Can't find a supported preview size smaller than 960x720."); 403bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen findBestPreviewSize(supportedSizes, false, false); 404bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 405bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 406bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen Log.v(TAG, "preview h = " + mPreviewHeight + " , w = " + mPreviewWidth); 407bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen parameters.setPreviewSize(mPreviewWidth, mPreviewHeight); 408bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 409bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen List<int[]> frameRates = parameters.getSupportedPreviewFpsRange(); 410bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen int last = frameRates.size() - 1; 411bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen int minFps = (frameRates.get(last))[Parameters.PREVIEW_FPS_MIN_INDEX]; 412bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen int maxFps = (frameRates.get(last))[Parameters.PREVIEW_FPS_MAX_INDEX]; 413bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen parameters.setPreviewFpsRange(minFps, maxFps); 414bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen Log.v(TAG, "preview fps: " + minFps + ", " + maxFps); 4153ab4f0912da83f7f5f8266a57a606d521c1649e3Wu-cheng Li 416d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen List<String> supportedFocusModes = parameters.getSupportedFocusModes(); 417d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen if (supportedFocusModes.indexOf(mTargetFocusMode) >= 0) { 418d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen parameters.setFocusMode(mTargetFocusMode); 419d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen } else { 420d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen // Use the default focus mode and log a message 421d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen Log.w(TAG, "Cannot set the focus mode to " + mTargetFocusMode + 422d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen " becuase the mode is not supported."); 423d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen } 424d3105c578427ac7507ca32ff1de4a92962de2357Wei-Ta Chen 42593ad273a53e7d2975a67d7d1f8a157f845e41cf2Wu-cheng Li parameters.setRecordingHint(false); 42643b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen 4272d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen mHorizontalViewAngle = parameters.getHorizontalViewAngle(); 4282d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen mVerticalViewAngle = parameters.getVerticalViewAngle(); 429bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 430bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 431bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen public int getPreviewBufSize() { 432bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen PixelFormat pixelInfo = new PixelFormat(); 433bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen PixelFormat.getPixelFormatInfo(mCameraDevice.getParameters().getPreviewFormat(), pixelInfo); 434bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen // TODO: remove this extra 32 byte after the driver bug is fixed. 435bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen return (mPreviewWidth * mPreviewHeight * pixelInfo.bitsPerPixel / 8) + 32; 436bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 437bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 438bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private void configureCamera(Parameters parameters) { 439bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen mCameraDevice.setParameters(parameters); 440bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 441bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 442a72d73cbac59db43d413291e4db66763be08143arepo sync private boolean switchToOtherMode(int mode) { 443a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong if (isFinishing()) { 44494f592fc405ca45b8794007cd9083c3250924b50Wei-Ta Chen return false; 445a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong } 446a72d73cbac59db43d413291e4db66763be08143arepo sync MenuHelper.gotoMode(mode, this); 447a72d73cbac59db43d413291e4db66763be08143arepo sync finish(); 448a72d73cbac59db43d413291e4db66763be08143arepo sync return true; 449a72d73cbac59db43d413291e4db66763be08143arepo sync } 450a72d73cbac59db43d413291e4db66763be08143arepo sync 451a72d73cbac59db43d413291e4db66763be08143arepo sync public boolean onModeChanged(int mode) { 452a72d73cbac59db43d413291e4db66763be08143arepo sync if (mode != ModePicker.MODE_PANORAMA) { 453a72d73cbac59db43d413291e4db66763be08143arepo sync return switchToOtherMode(mode); 454a72d73cbac59db43d413291e4db66763be08143arepo sync } else { 455a72d73cbac59db43d413291e4db66763be08143arepo sync return true; 456a72d73cbac59db43d413291e4db66763be08143arepo sync } 457a72d73cbac59db43d413291e4db66763be08143arepo sync } 458a72d73cbac59db43d413291e4db66763be08143arepo sync 4592faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong @Override 460575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi public void onMosaicSurfaceChanged() { 461575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi runOnUiThread(new Runnable() { 462575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi @Override 463575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi public void run() { 46462bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong // If panorama is generating low res or high res mosaic, it 46562bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong // means users exit and come back to panorama. Do not start the 46662bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong // preview. Preview will be started after final mosaic is 46762bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong // generated. 46862bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong if (!mPausing && !mThreadRunning) { 469575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi startCameraPreview(); 470575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi } 471575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi } 472575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi }); 473575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi } 474575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi 475575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi @Override 4762faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong public void onMosaicSurfaceCreated(final int textureID) { 47736839102e03107e3fb121197036365a58ec2686eAngus Kong runOnUiThread(new Runnable() { 47836839102e03107e3fb121197036365a58ec2686eAngus Kong @Override 47936839102e03107e3fb121197036365a58ec2686eAngus Kong public void run() { 4802faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong if (mSurfaceTexture != null) { 4812faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mSurfaceTexture.release(); 4822faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong } 4832faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mSurfaceTexture = new SurfaceTexture(textureID); 4842faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong if (!mPausing) { 4852faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mSurfaceTexture.setOnFrameAvailableListener(PanoramaActivity.this); 4862faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong } 48736839102e03107e3fb121197036365a58ec2686eAngus Kong } 48836839102e03107e3fb121197036365a58ec2686eAngus Kong }); 48936839102e03107e3fb121197036365a58ec2686eAngus Kong } 49036839102e03107e3fb121197036365a58ec2686eAngus Kong 49141a2e9735136f372de95652d0828600282c8e967mbansal public void runViewFinder() { 4922faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.setWarping(false); 4932faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong // Call preprocess to render it to low-res and high-res RGB textures. 4942faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.preprocess(mTransformMatrix); 4952faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.setReady(); 4962faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.requestRender(); 49741a2e9735136f372de95652d0828600282c8e967mbansal } 49841a2e9735136f372de95652d0828600282c8e967mbansal 49941a2e9735136f372de95652d0828600282c8e967mbansal public void runMosaicCapture() { 5002faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.setWarping(true); 5012faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong // Call preprocess to render it to low-res and high-res RGB textures. 5022faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.preprocess(mTransformMatrix); 5032faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong // Lock the conditional variable to ensure the order of transferGPUtoCPU and 5042faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong // mMosaicFrame.processFrame(). 5052faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.lockPreviewReadyFlag(); 50641a2e9735136f372de95652d0828600282c8e967mbansal // Now, transfer the textures from GPU to CPU memory for processing 5072faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.transferGPUtoCPU(); 50841a2e9735136f372de95652d0828600282c8e967mbansal // Wait on the condition variable (will be opened when GPU->CPU transfer is done). 5092faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.waitUntilPreviewReady(); 5100adf2489520d3a98a56e081aeacb1ab9336a012fWei-Ta Chen mMosaicFrameProcessor.processFrame(); 51141a2e9735136f372de95652d0828600282c8e967mbansal } 51241a2e9735136f372de95652d0828600282c8e967mbansal 513739f9e1541c30735e45d5cb90255dd36a32d3604Angus Kong public synchronized void onFrameAvailable(SurfaceTexture surface) { 5144d1c2846e24a7f7f6c8ff59e01ca36a000344944Angus Kong /* This function may be called by some random thread, 51541a2e9735136f372de95652d0828600282c8e967mbansal * so let's be safe and use synchronize. No OpenGL calls can be done here. 51641a2e9735136f372de95652d0828600282c8e967mbansal */ 5170cefcea01849364be6955a1b3f7e7d1639010abcAngus Kong // Frames might still be available after the activity is paused. If we call onFrameAvailable 5180cefcea01849364be6955a1b3f7e7d1639010abcAngus Kong // after pausing, the GL thread will crash. 5190cefcea01849364be6955a1b3f7e7d1639010abcAngus Kong if (mPausing) return; 5200cefcea01849364be6955a1b3f7e7d1639010abcAngus Kong 5212faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong // Updating the texture should be done in the GL thread which mMosaicView is attached. 5222faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.queueEvent(new Runnable() { 5232faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong @Override 5242faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong public void run() { 5250cefcea01849364be6955a1b3f7e7d1639010abcAngus Kong // Check if the activity is paused here can speed up the onPause() process. 5260cefcea01849364be6955a1b3f7e7d1639010abcAngus Kong if (mPausing) return; 5272faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mSurfaceTexture.updateTexImage(); 5282faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mSurfaceTexture.getTransformMatrix(mTransformMatrix); 5292faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong } 5302faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong }); 5312faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong // Update the transformation matrix for mosaic pre-process. 532a466abbd54caa8100a1ef6584a5b0db78224a125Angus Kong if (mCaptureState == CAPTURE_STATE_VIEWFINDER) { 53341a2e9735136f372de95652d0828600282c8e967mbansal runViewFinder(); 53441a2e9735136f372de95652d0828600282c8e967mbansal } else { 53541a2e9735136f372de95652d0828600282c8e967mbansal runMosaicCapture(); 53641a2e9735136f372de95652d0828600282c8e967mbansal } 53741a2e9735136f372de95652d0828600282c8e967mbansal } 53841a2e9735136f372de95652d0828600282c8e967mbansal 5396108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong private void hideDirectionIndicators() { 5406108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong mLeftIndicator.setVisibility(View.GONE); 5416108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong mRightIndicator.setVisibility(View.GONE); 5426108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong } 5436108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong 5446108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong private void showDirectionIndicators(int direction) { 5456108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong switch (direction) { 5466108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong case PanoProgressBar.DIRECTION_NONE: 5476108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong mLeftIndicator.setVisibility(View.VISIBLE); 5486108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong mRightIndicator.setVisibility(View.VISIBLE); 5496108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong break; 5506108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong case PanoProgressBar.DIRECTION_LEFT: 5516108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong mLeftIndicator.setVisibility(View.VISIBLE); 5526108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong mRightIndicator.setVisibility(View.GONE); 5536108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong break; 5546108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong case PanoProgressBar.DIRECTION_RIGHT: 5556108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong mLeftIndicator.setVisibility(View.GONE); 5566108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong mRightIndicator.setVisibility(View.VISIBLE); 5576108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong break; 5586108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong } 5596108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong } 5606108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong 561a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong public void startCapture() { 5628a2c41754655a3733175fce81fb7506ff7022959Angus Kong // Reset values so we can do this again. 56313e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong mCancelComputation = false; 5648a2c41754655a3733175fce81fb7506ff7022959Angus Kong mTimeTaken = System.currentTimeMillis(); 565a466abbd54caa8100a1ef6584a5b0db78224a125Angus Kong mCaptureState = CAPTURE_STATE_MOSAIC; 566fcdf619d92701052621a96572d956d047e07cf24Angus Kong mShutterButton.setBackgroundResource(R.drawable.btn_shutter_pan_recording); 5678df38bbe67338a1f5dc58996bd8866f4c1fe264dAngus Kong mCaptureIndicator.setVisibility(View.VISIBLE); 5686108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong showDirectionIndicators(PanoProgressBar.DIRECTION_NONE); 5694a3026b84fa4fd403317b30b6a9db61125fecfa2heech.park mThumbnailView.setEnabled(false); 5708a2c41754655a3733175fce81fb7506ff7022959Angus Kong 571c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong mCompassValueXStart = mCompassValueXStartBuffer; 572c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong mCompassValueYStart = mCompassValueYStartBuffer; 573c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong mTimestamp = 0; 574c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong 5758a2c41754655a3733175fce81fb7506ff7022959Angus Kong mMosaicFrameProcessor.setProgressListener(new MosaicFrameProcessor.ProgressListener() { 5768a2c41754655a3733175fce81fb7506ff7022959Angus Kong @Override 577d991766dc3bcc03a02c6648e2cfd54ee4f8cbd9eAngus Kong public void onProgress(boolean isFinished, float panningRateX, float panningRateY, 578d991766dc3bcc03a02c6648e2cfd54ee4f8cbd9eAngus Kong float progressX, float progressY) { 5792d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen float accumulatedHorizontalAngle = progressX * mHorizontalViewAngle; 5802d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen float accumulatedVerticalAngle = progressY * mVerticalViewAngle; 581c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong if (isFinished 5822d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen || (Math.abs(accumulatedHorizontalAngle) >= DEFAULT_SWEEP_ANGLE) 5832d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen || (Math.abs(accumulatedVerticalAngle) >= DEFAULT_SWEEP_ANGLE)) { 58427c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong stopCapture(false); 5858a2c41754655a3733175fce81fb7506ff7022959Angus Kong } else { 5862d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen float panningRateXInDegree = panningRateX * mHorizontalViewAngle; 5872d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen float panningRateYInDegree = panningRateY * mVerticalViewAngle; 5882d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen updateProgress(panningRateXInDegree, panningRateYInDegree, 5892d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen accumulatedHorizontalAngle, accumulatedVerticalAngle); 5908a2c41754655a3733175fce81fb7506ff7022959Angus Kong } 5918a2c41754655a3733175fce81fb7506ff7022959Angus Kong } 5928a2c41754655a3733175fce81fb7506ff7022959Angus Kong }); 5938a2c41754655a3733175fce81fb7506ff7022959Angus Kong 5942512c685868eadb274f5be8cd71068078b1f5dddMark Wagner if (mModePicker != null) mModePicker.setEnabled(false); 5952512c685868eadb274f5be8cd71068078b1f5dddMark Wagner 596057040c0e19834d98719143c2627a9f0df3e4c35Angus Kong mPanoProgressBar.reset(); 597057040c0e19834d98719143c2627a9f0df3e4c35Angus Kong // TODO: calculate the indicator width according to different devices to reflect the actual 598057040c0e19834d98719143c2627a9f0df3e4c35Angus Kong // angle of view of the camera device. 599057040c0e19834d98719143c2627a9f0df3e4c35Angus Kong mPanoProgressBar.setIndicatorWidth(20); 600057040c0e19834d98719143c2627a9f0df3e4c35Angus Kong mPanoProgressBar.setMaxProgress(DEFAULT_SWEEP_ANGLE); 601057040c0e19834d98719143c2627a9f0df3e4c35Angus Kong mPanoProgressBar.setVisibility(View.VISIBLE); 602e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen mDeviceOrientationAtCapture = mDeviceOrientation; 603bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang keepScreenOn(); 6048a2c41754655a3733175fce81fb7506ff7022959Angus Kong } 6058a2c41754655a3733175fce81fb7506ff7022959Angus Kong 60627c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong private void stopCapture(boolean aborted) { 607a466abbd54caa8100a1ef6584a5b0db78224a125Angus Kong mCaptureState = CAPTURE_STATE_VIEWFINDER; 6088df38bbe67338a1f5dc58996bd8866f4c1fe264dAngus Kong mCaptureIndicator.setVisibility(View.GONE); 6098b0e23544474480345937c0c0985429f61569761Angus Kong hideTooFastIndication(); 6106108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong hideDirectionIndicators(); 6114a3026b84fa4fd403317b30b6a9db61125fecfa2heech.park mThumbnailView.setEnabled(true); 61241a2e9735136f372de95652d0828600282c8e967mbansal 6138a2c41754655a3733175fce81fb7506ff7022959Angus Kong mMosaicFrameProcessor.setProgressListener(null); 61436839102e03107e3fb121197036365a58ec2686eAngus Kong stopCameraPreview(); 61541a2e9735136f372de95652d0828600282c8e967mbansal 6162faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mSurfaceTexture.setOnFrameAvailableListener(null); 61741a2e9735136f372de95652d0828600282c8e967mbansal 61827c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong if (!aborted && !mThreadRunning) { 619ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong mRotateDialog.showWaitingDialog(mPreparePreviewString); 620215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong runBackgroundThread(new Thread() { 621142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong @Override 622142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong public void run() { 6237648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li MosaicJpeg jpeg = generateFinalMosaic(false); 624e1178a73fd5756771d25d0b8375452450f509e99mbansal 62513e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong if (jpeg != null && jpeg.isValid) { 626e1178a73fd5756771d25d0b8375452450f509e99mbansal Bitmap bitmap = null; 62713e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong bitmap = BitmapFactory.decodeByteArray(jpeg.data, 0, jpeg.data.length); 628e1178a73fd5756771d25d0b8375452450f509e99mbansal mMainHandler.sendMessage(mMainHandler.obtainMessage( 629e1178a73fd5756771d25d0b8375452450f509e99mbansal MSG_LOW_RES_FINAL_MOSAIC_READY, bitmap)); 63013e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong } else { 63113e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong mMainHandler.sendMessage(mMainHandler.obtainMessage( 63213e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong MSG_RESET_TO_PREVIEW)); 633ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong } 634142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 6355fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong }); 636142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 6372512c685868eadb274f5be8cd71068078b1f5dddMark Wagner // do we have to wait for the thread to complete before enabling this? 6382512c685868eadb274f5be8cd71068078b1f5dddMark Wagner if (mModePicker != null) mModePicker.setEnabled(true); 639bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang keepScreenOnAwhile(); 6408a2c41754655a3733175fce81fb7506ff7022959Angus Kong } 6418a2c41754655a3733175fce81fb7506ff7022959Angus Kong 6428b0e23544474480345937c0c0985429f61569761Angus Kong private void showTooFastIndication() { 6438b0e23544474480345937c0c0985429f61569761Angus Kong mTooFastPrompt.setVisibility(View.VISIBLE); 6448b0e23544474480345937c0c0985429f61569761Angus Kong mFastIndicationBorder.setVisibility(View.VISIBLE); 645fa959aede9b1fe9d510108e883a2f16cf28c9033Angus Kong mPanoProgressBar.setIndicatorColor(mIndicatorColorFast); 6468b0e23544474480345937c0c0985429f61569761Angus Kong mLeftIndicator.setEnabled(true); 6478b0e23544474480345937c0c0985429f61569761Angus Kong mRightIndicator.setEnabled(true); 6488b0e23544474480345937c0c0985429f61569761Angus Kong } 6498b0e23544474480345937c0c0985429f61569761Angus Kong 6508b0e23544474480345937c0c0985429f61569761Angus Kong private void hideTooFastIndication() { 6518b0e23544474480345937c0c0985429f61569761Angus Kong mTooFastPrompt.setVisibility(View.GONE); 6528b0e23544474480345937c0c0985429f61569761Angus Kong mFastIndicationBorder.setVisibility(View.GONE); 653fa959aede9b1fe9d510108e883a2f16cf28c9033Angus Kong mPanoProgressBar.setIndicatorColor(mIndicatorColor); 6548b0e23544474480345937c0c0985429f61569761Angus Kong mLeftIndicator.setEnabled(false); 6558b0e23544474480345937c0c0985429f61569761Angus Kong mRightIndicator.setEnabled(false); 6568b0e23544474480345937c0c0985429f61569761Angus Kong } 6578b0e23544474480345937c0c0985429f61569761Angus Kong 6582d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen private void updateProgress(float panningRateXInDegree, float panningRateYInDegree, 6592d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen float progressHorizontalAngle, float progressVerticalAngle) { 6602faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.setReady(); 6612faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.requestRender(); 662eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 66343b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen // TODO: Now we just display warning message by the panning speed. 66443b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen // Since we only support horizontal panning, we should display a warning message 66543b0b2ccd5949ee8fc377c37e7e2b82a26c88ca8Wei-Ta Chen // in UI when there're significant vertical movements. 6662d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen if ((Math.abs(panningRateXInDegree) > PANNING_SPEED_THRESHOLD) 6672d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen || (Math.abs(panningRateYInDegree) > PANNING_SPEED_THRESHOLD)) { 6688b0e23544474480345937c0c0985429f61569761Angus Kong showTooFastIndication(); 6698a2c41754655a3733175fce81fb7506ff7022959Angus Kong } else { 6708b0e23544474480345937c0c0985429f61569761Angus Kong hideTooFastIndication(); 6718a2c41754655a3733175fce81fb7506ff7022959Angus Kong } 6722d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen int angleInMajorDirection = 6732d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen (Math.abs(progressHorizontalAngle) > Math.abs(progressVerticalAngle)) 6742d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen ? (int) progressHorizontalAngle 6752d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen : (int) progressVerticalAngle; 6762d3391e6be57aeeb7e713f25a484445660b101e3Wei-Ta Chen mPanoProgressBar.setProgress((angleInMajorDirection)); 6778a2c41754655a3733175fce81fb7506ff7022959Angus Kong } 6788a2c41754655a3733175fce81fb7506ff7022959Angus Kong 679bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen private void createContentView() { 680bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen setContentView(R.layout.panorama); 681bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 682a466abbd54caa8100a1ef6584a5b0db78224a125Angus Kong mCaptureState = CAPTURE_STATE_VIEWFINDER; 68341a2e9735136f372de95652d0828600282c8e967mbansal 684057040c0e19834d98719143c2627a9f0df3e4c35Angus Kong Resources appRes = getResources(); 685057040c0e19834d98719143c2627a9f0df3e4c35Angus Kong 686a955261dd734524eb7d8e1af76c695122efc8aa7Angus Kong mCaptureLayout = (View) findViewById(R.id.pano_capture_layout); 687215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong mPanoProgressBar = (PanoProgressBar) findViewById(R.id.pano_pan_progress_bar); 688057040c0e19834d98719143c2627a9f0df3e4c35Angus Kong mPanoProgressBar.setBackgroundColor(appRes.getColor(R.color.pano_progress_empty)); 689057040c0e19834d98719143c2627a9f0df3e4c35Angus Kong mPanoProgressBar.setDoneColor(appRes.getColor(R.color.pano_progress_done)); 690fa959aede9b1fe9d510108e883a2f16cf28c9033Angus Kong mIndicatorColor = appRes.getColor(R.color.pano_progress_indication); 691fa959aede9b1fe9d510108e883a2f16cf28c9033Angus Kong mIndicatorColorFast = appRes.getColor(R.color.pano_progress_indication_fast); 692fa959aede9b1fe9d510108e883a2f16cf28c9033Angus Kong mPanoProgressBar.setIndicatorColor(mIndicatorColor); 6936108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong mPanoProgressBar.setOnDirectionChangeListener( 6946108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong new PanoProgressBar.OnDirectionChangeListener () { 6956108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong @Override 6966108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong public void onDirectionChange(int direction) { 6976108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong if (mCaptureState == CAPTURE_STATE_MOSAIC) { 6986108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong showDirectionIndicators(direction); 6996108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong } 7006108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong } 7016108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong }); 7026108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong 7036108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong mLeftIndicator = (ImageView) findViewById(R.id.pano_pan_left_indicator); 7046108e0ed3a6b03deed2a8586d98607a6756637b1Angus Kong mRightIndicator = (ImageView) findViewById(R.id.pano_pan_right_indicator); 7058b0e23544474480345937c0c0985429f61569761Angus Kong mLeftIndicator.setEnabled(false); 7068b0e23544474480345937c0c0985429f61569761Angus Kong mRightIndicator.setEnabled(false); 707fbc5751416caa3a0d065ae15f56d1fb0253552c5Angus Kong mTooFastPrompt = (TextView) findViewById(R.id.pano_capture_too_fast_textview); 7088b0e23544474480345937c0c0985429f61569761Angus Kong mFastIndicationBorder = (View) findViewById(R.id.pano_speed_indication_border); 709bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 710215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong mSavingProgressBar = (PanoProgressBar) findViewById(R.id.pano_saving_progress_bar); 711215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong mSavingProgressBar.setIndicatorWidth(0); 712215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong mSavingProgressBar.setMaxProgress(100); 713215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong mSavingProgressBar.setBackgroundColor(appRes.getColor(R.color.pano_progress_empty)); 714215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong mSavingProgressBar.setDoneColor(appRes.getColor(R.color.pano_progress_indication)); 715215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong 716d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang mCaptureIndicator = (RotateLayout) findViewById(R.id.pano_capture_indicator); 7178df38bbe67338a1f5dc58996bd8866f4c1fe264dAngus Kong 718a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong mThumbnailView = (RotateImageView) findViewById(R.id.thumbnail); 7194a3026b84fa4fd403317b30b6a9db61125fecfa2heech.park mThumbnailView.enableFilter(false); 720a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong 7215af9472f1c260c1a3b54d2e1bd448c27b5e5968fWei-Ta Chen mReviewLayout = (View) findViewById(R.id.pano_review_layout); 7225af9472f1c260c1a3b54d2e1bd448c27b5e5968fWei-Ta Chen mReview = (ImageView) findViewById(R.id.pano_reviewarea); 7232faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView = (MosaicRendererSurfaceView) findViewById(R.id.pano_renderer); 7242faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.getRenderer().setMosaicSurfaceCreateListener(this); 725eeb94d4de94bfd4e01f3a716803f77a530f5b92cmbansal 726a72d73cbac59db43d413291e4db66763be08143arepo sync mModePicker = (ModePicker) findViewById(R.id.mode_picker); 727a72d73cbac59db43d413291e4db66763be08143arepo sync mModePicker.setVisibility(View.VISIBLE); 728a72d73cbac59db43d413291e4db66763be08143arepo sync mModePicker.setOnModeChangeListener(this); 729a72d73cbac59db43d413291e4db66763be08143arepo sync mModePicker.setCurrentMode(ModePicker.MODE_PANORAMA); 7307648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li 731fcdf619d92701052621a96572d956d047e07cf24Angus Kong mShutterButton = (ShutterButton) findViewById(R.id.shutter_button); 732fcdf619d92701052621a96572d956d047e07cf24Angus Kong mShutterButton.setBackgroundResource(R.drawable.btn_shutter_pan); 733fcdf619d92701052621a96572d956d047e07cf24Angus Kong mShutterButton.setOnShutterButtonListener(this); 734fcdf619d92701052621a96572d956d047e07cf24Angus Kong 7357648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li mPanoLayout = findViewById(R.id.pano_layout); 736d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang 737ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong mRotateDialog = new RotateDialogController(this, R.layout.rotate_dialog); 738d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang 739d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { 740d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang Rotatable[] rotateLayout = { 741d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang (Rotatable) findViewById(R.id.pano_pan_progress_bar_layout), 742d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang (Rotatable) findViewById(R.id.pano_capture_too_fast_textview_layout), 743d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang (Rotatable) findViewById(R.id.pano_review_saving_indication_layout), 744d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang (Rotatable) findViewById(R.id.pano_saving_progress_bar_layout), 745d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang (Rotatable) findViewById(R.id.pano_review_cancel_button_layout), 746562db5a0ec57f65cf4014ce3f7dad0f9324bb2f1Angus Kong (Rotatable) findViewById(R.id.pano_rotate_reviewarea), 747d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang (Rotatable) mRotateDialog, 7483a3fd8f6cf7c939cacbd3da09e80d3df074a00e4Angus Kong (Rotatable) mCaptureIndicator, 7493a3fd8f6cf7c939cacbd3da09e80d3df074a00e4Angus Kong (Rotatable) mModePicker, 7503a3fd8f6cf7c939cacbd3da09e80d3df074a00e4Angus Kong (Rotatable) mThumbnailView}; 751d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang for (Rotatable r : rotateLayout) { 752d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang r.setOrientation(270); 753d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang } 754d33109730e0ab81230f84e2bd35599e8e24fc4baChung-yih Wang } 755bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 756bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 757fcdf619d92701052621a96572d956d047e07cf24Angus Kong @Override 7581bca5eaaa3c6d3fd36df572546715e4e515cf9e6Wu-cheng Li public void onShutterButtonClick() { 7592faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong // If mSurfaceTexture == null then GL setup is not finished yet. 7602faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong // No buttons can be pressed. 7612faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong if (mPausing || mThreadRunning || mSurfaceTexture == null) return; 762a466abbd54caa8100a1ef6584a5b0db78224a125Angus Kong // Since this button will stay on the screen when capturing, we need to check the state 763a466abbd54caa8100a1ef6584a5b0db78224a125Angus Kong // right now. 764fcdf619d92701052621a96572d956d047e07cf24Angus Kong switch (mCaptureState) { 765fcdf619d92701052621a96572d956d047e07cf24Angus Kong case CAPTURE_STATE_VIEWFINDER: 7661461b5333aab31faee65272d64c2ac7f9809d4d0Eino-Ville Talvala mCameraSound.play(MediaActionSound.START_VIDEO_RECORDING); 767fcdf619d92701052621a96572d956d047e07cf24Angus Kong startCapture(); 768fcdf619d92701052621a96572d956d047e07cf24Angus Kong break; 769fcdf619d92701052621a96572d956d047e07cf24Angus Kong case CAPTURE_STATE_MOSAIC: 7701461b5333aab31faee65272d64c2ac7f9809d4d0Eino-Ville Talvala mCameraSound.play(MediaActionSound.STOP_VIDEO_RECORDING); 77127c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong stopCapture(false); 772a466abbd54caa8100a1ef6584a5b0db78224a125Angus Kong } 773739f9e1541c30735e45d5cb90255dd36a32d3604Angus Kong } 774739f9e1541c30735e45d5cb90255dd36a32d3604Angus Kong 775fcdf619d92701052621a96572d956d047e07cf24Angus Kong @Override 7761bca5eaaa3c6d3fd36df572546715e4e515cf9e6Wu-cheng Li public void onShutterButtonFocus(boolean pressed) { 777142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 778142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 779215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong public void reportProgress() { 780215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong mSavingProgressBar.reset(); 781215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong mSavingProgressBar.setRightIncreasing(true); 78250b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal Thread t = new Thread() { 78350b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal @Override 78450b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal public void run() { 7856f6ea6ab6dad370d2cc378be91a2649ae44b2c94Angus Kong while (mThreadRunning) { 786e1178a73fd5756771d25d0b8375452450f509e99mbansal final int progress = mMosaicFrameProcessor.reportProgress( 787215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong true, mCancelComputation); 78850b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal 7896f6ea6ab6dad370d2cc378be91a2649ae44b2c94Angus Kong try { 790215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong synchronized (mWaitObject) { 791215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong mWaitObject.wait(50); 792215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong } 793215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong } catch (InterruptedException e) { 7946f6ea6ab6dad370d2cc378be91a2649ae44b2c94Angus Kong throw new RuntimeException("Panorama reportProgress failed", e); 7956f6ea6ab6dad370d2cc378be91a2649ae44b2c94Angus Kong } 7966f6ea6ab6dad370d2cc378be91a2649ae44b2c94Angus Kong // Update the progress bar 79750b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal runOnUiThread(new Runnable() { 79850b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal public void run() { 799215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong mSavingProgressBar.setProgress(progress); 80050b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal } 80150b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal }); 80250b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal } 80350b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal } 80450b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal }; 80550b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal t.start(); 80650b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal } 80750b3c890986aadb3780b4da8c0b8dbb0f1422ebambansal 80882dd2a3b7ba88a3ea051d2b3960310891a243dadMark Wagner private void initThumbnailButton() { 80982dd2a3b7ba88a3ea051d2b3960310891a243dadMark Wagner // Load the thumbnail from the disk. 81082dd2a3b7ba88a3ea051d2b3960310891a243dadMark Wagner if (mThumbnail == null) { 81182dd2a3b7ba88a3ea051d2b3960310891a243dadMark Wagner mThumbnail = Thumbnail.loadFrom(new File(getFilesDir(), Thumbnail.LAST_THUMB_FILENAME)); 81282dd2a3b7ba88a3ea051d2b3960310891a243dadMark Wagner } 81382dd2a3b7ba88a3ea051d2b3960310891a243dadMark Wagner updateThumbnailButton(); 81482dd2a3b7ba88a3ea051d2b3960310891a243dadMark Wagner } 81582dd2a3b7ba88a3ea051d2b3960310891a243dadMark Wagner 8169a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner private void updateThumbnailButton() { 8179a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner // Update last image if URI is invalid and the storage is ready. 8189a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner ContentResolver contentResolver = getContentResolver(); 8199a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner if ((mThumbnail == null || !Util.isUriValid(mThumbnail.getUri(), contentResolver))) { 8209a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner mThumbnail = Thumbnail.getLastThumbnail(contentResolver); 8219a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner } 8229a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner if (mThumbnail != null) { 8239a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner mThumbnailView.setBitmap(mThumbnail.getBitmap()); 8249a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner } else { 8259a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner mThumbnailView.setBitmap(null); 8269a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner } 8279a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner } 8289a7cba43937e7c74ebd9778bca40afc89145e3e1Mark Wagner 82962bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong private void saveThumbnailToFile() { 83062bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong if (mThumbnail != null && !mThumbnail.fromFile()) { 83162bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong mThumbnail.saveTo(new File(getFilesDir(), Thumbnail.LAST_THUMB_FILENAME)); 83262bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong } 83362bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong } 83462bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong 835215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong public void saveHighResMosaic() { 836215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong runBackgroundThread(new Thread() { 837142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong @Override 838142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong public void run() { 83962bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong mPartialWakeLock.acquire(); 84062bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong MosaicJpeg jpeg; 84162bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong try { 84262bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong jpeg = generateFinalMosaic(true); 84362bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong } finally { 84462bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong mPartialWakeLock.release(); 84562bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong } 846e1178a73fd5756771d25d0b8375452450f509e99mbansal 84713e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong if (jpeg == null) { // Cancelled by user. 84813e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong mMainHandler.sendEmptyMessage(MSG_RESET_TO_PREVIEW); 84913e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong } else if (!jpeg.isValid) { // Error when generating mosaic. 85013e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong mMainHandler.sendEmptyMessage(MSG_GENERATE_FINAL_MOSAIC_ERROR); 85122d4b7fbace56c03092eb088a4df98e04a6681afAngus Kong } else { 852e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen // The panorama image returned from the library is orientated based on the 853e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen // natural orientation of a camera. We need to set an orientation for the image 854e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen // in its EXIF header, so the image can be displayed correctly. 855e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen // The orientation is calculated from compensating the 856e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen // device orientation at capture and the camera orientation respective to 857e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen // the natural orientation of the device. 858e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen int orientation = (mDeviceOrientationAtCapture + mCameraOrientation) % 360; 859ea312297ff6132bbafed99b90a72e4858b888fa4Angus Kong Uri uri = savePanorama(jpeg.data, jpeg.width, jpeg.height, orientation); 86013e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong if (uri != null) { 86166188959498860c8b43ab7b9119c7b5c890c83dcWei-Ta Chen // Create a thumbnail whose width or height is equal or bigger 86266188959498860c8b43ab7b9119c7b5c890c83dcWei-Ta Chen // than the screen's width or height. 86366188959498860c8b43ab7b9119c7b5c890c83dcWei-Ta Chen int widthRatio = (int) Math.ceil((double) jpeg.width 86466188959498860c8b43ab7b9119c7b5c890c83dcWei-Ta Chen / mPanoLayout.getWidth()); 86566188959498860c8b43ab7b9119c7b5c890c83dcWei-Ta Chen int heightRatio = (int) Math.ceil((double) jpeg.height 86666188959498860c8b43ab7b9119c7b5c890c83dcWei-Ta Chen / mPanoLayout.getHeight()); 86766188959498860c8b43ab7b9119c7b5c890c83dcWei-Ta Chen int inSampleSize = Integer.highestOneBit( 86866188959498860c8b43ab7b9119c7b5c890c83dcWei-Ta Chen Math.max(widthRatio, heightRatio)); 86913e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong mThumbnail = Thumbnail.createThumbnail( 87013e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong jpeg.data, orientation, inSampleSize, uri); 871d22fff61ae44ea5213aeb91f400bfe1456411d25Angus Kong Util.broadcastNewPicture(PanoramaActivity.this, uri); 87222d4b7fbace56c03092eb088a4df98e04a6681afAngus Kong } 87313e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong mMainHandler.sendMessage( 87413e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong mMainHandler.obtainMessage(MSG_RESET_TO_PREVIEW_WITH_THUMBNAIL)); 875a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong } 876142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 8775fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong }); 878215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong reportProgress(); 879215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong } 880215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong 881215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong private void runBackgroundThread(Thread thread) { 8825fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong mThreadRunning = true; 8835fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong thread.start(); 8845fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong } 8855fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong 8865fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong private void onBackgroundThreadFinished() { 8875fde6d5259fccaed4bc517697a4930d3b69ae860Angus Kong mThreadRunning = false; 888ae557ecc220f9d491e8c65b1c895827fbedcdafeAngus Kong mRotateDialog.dismissDialog(); 889142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 890142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 891ef011a1e479f8e801318eba2dccb50fac1590d3cAngus Kong private void cancelHighResComputation() { 892215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong mCancelComputation = true; 893215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong synchronized (mWaitObject) { 894215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong mWaitObject.notify(); 895215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong } 896142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 897142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 898a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong @OnClickAttr 899ef011a1e479f8e801318eba2dccb50fac1590d3cAngus Kong public void onCancelButtonClicked(View v) { 900ef011a1e479f8e801318eba2dccb50fac1590d3cAngus Kong if (mPausing || mSurfaceTexture == null) return; 901ef011a1e479f8e801318eba2dccb50fac1590d3cAngus Kong cancelHighResComputation(); 902ef011a1e479f8e801318eba2dccb50fac1590d3cAngus Kong } 903ef011a1e479f8e801318eba2dccb50fac1590d3cAngus Kong 904ef011a1e479f8e801318eba2dccb50fac1590d3cAngus Kong @OnClickAttr 905a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong public void onThumbnailClicked(View v) { 906a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong if (mPausing || mThreadRunning || mSurfaceTexture == null) return; 907a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong showSharePopup(); 908a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong } 909a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong 910a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong private void showSharePopup() { 911a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong if (mThumbnail == null) return; 912a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong Uri uri = mThumbnail.getUri(); 913a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong if (mSharePopup == null || !uri.equals(mSharePopup.getUri())) { 914a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong // The orientation compensation is set to 0 here because we only support landscape. 9155201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner mSharePopup = new SharePopup(this, uri, mThumbnail.getBitmap(), 9165201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner mOrientationCompensation, 917977d06c6278cb7b131ed3c0960853d9168aacbddWu-cheng Li findViewById(R.id.frame_layout)); 918a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong } 919a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong mSharePopup.showAtLocation(mThumbnailView, Gravity.NO_GRAVITY, 0, 0); 920a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong } 921a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong 92227c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong private void reset() { 923a466abbd54caa8100a1ef6584a5b0db78224a125Angus Kong mCaptureState = CAPTURE_STATE_VIEWFINDER; 92441a2e9735136f372de95652d0828600282c8e967mbansal 92541a2e9735136f372de95652d0828600282c8e967mbansal mReviewLayout.setVisibility(View.GONE); 926fcdf619d92701052621a96572d956d047e07cf24Angus Kong mShutterButton.setBackgroundResource(R.drawable.btn_shutter_pan); 927057040c0e19834d98719143c2627a9f0df3e4c35Angus Kong mPanoProgressBar.setVisibility(View.GONE); 92860fc534ec8f68d95a486984cb396a2da0e200518Angus Kong mCaptureLayout.setVisibility(View.VISIBLE); 929142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong mMosaicFrameProcessor.reset(); 93041a2e9735136f372de95652d0828600282c8e967mbansal 9312faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mSurfaceTexture.setOnFrameAvailableListener(this); 93227c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong } 93341a2e9735136f372de95652d0828600282c8e967mbansal 93427c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong private void resetToPreview() { 93527c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong reset(); 93636839102e03107e3fb121197036365a58ec2686eAngus Kong if (!mPausing) startCameraPreview(); 937142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 938142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 939142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong private void showFinalMosaic(Bitmap bitmap) { 940142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong if (bitmap != null) { 941142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong mReview.setImageBitmap(bitmap); 942142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 943ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong mCaptureLayout.setVisibility(View.GONE); 944ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong mReviewLayout.setVisibility(View.VISIBLE); 945142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 946142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 947ea312297ff6132bbafed99b90a72e4858b888fa4Angus Kong private Uri savePanorama(byte[] jpegData, int width, int height, int orientation) { 948ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong if (jpegData != null) { 949e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen String filename = PanoUtil.createName( 950ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong getResources().getString(R.string.pano_file_name_format), mTimeTaken); 951e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen Uri uri = Storage.addImage(getContentResolver(), filename, mTimeTaken, null, 952ea312297ff6132bbafed99b90a72e4858b888fa4Angus Kong orientation, jpegData, width, height); 953e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen if (uri != null && orientation != 0) { 954e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen String filepath = Storage.generateFilepath(filename); 955e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen try { 956e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen // Save the orientation in EXIF. 957e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen ExifInterface exif = new ExifInterface(filepath); 958e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen exif.setAttribute(ExifInterface.TAG_ORIENTATION, 959e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen getExifOrientation(orientation)); 960e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen exif.saveAttributes(); 961e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen } catch (IOException e) { 962e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen Log.e(TAG, "cannot set exif data: " + filepath); 963e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen } 964e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen } 965e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen return uri; 966142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 967a907c122ccec649c6cedf3a45b1c426a5fca932eAngus Kong return null; 968142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 969142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 970e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen private static String getExifOrientation(int orientation) { 971e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen switch (orientation) { 972e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen case 0: 973e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen return String.valueOf(ExifInterface.ORIENTATION_NORMAL); 974e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen case 90: 975e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen return String.valueOf(ExifInterface.ORIENTATION_ROTATE_90); 976e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen case 180: 977e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen return String.valueOf(ExifInterface.ORIENTATION_ROTATE_180); 978e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen case 270: 979e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen return String.valueOf(ExifInterface.ORIENTATION_ROTATE_270); 980e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen default: 981e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen throw new AssertionError("invalid: " + orientation); 982e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen } 983e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen } 984e0bbb93f6a598206ecd6e09150d51eae64bd3507Wei-Ta Chen 985142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong private void clearMosaicFrameProcessorIfNeeded() { 986142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong if (!mPausing || mThreadRunning) return; 987142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong mMosaicFrameProcessor.clear(); 988142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 989142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong 990142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong private void initMosaicFrameProcessorIfNeeded() { 991142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong if (mPausing || mThreadRunning) return; 992142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong if (mMosaicFrameProcessor == null) { 993142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong // Start the activity for the first time. 994c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong mMosaicFrameProcessor = new MosaicFrameProcessor( 9950adf2489520d3a98a56e081aeacb1ab9336a012fWei-Ta Chen mPreviewWidth, mPreviewHeight, getPreviewBufSize()); 996142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong } 997142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong mMosaicFrameProcessor.initialize(); 998bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 999bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 1000bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen @Override 1001bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen protected void onPause() { 1002bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen super.onPause(); 10034d1c2846e24a7f7f6c8ff59e01ca36a000344944Angus Kong 1004142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong mPausing = true; 100527c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong // Stop the capturing first. 100627c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong if (mCaptureState == CAPTURE_STATE_MOSAIC) { 100727c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong stopCapture(true); 100827c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong reset(); 100927c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong } 10108b084a607d0b207272d5c87fecbb5d33cbef1b4fMark Wagner if (mSharePopup != null) mSharePopup.dismiss(); 10115201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner 101262bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong saveThumbnailToFile(); 10135201b1e0051877d8e8ed0ef5b461ffcac534eb5cMark Wagner 101427c7ab8a5d3dd50a62be80900abe6890c7182956Angus Kong releaseCamera(); 10152faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong mMosaicView.onPause(); 1016142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong clearMosaicFrameProcessorIfNeeded(); 1017c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong mOrientationEventListener.disable(); 1018bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang resetScreenOn(); 101990089f9eddde732725c43dcad07f4567ed8cb776Wu-cheng Li mCameraSound.release(); 102094f592fc405ca45b8794007cd9083c3250924b50Wei-Ta Chen System.gc(); 1021bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 1022bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 1023bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen @Override 10247d9eadd0c6c38b3761b7e8d3fa3658d194810d60Jim Miller protected void doOnResume() { 1025142402d57c1689c1342d096c976b9b0826f8ce1aAngus Kong mPausing = false; 1026c89a0eb7b1f0cd5cd45de8fd08ff051f6f74f382Angus Kong mOrientationEventListener.enable(); 1027215f7ecf1fcc861986397fdf6724602d4775ab2cAngus Kong 1028a466abbd54caa8100a1ef6584a5b0db78224a125Angus Kong mCaptureState = CAPTURE_STATE_VIEWFINDER; 102980583a299a9c8964cf09e482380c3bda0670ad6fChih-yu Huang try { 103080583a299a9c8964cf09e482380c3bda0670ad6fChih-yu Huang setupCamera(); 1031575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi 103280583a299a9c8964cf09e482380c3bda0670ad6fChih-yu Huang // Camera must be initialized before MosaicFrameProcessor is initialized. 103380583a299a9c8964cf09e482380c3bda0670ad6fChih-yu Huang // The preview size has to be decided by camera device. 103480583a299a9c8964cf09e482380c3bda0670ad6fChih-yu Huang initMosaicFrameProcessorIfNeeded(); 103580583a299a9c8964cf09e482380c3bda0670ad6fChih-yu Huang mMosaicView.onResume(); 103682dd2a3b7ba88a3ea051d2b3960310891a243dadMark Wagner 103780583a299a9c8964cf09e482380c3bda0670ad6fChih-yu Huang initThumbnailButton(); 103880583a299a9c8964cf09e482380c3bda0670ad6fChih-yu Huang keepScreenOnAwhile(); 103980583a299a9c8964cf09e482380c3bda0670ad6fChih-yu Huang } catch (CameraHardwareException e) { 104080583a299a9c8964cf09e482380c3bda0670ad6fChih-yu Huang Util.showErrorAndFinish(this, R.string.cannot_connect_camera); 1041749d056cd82ebfe6e613596d9e22dd355aeeec41Chung-yih Wang return; 104280583a299a9c8964cf09e482380c3bda0670ad6fChih-yu Huang } catch (CameraDisabledException e) { 104380583a299a9c8964cf09e482380c3bda0670ad6fChih-yu Huang Util.showErrorAndFinish(this, R.string.camera_disabled); 1044749d056cd82ebfe6e613596d9e22dd355aeeec41Chung-yih Wang return; 104580583a299a9c8964cf09e482380c3bda0670ad6fChih-yu Huang } 1046749d056cd82ebfe6e613596d9e22dd355aeeec41Chung-yih Wang // Dismiss open menu if exists. 1047749d056cd82ebfe6e613596d9e22dd355aeeec41Chung-yih Wang PopupManager.getInstance(this).notifyShowPopup(null); 1048bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 1049bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 10500a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen /** 10510a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen * Generate the final mosaic image. 10520a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen * 10530a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen * @param highRes flag to indicate whether we want to get a high-res version. 10540a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen * @return a MosaicJpeg with its isValid flag set to true if successful; null if the generation 10550a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen * process is cancelled; and a MosaicJpeg with its isValid flag set to false if there 10560a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen * is an error in generating the final mosaic. 10570a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen */ 10587648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li public MosaicJpeg generateFinalMosaic(boolean highRes) { 10590a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen int mosaicReturnCode = mMosaicFrameProcessor.createMosaic(highRes); 10600a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen if (mosaicReturnCode == Mosaic.MOSAIC_RET_CANCELLED) { 1061e1178a73fd5756771d25d0b8375452450f509e99mbansal return null; 10620a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen } else if (mosaicReturnCode == Mosaic.MOSAIC_RET_ERROR) { 10630a039136e8e46ddbcb45b55e92d80ddb2ddfc2c2Wei-Ta Chen return new MosaicJpeg(); 106413e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong } 1065bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen 1066ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong byte[] imageData = mMosaicFrameProcessor.getFinalMosaicNV21(); 1067ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong if (imageData == null) { 1068ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong Log.e(TAG, "getFinalMosaicNV21() returned null."); 106913e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong return new MosaicJpeg(); 10708a2c41754655a3733175fce81fb7506ff7022959Angus Kong } 10718a2c41754655a3733175fce81fb7506ff7022959Angus Kong 1072ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong int len = imageData.length - 8; 1073ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong int width = (imageData[len + 0] << 24) + ((imageData[len + 1] & 0xFF) << 16) 1074ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong + ((imageData[len + 2] & 0xFF) << 8) + (imageData[len + 3] & 0xFF); 1075ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong int height = (imageData[len + 4] << 24) + ((imageData[len + 5] & 0xFF) << 16) 1076ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong + ((imageData[len + 6] & 0xFF) << 8) + (imageData[len + 7] & 0xFF); 1077ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong Log.v(TAG, "ImLength = " + (len) + ", W = " + width + ", H = " + height); 10788a2c41754655a3733175fce81fb7506ff7022959Angus Kong 1079e46486104523760a4433f03e09ed615987d83b6cAngus Kong if (width <= 0 || height <= 0) { 1080e46486104523760a4433f03e09ed615987d83b6cAngus Kong // TODO: pop up a error meesage indicating that the final result is not generated. 1081e46486104523760a4433f03e09ed615987d83b6cAngus Kong Log.e(TAG, "width|height <= 0!!, len = " + (len) + ", W = " + width + ", H = " + 1082e46486104523760a4433f03e09ed615987d83b6cAngus Kong height); 108313e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong return new MosaicJpeg(); 1084e46486104523760a4433f03e09ed615987d83b6cAngus Kong } 1085e46486104523760a4433f03e09ed615987d83b6cAngus Kong 1086ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong YuvImage yuvimage = new YuvImage(imageData, ImageFormat.NV21, width, height, null); 1087ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong ByteArrayOutputStream out = new ByteArrayOutputStream(); 1088ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong yuvimage.compressToJpeg(new Rect(0, 0, width, height), 100, out); 1089ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong try { 1090ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong out.close(); 1091ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong } catch (Exception e) { 1092ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong Log.e(TAG, "Exception in storing final mosaic", e); 109313e2b964e821f6ee40cf5715b6baec19c7fd09b8Angus Kong return new MosaicJpeg(); 1094ef91f8514bf3c21091dde6b292f9616464dc32e8Angus Kong } 10957648319f0416b86ae13b97eeba0466581ace1a48Wu-cheng Li return new MosaicJpeg(out.toByteArray(), width, height); 1096bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen } 10978a2c41754655a3733175fce81fb7506ff7022959Angus Kong 109841a2e9735136f372de95652d0828600282c8e967mbansal private void setPreviewTexture(SurfaceTexture surface) { 109998f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen try { 110041a2e9735136f372de95652d0828600282c8e967mbansal mCameraDevice.setPreviewTexture(surface); 110198f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen } catch (Throwable ex) { 110298f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen releaseCamera(); 110341a2e9735136f372de95652d0828600282c8e967mbansal throw new RuntimeException("setPreviewTexture failed", ex); 110498f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen } 110598f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen } 110698f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen 110736839102e03107e3fb121197036365a58ec2686eAngus Kong private void startCameraPreview() { 110898f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen // If we're previewing already, stop the preview first (this will blank 110998f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen // the screen). 111036839102e03107e3fb121197036365a58ec2686eAngus Kong if (mCameraState != PREVIEW_STOPPED) stopCameraPreview(); 111198f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen 1112d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // Set the display orientation to 0, so that the underlying mosaic library 1113d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // can always get undistorted mPreviewWidth x mPreviewHeight image data 1114d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen // from SurfaceTexture. 1115d32aa042a7d7fdb52cd8cec571e7c648f837eaffWei-Ta Chen mCameraDevice.setDisplayOrientation(0); 1116575b49275691f5b539fe2c6dfde1741645dc3e93Raji Reddy Kandi 11172faf16a90a6a6d18e40faf45ced217b913b214b6Angus Kong setPreviewTexture(mSurfaceTexture); 111898f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen 111998f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen try { 112098f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen Log.v(TAG, "startPreview"); 112198f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen mCameraDevice.startPreview(); 112298f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen } catch (Throwable ex) { 112398f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen releaseCamera(); 112498f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen throw new RuntimeException("startPreview failed", ex); 112598f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen } 112698f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen mCameraState = PREVIEW_ACTIVE; 112798f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen } 112898f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen 112936839102e03107e3fb121197036365a58ec2686eAngus Kong private void stopCameraPreview() { 113098f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen if (mCameraDevice != null && mCameraState != PREVIEW_STOPPED) { 113198f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen Log.v(TAG, "stopPreview"); 113298f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen mCameraDevice.stopPreview(); 113398f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen } 113498f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen mCameraState = PREVIEW_STOPPED; 113598f41918daf64318a7da4ec94712eeb8d6697f31Wei-Ta Chen } 1136bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang 1137bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang @Override 1138bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang public void onUserInteraction() { 1139bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang super.onUserInteraction(); 1140bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang if (mCaptureState != CAPTURE_STATE_MOSAIC) keepScreenOnAwhile(); 1141bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang } 1142bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang 114362bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong @Override 114462bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong public void onBackPressed() { 114562bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong // If panorama is generating low res or high res mosaic, ignore back 114662bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong // key. So the activity will not be destroyed. 114762bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong if (mThreadRunning) return; 114862bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong super.onBackPressed(); 114962bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong } 115062bbca8320c3861fa9b18a7eab26a42116bef9dfAngus Kong 1151bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang private void resetScreenOn() { 1152bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang mMainHandler.removeMessages(MSG_CLEAR_SCREEN_DELAY); 1153bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 1154bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang } 1155bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang 1156bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang private void keepScreenOnAwhile() { 1157bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang mMainHandler.removeMessages(MSG_CLEAR_SCREEN_DELAY); 1158bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 1159bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang mMainHandler.sendEmptyMessageDelayed(MSG_CLEAR_SCREEN_DELAY, SCREEN_DELAY); 1160bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang } 1161bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang 1162bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang private void keepScreenOn() { 1163bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang mMainHandler.removeMessages(MSG_CLEAR_SCREEN_DELAY); 1164bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 1165bc85294715ce88c8378af3b77f7a0d27d7ceeabaChih-Chung Chang } 1166bdc7e2b461064b25b7f17b0941077fc97653093dWei-Ta Chen} 1167