summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--jni/feature_mos/src/mosaic/Blend.cpp24
-rw-r--r--jni/feature_mos/src/mosaic/Blend.h5
-rw-r--r--jni/feature_mos/src/mosaic/Mosaic.cpp22
-rw-r--r--jni/feature_mos/src/mosaic/Mosaic.h3
-rw-r--r--jni/feature_mos_jni.cpp50
-rw-r--r--src/com/android/camera/panorama/Mosaic.java15
-rw-r--r--src/com/android/camera/panorama/MosaicFrameProcessor.java8
-rw-r--r--src/com/android/camera/panorama/PanoramaActivity.java76
8 files changed, 154 insertions, 49 deletions
diff --git a/jni/feature_mos/src/mosaic/Blend.cpp b/jni/feature_mos/src/mosaic/Blend.cpp
index ee67d5a..cc146a8 100644
--- a/jni/feature_mos/src/mosaic/Blend.cpp
+++ b/jni/feature_mos/src/mosaic/Blend.cpp
@@ -91,7 +91,7 @@ void Blend::AlignToMiddleFrame(MosaicFrame **frames, int frames_size)
int Blend::runBlend(MosaicFrame **frames, int frames_size,
ImageType &imageMosaicYVU, int &mosaicWidth, int &mosaicHeight,
- float &progress)
+ float &progress, bool &cancelComputation)
{
int ret;
int numCenters;
@@ -185,7 +185,7 @@ int Blend::runBlend(MosaicFrame **frames, int frames_size,
// Do merging and blending :
ret = DoMergeAndBlend(frames, numCenters, width, height, *imgMos, fullRect,
- cropping_rect, progress);
+ cropping_rect, progress, cancelComputation);
if (m_wb.blendingType == BLEND_TYPE_HORZ)
CropFinalMosaic(*imgMos, cropping_rect);
@@ -207,7 +207,7 @@ int Blend::runBlend(MosaicFrame **frames, int frames_size,
mosaicHeight = Mheight;
}
- return BLEND_RET_OK;
+ return ret;
}
@@ -256,7 +256,7 @@ int Blend::FillFramePyramid(MosaicFrame *mb)
int Blend::DoMergeAndBlend(MosaicFrame **frames, int nsite,
int width, int height, YUVinfo &imgMos, MosaicRect &rect,
- MosaicRect &cropping_rect, float &progress)
+ MosaicRect &cropping_rect, float &progress, bool &cancelComputation)
{
m_pMosaicYPyr = NULL;
m_pMosaicUPyr = NULL;
@@ -280,6 +280,14 @@ int Blend::DoMergeAndBlend(MosaicFrame **frames, int nsite,
site_idx = 0;
for(CSite *csite = m_AllSites; csite < esite; csite++)
{
+ if(cancelComputation)
+ {
+ if (m_pMosaicVPyr) free(m_pMosaicVPyr);
+ if (m_pMosaicUPyr) free(m_pMosaicUPyr);
+ if (m_pMosaicYPyr) free(m_pMosaicYPyr);
+ return BLEND_RET_CANCELLED;
+ }
+
mb = csite->getMb();
mb->vcrect = mb->brect;
@@ -294,6 +302,14 @@ int Blend::DoMergeAndBlend(MosaicFrame **frames, int nsite,
site_idx = 0;
for(CSite *csite = m_AllSites; csite < esite; csite++)
{
+ if(cancelComputation)
+ {
+ if (m_pMosaicVPyr) free(m_pMosaicVPyr);
+ if (m_pMosaicUPyr) free(m_pMosaicUPyr);
+ if (m_pMosaicYPyr) free(m_pMosaicYPyr);
+ return BLEND_RET_CANCELLED;
+ }
+
mb = csite->getMb();
diff --git a/jni/feature_mos/src/mosaic/Blend.h b/jni/feature_mos/src/mosaic/Blend.h
index 013fbbf..c878be4 100644
--- a/jni/feature_mos/src/mosaic/Blend.h
+++ b/jni/feature_mos/src/mosaic/Blend.h
@@ -68,6 +68,7 @@ public:
static const int BLEND_RET_ERROR = -1;
static const int BLEND_RET_OK = 0;
static const int BLEND_RET_ERROR_MEMORY = 1;
+ static const int BLEND_RET_CANCELLED = -2;
Blend();
~Blend();
@@ -75,7 +76,7 @@ public:
int initialize(int blendingType, int frame_width, int frame_height);
int runBlend(MosaicFrame **frames, int frames_size, ImageType &imageMosaicYVU,
- int &mosaicWidth, int &mosaicHeight, float &progress);
+ int &mosaicWidth, int &mosaicHeight, float &progress, bool &cancelComputation);
protected:
@@ -105,7 +106,7 @@ protected:
void ClipBlendRect(CSite *csite, BlendRect &brect);
void AlignToMiddleFrame(MosaicFrame **frames, int frames_size);
- int DoMergeAndBlend(MosaicFrame **frames, int nsite, int width, int height, YUVinfo &imgMos, MosaicRect &rect, MosaicRect &cropping_rect, float &progress);
+ int DoMergeAndBlend(MosaicFrame **frames, int nsite, int width, int height, YUVinfo &imgMos, MosaicRect &rect, MosaicRect &cropping_rect, float &progress, bool &cancelComputation);
void ComputeMask(CSite *csite, BlendRect &vcrect, BlendRect &brect, MosaicRect &rect, YUVinfo &imgMos, int site_idx);
void ProcessPyramidForThisFrame(CSite *csite, BlendRect &vcrect, BlendRect &brect, MosaicRect &rect, YUVinfo &imgMos, double trs[3][3], int site_idx);
diff --git a/jni/feature_mos/src/mosaic/Mosaic.cpp b/jni/feature_mos/src/mosaic/Mosaic.cpp
index 988ec28..3dc1e1d 100644
--- a/jni/feature_mos/src/mosaic/Mosaic.cpp
+++ b/jni/feature_mos/src/mosaic/Mosaic.cpp
@@ -153,7 +153,7 @@ int Mosaic::addFrame(ImageType imageYVU)
}
-int Mosaic::createMosaic(float &progress)
+int Mosaic::createMosaic(float &progress, bool &cancelComputation)
{
printf("Creating mosaic\n");
@@ -172,14 +172,28 @@ int Mosaic::createMosaic(float &progress)
}
+ int ret;
+
// Blend the mosaic (alignment has already been done)
if (blender != NULL)
{
- blender->runBlend((MosaicFrame **) frames, frames_size, imageMosaicYVU,
- mosaicWidth, mosaicHeight, progress);
+ ret = blender->runBlend((MosaicFrame **) frames, frames_size, imageMosaicYVU,
+ mosaicWidth, mosaicHeight, progress, cancelComputation);
}
- return MOSAIC_RET_OK;
+ switch(ret)
+ {
+ case Blend::BLEND_RET_ERROR:
+ case Blend::BLEND_RET_ERROR_MEMORY:
+ ret = MOSAIC_RET_ERROR;
+ break;
+ case Blend::BLEND_RET_CANCELLED:
+ ret = MOSAIC_RET_CANCELLED;
+ break;
+ case Blend::BLEND_RET_OK:
+ ret = MOSAIC_RET_OK;
+ }
+ return ret;
}
ImageType Mosaic::getMosaic(int &width, int &height)
diff --git a/jni/feature_mos/src/mosaic/Mosaic.h b/jni/feature_mos/src/mosaic/Mosaic.h
index 25abc43..ecf0536 100644
--- a/jni/feature_mos/src/mosaic/Mosaic.h
+++ b/jni/feature_mos/src/mosaic/Mosaic.h
@@ -112,7 +112,7 @@ public:
* \param progress Variable to set the current progress in.
* \return Return code signifying success or failure.
*/
- int createMosaic(float &progress);
+ int createMosaic(float &progress, bool &cancelComputation);
/*!
* Obtains the resulting mosaic and its dimensions.
@@ -141,6 +141,7 @@ public:
*/
static const int MOSAIC_RET_OK = 1;
static const int MOSAIC_RET_ERROR = -1;
+ static const int MOSAIC_RET_CANCELLED = -2;
protected:
diff --git a/jni/feature_mos_jni.cpp b/jni/feature_mos_jni.cpp
index 1c163ab..84647b9 100644
--- a/jni/feature_mos_jni.cpp
+++ b/jni/feature_mos_jni.cpp
@@ -67,9 +67,10 @@ ImageType resultBGR = ImageUtils::IMAGE_TYPE_NOIMAGE;
float gTRS[10];
// Variables to keep track of the mosaic computation progress for both LR & HR.
float gProgress[NR];
+// Variables to be able to cancel the mosaic computation when the GUI says so.
+bool gCancelComputation[NR];
int c;
-int ret;
int width=0, height=0;
int mosaicWidth=0, mosaicHeight=0;
@@ -207,19 +208,21 @@ int AddFrame(int mID, int k, float* trs1d)
return ret_code;
}
-void Finalize(int mID)
+int Finalize(int mID)
{
double t0, t1, time_c;
t0 = now_ms();
// Create the mosaic
- ret = mosaic[mID]->createMosaic(gProgress[mID]);
+ int ret = mosaic[mID]->createMosaic(gProgress[mID], gCancelComputation[mID]);
t1 = now_ms();
time_c = t1 - t0;
LOGV("CreateMosaic: %g ms",time_c);
// Get back the result
resultYVU = mosaic[mID]->getMosaic(mosaicWidth, mosaicHeight);
+
+ return ret;
}
void YUV420toYVU24(ImageType yvu24, ImageType yuv420sp, int width, int height)
@@ -532,23 +535,33 @@ JNIEXPORT void JNICALL Java_com_android_camera_panorama_Mosaic_reset(
gProgress[LR] = 0.0;
gProgress[HR] = 0.0;
+ gCancelComputation[LR] = false;
+ gCancelComputation[HR] = false;
+
Init(LR,MAX_FRAMES_LR);
}
JNIEXPORT jint JNICALL Java_com_android_camera_panorama_Mosaic_reportProgress(
- JNIEnv* env, jobject thiz, jboolean hires)
+ JNIEnv* env, jobject thiz, jboolean hires, jboolean cancel_computation)
{
if(bool(hires))
+ gCancelComputation[HR] = cancel_computation;
+ else
+ gCancelComputation[LR] = cancel_computation;
+
+ if(bool(hires))
return (jint) gProgress[HR];
else
return (jint) gProgress[LR];
}
-JNIEXPORT void JNICALL Java_com_android_camera_panorama_Mosaic_createMosaic(
+JNIEXPORT jint JNICALL Java_com_android_camera_panorama_Mosaic_createMosaic(
JNIEnv* env, jobject thiz, jboolean value)
{
high_res = bool(value);
+ int ret;
+
if(high_res)
{
double t0, t1, time_c;
@@ -560,28 +573,41 @@ JNIEXPORT void JNICALL Java_com_android_camera_panorama_Mosaic_createMosaic(
for(int k = 0; k < frame_number_HR; k++)
{
+ if (gCancelComputation[HR])
+ break;
AddFrame(HR, k, NULL);
gProgress[HR] += TIME_PERCENT_ALIGN/frame_number_HR;
}
- gProgress[HR] = TIME_PERCENT_ALIGN;
+ if (gCancelComputation[HR])
+ {
+ ret = Mosaic::MOSAIC_RET_CANCELLED;
+ }
+ else
+ {
+ gProgress[HR] = TIME_PERCENT_ALIGN;
- t1 = now_ms();
- time_c = t1 - t0;
- LOGV("AlignAll [HR]: %g ms",time_c);
+ t1 = now_ms();
+ time_c = t1 - t0;
+ LOGV("AlignAll [HR]: %g ms",time_c);
- Finalize(HR);
+ ret = Finalize(HR);
- gProgress[HR] = 100.0;
+ gProgress[HR] = 100.0;
+ }
high_res = false;
}
else
{
gProgress[LR] = TIME_PERCENT_ALIGN;
- Finalize(LR);
+
+ ret = Finalize(LR);
+
gProgress[LR] = 100.0;
}
+
+ return (jint) ret;
}
JNIEXPORT jintArray JNICALL Java_com_android_camera_panorama_Mosaic_getFinalMosaic(
diff --git a/src/com/android/camera/panorama/Mosaic.java b/src/com/android/camera/panorama/Mosaic.java
index ef9d367..b586aad 100644
--- a/src/com/android/camera/panorama/Mosaic.java
+++ b/src/com/android/camera/panorama/Mosaic.java
@@ -67,6 +67,13 @@ public class Mosaic {
*/
public static final int BLENDTYPE_HORIZONTAL =3;
+ /**
+ * 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;
+
static {
System.loadLibrary("jni_mosaic");
}
@@ -129,8 +136,10 @@ public class 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 void createMosaic(boolean value);
+ public native int createMosaic(boolean value);
/**
* Get the data for the created mosaic.
@@ -161,8 +170,10 @@ public class Mosaic {
* 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);
+ public native int reportProgress(boolean hires, boolean cancelComputation);
}
diff --git a/src/com/android/camera/panorama/MosaicFrameProcessor.java b/src/com/android/camera/panorama/MosaicFrameProcessor.java
index c67508f..dde4a22 100644
--- a/src/com/android/camera/panorama/MosaicFrameProcessor.java
+++ b/src/com/android/camera/panorama/MosaicFrameProcessor.java
@@ -78,8 +78,8 @@ public class MosaicFrameProcessor {
mProgressListener = listener;
}
- public int reportProgress(boolean hires) {
- return mMosaicer.reportProgress(hires);
+ public int reportProgress(boolean hires, boolean cancel) {
+ return mMosaicer.reportProgress(hires, cancel);
}
public void initialize() {
@@ -126,8 +126,8 @@ public class MosaicFrameProcessor {
mMosaicer.reset();
}
- public void createMosaic(boolean highRes) {
- mMosaicer.createMosaic(highRes);
+ public int createMosaic(boolean highRes) {
+ return mMosaicer.createMosaic(highRes);
}
public byte[] getFinalMosaicNV21() {
diff --git a/src/com/android/camera/panorama/PanoramaActivity.java b/src/com/android/camera/panorama/PanoramaActivity.java
index c2cb837..0aefb07 100644
--- a/src/com/android/camera/panorama/PanoramaActivity.java
+++ b/src/com/android/camera/panorama/PanoramaActivity.java
@@ -53,6 +53,8 @@ import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
+import android.hardware.Camera.Parameters;
+import android.hardware.Camera.Size;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -62,6 +64,7 @@ import android.view.Gravity;
import android.view.OrientationEventListener;
import android.view.View;
import android.view.WindowManager;
+import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
@@ -84,6 +87,7 @@ public class PanoramaActivity extends Activity implements
private static final int MSG_RESET_TO_PREVIEW_WITH_THUMBNAIL = 2;
private static final int MSG_GENERATE_FINAL_MOSAIC_ERROR = 3;
private static final int MSG_DISMISS_ALERT_DIALOG_AND_RESET_TO_PREVIEW = 4;
+ private static final int MSG_GENERATE_FINAL_MOSAIC_CANCELLED = 5;
private static final String TAG = "PanoramaActivity";
private static final int PREVIEW_STOPPED = 0;
@@ -155,6 +159,8 @@ public class PanoramaActivity extends Activity implements
private Handler mMainHandler;
private SurfaceTexture mSurfaceTexture;
private boolean mThreadRunning;
+ private boolean mCancelComputation;
+ private int mMosaicComputationStatus;
private float[] mTransformMatrix;
private float mHorizontalViewAngle;
@@ -247,6 +253,9 @@ public class PanoramaActivity extends Activity implements
mAlertDialog = null;
resetToPreview();
break;
+ case MSG_GENERATE_FINAL_MOSAIC_CANCELLED:
+ onBackgroundThreadFinished();
+ resetToPreview();
}
clearMosaicFrameProcessorIfNeeded();
}
@@ -469,12 +478,15 @@ public class PanoramaActivity extends Activity implements
@Override
public void run() {
MosaicJpeg jpeg = generateFinalMosaic(false);
- Bitmap bitmap = null;
- if (jpeg != null) {
- bitmap = BitmapFactory.decodeByteArray(jpeg.data, 0, jpeg.data.length);
+
+ if (mMosaicComputationStatus == Mosaic.MOSAIC_RET_OK) {
+ Bitmap bitmap = null;
+ if (jpeg != null) {
+ bitmap = BitmapFactory.decodeByteArray(jpeg.data, 0, jpeg.data.length);
+ }
+ mMainHandler.sendMessage(mMainHandler.obtainMessage(
+ MSG_LOW_RES_FINAL_MOSAIC_READY, bitmap));
}
- mMainHandler.sendMessage(mMainHandler.obtainMessage(
- MSG_LOW_RES_FINAL_MOSAIC_READY, bitmap));
}
});
reportProgress(false);
@@ -561,7 +573,8 @@ public class PanoramaActivity extends Activity implements
@Override
public void run() {
while (mThreadRunning) {
- final int progress = mMosaicFrameProcessor.reportProgress(highRes);
+ final int progress = mMosaicFrameProcessor.reportProgress(
+ highRes, mCancelComputation);
try {
Thread.sleep(50);
@@ -591,20 +604,27 @@ public class PanoramaActivity extends Activity implements
@Override
public void run() {
MosaicJpeg jpeg = generateFinalMosaic(true);
- if (jpeg == null) {
- mMainHandler.sendEmptyMessage(MSG_GENERATE_FINAL_MOSAIC_ERROR);
+
+ if (mMosaicComputationStatus == Mosaic.MOSAIC_RET_CANCELLED) {
+ mMainHandler.sendEmptyMessage(MSG_GENERATE_FINAL_MOSAIC_CANCELLED);
} else {
- int orientation = Exif.getOrientation(jpeg.data);
- Uri uri = savePanorama(jpeg.data, orientation);
- if (uri != null) {
- // Create a thumbnail whose width is equal or bigger than the entire screen.
- int ratio = (int) Math.ceil((double) jpeg.width / mPanoLayout.getWidth());
- int inSampleSize = Integer.highestOneBit(ratio);
- mThumbnail = Thumbnail.createThumbnail(
- jpeg.data, orientation, inSampleSize, uri);
+ if (jpeg == null) {
+ mMainHandler.sendEmptyMessage(MSG_GENERATE_FINAL_MOSAIC_ERROR);
+ } else {
+ int orientation = Exif.getOrientation(jpeg.data);
+ Uri uri = savePanorama(jpeg.data, orientation);
+ if (uri != null) {
+ // Create a thumbnail whose width is equal or bigger
+ // than the entire screen.
+ int ratio = (int) Math.ceil((double) jpeg.width /
+ mPanoLayout.getWidth());
+ int inSampleSize = Integer.highestOneBit(ratio);
+ mThumbnail = Thumbnail.createThumbnail(
+ jpeg.data, orientation, inSampleSize, uri);
+ }
+ mMainHandler.sendMessage(
+ mMainHandler.obtainMessage(MSG_RESET_TO_PREVIEW_WITH_THUMBNAIL));
}
- mMainHandler.sendMessage(
- mMainHandler.obtainMessage(MSG_RESET_TO_PREVIEW_WITH_THUMBNAIL));
}
}
});
@@ -622,7 +642,17 @@ public class PanoramaActivity extends Activity implements
mProgressDialog.setMax(100);
mProgressDialog.setMessage(str);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
- mProgressDialog.setCancelable(false); // Don't allow back key to dismiss this dialog.
+ // TODO: update the UI according to specs.
+// mProgressDialog.setCancelable(false); // Don't allow back key to dismiss this dialog.
+ mProgressDialog.setCancelable(true);
+
+ mProgressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel",
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog,
+ int whichButton) {
+ mCancelComputation = true;
+ }
+ });
mProgressDialog.show();
} else {
mPanoramaPrepareDialogFadeIn.start();
@@ -669,6 +699,7 @@ public class PanoramaActivity extends Activity implements
private void resetToPreview() {
mCaptureState = CAPTURE_STATE_VIEWFINDER;
+ mCancelComputation = false;
mReviewLayout.setVisibility(View.GONE);
mShutterButton.setBackgroundResource(R.drawable.btn_shutter_pan);
@@ -804,7 +835,12 @@ public class PanoramaActivity extends Activity implements
};
public MosaicJpeg generateFinalMosaic(boolean highRes) {
- mMosaicFrameProcessor.createMosaic(highRes);
+ int ret = mMosaicFrameProcessor.createMosaic(highRes);
+
+ mMosaicComputationStatus = ret;
+
+ if (ret == Mosaic.MOSAIC_RET_CANCELLED)
+ return null;
byte[] imageData = mMosaicFrameProcessor.getFinalMosaicNV21();
if (imageData == null) {