summaryrefslogtreecommitdiffstats
path: root/src/com
diff options
context:
space:
mode:
Diffstat (limited to 'src/com')
-rw-r--r--src/com/android/camera/Mosaic.java206
-rw-r--r--src/com/android/camera/MosaicFrameProcessor.java237
-rw-r--r--src/com/android/camera/MosaicPreviewRenderer.java183
-rw-r--r--src/com/android/camera/MosaicRenderer.java89
-rw-r--r--src/com/android/camera/WideAnglePanoramaController.java35
-rw-r--r--src/com/android/camera/WideAnglePanoramaModule.java1062
-rw-r--r--src/com/android/camera/WideAnglePanoramaUI.java495
-rw-r--r--src/com/android/camera/module/ModulesInfo.java2
8 files changed, 0 insertions, 2309 deletions
diff --git a/src/com/android/camera/Mosaic.java b/src/com/android/camera/Mosaic.java
deleted file mode 100644
index b1d10c05b..000000000
--- a/src/com/android/camera/Mosaic.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.camera;
-
-/**
- * The Java interface to JNI calls regarding mosaic stitching.
- *
- * A high-level usage is:
- *
- * Mosaic mosaic = new Mosaic();
- * mosaic.setSourceImageDimensions(width, height);
- * mosaic.reset(blendType);
- *
- * while ((pixels = hasNextImage()) != null) {
- * mosaic.setSourceImage(pixels);
- * }
- *
- * mosaic.createMosaic(highRes);
- * byte[] result = mosaic.getFinalMosaic();
- *
- */
-public class Mosaic {
- /**
- * In this mode, the images are stitched together in the same spatial arrangement as acquired
- * i.e. if the user follows a curvy trajectory, the image boundary of the resulting mosaic will
- * be curved in the same manner. This mode is useful if the user wants to capture a mosaic as
- * if "painting" the scene using the smart-phone device and does not want any corrective warps
- * to distort the captured images.
- */
- public static final int BLENDTYPE_FULL = 0;
-
- /**
- * This mode is the same as BLENDTYPE_FULL except that the resulting mosaic is rotated
- * to balance the first and last images to be approximately at the same vertical offset in the
- * output mosaic. This is useful when acquiring a mosaic by a typical panning-like motion to
- * remove a one-sided curve in the mosaic (typically due to the camera not staying horizontal
- * during the video capture) and convert it to a more symmetrical "smiley-face" like output.
- */
- public static final int BLENDTYPE_PAN = 1;
-
- /**
- * This mode compensates for typical "smiley-face" like output in longer mosaics and creates
- * a rectangular mosaic with minimal black borders (by unwrapping the mosaic onto an imaginary
- * cylinder). If the user follows a curved trajectory (instead of a perfect panning trajectory),
- * the resulting mosaic here may suffer from some image distortions in trying to map the
- * trajectory to a cylinder.
- */
- public static final int BLENDTYPE_CYLINDERPAN = 2;
-
- /**
- * This mode is basically BLENDTYPE_CYLINDERPAN plus doing a rectangle cropping before returning
- * the mosaic. The mode is useful for making the resulting mosaic have a rectangle shape.
- */
- public static final int BLENDTYPE_HORIZONTAL =3;
-
- /**
- * This strip type will use the default thin strips where the strips are
- * spaced according to the image capture rate.
- */
- public static final int STRIPTYPE_THIN = 0;
-
- /**
- * This strip type will use wider strips for blending. The strip separation
- * is controlled by a threshold on the native side. Since the strips are
- * wider, there is an additional cross-fade blending step to make the seam
- * boundaries smoother. Since this mode uses lesser image frames, it is
- * computationally more efficient than the thin strip mode.
- */
- public static final int STRIPTYPE_WIDE = 1;
-
- /**
- * Return flags returned by createMosaic() are one of the following.
- */
- public static final int MOSAIC_RET_OK = 1;
- public static final int MOSAIC_RET_ERROR = -1;
- public static final int MOSAIC_RET_CANCELLED = -2;
- public static final int MOSAIC_RET_LOW_TEXTURE = -3;
- public static final int MOSAIC_RET_FEW_INLIERS = 2;
-
-
- static {
- System.loadLibrary("jni_mosaic");
- }
-
- /**
- * Allocate memory for the image frames at the given resolution.
- *
- * @param width width of the input frames in pixels
- * @param height height of the input frames in pixels
- */
- public native void allocateMosaicMemory(int width, int height);
-
- /**
- * Free memory allocated by allocateMosaicMemory.
- *
- */
- public native void freeMosaicMemory();
-
- /**
- * Pass the input image frame to the native layer. Each time the a new
- * source image t is set, the transformation matrix from the first source
- * image to t is computed and returned.
- *
- * @param pixels source image of NV21 format.
- * @return Float array of length 11; first 9 entries correspond to the 3x3
- * transformation matrix between the first frame and the passed frame;
- * the 10th entry is the number of the passed frame, where the counting
- * starts from 1; and the 11th entry is the returning code, whose value
- * is one of those MOSAIC_RET_* returning flags defined above.
- */
- public native float[] setSourceImage(byte[] pixels);
-
- /**
- * This is an alternative to the setSourceImage function above. This should
- * be called when the image data is already on the native side in a fixed
- * byte array. In implementation, this array is filled by the GL thread
- * using glReadPixels directly from GPU memory (where it is accessed by
- * an associated SurfaceTexture).
- *
- * @return Float array of length 11; first 9 entries correspond to the 3x3
- * transformation matrix between the first frame and the passed frame;
- * the 10th entry is the number of the passed frame, where the counting
- * starts from 1; and the 11th entry is the returning code, whose value
- * is one of those MOSAIC_RET_* returning flags defined above.
- */
- public native float[] setSourceImageFromGPU();
-
- /**
- * Set the type of blending.
- *
- * @param type the blending type defined in the class. {BLENDTYPE_FULL,
- * BLENDTYPE_PAN, BLENDTYPE_CYLINDERPAN, BLENDTYPE_HORIZONTAL}
- */
- public native void setBlendingType(int type);
-
- /**
- * Set the type of strips to use for blending.
- * @param type the blending strip type to use {STRIPTYPE_THIN,
- * STRIPTYPE_WIDE}.
- */
- public native void setStripType(int type);
-
- /**
- * Tell the native layer to create the final mosaic after all the input frame
- * data have been collected.
- * The case of generating high-resolution mosaic may take dozens of seconds to finish.
- *
- * @param value True means generating a high-resolution mosaic -
- * which is based on the original images set in setSourceImage().
- * False means generating a low-resolution version -
- * which is based on 1/4 downscaled images from the original images.
- * @return Returns a status code suggesting if the mosaic building was
- * successful, in error, or was cancelled by the user.
- */
- public native int createMosaic(boolean value);
-
- /**
- * Get the data for the created mosaic.
- *
- * @return Returns an integer array which contains the final mosaic in the ARGB_8888 format.
- * The first MosaicWidth*MosaicHeight values contain the image data, followed by 2
- * integers corresponding to the values MosaicWidth and MosaicHeight respectively.
- */
- public native int[] getFinalMosaic();
-
- /**
- * Get the data for the created mosaic.
- *
- * @return Returns a byte array which contains the final mosaic in the NV21 format.
- * The first MosaicWidth*MosaicHeight*1.5 values contain the image data, followed by
- * 8 bytes which pack the MosaicWidth and MosaicHeight integers into 4 bytes each
- * respectively.
- */
- public native byte[] getFinalMosaicNV21();
-
- /**
- * Reset the state of the frame arrays which maintain the captured frame data.
- * Also re-initializes the native mosaic object to make it ready for capturing a new mosaic.
- */
- public native void reset();
-
- /**
- * Get the progress status of the mosaic computation process.
- * @param hires Boolean flag to select whether to report progress of the
- * low-res or high-res mosaicer.
- * @param cancelComputation Boolean flag to allow cancelling the
- * mosaic computation when needed from the GUI end.
- * @return Returns a number from 0-100 where 50 denotes that the mosaic
- * computation is 50% done.
- */
- public native int reportProgress(boolean hires, boolean cancelComputation);
-}
diff --git a/src/com/android/camera/MosaicFrameProcessor.java b/src/com/android/camera/MosaicFrameProcessor.java
deleted file mode 100644
index cb305344d..000000000
--- a/src/com/android/camera/MosaicFrameProcessor.java
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.camera;
-
-import android.util.Log;
-
-/**
- * A singleton to handle the processing of each frame by {@link Mosaic}.
- */
-public class MosaicFrameProcessor {
- private static final String TAG = "MosaicFrameProcessor";
- private static final int NUM_FRAMES_IN_BUFFER = 2;
- private static final int MAX_NUMBER_OF_FRAMES = 100;
- private static final int MOSAIC_RET_CODE_INDEX = 10;
- private static final int FRAME_COUNT_INDEX = 9;
- private static final int X_COORD_INDEX = 2;
- private static final int Y_COORD_INDEX = 5;
- private static final int HR_TO_LR_DOWNSAMPLE_FACTOR = 4;
- private static final int WINDOW_SIZE = 3;
-
- private Mosaic mMosaicer;
- private boolean mIsMosaicMemoryAllocated = false;
- private float mTranslationLastX;
- private float mTranslationLastY;
-
- private int mFillIn = 0;
- private int mTotalFrameCount = 0;
- private int mLastProcessFrameIdx = -1;
- private int mCurrProcessFrameIdx = -1;
- private boolean mFirstRun;
-
- // Panning rate is in unit of percentage of image content translation per
- // frame. Use moving average to calculate the panning rate.
- private float mPanningRateX;
- private float mPanningRateY;
-
- private float[] mDeltaX = new float[WINDOW_SIZE];
- private float[] mDeltaY = new float[WINDOW_SIZE];
- private int mOldestIdx = 0;
- private float mTotalTranslationX = 0f;
- private float mTotalTranslationY = 0f;
-
- private ProgressListener mProgressListener;
-
- private int mPreviewWidth;
- private int mPreviewHeight;
- private int mPreviewBufferSize;
-
- private static MosaicFrameProcessor sMosaicFrameProcessor; // singleton
-
- public interface ProgressListener {
- public void onProgress(boolean isFinished, float panningRateX, float panningRateY,
- float progressX, float progressY);
- }
-
- public static MosaicFrameProcessor getInstance() {
- if (sMosaicFrameProcessor == null) {
- sMosaicFrameProcessor = new MosaicFrameProcessor();
- }
- return sMosaicFrameProcessor;
- }
-
- private MosaicFrameProcessor() {
- mMosaicer = new Mosaic();
- }
-
- public void setProgressListener(ProgressListener listener) {
- mProgressListener = listener;
- }
-
- public int reportProgress(boolean hires, boolean cancel) {
- return mMosaicer.reportProgress(hires, cancel);
- }
-
- public void initialize(int previewWidth, int previewHeight, int bufSize) {
- mPreviewWidth = previewWidth;
- mPreviewHeight = previewHeight;
- mPreviewBufferSize = bufSize;
- setupMosaicer(mPreviewWidth, mPreviewHeight, mPreviewBufferSize);
- setStripType(Mosaic.STRIPTYPE_WIDE);
- // no need to call reset() here. reset() should be called by the client
- // after this initialization before calling other methods of this object.
- }
-
- public void clear() {
- if (mIsMosaicMemoryAllocated) {
- mMosaicer.freeMosaicMemory();
- mIsMosaicMemoryAllocated = false;
- }
- synchronized (this) {
- notify();
- }
- }
-
- public boolean isMosaicMemoryAllocated() {
- return mIsMosaicMemoryAllocated;
- }
-
- public void setStripType(int type) {
- mMosaicer.setStripType(type);
- }
-
- private void setupMosaicer(int previewWidth, int previewHeight, int bufSize) {
- Log.v(TAG, "setupMosaicer w, h=" + previewWidth + ',' + previewHeight + ',' + bufSize);
-
- if (mIsMosaicMemoryAllocated) throw new RuntimeException("MosaicFrameProcessor in use!");
- mIsMosaicMemoryAllocated = true;
- mMosaicer.allocateMosaicMemory(previewWidth, previewHeight);
- }
-
- public void reset() {
- // reset() can be called even if MosaicFrameProcessor is not initialized.
- // Only counters will be changed.
- mFirstRun = true;
- mTotalFrameCount = 0;
- mFillIn = 0;
- mTotalTranslationX = 0;
- mTranslationLastX = 0;
- mTotalTranslationY = 0;
- mTranslationLastY = 0;
- mPanningRateX = 0;
- mPanningRateY = 0;
- mLastProcessFrameIdx = -1;
- mCurrProcessFrameIdx = -1;
- for (int i = 0; i < WINDOW_SIZE; ++i) {
- mDeltaX[i] = 0f;
- mDeltaY[i] = 0f;
- }
- mMosaicer.reset();
- }
-
- public int createMosaic(boolean highRes) {
- return mMosaicer.createMosaic(highRes);
- }
-
- public byte[] getFinalMosaicNV21() {
- return mMosaicer.getFinalMosaicNV21();
- }
-
- // Processes the last filled image frame through the mosaicer and
- // updates the UI to show progress.
- // When done, processes and displays the final mosaic.
- public void processFrame() {
- if (!mIsMosaicMemoryAllocated) {
- // clear() is called and buffers are cleared, stop computation.
- // This can happen when the onPause() is called in the activity, but still some frames
- // are not processed yet and thus the callback may be invoked.
- return;
- }
-
- mCurrProcessFrameIdx = mFillIn;
- mFillIn = ((mFillIn + 1) % NUM_FRAMES_IN_BUFFER);
-
- // Check that we are trying to process a frame different from the
- // last one processed (useful if this class was running asynchronously)
- if (mCurrProcessFrameIdx != mLastProcessFrameIdx) {
- mLastProcessFrameIdx = mCurrProcessFrameIdx;
-
- // TODO: make the termination condition regarding reaching
- // MAX_NUMBER_OF_FRAMES solely determined in the library.
- if (mTotalFrameCount < MAX_NUMBER_OF_FRAMES) {
- // If we are still collecting new frames for the current mosaic,
- // process the new frame.
- calculateTranslationRate();
-
- // Publish progress of the ongoing processing
- if (mProgressListener != null) {
- mProgressListener.onProgress(false, mPanningRateX, mPanningRateY,
- mTranslationLastX * HR_TO_LR_DOWNSAMPLE_FACTOR / mPreviewWidth,
- mTranslationLastY * HR_TO_LR_DOWNSAMPLE_FACTOR / mPreviewHeight);
- }
- } else {
- if (mProgressListener != null) {
- mProgressListener.onProgress(true, mPanningRateX, mPanningRateY,
- mTranslationLastX * HR_TO_LR_DOWNSAMPLE_FACTOR / mPreviewWidth,
- mTranslationLastY * HR_TO_LR_DOWNSAMPLE_FACTOR / mPreviewHeight);
- }
- }
- }
- }
-
- public void calculateTranslationRate() {
- float[] frameData = mMosaicer.setSourceImageFromGPU();
- int ret_code = (int) frameData[MOSAIC_RET_CODE_INDEX];
- mTotalFrameCount = (int) frameData[FRAME_COUNT_INDEX];
- float translationCurrX = frameData[X_COORD_INDEX];
- float translationCurrY = frameData[Y_COORD_INDEX];
-
- if (mFirstRun) {
- // First time: no need to update delta values.
- mTranslationLastX = translationCurrX;
- mTranslationLastY = translationCurrY;
- mFirstRun = false;
- return;
- }
-
- // Moving average: remove the oldest translation/deltaTime and
- // add the newest translation/deltaTime in
- int idx = mOldestIdx;
- mTotalTranslationX -= mDeltaX[idx];
- mTotalTranslationY -= mDeltaY[idx];
- mDeltaX[idx] = Math.abs(translationCurrX - mTranslationLastX);
- mDeltaY[idx] = Math.abs(translationCurrY - mTranslationLastY);
- mTotalTranslationX += mDeltaX[idx];
- mTotalTranslationY += mDeltaY[idx];
-
- // The panning rate is measured as the rate of the translation percentage in
- // image width/height. Take the horizontal panning rate for example, the image width
- // used in finding the translation is (PreviewWidth / HR_TO_LR_DOWNSAMPLE_FACTOR).
- // To get the horizontal translation percentage, the horizontal translation,
- // (translationCurrX - mTranslationLastX), is divided by the
- // image width. We then get the rate by dividing the translation percentage with the
- // number of frames.
- mPanningRateX = mTotalTranslationX /
- (mPreviewWidth / HR_TO_LR_DOWNSAMPLE_FACTOR) / WINDOW_SIZE;
- mPanningRateY = mTotalTranslationY /
- (mPreviewHeight / HR_TO_LR_DOWNSAMPLE_FACTOR) / WINDOW_SIZE;
-
- mTranslationLastX = translationCurrX;
- mTranslationLastY = translationCurrY;
- mOldestIdx = (mOldestIdx + 1) % WINDOW_SIZE;
- }
-}
diff --git a/src/com/android/camera/MosaicPreviewRenderer.java b/src/com/android/camera/MosaicPreviewRenderer.java
deleted file mode 100644
index 42da4d9e7..000000000
--- a/src/com/android/camera/MosaicPreviewRenderer.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.camera;
-
-import android.graphics.SurfaceTexture;
-import android.os.ConditionVariable;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Message;
-
-import javax.microedition.khronos.opengles.GL10;
-
-public class MosaicPreviewRenderer {
-
- @SuppressWarnings("unused")
- private static final String TAG = "CAM_MosaicPreviewRenderer";
-
- private int mWidth; // width of the view in UI
- private int mHeight; // height of the view in UI
-
- private boolean mIsLandscape = true;
- private final float[] mTransformMatrix = new float[16];
-
- private ConditionVariable mEglThreadBlockVar = new ConditionVariable();
- private HandlerThread mEglThread;
- private MyHandler mHandler;
- private SurfaceTextureRenderer mSTRenderer;
-
- private SurfaceTexture mInputSurfaceTexture;
-
- private class MyHandler extends Handler {
- public static final int MSG_INIT_SYNC = 0;
- public static final int MSG_SHOW_PREVIEW_FRAME_SYNC = 1;
- public static final int MSG_SHOW_PREVIEW_FRAME = 2;
- public static final int MSG_ALIGN_FRAME_SYNC = 3;
- public static final int MSG_RELEASE = 4;
-
- public MyHandler(Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_INIT_SYNC:
- doInit();
- mEglThreadBlockVar.open();
- break;
- case MSG_SHOW_PREVIEW_FRAME_SYNC:
- doShowPreviewFrame();
- mEglThreadBlockVar.open();
- break;
- case MSG_SHOW_PREVIEW_FRAME:
- doShowPreviewFrame();
- break;
- case MSG_ALIGN_FRAME_SYNC:
- doAlignFrame();
- mEglThreadBlockVar.open();
- break;
- case MSG_RELEASE:
- doRelease();
- mEglThreadBlockVar.open();
- break;
- }
- }
-
- private void doAlignFrame() {
- mInputSurfaceTexture.updateTexImage();
- mInputSurfaceTexture.getTransformMatrix(mTransformMatrix);
-
- MosaicRenderer.setWarping(true);
- // Call preprocess to render it to low-res and high-res RGB textures.
- MosaicRenderer.preprocess(mTransformMatrix);
- // Now, transfer the textures from GPU to CPU memory for processing
- MosaicRenderer.transferGPUtoCPU();
- MosaicRenderer.updateMatrix();
- MosaicRenderer.step();
- }
-
- private void doShowPreviewFrame() {
- mInputSurfaceTexture.updateTexImage();
- mInputSurfaceTexture.getTransformMatrix(mTransformMatrix);
-
- MosaicRenderer.setWarping(false);
- // Call preprocess to render it to low-res and high-res RGB textures.
- MosaicRenderer.preprocess(mTransformMatrix);
- MosaicRenderer.updateMatrix();
- MosaicRenderer.step();
- }
-
- private void doInit() {
- mInputSurfaceTexture = new SurfaceTexture(MosaicRenderer.init());
- MosaicRenderer.reset(mWidth, mHeight, mIsLandscape);
- }
-
- private void doRelease() {
- releaseSurfaceTexture(mInputSurfaceTexture);
- mEglThread.quit();
- }
-
- private void releaseSurfaceTexture(SurfaceTexture st) {
- st.release();
- }
-
- // Should be called from other thread.
- public void sendMessageSync(int msg) {
- mEglThreadBlockVar.close();
- sendEmptyMessage(msg);
- mEglThreadBlockVar.block();
- }
- }
-
- /**
- * Constructor.
- *
- * @param tex The {@link SurfaceTexture} for the final UI output.
- * @param w The width of the UI view.
- * @param h The height of the UI view.
- * @param isLandscape The UI orientation. {@code true} if in landscape,
- * false if in portrait.
- */
- public MosaicPreviewRenderer(SurfaceTexture tex, int w, int h, boolean isLandscape) {
- mIsLandscape = isLandscape;
-
- mEglThread = new HandlerThread("PanoramaRealtimeRenderer");
- mEglThread.start();
- mHandler = new MyHandler(mEglThread.getLooper());
- mWidth = w;
- mHeight = h;
-
- SurfaceTextureRenderer.FrameDrawer dummy = new SurfaceTextureRenderer.FrameDrawer() {
- @Override
- public void onDrawFrame(GL10 gl) {
- // nothing, we have our draw functions.
- }
- };
- mSTRenderer = new SurfaceTextureRenderer(tex, mHandler, dummy);
-
- // We need to sync this because the generation of surface texture for input is
- // done here and the client will continue with the assumption that the
- // generation is completed.
- mHandler.sendMessageSync(MyHandler.MSG_INIT_SYNC);
- }
-
- public void release() {
- mSTRenderer.release();
- mHandler.sendMessageSync(MyHandler.MSG_RELEASE);
- }
-
- public void showPreviewFrameSync() {
- mHandler.sendMessageSync(MyHandler.MSG_SHOW_PREVIEW_FRAME_SYNC);
- mSTRenderer.draw(true);
- }
-
- public void showPreviewFrame() {
- mHandler.sendEmptyMessage(MyHandler.MSG_SHOW_PREVIEW_FRAME);
- mSTRenderer.draw(false);
- }
-
- public void alignFrameSync() {
- mHandler.sendMessageSync(MyHandler.MSG_ALIGN_FRAME_SYNC);
- mSTRenderer.draw(true);
- }
-
- public SurfaceTexture getInputSurfaceTexture() {
- return mInputSurfaceTexture;
- }
-}
diff --git a/src/com/android/camera/MosaicRenderer.java b/src/com/android/camera/MosaicRenderer.java
deleted file mode 100644
index c50ca0d52..000000000
--- a/src/com/android/camera/MosaicRenderer.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.camera;
-
-/**
- * The Java interface to JNI calls regarding mosaic preview rendering.
- *
- */
-public class MosaicRenderer
-{
- static
- {
- System.loadLibrary("jni_mosaic");
- }
-
- /**
- * Function to be called in onSurfaceCreated() to initialize
- * the GL context, load and link the shaders and create the
- * program. Returns a texture ID to be used for SurfaceTexture.
- *
- * @return textureID the texture ID of the newly generated texture to
- * be assigned to the SurfaceTexture object.
- */
- public static native int init();
-
- /**
- * Pass the drawing surface's width and height to initialize the
- * renderer viewports and FBO dimensions.
- *
- * @param width width of the drawing surface in pixels.
- * @param height height of the drawing surface in pixels.
- * @param isLandscapeOrientation is the orientation of the activity layout in landscape.
- */
- public static native void reset(int width, int height, boolean isLandscapeOrientation);
-
- /**
- * Calling this function will render the SurfaceTexture to a new 2D texture
- * using the provided STMatrix.
- *
- * @param stMatrix texture coordinate transform matrix obtained from the
- * Surface texture
- */
- public static native void preprocess(float[] stMatrix);
-
- /**
- * This function calls glReadPixels to transfer both the low-res and high-res
- * data from the GPU memory to the CPU memory for further processing by the
- * mosaicing library.
- */
- public static native void transferGPUtoCPU();
-
- /**
- * Function to be called in onDrawFrame() to update the screen with
- * the new frame data.
- */
- public static native void step();
-
- /**
- * Call this function when a new low-res frame has been processed by
- * the mosaicing library. This will tell the renderer library to
- * update its texture and warping transformation. Any calls to step()
- * after this call will use the new image frame and transformation data.
- */
- public static native void updateMatrix();
-
- /**
- * This function allows toggling between showing the input image data
- * (without applying any warp) and the warped image data. For running
- * the renderer as a viewfinder, we set the flag to false. To see the
- * preview mosaic, we set the flag to true.
- *
- * @param flag boolean flag to set the warping to true or false.
- */
- public static native void setWarping(boolean flag);
-}
diff --git a/src/com/android/camera/WideAnglePanoramaController.java b/src/com/android/camera/WideAnglePanoramaController.java
deleted file mode 100644
index d711c0942..000000000
--- a/src/com/android/camera/WideAnglePanoramaController.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.camera;
-
-/**
- * The interface that controls the wide angle panorama module.
- */
-public interface WideAnglePanoramaController {
-
- public void onPreviewUIReady();
-
- public void onPreviewUIDestroyed();
-
- public void cancelHighResStitching();
-
- public void onShutterButtonClick();
-
- public void onPreviewUILayoutChange(int l, int t, int r, int b);
-
- public int getCameraOrientation();
-}
diff --git a/src/com/android/camera/WideAnglePanoramaModule.java b/src/com/android/camera/WideAnglePanoramaModule.java
deleted file mode 100644
index 7981bae2b..000000000
--- a/src/com/android/camera/WideAnglePanoramaModule.java
+++ /dev/null
@@ -1,1062 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.camera;
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.ImageFormat;
-import android.graphics.PixelFormat;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.graphics.SurfaceTexture;
-import android.graphics.YuvImage;
-import android.hardware.Camera.Parameters;
-import android.hardware.Camera.Size;
-import android.location.Location;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.Handler;
-import android.os.Message;
-import android.os.PowerManager;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.OrientationEventListener;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.camera.app.CameraManager.CameraProxy;
-import com.android.camera.app.AppController;
-import com.android.camera.app.MediaSaver;
-import com.android.camera.data.LocalData;
-import com.android.camera.exif.ExifInterface;
-import com.android.camera.module.ModuleController;
-import com.android.camera.util.CameraUtil;
-import com.android.camera.util.UsageStatistics;
-import com.android.camera2.R;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-import java.util.TimeZone;
-
-/**
- * Activity to handle panorama capturing.
- */
-public class WideAnglePanoramaModule
- extends CameraModule
- implements ModuleController,
- WideAnglePanoramaController,
- SurfaceTexture.OnFrameAvailableListener {
-
- public static final int DEFAULT_SWEEP_ANGLE = 160;
- public static final int DEFAULT_BLEND_MODE = Mosaic.BLENDTYPE_HORIZONTAL;
- public static final int DEFAULT_CAPTURE_PIXELS = 960 * 720;
-
- private static final int MSG_LOW_RES_FINAL_MOSAIC_READY = 1;
- private static final int MSG_GENERATE_FINAL_MOSAIC_ERROR = 2;
- private static final int MSG_END_DIALOG_RESET_TO_PREVIEW = 3;
- private static final int MSG_RESET_TO_PREVIEW = 4;
-
- private static final int SCREEN_DELAY = 2 * 60 * 1000;
-
- @SuppressWarnings("unused")
- private static final String TAG = "CAM_WidePanoModule";
- private static final int PREVIEW_STOPPED = 0;
- private static final int PREVIEW_ACTIVE = 1;
- public static final int CAPTURE_STATE_VIEWFINDER = 0;
- public static final int CAPTURE_STATE_MOSAIC = 1;
-
- // The unit of speed is degrees per frame.
- private static final float PANNING_SPEED_THRESHOLD = 2.5f;
- private static final boolean DEBUG = false;
-
- private ContentResolver mContentResolver;
- private WideAnglePanoramaUI mUI;
-
- private MosaicPreviewRenderer mMosaicPreviewRenderer;
- private final Object mRendererLock = new Object();
- private final Object mWaitObject = new Object();
-
- private String mPreparePreviewString;
- private String mDialogTitle;
- private String mDialogOkString;
- private String mDialogPanoramaFailedString;
- private String mDialogWaitingPreviousString;
-
- private int mPreviewUIWidth;
- private int mPreviewUIHeight;
- private boolean mUsingFrontCamera;
- private int mCameraPreviewWidth;
- private int mCameraPreviewHeight;
- private int mCameraState;
- private int mCaptureState;
- private PowerManager.WakeLock mPartialWakeLock;
- private MosaicFrameProcessor mMosaicFrameProcessor;
- private boolean mMosaicFrameProcessorInitialized;
- private AsyncTask <Void, Void, Void> mWaitProcessorTask;
- private long mTimeTaken;
- private Handler mMainHandler;
- private SurfaceTexture mCameraTexture;
- private boolean mThreadRunning;
- private boolean mCancelComputation;
- private float mHorizontalViewAngle;
- private float mVerticalViewAngle;
-
- // Prefer FOCUS_MODE_INFINITY to FOCUS_MODE_CONTINUOUS_VIDEO because of
- // getting a better image quality by the former.
- private final String mTargetFocusMode = Parameters.FOCUS_MODE_INFINITY;
-
- private PanoOrientationEventListener mOrientationEventListener;
- // The value could be 0, 90, 180, 270 for the 4 different orientations measured in clockwise
- // respectively.
- private int mDeviceOrientation;
- private int mDeviceOrientationAtCapture;
- private int mCameraOrientation;
- private int mOrientationCompensation;
-
- private SoundClips.Player mSoundPlayer;
-
- private Runnable mOnFrameAvailableRunnable;
-
- private CameraActivity mActivity;
- private View mRootView;
- private CameraProxy mCameraDevice;
- private boolean mPaused;
-
- private LocationManager mLocationManager;
- private ComboPreferences mPreferences;
- private boolean mMosaicPreviewConfigured;
- private boolean mPreviewFocused = true;
-
- /**
- * Constructs a new Wide-Angle panorama module.
- */
- public WideAnglePanoramaModule(AppController app) {
- super(app);
- }
-
- @Override
- public void onPreviewUIReady() {
- configMosaicPreview();
- }
-
- @Override
- public void onPreviewUIDestroyed() {
-
- }
-
- private class MosaicJpeg {
- public MosaicJpeg(byte[] data, int width, int height) {
- this.data = data;
- this.width = width;
- this.height = height;
- this.isValid = true;
- }
-
- public MosaicJpeg() {
- this.data = null;
- this.width = 0;
- this.height = 0;
- this.isValid = false;
- }
-
- public final byte[] data;
- public final int width;
- public final int height;
- public final boolean isValid;
- }
-
- private class PanoOrientationEventListener extends OrientationEventListener {
- public PanoOrientationEventListener(Context context) {
- super(context);
- }
-
- @Override
- public void onOrientationChanged(int orientation) {
- // We keep the last known orientation. So if the user first orient
- // the camera then point the camera to floor or sky, we still have
- // the correct orientation.
- if (orientation == ORIENTATION_UNKNOWN) return;
- mDeviceOrientation = CameraUtil.roundOrientation(orientation, mDeviceOrientation);
- // When the screen is unlocked, display rotation may change. Always
- // calculate the up-to-date orientationCompensation.
- int orientationCompensation = mDeviceOrientation
- + CameraUtil.getDisplayRotation(mActivity) % 360;
- if (mOrientationCompensation != orientationCompensation) {
- mOrientationCompensation = orientationCompensation;
- }
- }
- }
-
- @Override
- public void init(AppController app, boolean isSecureCamera, boolean isCaptureIntent) {
- mActivity = (CameraActivity) app.getAndroidContext();
- mRootView = app.getModuleLayoutRoot();
-
- mCaptureState = CAPTURE_STATE_VIEWFINDER;
- mUI = new WideAnglePanoramaUI(mActivity, this, (ViewGroup) mRootView);
- mUI.setCaptureProgressOnDirectionChangeListener(
- new PanoProgressBar.OnDirectionChangeListener() {
- @Override
- public void onDirectionChange(int direction) {
- if (mCaptureState == CAPTURE_STATE_MOSAIC) {
- mUI.showDirectionIndicators(direction);
- }
- }
- });
-
- mContentResolver = mActivity.getContentResolver();
- // This runs in UI thread.
- mOnFrameAvailableRunnable = new Runnable() {
- @Override
- public void run() {
- // Frames might still be available after the activity is paused.
- // If we call onFrameAvailable after pausing, the GL thread will crash.
- if (mPaused) return;
-
- MosaicPreviewRenderer renderer = null;
- synchronized (mRendererLock) {
- if (mMosaicPreviewRenderer == null) {
- return;
- }
- renderer = mMosaicPreviewRenderer;
- }
- if (mRootView.getVisibility() != View.VISIBLE) {
- renderer.showPreviewFrameSync();
- mRootView.setVisibility(View.VISIBLE);
- } else {
- if (mCaptureState == CAPTURE_STATE_VIEWFINDER) {
- renderer.showPreviewFrame();
- } else {
- renderer.alignFrameSync();
- mMosaicFrameProcessor.processFrame();
- }
- }
- }
- };
-
- PowerManager pm = (PowerManager) mActivity.getSystemService(Context.POWER_SERVICE);
- mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Panorama");
-
- mOrientationEventListener = new PanoOrientationEventListener(mActivity);
-
- mMosaicFrameProcessor = MosaicFrameProcessor.getInstance();
-
- Resources appRes = mActivity.getResources();
- mPreparePreviewString = appRes.getString(R.string.pano_dialog_prepare_preview);
- mDialogTitle = appRes.getString(R.string.pano_dialog_title);
- mDialogOkString = appRes.getString(R.string.dialog_ok);
- mDialogPanoramaFailedString = appRes.getString(R.string.pano_dialog_panorama_failed);
- mDialogWaitingPreviousString = appRes.getString(R.string.pano_dialog_waiting_previous);
-
- mPreferences = new ComboPreferences(mActivity);
- mLocationManager = mActivity.getLocationManager();
-
- mMainHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_LOW_RES_FINAL_MOSAIC_READY:
- onBackgroundThreadFinished();
- showFinalMosaic((Bitmap) msg.obj);
- saveHighResMosaic();
- break;
- case MSG_GENERATE_FINAL_MOSAIC_ERROR:
- onBackgroundThreadFinished();
- if (mPaused) {
- resetToPreviewIfPossible();
- } else {
- mUI.showAlertDialog(
- mDialogTitle, mDialogPanoramaFailedString,
- mDialogOkString, new Runnable() {
- @Override
- public void run() {
- resetToPreviewIfPossible();
- }
- });
- }
- clearMosaicFrameProcessorIfNeeded();
- break;
- case MSG_END_DIALOG_RESET_TO_PREVIEW:
- onBackgroundThreadFinished();
- resetToPreviewIfPossible();
- clearMosaicFrameProcessorIfNeeded();
- break;
- case MSG_RESET_TO_PREVIEW:
- resetToPreviewIfPossible();
- break;
- }
- }
- };
- }
-
- @Override
- public void onPreviewFocusChanged(boolean previewFocused) {
- mPreviewFocused = previewFocused;
- mUI.onPreviewFocusChanged(previewFocused);
- }
-
- @Override
- public boolean arePreviewControlsVisible() {
- return mUI.arePreviewControlsVisible();
- }
-
- /**
- * Opens camera and sets the parameters.
- *
- * @return Whether the camera was opened successfully.
- */
- private boolean setupCamera() {
- if (!openCamera()) {
- return false;
- }
- Parameters parameters = mCameraDevice.getParameters();
- setupCaptureParams(parameters);
- configureCamera(parameters);
- return true;
- }
-
- private void releaseCamera() {
- if (mCameraDevice != null) {
- CameraHolder.instance().release();
- mCameraDevice = null;
- mCameraState = PREVIEW_STOPPED;
- }
- }
-
- /**
- * Opens the camera device. The back camera has priority over the front
- * one.
- *
- * @return Whether the camera was opened successfully.
- */
- private boolean openCamera() {
- int cameraId = CameraHolder.instance().getBackCameraId();
- // If there is no back camera, use the first camera. Camera id starts
- // from 0. Currently if a camera is not back facing, it is front facing.
- // This is also forward compatible if we have a new facing other than
- // back or front in the future.
- if (cameraId == -1) cameraId = 0;
- mCameraDevice = CameraUtil.openCamera(mActivity, cameraId,
- mMainHandler, mActivity.getCameraOpenErrorCallback());
- if (mCameraDevice == null) {
- return false;
- }
- mCameraOrientation = CameraUtil.getCameraOrientation(cameraId);
- if (cameraId == CameraHolder.instance().getFrontCameraId()) mUsingFrontCamera = true;
- return true;
- }
-
- private boolean findBestPreviewSize(List<Size> supportedSizes, boolean need4To3,
- boolean needSmaller) {
- int pixelsDiff = DEFAULT_CAPTURE_PIXELS;
- boolean hasFound = false;
- for (Size size : supportedSizes) {
- int h = size.height;
- int w = size.width;
- // we only want 4:3 format.
- int d = DEFAULT_CAPTURE_PIXELS - h * w;
- if (needSmaller && d < 0) { // no bigger preview than 960x720.
- continue;
- }
- if (need4To3 && (h * 4 != w * 3)) {
- continue;
- }
- d = Math.abs(d);
- if (d < pixelsDiff) {
- mCameraPreviewWidth = w;
- mCameraPreviewHeight = h;
- pixelsDiff = d;
- hasFound = true;
- }
- }
- return hasFound;
- }
-
- private void setupCaptureParams(Parameters parameters) {
- List<Size> supportedSizes = parameters.getSupportedPreviewSizes();
- if (!findBestPreviewSize(supportedSizes, true, true)) {
- Log.w(TAG, "No 4:3 ratio preview size supported.");
- if (!findBestPreviewSize(supportedSizes, false, true)) {
- Log.w(TAG, "Can't find a supported preview size smaller than 960x720.");
- findBestPreviewSize(supportedSizes, false, false);
- }
- }
- Log.d(TAG, "camera preview h = "
- + mCameraPreviewHeight + " , w = " + mCameraPreviewWidth);
- parameters.setPreviewSize(mCameraPreviewWidth, mCameraPreviewHeight);
-
- List<int[]> frameRates = parameters.getSupportedPreviewFpsRange();
- int last = frameRates.size() - 1;
- int minFps = (frameRates.get(last))[Parameters.PREVIEW_FPS_MIN_INDEX];
- int maxFps = (frameRates.get(last))[Parameters.PREVIEW_FPS_MAX_INDEX];
- parameters.setPreviewFpsRange(minFps, maxFps);
- Log.d(TAG, "preview fps: " + minFps + ", " + maxFps);
-
- List<String> supportedFocusModes = parameters.getSupportedFocusModes();
- if (supportedFocusModes.indexOf(mTargetFocusMode) >= 0) {
- parameters.setFocusMode(mTargetFocusMode);
- } else {
- // Use the default focus mode and log a message
- Log.w(TAG, "Cannot set the focus mode to " + mTargetFocusMode +
- " becuase the mode is not supported.");
- }
-
- parameters.set(CameraUtil.RECORDING_HINT, CameraUtil.FALSE);
-
- mHorizontalViewAngle = parameters.getHorizontalViewAngle();
- mVerticalViewAngle = parameters.getVerticalViewAngle();
- }
-
- public int getPreviewBufSize() {
- PixelFormat pixelInfo = new PixelFormat();
- PixelFormat.getPixelFormatInfo(mCameraDevice.getParameters().getPreviewFormat(), pixelInfo);
- // TODO: remove this extra 32 byte after the driver bug is fixed.
- return (mCameraPreviewWidth * mCameraPreviewHeight * pixelInfo.bitsPerPixel / 8) + 32;
- }
-
- private void configureCamera(Parameters parameters) {
- mCameraDevice.setParameters(parameters);
- }
-
- /**
- * Configures the preview renderer according to the dimension defined by
- * {@code mPreviewUIWidth} and {@code mPreviewUIHeight}.
- * Will stop the camera preview first.
- */
- private void configMosaicPreview() {
- if (mPreviewUIWidth == 0 || mPreviewUIHeight == 0
- || mUI.getSurfaceTexture() == null) {
- return;
- }
-
- stopCameraPreview();
- synchronized (mRendererLock) {
- if (mMosaicPreviewRenderer != null) {
- mMosaicPreviewRenderer.release();
- }
- mMosaicPreviewRenderer = null;
- }
- final boolean isLandscape =
- (mActivity.getResources().getConfiguration().orientation ==
- Configuration.ORIENTATION_LANDSCAPE);
- mUI.flipPreviewIfNeeded();
- MosaicPreviewRenderer renderer = new MosaicPreviewRenderer(
- mUI.getSurfaceTexture(),
- mPreviewUIWidth, mPreviewUIHeight, isLandscape);
- synchronized (mRendererLock) {
- mMosaicPreviewRenderer = renderer;
- mCameraTexture = mMosaicPreviewRenderer.getInputSurfaceTexture();
-
- if (!mPaused && !mThreadRunning && mWaitProcessorTask == null) {
- mMainHandler.sendEmptyMessage(MSG_RESET_TO_PREVIEW);
- }
- mRendererLock.notifyAll();
- }
- mMosaicPreviewConfigured = true;
- resetToPreviewIfPossible();
- }
-
- /**
- * Receives the layout change event from the preview area. So we can
- * initialize the mosaic preview renderer.
- */
- @Override
- public void onPreviewUILayoutChange(int l, int t, int r, int b) {
- Log.d(TAG, "layout change: " + (r - l) + "/" + (b - t));
- mPreviewUIWidth = r - l;
- mPreviewUIHeight = b - t;
- configMosaicPreview();
- }
-
- @Override
- public void onFrameAvailable(SurfaceTexture surface) {
- /* This function may be called by some random thread,
- * so let's be safe and jump back to ui thread.
- * No OpenGL calls can be done here. */
- mActivity.runOnUiThread(mOnFrameAvailableRunnable);
- }
-
- public void startCapture() {
- // Reset values so we can do this again.
- mCancelComputation = false;
- mTimeTaken = System.currentTimeMillis();
- mActivity.setSwipingEnabled(false);
- mCaptureState = CAPTURE_STATE_MOSAIC;
- mUI.onStartCapture();
-
- mMosaicFrameProcessor.setProgressListener(new MosaicFrameProcessor.ProgressListener() {
- @Override
- public void onProgress(boolean isFinished, float panningRateX, float panningRateY,
- float progressX, float progressY) {
- float accumulatedHorizontalAngle = progressX * mHorizontalViewAngle;
- float accumulatedVerticalAngle = progressY * mVerticalViewAngle;
- if (isFinished
- || (Math.abs(accumulatedHorizontalAngle) >= DEFAULT_SWEEP_ANGLE)
- || (Math.abs(accumulatedVerticalAngle) >= DEFAULT_SWEEP_ANGLE)) {
- stopCapture(false);
- } else {
- float panningRateXInDegree = panningRateX * mHorizontalViewAngle;
- float panningRateYInDegree = panningRateY * mVerticalViewAngle;
- mUI.updateCaptureProgress(panningRateXInDegree, panningRateYInDegree,
- accumulatedHorizontalAngle, accumulatedVerticalAngle,
- PANNING_SPEED_THRESHOLD);
- }
- }
- });
-
- mUI.resetCaptureProgress();
- // TODO: calculate the indicator width according to different devices to reflect the actual
- // angle of view of the camera device.
- mUI.setMaxCaptureProgress(DEFAULT_SWEEP_ANGLE);
- mUI.showCaptureProgress();
- mDeviceOrientationAtCapture = mDeviceOrientation;
- mActivity.enableKeepScreenOn(true);
- // TODO: mActivity.getOrientationManager().lockOrientation();
- mActivity.lockOrientation();
- int degrees = CameraUtil.getDisplayRotation(mActivity);
- int cameraId = CameraHolder.instance().getBackCameraId();
- int orientation = CameraUtil.getDisplayOrientation(degrees, cameraId);
- mUI.setProgressOrientation(orientation);
- }
-
- private void stopCapture(boolean aborted) {
- mCaptureState = CAPTURE_STATE_VIEWFINDER;
- mUI.onStopCapture();
-
- mMosaicFrameProcessor.setProgressListener(null);
- stopCameraPreview();
-
- mCameraTexture.setOnFrameAvailableListener(null);
-
- if (!aborted && !mThreadRunning) {
- mUI.showWaitingDialog(mPreparePreviewString);
- // Hide shutter button, shutter icon, etc when waiting for
- // panorama to stitch
- mUI.hideUI();
- runBackgroundThread(new Thread() {
- @Override
- public void run() {
- MosaicJpeg jpeg = generateFinalMosaic(false);
-
- if (jpeg != null && jpeg.isValid) {
- Bitmap bitmap = null;
- bitmap = BitmapFactory.decodeByteArray(jpeg.data, 0, jpeg.data.length);
- mMainHandler.sendMessage(mMainHandler.obtainMessage(
- MSG_LOW_RES_FINAL_MOSAIC_READY, bitmap));
- } else {
- mMainHandler.sendMessage(mMainHandler.obtainMessage(
- MSG_END_DIALOG_RESET_TO_PREVIEW));
- }
- }
- });
- }
- mActivity.enableKeepScreenOn(false);
- }
-
- @Override
- public void onShutterButtonClick() {
- // If mCameraTexture == null then GL setup is not finished yet.
- // No buttons can be pressed.
- if (mPaused || mThreadRunning || mCameraTexture == null) {
- return;
- }
- // Since this button will stay on the screen when capturing, we need to check the state
- // right now.
- switch (mCaptureState) {
- case CAPTURE_STATE_VIEWFINDER:
- final long storageSpaceBytes = mActivity.getStorageSpaceBytes();
- if(storageSpaceBytes <= Storage.LOW_STORAGE_THRESHOLD_BYTES) {
- Log.w(TAG, "Low storage warning: " + storageSpaceBytes);
- return;
- }
- mSoundPlayer.play(SoundClips.START_VIDEO_RECORDING);
- startCapture();
- break;
- case CAPTURE_STATE_MOSAIC:
- mSoundPlayer.play(SoundClips.STOP_VIDEO_RECORDING);
- stopCapture(false);
- break;
- default:
- Log.w(TAG, "Unknown capture state: " + mCaptureState);
- break;
- }
- }
-
- public void reportProgress() {
- mUI.resetSavingProgress();
- Thread t = new Thread() {
- @Override
- public void run() {
- while (mThreadRunning) {
- final int progress = mMosaicFrameProcessor.reportProgress(
- true, mCancelComputation);
-
- try {
- synchronized (mWaitObject) {
- mWaitObject.wait(50);
- }
- } catch (InterruptedException e) {
- throw new RuntimeException("Panorama reportProgress failed", e);
- }
- // Update the progress bar
- mActivity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mUI.updateSavingProgress(progress);
- }
- });
- }
- }
- };
- t.start();
- }
-
- private int getCaptureOrientation() {
- // The panorama image returned from the library is oriented based on the
- // natural orientation of a camera. We need to set an orientation for the image
- // in its EXIF header, so the image can be displayed correctly.
- // The orientation is calculated from compensating the
- // device orientation at capture and the camera orientation respective to
- // the natural orientation of the device.
- int orientation;
- if (mUsingFrontCamera) {
- // mCameraOrientation is negative with respect to the front facing camera.
- // See document of android.hardware.Camera.Parameters.setRotation.
- orientation = (mDeviceOrientationAtCapture - mCameraOrientation + 360) % 360;
- } else {
- orientation = (mDeviceOrientationAtCapture + mCameraOrientation) % 360;
- }
- return orientation;
- }
-
- /** The orientation of the camera image. The value is the angle that the camera
- * image needs to be rotated clockwise so it shows correctly on the display
- * in its natural orientation. It should be 0, 90, 180, or 270.*/
- @Override
- public int getCameraOrientation() {
- return mCameraOrientation;
- }
-
- public void saveHighResMosaic() {
- runBackgroundThread(new Thread() {
- @Override
- public void run() {
- mPartialWakeLock.acquire();
- MosaicJpeg jpeg;
- try {
- jpeg = generateFinalMosaic(true);
- } finally {
- mPartialWakeLock.release();
- }
-
- if (jpeg == null) { // Cancelled by user.
- mMainHandler.sendEmptyMessage(MSG_END_DIALOG_RESET_TO_PREVIEW);
- } else if (!jpeg.isValid) { // Error when generating mosaic.
- mMainHandler.sendEmptyMessage(MSG_GENERATE_FINAL_MOSAIC_ERROR);
- } else {
- int orientation = getCaptureOrientation();
- final Uri uri = savePanorama(jpeg.data, jpeg.width, jpeg.height, orientation);
- if (uri != null) {
- mActivity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- mActivity.notifyNewMedia(uri);
- }
- });
- }
- mMainHandler.sendMessage(
- mMainHandler.obtainMessage(MSG_END_DIALOG_RESET_TO_PREVIEW));
- }
- }
- });
- reportProgress();
- }
-
- private void runBackgroundThread(Thread thread) {
- mThreadRunning = true;
- thread.start();
- }
-
- private void onBackgroundThreadFinished() {
- mThreadRunning = false;
- mUI.dismissAllDialogs();
- }
-
- private void cancelHighResComputation() {
- mCancelComputation = true;
- synchronized (mWaitObject) {
- mWaitObject.notify();
- }
- }
-
- // This function will be called upon the first camera frame is available.
- private void reset() {
- mCaptureState = CAPTURE_STATE_VIEWFINDER;
-
- mActivity.unlockOrientation();
- mUI.reset();
- mActivity.setSwipingEnabled(true);
- // Orientation change will trigger onLayoutChange->configMosaicPreview->
- // resetToPreview. Do not show the capture UI in film strip.
- if (mPreviewFocused) {
- mUI.showPreviewUI();
- }
- mMosaicFrameProcessor.reset();
- }
-
- private void resetToPreviewIfPossible() {
- reset();
- if (!mMosaicFrameProcessorInitialized
- || mUI.getSurfaceTexture() == null
- || !mMosaicPreviewConfigured) {
- return;
- }
- if (!mPaused) {
- startCameraPreview();
- }
- }
-
- private void showFinalMosaic(Bitmap bitmap) {
- mUI.showFinalMosaic(bitmap, getCaptureOrientation());
- }
-
- private Uri savePanorama(byte[] jpegData, int width, int height, int orientation) {
- if (jpegData != null) {
- String filename = PanoUtil.createName(
- mActivity.getResources().getString(R.string.pano_file_name_format), mTimeTaken);
- String filepath = Storage.generateFilepath(filename);
-
- UsageStatistics.onEvent(UsageStatistics.COMPONENT_PANORAMA,
- UsageStatistics.ACTION_CAPTURE_DONE, null, 0,
- UsageStatistics.hashFileName(filename + ".jpg"));
-
- Location loc = mLocationManager.getCurrentLocation();
- ExifInterface exif = new ExifInterface();
- try {
- exif.readExif(jpegData);
- exif.addGpsDateTimeStampTag(mTimeTaken);
- exif.addDateTimeStampTag(ExifInterface.TAG_DATE_TIME, mTimeTaken,
- TimeZone.getDefault());
- exif.setTag(exif.buildTag(ExifInterface.TAG_ORIENTATION,
- ExifInterface.getOrientationValueForRotation(orientation)));
- writeLocation(loc, exif);
- exif.writeExif(jpegData, filepath);
- } catch (IOException e) {
- Log.e(TAG, "Cannot set exif for " + filepath, e);
- Storage.writeFile(filepath, jpegData);
- }
- int jpegLength = (int) (new File(filepath).length());
- return Storage.addImage(mContentResolver, filename, mTimeTaken, loc, orientation,
- jpegLength, filepath, width, height, LocalData.MIME_TYPE_JPEG);
- }
- return null;
- }
-
- private static void writeLocation(Location location, ExifInterface exif) {
- if (location == null) {
- return;
- }
- exif.addGpsTags(location.getLatitude(), location.getLongitude());
- exif.setTag(exif.buildTag(ExifInterface.TAG_GPS_PROCESSING_METHOD, location.getProvider()));
- }
-
- private void clearMosaicFrameProcessorIfNeeded() {
- if (!mPaused || mThreadRunning) return;
- // Only clear the processor if it is initialized by this activity
- // instance. Other activity instances may be using it.
- if (mMosaicFrameProcessorInitialized) {
- mMosaicFrameProcessor.clear();
- mMosaicFrameProcessorInitialized = false;
- }
- }
-
- private void initMosaicFrameProcessorIfNeeded() {
- if (mPaused || mThreadRunning) {
- return;
- }
-
- mMosaicFrameProcessor.initialize(
- mCameraPreviewWidth, mCameraPreviewHeight, getPreviewBufSize());
- mMosaicFrameProcessorInitialized = true;
- }
-
- @Override
- public void resume() {
- mPaused = false;
- mOrientationEventListener.enable();
-
- mCaptureState = CAPTURE_STATE_VIEWFINDER;
-
- if (!setupCamera()) {
- Log.e(TAG, "Failed to open camera, aborting");
- return;
- }
-
- // Set up sound playback for shutter button
- mSoundPlayer = SoundClips.getPlayer(mActivity);
-
- // Check if another panorama instance is using the mosaic frame processor.
- mUI.dismissAllDialogs();
- if (!mThreadRunning && mMosaicFrameProcessor.isMosaicMemoryAllocated()) {
- mUI.showWaitingDialog(mDialogWaitingPreviousString);
- // If stitching is still going on, make sure switcher and shutter button
- // are not showing
- mUI.hideUI();
- mWaitProcessorTask = new WaitProcessorTask().execute();
- } else {
- // Camera must be initialized before MosaicFrameProcessor is
- // initialized. The preview size has to be decided by camera device.
- initMosaicFrameProcessorIfNeeded();
- Point size = mUI.getPreviewAreaSize();
- mPreviewUIWidth = size.x;
- mPreviewUIHeight = size.y;
- configMosaicPreview();
- mActivity.updateStorageSpaceAndHint();
- }
-
- // Initialize location service.
- boolean recordLocation = RecordLocationPreference.get(mPreferences,
- mContentResolver);
- mLocationManager.recordLocation(recordLocation);
- UsageStatistics.onContentViewChanged(
- UsageStatistics.COMPONENT_CAMERA, "PanoramaModule");
- }
-
- @Override
- public void pause() {
- mPaused = true;
- if (mLocationManager != null) mLocationManager.recordLocation(false);
- mOrientationEventListener.disable();
- if (mCameraDevice == null) {
- // Camera open failed. Nothing should be done here.
- return;
- }
- // Stop the capturing first.
- if (mCaptureState == CAPTURE_STATE_MOSAIC) {
- stopCapture(true);
- reset();
- }
- mUI.showPreviewCover();
- releaseCamera();
- synchronized (mRendererLock) {
- mCameraTexture = null;
-
- // The preview renderer might not have a chance to be initialized
- // before onPause().
- if (mMosaicPreviewRenderer != null) {
- mMosaicPreviewRenderer.release();
- mMosaicPreviewRenderer = null;
- }
- }
-
- clearMosaicFrameProcessorIfNeeded();
- if (mWaitProcessorTask != null) {
- mWaitProcessorTask.cancel(true);
- mWaitProcessorTask = null;
- }
- mActivity.enableKeepScreenOn(false);
- if (mSoundPlayer != null) {
- mSoundPlayer.release();
- mSoundPlayer = null;
- }
- System.gc();
- }
-
- @Override
- public void destroy() {
- // TODO: implement this.
- }
-
- @Override
- public void onPreviewSizeChanged(int width, int height) {
- // TODO: implement this.
- }
-
- @Override
- public void onLayoutOrientationChanged(boolean isLandscape) {
- mUI.onConfigurationChanged(isLandscape, mThreadRunning);
- }
-
- @Override
- public void onOrientationChanged(int orientation) {
- }
-
- @Override
- public void onCameraAvailable(CameraProxy cameraProxy) {
- // TODO: implement this.
- }
-
- /**
- * Generate the final mosaic image.
- *
- * @param highRes flag to indicate whether we want to get a high-res version.
- * @return a MosaicJpeg with its isValid flag set to true if successful; null if the generation
- * process is cancelled; and a MosaicJpeg with its isValid flag set to false if there
- * is an error in generating the final mosaic.
- */
- public MosaicJpeg generateFinalMosaic(boolean highRes) {
- int mosaicReturnCode = mMosaicFrameProcessor.createMosaic(highRes);
- if (mosaicReturnCode == Mosaic.MOSAIC_RET_CANCELLED) {
- return null;
- } else if (mosaicReturnCode == Mosaic.MOSAIC_RET_ERROR) {
- return new MosaicJpeg();
- }
-
- byte[] imageData = mMosaicFrameProcessor.getFinalMosaicNV21();
- if (imageData == null) {
- Log.e(TAG, "getFinalMosaicNV21() returned null.");
- return new MosaicJpeg();
- }
-
- int len = imageData.length - 8;
- int width = (imageData[len + 0] << 24) + ((imageData[len + 1] & 0xFF) << 16)
- + ((imageData[len + 2] & 0xFF) << 8) + (imageData[len + 3] & 0xFF);
- int height = (imageData[len + 4] << 24) + ((imageData[len + 5] & 0xFF) << 16)
- + ((imageData[len + 6] & 0xFF) << 8) + (imageData[len + 7] & 0xFF);
- Log.d(TAG, "ImLength = " + (len) + ", W = " + width + ", H = " + height);
-
- if (width <= 0 || height <= 0) {
- // TODO: pop up an error message indicating that the final result is not generated.
- Log.e(TAG, "width|height <= 0!!, len = " + (len) + ", W = " + width + ", H = " +
- height);
- return new MosaicJpeg();
- }
-
- YuvImage yuvimage = new YuvImage(imageData, ImageFormat.NV21, width, height, null);
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- yuvimage.compressToJpeg(new Rect(0, 0, width, height), 100, out);
- try {
- out.close();
- } catch (Exception e) {
- Log.e(TAG, "Exception in storing final mosaic", e);
- return new MosaicJpeg();
- }
- return new MosaicJpeg(out.toByteArray(), width, height);
- }
-
- private void startCameraPreview() {
- if (mCameraDevice == null) {
- // Camera open failed. Return.
- return;
- }
-
- if (mUI.getSurfaceTexture() == null) {
- // UI is not ready.
- return;
- }
-
- // This works around a driver issue. startPreview may fail if
- // stopPreview/setPreviewTexture/startPreview are called several times
- // in a row. mCameraTexture can be null after pressing home during
- // mosaic generation and coming back. Preview will be started later in
- // onLayoutChange->configMosaicPreview. This also reduces the latency.
- synchronized (mRendererLock) {
- if (mCameraTexture == null) return;
-
- // If we're previewing already, stop the preview first (this will
- // blank the screen).
- if (mCameraState != PREVIEW_STOPPED) stopCameraPreview();
-
- // Set the display orientation to 0, so that the underlying mosaic
- // library can always get undistorted mCameraPreviewWidth x mCameraPreviewHeight
- // image data from SurfaceTexture.
- mCameraDevice.setDisplayOrientation(0);
-
- mCameraTexture.setOnFrameAvailableListener(this);
- mCameraDevice.setPreviewTexture(mCameraTexture);
- }
- mCameraDevice.startPreview();
- mCameraState = PREVIEW_ACTIVE;
- }
-
- private void stopCameraPreview() {
- if (mCameraDevice != null && mCameraState != PREVIEW_STOPPED) {
- mCameraDevice.stopPreview();
- }
- mCameraState = PREVIEW_STOPPED;
- }
-
- @Override
- public boolean onBackPressed() {
- // If panorama is generating low res or high res mosaic, ignore back
- // key. So the activity will not be destroyed.
- if (mThreadRunning) return true;
- return false;
- }
-
- private class WaitProcessorTask extends AsyncTask<Void, Void, Void> {
- @Override
- protected Void doInBackground(Void... params) {
- synchronized (mMosaicFrameProcessor) {
- while (!isCancelled() && mMosaicFrameProcessor.isMosaicMemoryAllocated()) {
- try {
- mMosaicFrameProcessor.wait();
- } catch (Exception e) {
- // ignore
- }
- }
- }
- mActivity.updateStorageSpace();
- return null;
- }
-
- @Override
- protected void onPostExecute(Void result) {
- mWaitProcessorTask = null;
- mUI.dismissAllDialogs();
- // TODO (shkong): mGLRootView.setVisibility(View.VISIBLE);
- initMosaicFrameProcessorIfNeeded();
- Point size = mUI.getPreviewAreaSize();
- mPreviewUIWidth = size.x;
- mPreviewUIHeight = size.y;
- configMosaicPreview();
- resetToPreviewIfPossible();
- mActivity.updateStorageHint(mActivity.getStorageSpaceBytes());
- }
- }
-
- @Override
- public void cancelHighResStitching() {
- if (mPaused || mCameraTexture == null) return;
- cancelHighResComputation();
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- return false;
- }
-
- @Override
- public boolean onKeyUp(int keyCode, KeyEvent event) {
- return false;
- }
-
- @Override
- public void onSingleTapUp(View view, int x, int y) {
- }
-
- @Override
- public void onMediaSaverAvailable(MediaSaver s) {
- // do nothing.
- }
-}
diff --git a/src/com/android/camera/WideAnglePanoramaUI.java b/src/com/android/camera/WideAnglePanoramaUI.java
deleted file mode 100644
index 58a1a3231..000000000
--- a/src/com/android/camera/WideAnglePanoramaUI.java
+++ /dev/null
@@ -1,495 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.camera;
-
-import android.app.AlertDialog;
-import android.app.ProgressDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.graphics.SurfaceTexture;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.TextureView;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-import com.android.camera.ui.CameraControls;
-import com.android.camera.util.CameraUtil;
-import com.android.camera2.R;
-
-/**
- * The UI of {@link WideAnglePanoramaModule}.
- */
-public class WideAnglePanoramaUI implements
- TextureView.SurfaceTextureListener,
- ShutterButton.OnShutterButtonListener,
- View.OnLayoutChangeListener {
-
- @SuppressWarnings("unused")
- private static final String TAG = "CAM_WidePanoramaUI";
-
- private CameraActivity mActivity;
- private WideAnglePanoramaController mController;
-
- private ViewGroup mRootView;
- private FrameLayout mCaptureLayout;
- private View mReviewLayout;
- private ImageView mReview;
- private View mPreviewBorder;
- private View mLeftIndicator;
- private View mRightIndicator;
- private View mCaptureIndicator;
- private PanoProgressBar mCaptureProgressBar;
- private PanoProgressBar mSavingProgressBar;
- private TextView mTooFastPrompt;
- private View mPreviewLayout;
- private ViewGroup mReviewControl;
- private TextureView mTextureView;
- private ShutterButton mShutterButton;
- private CameraControls mCameraControls;
-
- private Matrix mProgressDirectionMatrix = new Matrix();
- private float[] mProgressAngle = new float[2];
-
- private DialogHelper mDialogHelper;
-
- // Color definitions.
- private int mIndicatorColor;
- private int mIndicatorColorFast;
- private int mReviewBackground;
- private SurfaceTexture mSurfaceTexture;
- private View mPreviewCover;
-
- /** Constructor. */
- public WideAnglePanoramaUI(
- CameraActivity activity,
- WideAnglePanoramaController controller,
- ViewGroup root) {
- mActivity = activity;
- mController = controller;
- mRootView = root;
-
- createContentView();
- }
-
- public void onStartCapture() {
- mShutterButton.setImageResource(R.drawable.btn_shutter_recording);
- mCaptureIndicator.setVisibility(View.VISIBLE);
- showDirectionIndicators(PanoProgressBar.DIRECTION_NONE);
- }
-
- public void showPreviewUI() {
- mCaptureLayout.setVisibility(View.VISIBLE);
- showUI();
- }
-
- public void onStopCapture() {
- mCaptureIndicator.setVisibility(View.INVISIBLE);
- hideTooFastIndication();
- hideDirectionIndicators();
- }
-
- public void hideUI() {
- mCameraControls.setVisibility(View.INVISIBLE);
- }
-
- public void showUI() {
- mCameraControls.setVisibility(View.VISIBLE);
- }
-
- public void onPreviewFocusChanged(boolean previewFocused) {
- if (previewFocused) {
- showUI();
- } else {
- hideUI();
- }
- }
-
- public boolean arePreviewControlsVisible() {
- return (mCameraControls.getVisibility() == View.VISIBLE);
- }
-
- public void setCaptureProgressOnDirectionChangeListener(
- PanoProgressBar.OnDirectionChangeListener listener) {
- mCaptureProgressBar.setOnDirectionChangeListener(listener);
- }
-
- public void resetCaptureProgress() {
- mCaptureProgressBar.reset();
- }
-
- public void setMaxCaptureProgress(int max) {
- mCaptureProgressBar.setMaxProgress(max);
- }
-
- public void showCaptureProgress() {
- mCaptureProgressBar.setVisibility(View.VISIBLE);
- }
-
- public void updateCaptureProgress(
- float panningRateXInDegree, float panningRateYInDegree,
- float progressHorizontalAngle, float progressVerticalAngle,
- float maxPanningSpeed) {
-
- if ((Math.abs(panningRateXInDegree) > maxPanningSpeed)
- || (Math.abs(panningRateYInDegree) > maxPanningSpeed)) {
- showTooFastIndication();
- } else {
- hideTooFastIndication();
- }
-
- // progressHorizontalAngle and progressVerticalAngle are relative to the
- // camera. Convert them to UI direction.
- mProgressAngle[0] = progressHorizontalAngle;
- mProgressAngle[1] = progressVerticalAngle;
- mProgressDirectionMatrix.mapPoints(mProgressAngle);
-
- int angleInMajorDirection =
- (Math.abs(mProgressAngle[0]) > Math.abs(mProgressAngle[1]))
- ? (int) mProgressAngle[0]
- : (int) mProgressAngle[1];
- mCaptureProgressBar.setProgress((angleInMajorDirection));
- }
-
- public void setProgressOrientation(int orientation) {
- mProgressDirectionMatrix.reset();
- mProgressDirectionMatrix.postRotate(orientation);
- }
-
- public void showDirectionIndicators(int direction) {
- switch (direction) {
- case PanoProgressBar.DIRECTION_NONE:
- mLeftIndicator.setVisibility(View.VISIBLE);
- mRightIndicator.setVisibility(View.VISIBLE);
- break;
- case PanoProgressBar.DIRECTION_LEFT:
- mLeftIndicator.setVisibility(View.VISIBLE);
- mRightIndicator.setVisibility(View.INVISIBLE);
- break;
- case PanoProgressBar.DIRECTION_RIGHT:
- mLeftIndicator.setVisibility(View.INVISIBLE);
- mRightIndicator.setVisibility(View.VISIBLE);
- break;
- }
- }
-
- public SurfaceTexture getSurfaceTexture() {
- return mSurfaceTexture;
- }
-
- @Override
- public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i2) {
- mSurfaceTexture = surfaceTexture;
- mController.onPreviewUIReady();
- }
-
- @Override
- public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i2) {
-
- }
-
- @Override
- public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
- mController.onPreviewUIDestroyed();
- mSurfaceTexture = null;
- Log.d(TAG, "surfaceTexture is destroyed");
- return true;
- }
-
- @Override
- public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
- // Make sure preview cover is hidden if preview data is available.
- if (mPreviewCover.getVisibility() != View.GONE) {
- mPreviewCover.setVisibility(View.GONE);
- }
- }
-
- private void hideDirectionIndicators() {
- mLeftIndicator.setVisibility(View.INVISIBLE);
- mRightIndicator.setVisibility(View.INVISIBLE);
- }
-
- public Point getPreviewAreaSize() {
- return new Point(
- mTextureView.getWidth(), mTextureView.getHeight());
- }
-
- public void reset() {
- mShutterButton.setImageResource(R.drawable.btn_new_shutter);
- mReviewLayout.setVisibility(View.GONE);
- mCaptureProgressBar.setVisibility(View.INVISIBLE);
- }
-
- public void showFinalMosaic(Bitmap bitmap, int orientation) {
- if (bitmap != null && orientation != 0) {
- Matrix rotateMatrix = new Matrix();
- rotateMatrix.setRotate(orientation);
- bitmap = Bitmap.createBitmap(
- bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(),
- rotateMatrix, false);
- }
-
- mReview.setImageBitmap(bitmap);
- mCaptureLayout.setVisibility(View.GONE);
- mReviewLayout.setVisibility(View.VISIBLE);
- }
-
- public void onConfigurationChanged(
- boolean isLandscape, boolean threadRunning) {
- Drawable lowResReview = null;
- if (threadRunning) lowResReview = mReview.getDrawable();
-
- // Change layout in response to configuration change
- LayoutInflater inflater = (LayoutInflater)
- mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-
- mReviewControl.removeAllViews();
- inflater.inflate(R.layout.pano_review_control, mReviewControl, true);
-
- mRootView.bringChildToFront(mCameraControls);
- setViews(mActivity.getResources());
- if (threadRunning) {
- mReview.setImageDrawable(lowResReview);
- mCaptureLayout.setVisibility(View.GONE);
- mReviewLayout.setVisibility(View.VISIBLE);
- }
- }
-
- public void resetSavingProgress() {
- mSavingProgressBar.reset();
- mSavingProgressBar.setRightIncreasing(true);
- }
-
- public void updateSavingProgress(int progress) {
- mSavingProgressBar.setProgress(progress);
- }
-
- @Override
- public void onShutterButtonFocus(boolean pressed) {
- // Do nothing.
- }
-
- @Override
- public void onShutterButtonClick() {
- mController.onShutterButtonClick();
- }
-
- @Override
- public void onLayoutChange(
- View v, int l, int t, int r, int b,
- int oldl, int oldt, int oldr, int oldb) {
- mController.onPreviewUILayoutChange(l, t, r, b);
- }
-
- public void showAlertDialog(
- String title, String failedString,
- String OKString, Runnable runnable) {
- mDialogHelper.showAlertDialog(title, failedString, OKString, runnable);
- }
-
- public void showWaitingDialog(String title) {
- mDialogHelper.showWaitingDialog(title);
- }
-
- public void dismissAllDialogs() {
- mDialogHelper.dismissAll();
- }
-
- private void createContentView() {
- LayoutInflater inflator = (LayoutInflater) mActivity
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- inflator.inflate(R.layout.panorama_module, mRootView, true);
-
- Resources appRes = mActivity.getResources();
- mIndicatorColor = appRes.getColor(R.color.pano_progress_indication);
- mReviewBackground = appRes.getColor(R.color.review_background);
- mIndicatorColorFast = appRes.getColor(R.color.pano_progress_indication_fast);
-
- mPreviewCover = mRootView.findViewById(R.id.preview_cover);
- mPreviewLayout = mRootView.findViewById(R.id.pano_preview_layout);
- mReviewControl = (ViewGroup) mRootView.findViewById(R.id.pano_review_control);
- mReviewLayout = mRootView.findViewById(R.id.pano_review_layout);
- mReview = (ImageView) mRootView.findViewById(R.id.pano_reviewarea);
- mCaptureLayout = (FrameLayout) mRootView.findViewById(R.id.panorama_capture_layout);
- mCaptureProgressBar = (PanoProgressBar) mRootView.findViewById(R.id.pano_pan_progress_bar);
- mCaptureProgressBar.setBackgroundColor(appRes.getColor(R.color.pano_progress_empty));
- mCaptureProgressBar.setDoneColor(appRes.getColor(R.color.pano_progress_done));
- mCaptureProgressBar.setIndicatorColor(mIndicatorColor);
- mCaptureProgressBar.setIndicatorWidth(20);
-
- mPreviewBorder = mCaptureLayout.findViewById(R.id.pano_preview_area_border);
-
- mLeftIndicator = mRootView.findViewById(R.id.pano_pan_left_indicator);
- mRightIndicator = mRootView.findViewById(R.id.pano_pan_right_indicator);
- mLeftIndicator.setEnabled(false);
- mRightIndicator.setEnabled(false);
- mTooFastPrompt = (TextView) mRootView.findViewById(R.id.pano_capture_too_fast_textview);
- mCaptureIndicator = mRootView.findViewById(R.id.pano_capture_indicator);
-
- mShutterButton = (ShutterButton) mRootView.findViewById(R.id.shutter_button);
- mShutterButton.setImageResource(R.drawable.btn_new_shutter);
- mShutterButton.setOnShutterButtonListener(this);
- // Hide menu and indicators.
- mRootView.findViewById(R.id.menu).setVisibility(View.GONE);
- mRootView.findViewById(R.id.on_screen_indicators).setVisibility(View.GONE);
- mReview.setBackgroundColor(mReviewBackground);
-
- mTextureView = (TextureView) mRootView.findViewById(R.id.pano_preview_textureview);
- mTextureView.setSurfaceTextureListener(this);
- mTextureView.addOnLayoutChangeListener(this);
- mCameraControls = (CameraControls) mRootView.findViewById(R.id.camera_controls);
-
- mDialogHelper = new DialogHelper();
- setViews(appRes);
- }
-
- private void setViews(Resources appRes) {
- int weight = appRes.getInteger(R.integer.SRI_pano_layout_weight);
-
- LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mPreviewLayout.getLayoutParams();
- lp.weight = weight;
- mPreviewLayout.setLayoutParams(lp);
-
- lp = (LinearLayout.LayoutParams) mReview.getLayoutParams();
- lp.weight = weight;
- mPreviewLayout.setLayoutParams(lp);
-
- mSavingProgressBar = (PanoProgressBar) mRootView.findViewById(R.id.pano_saving_progress_bar);
- mSavingProgressBar.setIndicatorWidth(0);
- mSavingProgressBar.setMaxProgress(100);
- mSavingProgressBar.setBackgroundColor(appRes.getColor(R.color.pano_progress_empty));
- mSavingProgressBar.setDoneColor(appRes.getColor(R.color.pano_progress_indication));
-
- View cancelButton = mRootView.findViewById(R.id.pano_review_cancel_button);
- cancelButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View arg0) {
- mController.cancelHighResStitching();
- }
- });
-
-
- }
-
- private void showTooFastIndication() {
- mTooFastPrompt.setVisibility(View.VISIBLE);
- // The PreviewArea also contains the border for "too fast" indication.
- mPreviewBorder.setVisibility(View.VISIBLE);
- mCaptureProgressBar.setIndicatorColor(mIndicatorColorFast);
- mLeftIndicator.setEnabled(true);
- mRightIndicator.setEnabled(true);
- }
-
- private void hideTooFastIndication() {
- mTooFastPrompt.setVisibility(View.GONE);
- mPreviewBorder.setVisibility(View.INVISIBLE);
- mCaptureProgressBar.setIndicatorColor(mIndicatorColor);
- mLeftIndicator.setEnabled(false);
- mRightIndicator.setEnabled(false);
- }
-
- public void flipPreviewIfNeeded() {
- // Rotation needed to display image correctly clockwise
- int cameraOrientation = mController.getCameraOrientation();
- // Display rotated counter-clockwise
- int displayRotation = CameraUtil.getDisplayRotation(mActivity);
- // Rotation needed to display image correctly on current display
- int rotation = (cameraOrientation - displayRotation + 360) % 360;
- if (rotation >= 180) {
- mTextureView.setRotation(180);
- } else {
- mTextureView.setRotation(0);
- }
- }
-
- public void showPreviewCover() {
- mPreviewCover.setVisibility(View.VISIBLE);
- }
-
- private class DialogHelper {
- private ProgressDialog mProgressDialog;
- private AlertDialog mAlertDialog;
-
- DialogHelper() {
- mProgressDialog = null;
- mAlertDialog = null;
- }
-
- public void dismissAll() {
- if (mAlertDialog != null) {
- mAlertDialog.dismiss();
- mAlertDialog = null;
- }
- if (mProgressDialog != null) {
- mProgressDialog.dismiss();
- mProgressDialog = null;
- }
- }
-
- public void showAlertDialog(
- CharSequence title, CharSequence message,
- CharSequence buttonMessage, final Runnable buttonRunnable) {
- dismissAll();
- mAlertDialog = (new AlertDialog.Builder(mActivity))
- .setTitle(title)
- .setMessage(message)
- .setNeutralButton(buttonMessage, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialogInterface, int i) {
- buttonRunnable.run();
- }
- })
- .show();
- }
-
- public void showWaitingDialog(CharSequence message) {
- dismissAll();
- mProgressDialog = ProgressDialog.show(mActivity, null, message, true, false);
- }
- }
-
- private static class FlipBitmapDrawable extends BitmapDrawable {
-
- public FlipBitmapDrawable(Resources res, Bitmap bitmap) {
- super(res, bitmap);
- }
-
- @Override
- public void draw(Canvas canvas) {
- Rect bounds = getBounds();
- int cx = bounds.centerX();
- int cy = bounds.centerY();
- canvas.save(Canvas.MATRIX_SAVE_FLAG);
- canvas.rotate(180, cx, cy);
- super.draw(canvas);
- canvas.restore();
- }
- }
-}
diff --git a/src/com/android/camera/module/ModulesInfo.java b/src/com/android/camera/module/ModulesInfo.java
index b7a1ecce9..9fbd09525 100644
--- a/src/com/android/camera/module/ModulesInfo.java
+++ b/src/com/android/camera/module/ModulesInfo.java
@@ -20,9 +20,7 @@ import android.content.Context;
import com.android.camera.PhotoModule;
import com.android.camera.VideoModule;
-import com.android.camera.WideAnglePanoramaModule;
import com.android.camera.app.AppController;
-import com.android.camera.app.CameraServices;
import com.android.camera.app.ModuleManager;
import com.android.camera.ui.ModeListView;
import com.android.camera.util.GcamHelper;